diff -uNr e2undel-0.82.orig/Makefile e2undel-0.82/Makefile --- e2undel-0.82.orig/Makefile 2004-04-07 16:22:47.000000000 +0800 +++ e2undel-0.82/Makefile 2007-12-29 15:13:28.000000000 +0800 @@ -16,7 +16,7 @@ e2undel-file: e2undel-file.o $(OBJ_UNDEL) $(OBJ_FILE) - $(CC) $(LDFLAGS) -o e2undel e2undel-file.o\ + $(CC) $(LDFLAGS) -o e2undel e2undel-file.o \ $(OBJ_UNDEL) $(OBJ_FILE) $(LIBS_UNDEL) e2undel-file.o: e2undel.c e2undel.h gcc $(CFLAGS) -DWITH_FILE -c -o e2undel-file.o e2undel.c @@ -44,8 +44,8 @@ gcc $(CFLAGS) -c $< clean: - rm -f $(OBJ_UNDEL) $(OBJ_FILE) file.o e2undel.o e2undel-file.o\ - libundel.so.1.0 compactlog.o compactlog e2undel + rm -f $(OBJ_UNDEL) $(OBJ_FILE) file.o e2undel.o e2undel-file.o \ + libundel.so.1.0 libundel.o compactlog.o compactlog e2undel all: libundel e2undel-file compactlog diff -uNr e2undel-0.82.orig/e2undel.h e2undel-0.82/e2undel.h --- e2undel-0.82.orig/e2undel.h 2004-04-07 16:22:47.000000000 +0800 +++ e2undel-0.82/e2undel.h 2007-12-29 15:04:16.000000000 +0800 @@ -27,7 +27,7 @@ ext2_ino_t is unsigned int in ext2_types.h, but ino_t is unsigned long; we print each ext2_ino_t as long with a (long) type casting. Ugly hack. */ -#ifndef _EXT2_TYPES_H +#ifndef _EXT2FS_EXT2FS_H typedef ino_t ext2_ino_t; #endif diff -uNr e2undel-0.82.orig/libundel.c e2undel-0.82/libundel.c --- e2undel-0.82.orig/libundel.c 2004-04-07 16:22:47.000000000 +0800 +++ e2undel-0.82/libundel.c 2007-12-29 15:12:10.000000000 +0800 @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include /* compile as Position-Independent Code: @@ -26,6 +29,42 @@ FILE *f = NULL; +struct saved_cwd +{ + int desc; + char *name; +}; + +int save_cwd (struct saved_cwd *cwd) +{ + cwd->name = NULL; + + cwd->desc = open (".", O_RDONLY); + if (cwd->desc < 0) + { + cwd->name = getcwd (NULL, 0); + return cwd->name ? 0 : -1; + } + + return 0; +} + +int restore_cwd (const struct saved_cwd *cwd) +{ + if (0 <= cwd->desc) + return fchdir (cwd->desc); + else + return chdir (cwd->name); +} + +void free_cwd (struct saved_cwd *cwd) +{ + if (cwd->desc >= 0) + close (cwd->desc); + if (cwd->name) + free (cwd->name); +} + void _init() { f = fopen("/var/e2undel/e2undel", "a"); @@ -62,6 +101,65 @@ return err; } /* unlink() */ +int unlinkat(int dirfd, const char *pathname, int flags) +{ + struct saved_cwd saved_cwd; + int saved_errno; + int err; + struct stat buf; + char pwd[PATH_MAX]; + int (*unlinkatp)(int, char *, int) = dlsym(RTLD_NEXT, "unlinkat"); + + if (dirfd != AT_FDCWD) + { + if(save_cwd (&saved_cwd)!= 0) + { + return -1; + } + + if (fchdir (dirfd) != 0) + { + saved_errno = errno; + free_cwd(&saved_cwd); + errno = saved_errno; + return -1; + } + } + + if (NULL != pathname) + { + if (__lxstat(3, pathname, &buf)) buf.st_ino = 0; + if (!realpath(pathname, pwd)) pwd[0] = '\0'; + } + + err = (*unlinkatp)((int) AT_FDCWD, (char *) pathname, (int) flags); + + if (dirfd != AT_FDCWD) + { + if (restore_cwd (&saved_cwd) != 0) + { + return -1; + } + + free_cwd(&saved_cwd); + errno = saved_errno; + } + + if (err) return err; /* unlink() did not succeed */ + if (f) + { + if (!S_ISLNK(buf.st_mode)) /* !!! should we check for other file types? */ + { /* don't log deleted symlinks */ + fprintf(f, "%ld,%ld::%ld::%s\n", + (long) (buf.st_dev & 0xff00) / 256, + (long) buf.st_dev & 0xff, + (long) buf.st_ino, pwd[0] ? pwd : pathname); + fflush(f); + } + } /* if (f) */ + + return err; +} /* unlinkat() */ int remove(const char *pathname) { @@ -91,6 +189,33 @@ return err; } /* remove() */ +int rmdir(const char *pathname) +{ + int err; + struct stat buf; + char pwd[PATH_MAX]; + int (*rmdirp)(char *) = dlsym(RTLD_NEXT, "rmdir"); + + if (NULL != pathname) + { + if (__lxstat(3, pathname, &buf)) buf.st_ino = 0; + if (!realpath(pathname, pwd)) pwd[0] = '\0'; + } + err = (*rmdirp)((char *) pathname); + if (err) return err; /* remove() did not succeed */ + if (f) + { + if (!S_ISLNK(buf.st_mode)) /* !!! should we check for other file types? */ + { /* don't log deleted symlinks */ + fprintf(f, "%ld,%ld::%ld::%s\n", + (long) (buf.st_dev & 0xff00) / 256, + (long) buf.st_dev & 0xff, + (long) buf.st_ino, pwd[0] ? pwd : pathname); + fflush(f); + } + } /* if (f) */ + return err; +} /* rmdir() */ void _fini() {