aboutsummaryrefslogtreecommitdiff
path: root/lib/ext2fs/unlink.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2005-01-07 22:09:49 -0500
committerTheodore Ts'o <tytso@mit.edu>2005-01-07 22:09:49 -0500
commit4e60fb609b330fb488f2fcbfe9e330b1441201c0 (patch)
treebfa285295ee6d1e49ead4ff8b363941707dca991 /lib/ext2fs/unlink.c
parent1d3a95111820e3e8e79b2ae18ed04f050cd3f0cb (diff)
downloade2fsprogs-4e60fb609b330fb488f2fcbfe9e330b1441201c0.tar.gz
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.
Diffstat (limited to 'lib/ext2fs/unlink.c')
-rw-r--r--lib/ext2fs/unlink.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/lib/ext2fs/unlink.c b/lib/ext2fs/unlink.c
index 5612b3dd..e7b2182d 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;