Hi, I've reproduced this behaviour on Debian/jessie with dpkg 1.17.23, but the original issue appeared on Debian/wheezy with dpkg 1.16.15 (and old-stable as well as unstable might be very probably affected as well). What happened (with anonymized data): a Debian package shipped a file called /srv/repository/release/myscript.sh. Its underlying directory /srv/repository on the file system of the host is a *symlink* pointing to a different directory (because the data is served via NFS from a different system). When the package gets removed/purged (or in a package update the file /srv/repository/release/myscript.sh is no longer provided) the symlink /srv/repository gets removed by dpkg, even though there are other files inside the directory. The original data behind the symlink isn't removed/touched/modified, so no data loss from that perspective. *But* by removing the symlink - even though there's still data inside the directory behind the symlink - this can cause serious service disruptions (and also conflicting data sets), as it happened at a customer of mine a few hours ago. [BTW, for the investigation it would have been nice if there would be some information about such removals in dpkg's logs, it was far from trivial to identify this behaviour.] Demonstration follows: ,---- [ simple example for reproducing ] | root@demo ~ # ls -la /symlinktarget | total 0 | drwxr-xr-x 3 root root 60 Feb 23 22:56 ./ | drwxr-xr-x 34 root root 300 Feb 23 22:56 ../ | drwxr-xr-x 2 root root 60 Feb 23 22:58 repository/ | root@demo ~ # ls -la /symlinktarget/repository | total 4 | drwxr-xr-x 2 root root 60 Feb 23 22:58 ./ | drwxr-xr-x 3 root root 60 Feb 23 22:56 ../ | -rw-r--r-- 1 root root 4 Feb 23 22:57 foo | root@demo ~ # | root@demo ~ # ln -s /symlinktarget/repository /srv/repository | root@demo ~ # ls -la /srv/repository | lrwxrwxrwx 1 root root 25 Feb 23 22:59 /srv/repository -> /symlinktarget/repository/ | root@demo ~ # | root@demo ~ # dpkg -i foobar-demo_0.0.2_all.deb | Selecting previously unselected package foobar-demo. | (Reading database ... 123190 files and directories currently installed.) | Preparing to unpack foobar-demo_0.0.2_all.deb ... | Unpacking foobar-demo (0.0.2) ... | Setting up foobar-demo (0.0.2) ... | root@demo ~ # ls -la /srv/repository/release/myscript.sh | total 32 | drwxr-xr-x 2 root root 100 Feb 23 22:59 ./ | drwxr-xr-x 3 root root 80 Feb 23 22:59 ../ | -rwxr-xr-x 1 root root 1855 Feb 23 22:49 myscript.sh | root@demo ~ # dpkg -S /srv/repository/release/myscript.sh | foobar-demo: /srv/repository/release/myscript.sh | root@demo ~ # echo foo > /srv/repository/foo | root@demo ~ # ls -la /srv/repository/ | total 4 | drwxr-xr-x 3 root root 80 Feb 23 22:59 ./ | drwxr-xr-x 3 root root 60 Feb 23 22:56 ../ | -rw-r--r-- 1 root root 4 Feb 23 22:59 foo | drwxr-xr-x 2 root root 100 Feb 23 22:59 release/ | root@demo ~ # ls -la /srv/repository/foo | -rw-r--r-- 1 root root 4 Feb 23 22:59 /srv/repository/foo | root@demo ~ # apt-get --purge remove foobar-demo | Reading package lists... Done | Building dependency tree | Reading state information... Done | The following packages will be REMOVED: | foobar-demo* | 0 upgraded, 0 newly installed, 1 to remove and 3 not upgraded. | After this operation, 152 kB disk space will be freed. | Do you want to continue? [Y/n] y | (Reading database ... 123223 files and directories currently installed.) | Removing foobar-demo (0.0.2) ... | root@demo ~ # ls -la /srv/repository/foo | ls: cannot access /srv/repository/foo: No such file or directory | root@demo ~ # ls -la /srv/repository | ls: cannot access /srv/repository: No such file or directory | root@demo ~ # ls -la /symlinktarget/repository | total 4 | drwxr-xr-x 2 root root 60 Feb 23 23:00 ./ | drwxr-xr-x 3 root root 60 Feb 23 22:56 ../ | -rw-r--r-- 1 root root 4 Feb 23 22:59 foo | root@demo ~ # `---- regards, -mika-
Hi! Yes, I'm afraid that's currently "expected" behavior. dpkg expects to manage all paths it touches in the filesystem. In this case you are placing files inside an already existing (and externally managed) hierarchy, but dpkg does not know that, and when no other package owns that path it tries to remove it. Fixing this requires to track file meta-data, because otherwise dpkg does not know if there's been any local changes, or whether a path is really a symlink or a directory. A workaround could be to avoid removing a path if it contains other paths inside the same package, but that has too many corner cases. Consider the following, a package A ships /dir and /dir/file, and /dir is a symlink on the filesystem. And suddenly package B Replaces A and takes over /dir/file. If package B gets removed, then package A only owns /dir, and when that gets removed dpkg cannot know if it needs to remove it or not, because it does not contain any owned paths. So this is for now either a packaging or admin problem, and a wishlist from dpkg PoV. Thanks, Guillem