lkml.org 
[lkml]   [1997]   [Jul]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectPATCH: 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>)
\
 
 \ /
  Last update: 2005-03-22 13:40    [from the cache]
©2003-2014 Jasper Spaans. Advertise on this site