]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
Ex2fs_unlink() will return an error if both the name and inode number are
authorTheodore Ts'o <tytso@mit.edu>
Sat, 8 Jan 2005 03:09:49 +0000 (22:09 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 8 Jan 2005 03:09:49 +0000 (22:09 -0500)
unspecified, to avoid doing something surprising (such as unconditionally
deleting the first directory entry).   Directory entries are now deleted
by coalescing them with the previous directory entry if possible, to
avoid directory fragmentation.  This is not an issue with the e2fsprogs suite,
but may be a problem for some of the users of libext2fs, such as e2tools.

lib/ext2fs/ChangeLog
lib/ext2fs/unlink.c

index 7b5e80296c2c284db90958b8850069c884282eb6..260cd2f9f11cf8d9c5c980fb5cf48e06c3941705 100644 (file)
@@ -1,3 +1,12 @@
+2005-01-07  Theodore Ts'o  <tytso@mit.edu>
+
+       * unlink.c (ext2fs_unlink): If both the name and the inode number
+               are unspecified, then return an error, so that we don't do
+               something surprising such as unconditionally deleting the
+               first directory entry.
+               (unlink_proc): Delete directory entries by coalescing it
+               with the previous entry, to avoid directory fragmentation.
+
 2005-01-06  Theodore Ts'o  <tytso@mit.edu>
 
        * version.c (ext2fs_parse_version_string): Change parsing
index 5612b3dd009d6c2699f032ab4377a8280ad594d3..e7b2182d273e248fe7cda25364e287d3b3425746 100644 (file)
@@ -23,6 +23,7 @@ struct link_struct  {
        int             namelen;
        ext2_ino_t      inode;
        int             flags;
+       struct ext2_dir_entry *prev;
        int             done;
 };     
 
@@ -36,16 +37,29 @@ static int unlink_proc(struct ext2_dir_entry *dirent,
                     void       *priv_data)
 {
        struct link_struct *ls = (struct link_struct *) priv_data;
+       struct ext2_dir_entry *prev;
 
-       if (ls->name && ((dirent->name_len & 0xFF) != ls->namelen))
-               return 0;
-       if (ls->name && strncmp(ls->name, dirent->name,
-                               dirent->name_len & 0xFF))
-               return 0;
-       if (ls->inode && (dirent->inode != ls->inode))
-               return 0;
+       prev = ls->prev;
+       ls->prev = dirent;
 
-       dirent->inode = 0;
+       if (ls->name) {
+               if ((dirent->name_len & 0xFF) != ls->namelen)
+                       return 0;
+               if (strncmp(ls->name, dirent->name, dirent->name_len & 0xFF))
+                       return 0;
+       }
+       if (ls->inode) {
+               if (dirent->inode != ls->inode)
+                       return 0;
+       } else {
+               if (!dirent->inode)
+                       return 0;
+       }
+
+       if (prev) 
+               prev->rec_len += dirent->rec_len;
+       else
+               dirent->inode = 0;
        ls->done++;
        return DIRENT_ABORT|DIRENT_CHANGED;
 }
@@ -62,6 +76,9 @@ errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir,
 
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
+       if (!name && !ino)
+               return EXT2_ET_INVALID_ARGUMENT;
+
        if (!(fs->flags & EXT2_FLAG_RW))
                return EXT2_ET_RO_FILSYS;
 
@@ -70,8 +87,10 @@ errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir,
        ls.inode = ino;
        ls.flags = 0;
        ls.done = 0;
+       ls.prev = 0;
 
-       retval = ext2fs_dir_iterate(fs, dir, 0, 0, unlink_proc, &ls);
+       retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, 
+                                   0, unlink_proc, &ls);
        if (retval)
                return retval;