On Sat, Jan 28, 2006 at 12:50:41AM +0100, Frank Lichtenheld wrote:
> There is one problem with the patch: It has the potential
> to leave empty directories behind on removal (they will get
> removed on purge, though).
> This happens in the case that two packages which have both conffiles
> share a directory which has no conffiles in it. The directory will be
> left behind on removal even though there are no files left in it.
> (If that description was too terse, just ask. I can certainly explain
> that in more detail)
> 
> This is because the test isdirectoryinuse is actually not what we want
> to test. The _real_ question is "is directory in use by my own conffiles?"
> Because if it isn't, there is no problem... Can someone more familiar
> with dpkg tell me how to express this question in code?

I see what you mean.  In the example of openssl and ca-certificates, the
directory /etc/ssl/certs should not be taken off the file list of
ca-certificates because the postrm script has not yet deleted
ca-certificates.crt.  But I don't see an elegant way of coding an
algorithm checking things happening in scripts like postrm.

An other way of looking at your (valid!) point about deleting empty
directories in time, is that there's no point in keeping an empty
directory on a list of files of a package being "removed".

The attached patch is a variant of my previous patch.  It still fixes
the bug, but it also does not keep empty directories "in use" for longer
than necessary.

Regards,

Bart Martens

diff -ruN orig/dpkg-1.13.13/src/help.c dpkg-1.13.13/src/help.c
--- orig/dpkg-1.13.13/src/help.c        2006-01-18 09:30:03.000000000 +0100
+++ dpkg-1.13.13/src/help.c     2006-02-05 12:42:50.000000000 +0100
@@ -424,6 +424,32 @@
   return 0;
 }
 
+int isemptydir( char *path )
+{
+  /* Returns 1 if the directory is empty, 0 if not, and -1 if not sure */
+  DIR *dirptr;
+  struct dirent *direntry;
+
+  dirptr = opendir( path );
+  if( dirptr == NULL )
+    return -1; /* no idea */
+
+  while( direntry = readdir( dirptr ) )
+    if( strcmp( direntry->d_name, "." ) && strcmp( direntry->d_name, ".." ) ) {
+      closedir( dirptr );
+      return 0; /* not empty */
+    }
+
+  if( errno ) {
+    closedir( dirptr );
+    return -1; /* no idea */
+  }
+
+  closedir( dirptr );
+
+  return 1; /* empty */
+}
+
 void oldconffsetflags(const struct conffile *searchconff) {
   struct filenamenode *namenode;
   
diff -ruN orig/dpkg-1.13.13/src/main.h dpkg-1.13.13/src/main.h
--- orig/dpkg-1.13.13/src/main.h        2006-01-18 09:30:03.000000000 +0100
+++ dpkg-1.13.13/src/main.h     2006-02-05 11:30:54.000000000 +0100
@@ -195,6 +195,7 @@
                                   const char *ifok, const char *iffallback);
 void clear_istobes(void);
 int isdirectoryinuse(struct filenamenode *namenode, struct pkginfo *pkg);
+int isemptydir( char *path );
 
 enum debugflags {
   dbg_general=           00001,
diff -ruN orig/dpkg-1.13.13/src/remove.c dpkg-1.13.13/src/remove.c
--- orig/dpkg-1.13.13/src/remove.c      2006-01-18 09:30:03.000000000 +0100
+++ dpkg-1.13.13/src/remove.c   2006-02-05 11:37:08.000000000 +0100
@@ -240,7 +240,11 @@
          * package which uses it.  Other files should only be listed
          * in this package (but we don't check).
          */
-        if (isdirectoryinuse(namenode,pkg)) continue;
+        if (isdirectoryinuse(namenode,pkg)) {
+          if( isemptydir( fnvb.buf ) != 1 )
+            push_leftover(&leftover,namenode);
+              continue;
+        }
       }
       debug(dbg_eachfiledetail, "removal_bulk removing `%s'", fnvb.buf);
       if (!rmdir(fnvb.buf) || errno == ENOENT || errno == ELOOP) continue;
@@ -348,7 +352,11 @@
        * package which uses it.  Other files should only be listed
        * in this package (but we don't check).
        */
-      if (isdirectoryinuse(namenode,pkg)) continue;
+      if (isdirectoryinuse(namenode,pkg)) {
+        if( isemptydir( fnvb.buf ) != 1 )
+          push_leftover(&leftover,namenode);
+            continue;
+      }
     }
 
     debug(dbg_eachfiledetail, "removal_bulk removing `%s'", fnvb.buf);

Reply via email to