Messages in this thread Patch in this message | | | Date | Mon, 28 Jul 1997 13:50:04 +0200 (CEST) | From | Kurt Huwig <> | Subject | PATCH: ext2-undelete! |
| |
On Sun, 27 Jul 1997, Kurt Huwig wrote: > On Sun, 27 Jul 1997, Rogier Wolff wrote: > > Kurt Huwig wrote: > > > I looked through dejanews and found Rogier's patch. It did not patch in > > > directly, because the sources have changed a little bit, so I did it by > > > hand, together with minor changes: > > > > Kurt, there should be a followup that had a slightly different patch. > > There is an attribute bit that says "this file needs safe delete", > > which is currently unused. I didn't know that, so I wrote it without > > using that bit. Someon else volunteerd "but there is a bit, for which > > you just made the implementation". > > After some time, I found the patch.
Darren made some mistakes in his patch:
- he made the name of the directory adjustable via define, but overlooked that you need the length of it in 'ext2_lookup'. So it would only work if you use a name with 12 letters. I don't want to use 'strlen' here. - he did not move the 'ext2_unlink' code after 'do_ext2_rename', so it won't compile at all. A - he changed some of the 'printk' into 'ext2_debug' but still every move is reported via one printk...annoying - you/he said 'moveing' instead of 'moving'...ok my English is worse ;-)
I included the reference to 'chattr' and 'lsattr' in the config help. I think this will prevent any FAQs about how to set the 'u'-bit... ;-)
Kurt
------------------------------------------------------------- Impossible doesn't exist! Unmöglich gibt's nicht! Difficult exists. Schwierig gibt's.
--- linux/Documentation/Configure.help.orig Sun Jul 27 14:27:45 1997 +++ linux/Documentation/Configure.help Mon Jul 28 13:34:17 1997 @@ -2987,6 +2987,29 @@ sunsite.unc.edu:/pub/Linux/docs/faqs. This option will enlarge your kernel by about 41 kB. Default is Y. +Undelete support for ext2 filesystems +CONFIG_EXT2_UNDELETE + This enables an undelete feature for ext2-partitions. Files marked + with the ext2 attribute 'u' for 'undo remove' will be moved to a + .wastebasket directory at the top of the fs, similar to lost+found + and the bit will be cleared. If no .wastebasket directory exists + then undeletion is not active on that partition. All files created + in a directory with the 'u'-bit set will have it set, too. + You can use 'chattr' and 'lsattr' to change and view this attribute. + They are in the package 'e2fsprogs' available at + ftp://sunsite.unc.edu/pub/Linux/system/filesystems/ext2/ + At present if a file in the .wastebasket directory already exists + then _0 is appened to the next file of that name and so on. + CAVEATS: + - If a user has the right to delete a file, it will be moved + to the wastebasket regardless of the permissions of the + wastebasket. If you don't want security holes to others, you + should make the wastebasket mode 700. + - You have to make sure that the directory is emptied or your + harddisk will be full very soon! + - Remember to set the 'u' bit on undeleted files if you want them + to be undelete-able again. + xiafs filesystem support CONFIG_XIA_FS This is an old filesystem (= method to organize files on a harddisk --- linux/fs/Config.in.orig Thu Jul 17 01:02:37 1997 +++ linux/fs/Config.in Mon Jul 28 13:42:52 1997 @@ -11,6 +11,9 @@ tristate 'Second extended fs support' CONFIG_EXT2_FS if [ "$CONFIG_EXT2_FS" = "y" ]; then bool ' NO_ATIME support for ext2 filesystems' CONFIG_EXT2_NOATIME + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' Undelete support for ext2 filesystems (EXPERIMENTAL)' CONFIG_EXT2_UNDELETE + fi fi tristate 'xiafs filesystem support' CONFIG_XIA_FS --- linux/fs/ext2/namei.c.orig Sat Nov 30 11:21:20 1996 +++ linux/fs/ext2/namei.c Mon Jul 28 00:58:24 1997 @@ -695,73 +695,6 @@ return retval; } -int ext2_unlink (struct inode * dir, const char * name, int len) -{ - int retval; - struct inode * inode; - struct buffer_head * bh; - struct ext2_dir_entry * de; - -repeat: - if (!dir) - return -ENOENT; - retval = -ENOENT; - inode = NULL; - if (len > EXT2_NAME_LEN) { - iput (dir); - return -ENAMETOOLONG; - } - bh = ext2_find_entry (dir, name, len, &de); - if (!bh) - goto end_unlink; - if (!(inode = iget (dir->i_sb, de->inode))) - goto end_unlink; - if (inode->i_sb->dq_op) - inode->i_sb->dq_op->initialize (inode, -1); - retval = -EPERM; - if (S_ISDIR(inode->i_mode)) - goto end_unlink; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - goto end_unlink; - if (de->inode != inode->i_ino) { - iput(inode); - brelse(bh); - current->counter = 0; - schedule(); - goto repeat; - } - if ((dir->i_mode & S_ISVTX) && !fsuser() && - current->fsuid != inode->i_uid && - current->fsuid != dir->i_uid) - goto end_unlink; - if (!inode->i_nlink) { - ext2_warning (inode->i_sb, "ext2_unlink", - "Deleting nonexistent file (%lu), %d", - inode->i_ino, inode->i_nlink); - inode->i_nlink = 1; - } - retval = ext2_delete_entry (de, bh); - if (retval) - goto end_unlink; - dir->i_version = ++event; - mark_buffer_dirty(bh, 1); - if (IS_SYNC(dir)) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->i_dirt = 1; - inode->i_nlink--; - inode->i_dirt = 1; - inode->i_ctime = dir->i_ctime; - retval = 0; -end_unlink: - brelse (bh); - iput (inode); - iput (dir); - return retval; -} - int ext2_symlink (struct inode * dir, const char * name, int len, const char * symname) { @@ -1101,6 +1034,120 @@ iput (new_inode); iput (old_dir); iput (new_dir); + return retval; +} + +int ext2_unlink (struct inode * dir, const char * name, int len) +{ + int retval; + struct inode * inode; + struct buffer_head * bh; + struct ext2_dir_entry * de; + +repeat: + if (!dir) + return -ENOENT; + retval = -ENOENT; + inode = NULL; + if (len > EXT2_NAME_LEN) { + iput (dir); + return -ENAMETOOLONG; + } + bh = ext2_find_entry (dir, name, len, &de); + if (!bh) + goto end_unlink; + if (!(inode = iget (dir->i_sb, de->inode))) + goto end_unlink; + if (inode->i_sb->dq_op) + inode->i_sb->dq_op->initialize (inode, -1); + retval = -EPERM; + if (S_ISDIR(inode->i_mode)) + goto end_unlink; + if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + goto end_unlink; + if (de->inode != inode->i_ino) { + iput(inode); + brelse(bh); + current->counter = 0; + schedule(); + goto repeat; + } + if ((dir->i_mode & S_ISVTX) && !fsuser() && + current->fsuid != inode->i_uid && + current->fsuid != dir->i_uid) + goto end_unlink; + if (!inode->i_nlink) { + ext2_warning (inode->i_sb, "ext2_unlink", + "Deleting nonexistent file (%lu), %d", + inode->i_ino, inode->i_nlink); + inode->i_nlink = 1; + } +#ifdef CONFIG_EXT2_UNDELETE + /* Only move if 'UNDO REMOVE' bit set */ + if (inode->u.ext2_i.i_flags & EXT2_UNRM_FL) { + if (inode->i_sb) { + struct inode *wb,*tmp; + const char *new_name; + char buf[EXT2_NAME_LEN]; + int new_len; + int version; + + inode->i_sb->s_mounted->i_count++; + if (ext2_lookup (inode->i_sb->s_mounted,".wastebasket",12,&wb) == 0) { + ext2_debug ("inode_c=%d, dir_c=%d,wb_c=%d\n",inode->i_count,dir->i_count,wb->i_count); + new_name=name; + new_len = len; + version = 0; + wb->i_count++; + while (ext2_lookup (wb,new_name,new_len,&tmp) == 0) { + iput (tmp); + sprintf (buf,"%s_%d",name,version++); + new_name = buf; + new_len = strlen (buf); + wb->i_count++; + } + ext2_debug ("moving %s to wastebasket as %s.\n",name,new_name); + while (dir->i_sb->u.ext2_sb.s_rename_lock) + sleep_on (&dir->i_sb->u.ext2_sb.s_rename_wait); + dir->i_sb->u.ext2_sb.s_rename_lock = 1; + + retval = do_ext2_rename (dir, name, len, wb, new_name, new_len, 0); + + dir->i_sb->u.ext2_sb.s_rename_lock = 0; + wake_up (&dir->i_sb->u.ext2_sb.s_rename_wait); + ext2_debug ("inode_c=%d, dir_c=%d,wb_c=%d\n",inode->i_count,dir->i_count,wb->i_count); + brelse (bh); + inode->u.ext2_i.i_flags &= ~EXT2_UNRM_FL; + iput (inode); + return retval; + } else { + ext2_debug ("No wastebasket. Old unlink for %s....\n",name); + } + } else { + printk ("Warning: Undelete can't find a superblock for inode %ld\n" + "Deleting file normally.\n",inode->i_ino); + } + } +#endif + retval = ext2_delete_entry (de, bh); + if (retval) + goto end_unlink; + dir->i_version = ++event; + mark_buffer_dirty(bh, 1); + if (IS_SYNC(dir)) { + ll_rw_block (WRITE, 1, &bh); + wait_on_buffer (bh); + } + dir->i_ctime = dir->i_mtime = CURRENT_TIME; + dir->i_dirt = 1; + inode->i_nlink--; + inode->i_dirt = 1; + inode->i_ctime = dir->i_ctime; + retval = 0; +end_unlink: + brelse (bh); + iput (inode); + iput (dir); return retval; } --- /dev/null Sun Jun 29 17:10:20 1997 +++ linux/init/patches/ext2-undelete-2.0.30 Mon Jul 28 13:42:32 1997 @@ -0,0 +1 @@ +ext2 undelete support (Rogier Wolff <R.E.Wolff@BitWizard.nl>/Darren J Moffat <darren@xarius.demon.co.uk>/Kurt Huwig <kurt@huwig.de>) | |