Binary files e2undel-0.82.orig/.common.h.swp and e2undel-0.82/.common.h.swp differ diff -uNr e2undel-0.82.orig/e2undel.c e2undel-0.82/e2undel.c --- e2undel-0.82.orig/e2undel.c 2004-04-07 16:22:47.000000000 +0800 +++ e2undel-0.82/e2undel.c 2008-01-14 19:50:18.000000000 +0800 @@ -297,6 +297,11 @@ if (l->inode == inode) { del->name = l->name; + if(l->size != 0) + del->size = l->size; + del->block_list = l->block_list; + del->block_size = l->block_size; + n++; found = 1; } @@ -500,7 +505,7 @@ err = ext2fs_read_inode(fs, ino->inode, &inode_struct); if (err) { - com_err("file_type()", err, "while reading inode %ld", ino->inode); + com_err("file_type()", err, "while reading inode %ld", (long)ino->inode); return 0; } err = ext2fs_file_open(fs, ino->inode, 0, &e2_file); @@ -723,19 +728,20 @@ } /* name_inode() */ - - int dump_inode(ext2_filsys fs, struct one_inode *ino, char *fname) /* prints content of inode ino on fs into file fname */ /* -1: error, else: number of bytes written */ { errcode_t err; - struct ext2_inode inode_struct; int f; - ext2_file_t e2_file; - char buf[8192]; + int fdev = 0; + char buf[4096]; int written, all_written; - unsigned int n; + unsigned int block_number = 0; + char *c; + unsigned long start = 0, end = 0, first_block = 0, last_block = 0; + unsigned long i = 0; + int rtn; f = open(fname, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU|S_IRWXG|S_IRWXO); if (-1 == f) @@ -744,41 +750,90 @@ return -1; } - err = ext2fs_read_inode(fs, ino->inode, &inode_struct); - if (err) - { - com_err("dump_inode()", err, "while reading inode %u", ino->inode); - return -1; - } - err = ext2fs_file_open(fs, ino->inode, 0, &e2_file); - if (err) + fdev = open(fs->device_name, O_RDONLY, S_IRWXU|S_IRWXG|S_IRWXO); + if (-1 == fdev) { - com_err("dump_inode()", err, "while opening ext2 file"); + perror("/var/e2undel/disk"); return -1; } + c = ino->block_list; + all_written = 0; - while (1) + + while (c) { - err = ext2fs_file_read(e2_file, buf, sizeof(buf), &n); - if (err) + if (*c == ',') + c++; /* , */ + + if (*c == '\0') + break; + + c++; /* ( */ + start = atol(c); + while ( (*c >= '0') && (*c <= '9') ) c++; + + c++; /* - */ + end = atol(c); + while ( (*c >= '0') && (*c <= '9') ) c++; + + c++; /* ) */ + c++; /* : */ + first_block = atol(c); + while ( (*c >= '0') && (*c <= '9') ) c++; + + c++; /* - */ + last_block = atol(c); + while ( (*c >= '0') && (*c <= '9') ) c++; + + c++; + + while (block_number < start) { - com_err("dump_inode()", err, "while reading ext2 file"); - return -1; + /* hole in file */ + + rtn = (ino->size - all_written) > ino->block_size? ino->block_size : ino->size - all_written; + memset(buf, 0, rtn); + written = write(f, buf, rtn); + if (written != rtn) + { + perror(fname); + return -1; + } + + all_written += written; + block_number++; } - if (0 == n) break; - written = write(f, buf, n); - if (written != n) + + for (i = 0; i <= end - start; i++) { - perror(fname); - return -1; - } - all_written += written; - } /* while (1) */ - err = ext2fs_file_close(e2_file); + /* read block from device */ + rtn = pread(fdev, buf, \ + (ino->size - all_written) > ino->block_size? ino->block_size : ino->size - all_written, \ + (first_block + i) * ino->block_size \ + ); + if ( rtn < 0) + { + com_err("dump_inode()", rtn, "while reading device file"); + return -1; + } + + written = write(f, buf, rtn); + if (written != rtn) + { + perror(fname); + return -1; + } + + all_written += written; + block_number++; + } /* for */ + } + + err = close(fdev); if (err) { - com_err("dump_inode()", err, "while closing ext2 file"); + com_err("dump_inode()", err, "while closing device file"); return -1; } close(f); diff -uNr e2undel-0.82.orig/e2undel.h e2undel-0.82/e2undel.h --- e2undel-0.82.orig/e2undel.h 2007-12-29 15:37:06.000000000 +0800 +++ e2undel-0.82/e2undel.h 2008-01-14 20:00:12.000000000 +0800 @@ -37,6 +37,9 @@ ext2_ino_t inode; unsigned long dev; /* device number of file system */ char *name; + unsigned long size; + unsigned long block_size; + char *block_list; struct e2undel_log *next, *last; /* next and previous entry in ring list */ }; /* in list mode; next entry with larger */ /* smaller inode # in binary tree */ @@ -53,6 +56,8 @@ unsigned int bad_blocks; /* bad blocks; if > 0, inode is discarded in find_del() */ char *name; /* file name or type */ int interval; /* time interval since deletion from interval[] */ + unsigned long block_size; + char *block_list; struct one_inode *next; }; diff -uNr e2undel-0.82.orig/find_del.c e2undel-0.82/find_del.c --- e2undel-0.82.orig/find_del.c 2004-04-07 16:22:47.000000000 +0800 +++ e2undel-0.82/find_del.c 2008-01-14 19:57:56.000000000 +0800 @@ -86,6 +86,7 @@ fprintf(stderr, "="); fflush(stderr); } + err = ext2fs_get_next_inode(scan, &inode, &inode_struct); if (err) /* only EXT2_ET_BAD_BLOCK_IN_INODE_TABLE possible? */ { @@ -106,7 +107,7 @@ return NULL; } - if (ino_tmp.free_blocks && !ino_tmp.bad_blocks) + if (!ino_tmp.bad_blocks) { /* free blocks, and no bad blocks */ n_del++; if (!inode_list) diff -uNr e2undel-0.82.orig/libundel.c e2undel-0.82/libundel.c --- e2undel-0.82.orig/libundel.c 2007-12-29 15:37:06.000000000 +0800 +++ e2undel-0.82/libundel.c 2008-01-14 20:00:42.000000000 +0800 @@ -24,10 +24,136 @@ ld -shared -soname libundel.so.1 -ldl -o libundel.so.1.0 libundel.o */ +//#define _LARGEFILE64_SOURCE + +#include +#include +#include +#include +#include + + +#define FIBMAP _IO(0x00,1) /* bmap access */ +#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ + +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ +#define EXT3_IOC_GETFLAGS _IOR('f', 1, long) #define VERSION 0.2 +#define MAXLENTH 4096 + FILE *f = NULL; +char *block_list ; + +static unsigned long get_bmap(int fd, unsigned long block) +{ + int ret; + unsigned int b; + + b = block; + ret = ioctl(fd, FIBMAP, &b); /* FIBMAP takes a pointer to an integer */ + if (ret < 0) + { + if (errno == EPERM) + { + if (f) + { + // if (!S_ISLNK(buf.st_mode)) /* !!! should we check for other file types? */ + { /* don't log deleted symlinks */ + fprintf(f, "No permission to use FIBMAP ioctl.\n"); + fflush(f); + } + } /* if (f) */ + + return 0; + } + } + return b; +} + +int get_blocks(const char *filename) +{ +#ifdef HAVE_FSTAT64 + struct stat64 fileinfo; +#else + struct stat fileinfo; +#endif + int bs; + long fd; + unsigned long block, last_block = 0, first_cblock = 0, numblocks, i; + long bpib; /* Blocks per indirect block */ + char cblock_list[256]; + char pwd[PATH_MAX]; + + if (NULL != filename) + { + if (__lxstat(3, filename, &fileinfo)) + fileinfo.st_ino = 0; + + if (!realpath(filename, pwd)) + pwd[0] = '\0'; + } + + +#ifdef HAVE_OPEN64 + fd = open64(filename, O_RDONLY); +#else + fd = open(filename, O_RDONLY); +#endif + if (fd < 0) { + fprintf(stderr, "cannot open the file of %s\n", filename); + return -1; + } + + if (ioctl(fd, FIGETBSZ, &bs) < 0) { /* FIGETBSZ takes an int */ + perror("FIGETBSZ"); + close(fd); + return -1; + } + + bpib = bs / 4; + numblocks = (fileinfo.st_size + (bs-1)) / bs; + + sprintf(block_list, "%ld,%ld::%ld::%ld::%ld::", + (long) (fileinfo.st_dev & 0xff00) / 256, + (long) fileinfo.st_dev & 0xff, + (long) fileinfo.st_ino, + (long) fileinfo.st_size, (long)bs); + + for (i=0; i < numblocks; i++) { + block = get_bmap(fd, i); + + if (last_block == 0) { + first_cblock = block; + } + if (last_block && (block != last_block +1) ) { + sprintf(cblock_list, "(%ld-%ld):%ld-%ld,", i-(last_block-first_cblock)-1, i-1, first_cblock, last_block); + strcat(block_list, cblock_list); + first_cblock = block; + } + + if (i == numblocks - 1 ) { + if (last_block == 0) { + sprintf(cblock_list, "(%ld-%ld):%ld-%ld", i, i, first_cblock, block); + } + else { + sprintf(cblock_list, "(%ld-%ld):%ld-%ld", i-(last_block-first_cblock)-1, i, first_cblock, block); + } + + strcat(block_list, cblock_list); + } + + last_block = block; + } + + sprintf(cblock_list, "::%s", pwd[0] ? pwd : filename); + strcat(block_list, cblock_list); + + close(fd); + + return 0; +} struct saved_cwd { @@ -70,33 +196,28 @@ f = fopen("/var/e2undel/e2undel", "a"); if (!f) fprintf(stderr, "libundel: can't open log file, undeletion disabled\n"); + + block_list = malloc(sizeof(char)*MAXLENTH); } int unlink(const char *pathname) { int err; - struct stat buf; - char pwd[PATH_MAX]; int (*unlinkp)(char *) = dlsym(RTLD_NEXT, "unlink"); - if (NULL != pathname) + err = get_blocks(pathname); + if (err < 0) { - if (__lxstat(3, pathname, &buf)) buf.st_ino = 0; - if (!realpath(pathname, pwd)) pwd[0] = '\0'; + fprintf(stderr, "error while reading blocks from %s\n", pathname); } + err = (*unlinkp)((char *) pathname); 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); - } + fprintf(f, "%s\n", block_list); + fflush(f); } /* if (f) */ return err; } /* unlink() */ @@ -106,8 +227,6 @@ 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) @@ -126,10 +245,10 @@ } } - if (NULL != pathname) + err = get_blocks(pathname); + if (err < 0) { - if (__lxstat(3, pathname, &buf)) buf.st_ino = 0; - if (!realpath(pathname, pwd)) pwd[0] = '\0'; + fprintf(stderr, "error while reading blocks from %s\n", pathname); } err = (*unlinkatp)((int) AT_FDCWD, (char *) pathname, (int) flags); @@ -145,17 +264,11 @@ errno = saved_errno; } - if (err) return err; /* unlink() did not succeed */ + if (err) return err; /* unlink_at() 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); - } + fprintf(f, "%s\n", block_list); + fflush(f); } /* if (f) */ return err; @@ -164,55 +277,42 @@ int remove(const char *pathname) { int err; - struct stat buf; - char pwd[PATH_MAX]; int (*removep)(char *) = dlsym(RTLD_NEXT, "remove"); - if (NULL != pathname) + err = get_blocks(pathname); + if (err < 0) { - if (__lxstat(3, pathname, &buf)) buf.st_ino = 0; - if (!realpath(pathname, pwd)) pwd[0] = '\0'; + fprintf(stderr, "error while reading blocks from %s\n", pathname); } + err = (*removep)((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); - } + fprintf(f, "%s\n", block_list); + fflush(f); } /* if (f) */ 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) + err = get_blocks(pathname); + if (err < 0) { - if (__lxstat(3, pathname, &buf)) buf.st_ino = 0; - if (!realpath(pathname, pwd)) pwd[0] = '\0'; + fprintf(stderr, "error while reading blocks from %s\n", pathname); } + err = (*rmdirp)((char *) pathname); - if (err) return err; /* remove() did not succeed */ + if (err) return err; /* rmdir() 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); - } + fprintf(f, "%s\n", block_list); + fflush(f); } /* if (f) */ return err; } /* rmdir() */ @@ -220,4 +320,6 @@ void _fini() { if (f) fclose(f); + + if (block_list) free(block_list); } diff -uNr e2undel-0.82.orig/log.c e2undel-0.82/log.c --- e2undel-0.82.orig/log.c 2004-04-07 16:22:47.000000000 +0800 +++ e2undel-0.82/log.c 2008-01-14 08:06:24.000000000 +0800 @@ -18,7 +18,7 @@ { char buf[PATH_MAX+20]; /* file name + device and inode # */ unsigned long dev; /* device # of entry */ - char *c; + char *c, *temp; struct e2undel_log *l, *start, *previous; int i = 0; /* counts entries matching devnr */ int lines = 0; /* counts all entries */ @@ -62,9 +62,32 @@ } i++; l->dev = dev; + l->inode = atol(c); /* inode # */ while ( (*c >= '0') && (*c <= '9') ) c++; c++; c++; /* :: */ + + l->size = atol(c); /* size in bytes */ + while ( (*c >= '0') && (*c <= '9') ) c++; + c++; c++; /* :: */ + + l->block_size = atol(c); /* block size # */ + while ( (*c >= '0') && (*c <= '9') ) c++; + c++; c++; /* :: */ + + if (NULL == (l->block_list = malloc(strlen(c)+1))) + { + perror("reading log file"); + fclose(f); + return(NULL); + } + temp = strstr(c, "::"); + *(c+(temp-c)) = '\0'; + sprintf(l->block_list, "%s", c); + + c = temp; + c++; c++; /* :: */ + if (NULL == (l->name = malloc(strlen(c)+1))) { perror("reading log file"); @@ -72,6 +95,7 @@ return(NULL); } sprintf(l->name, "%s", c); + l->last = previous; if (previous) previous->next = l; else start = l; @@ -97,7 +121,7 @@ { char buf[PATH_MAX+16]; unsigned long dev; - char *c; + char *c, *temp; struct e2undel_log *l, *log, *start; int i = 0; /* counts entries matching devnr */ int lines = 0; /* counts all entries */ @@ -144,6 +168,28 @@ l->inode = atol(c); while ( (*c >= '0') && (*c <= '9') ) c++; c++; c++; + + l->size = atol(c); /* size in bytes */ + while ( (*c >= '0') && (*c <= '9') ) c++; + c++; c++; /* :: */ + + l->block_size = atol(c); /* block size # */ + while ( (*c >= '0') && (*c <= '9') ) c++; + c++; c++; /* :: */ + + if (NULL == (l->block_list = malloc(strlen(c)+1))) + { + perror("reading log file"); + fclose(f); + return(NULL); + } + temp = strstr(c, "::"); + *(c+(temp-c)) = '\0'; + sprintf(l->block_list, "%s", c); + + c = temp; + c++; c++; /* :: */ + if (NULL == (l->name = malloc(strlen(c)+1))) { perror("reading log file");