Hi,

(regarding the previous posts in this thread:)
while having a dpkg-maintscript-helper subcommand that cleans up files during 
purge may be nice to simplify writing maintainer scripts, I think the removal 
of (parent-) directories should stay dpkg's job.

(regarding the original problem:)
I'm seeing a lot of owned directories remaining in the piuparts tests for sid 
(they are treated as error for sid and warning for other distributions):
http://piuparts.debian.org/sid/owned_files_by_many_packages_error.html
http://piuparts.debian.org/sid/owned_files_after_purge_error.html

I tried to create a minimal package that triggers the behaviour. Looks like it 
is related to directories owned by multiple packages and their removal order.

A minimal example package is attached: extract, debuild, and you get 2 .debs:
foo and foobar both ship the empty /var/lib/foobar directory
foobar.postinst configure creates a file there
foobar.postrm purge cleans up the file created in the postinst
foo.postrm purge cleans up a nonexisting file there

# dpkg -i foo_1_all.deb foobar_1_all.deb
Selecting previously unselected package foo.
(Reading database ... 13543 files and directories currently installed.)
Unpacking foo (from foo_1_all.deb) ...
Selecting previously unselected package foobar.
Unpacking foobar (from foobar_1_all.deb) ...
Setting up foo (1) ...
Setting up foobar (1) ...

# dpkg -S $(find /var/lib/foobar)
foo, foobar: /var/lib/foobar
dpkg-query: no path found matching pattern /var/lib/foobar/state.

# dpkg --remove foo foobar
(Reading database ... 13550 files and directories currently installed.)
Removing foo ...
Removing foobar ...

# dpkg -S $(find /var/lib/foobar)
foobar: /var/lib/foobar
dpkg-query: no path found matching pattern /var/lib/foobar/state.

# dpkg --purge foo foobar
(Reading database ... 13544 files and directories currently installed.)
Removing foo ...
Purging configuration files for foo ...
Removing foobar ...
Purging configuration files for foobar ...

# find /var/lib/foobar
find: `/var/lib/foobar': No such file or directory

### OK this went fine, let's permute some arguments

# dpkg -i foobar_1_all.deb foo_1_all.deb
Selecting previously unselected package foobar.
(Reading database ... 13543 files and directories currently installed.)
Unpacking foobar (from foobar_1_all.deb) ...
Selecting previously unselected package foo.
Unpacking foo (from foo_1_all.deb) ...
Setting up foobar (1) ...
Setting up foo (1) ...

# dpkg -S $(find /var/lib/foobar)
foo, foobar: /var/lib/foobar
dpkg-query: no path found matching pattern /var/lib/foobar/state.

# dpkg --remove foobar foo
(Reading database ... 13550 files and directories currently installed.)
Removing foobar ...
Removing foo ...

# dpkg -S $(find /var/lib/foobar)
foo: /var/lib/foobar
dpkg-query: no path found matching pattern /var/lib/foobar/state.

# dpkg --purge foo foobar
(Reading database ... 13544 files and directories currently installed.)
Removing foo ...
Purging configuration files for foo ...
dpkg: warning: while removing foo, directory '/var/lib/foobar' not empty so 
not removed.
Removing foobar ...
Purging configuration files for foobar ...

# find /var/lib/foobar
/var/lib/foobar

# dpkg -S $(find /var/lib/foobar)
dpkg-query: no path found matching pattern /var/lib/foobar.


The problem seems to be which package keeps ownership of a shared directory in 
the case of removal. As it is now, this stays with the package to be removed 
last. But that one is not necessarily the one purged last.

IMO, during directory removal two cases are to be distinguished:
a) really empty directories (that either do not exist any more or rmdir on the 
   directory would succeed - not empty in the sense 'dpkg knows no file/dir 
   inside this directory'):
   these can be unregistered during REMOVE (aka removed from the file list of 
   the package being removed) and removed from the filesystem if the reference 
   count drops to 0
b) not empty directories (rmdir would fail regardless of dpkg knowing any file 
   below this path):
   these should be kept during REMOVE and should only be removed during PURGE
   (unregistered from the file list and eventually rmdir-ed, but a diagnostic   
   that removal failed should only be emitted after 'postrm purge' was run, 
   the reference count dropped to 0 but the directory still can't be removed)
For packages without postrm and with no conffiles (where REMOVE implies PURGE) 
this would not change the current behavior.

That way every package that has shipped some directory and cleans up something 
in there during postrm purge can be sure that it still owns the directory and 
dpkg will clean this up afterwards. If the directory was really empty earlier 
and dpkg decided to unregister (and possibly rmdir) it, there was also 
nothing left for the postrm purge to clean up. (And if files to be cleaned up 
during purge appear *after* the package was removed, this is a serious error 
elsewhere.)

I would really like to see this fixed for wheezy.


Andreas

Attachment: foobar_1.tar.gz
Description: application/tgz

Reply via email to