From: Theodore Ts'o Date: Sat, 8 Jan 2005 03:09:49 +0000 (-0500) Subject: Ex2fs_unlink() will return an error if both the name and inode number are X-Git-Tag: E2FSPROGS-1_36~74 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4e60fb609b330fb488f2fcbfe9e330b1441201c0;p=thirdparty%2Fe2fsprogs.git Ex2fs_unlink() will return an error if both the name and inode number are 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. --- diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index 7b5e80296..260cd2f9f 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,12 @@ +2005-01-07 Theodore Ts'o + + * 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 * version.c (ext2fs_parse_version_string): Change parsing diff --git a/lib/ext2fs/unlink.c b/lib/ext2fs/unlink.c index 5612b3dd0..e7b2182d2 100644 --- a/lib/ext2fs/unlink.c +++ b/lib/ext2fs/unlink.c @@ -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;