diff -Nru e2fsprogs-1.32/debugfs/debug_cmds.ct e2fsprogs-1.32.new/debugfs/debug_cmds.ct
--- e2fsprogs-1.32/debugfs/debug_cmds.ct	2002-08-31 09:13:29.000000000 +0200
+++ e2fsprogs-1.32.new/debugfs/debug_cmds.ct	2003-04-20 17:11:02.000000000 +0200
@@ -112,6 +112,9 @@
 request do_dump, "Dump an inode out to a file",
 	dump_inode, dump;
 
+request do_restore, "Restore deleted files",
+	restore;
+
 request do_cat, "Dump an inode out to stdout",
 	cat;
 
diff -Nru e2fsprogs-1.32/debugfs/Makefile.in e2fsprogs-1.32.new/debugfs/Makefile.in
--- e2fsprogs-1.32/debugfs/Makefile.in	2002-11-08 20:31:44.000000000 +0100
+++ e2fsprogs-1.32.new/debugfs/Makefile.in	2003-04-20 17:11:28.000000000 +0200
@@ -17,7 +17,7 @@
 MK_CMDS=	_SS_DIR_OVERRIDE=../lib/ss ../lib/ss/mk_cmds
 
 DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \
-	lsdel.o dump.o setsuper.o logdump.o htree.o
+	lsdel.o dump.o setsuper.o logdump.o htree.o restore.o
 
 SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \
 	$(srcdir)/ncheck.c $(srcdir)/icheck.c $(srcdir)/lsdel.c \
diff -Nru e2fsprogs-1.32/debugfs/restore.c e2fsprogs-1.32.new/debugfs/restore.c
--- e2fsprogs-1.32/debugfs/restore.c	1970-01-01 01:00:00.000000000 +0100
+++ e2fsprogs-1.32.new/debugfs/restore.c	2003-04-20 17:11:02.000000000 +0200
@@ -0,0 +1,221 @@
+/*
+ * restore.c -- restores deleted files
+ * 
+ * Copyright (C) 1994 Theodore Ts'o, 
+ *               2001 Torsten Werner <twerner@debian.org>
+ * This file may be redistributed under the terms of the GNU Public 
+ * License.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <utime.h>
+#include <assert.h>
+
+#include "debugfs.h"
+
+static __u32 dtime;
+
+static int set_blocks_proc(ext2_filsys fs, blk_t *blocknr,
+                               int blockcnt, void *private)
+{
+        ext2fs_mark_block_bitmap(fs->block_map,*blocknr);
+        return 0;
+}
+
+static int undel_inode (int ino)
+{
+	struct ext2_inode inode;
+	int retval;
+
+	if (!ino) return 0;
+	ext2fs_read_inode (current_fs, ino, &inode);
+	if (dtime && inode.i_dtime < dtime) return 0;
+	inode.i_dtime = 0;
+	inode.i_links_count++;
+	ext2fs_mark_inode_bitmap (current_fs->inode_map, ino);
+	if (inode.i_blocks) {
+		ext2fs_block_iterate (current_fs, ino, 0, NULL,
+			set_blocks_proc, NULL);
+	}
+	if (LINUX_S_ISDIR (inode.i_mode))
+		inode.i_size = inode.i_blocks*512;
+	retval = ext2fs_write_inode (current_fs, ino, &inode);
+	if (retval) {
+		com_err("undel_inode", retval, 
+			"while trying to write inode %d", ino);
+		return 0;
+	}
+	return 1;
+}
+
+static void restore_del (char *dir, char *begin, char *end)
+{
+	struct ext2_dir_entry_2 *entry = (struct ext2_dir_entry_2 *)
+		begin;
+	struct ext2_dir_entry_2 *next = (struct ext2_dir_entry_2 *)
+		(begin + EXT2_DIR_REC_LEN(entry->name_len));
+	char name[256];
+	int retval;
+	struct ext2_inode inode;
+
+	if (undel_inode (entry->inode)) {
+		strncpy (name, entry->name, entry->name_len);
+		name[entry->name_len] = 0;
+		printf ("%s/%s restored \n", strcmp(dir, "/") ? dir : "", name);
+	}
+
+	if (begin >= end)
+		return;
+	if ((char *)next >= end) {
+		entry->rec_len = end - begin;
+		assert (entry->rec_len > 0);
+		return;
+	}
+	while (!next->inode ||
+		!next->rec_len ||
+		next == entry ||
+		(char *)next+next->rec_len > end ||
+		(char *)next+EXT2_DIR_REC_LEN(next->name_len) > end ||
+		ext2fs_read_inode (current_fs, next->inode, &inode)) {
+		(char *)next += EXT2_DIR_PAD;
+		if ((char *)next >= end) {
+			entry->rec_len = end - begin;
+			assert (entry->rec_len > 0);
+			return;
+		}
+	}
+	entry->rec_len = (char *)next - begin;
+	assert (entry->rec_len > 0);
+	restore_del (dir, (char *)next, end);
+}
+
+static void find_del (char *dir, char *begin, char *end)
+{
+	char *buf = begin;
+	while (buf < end) {
+		struct ext2_dir_entry_2 *entry = 
+			(struct ext2_dir_entry_2 *) buf;
+		int rec_len = entry->rec_len;
+		restore_del (dir, buf, buf+rec_len);
+		buf += rec_len;
+	}
+}
+
+static void find_dirs (char *dir, char *begin, char *end);
+
+static void restore_dir (char *dir)
+{
+	errcode_t retval;
+	ino_t ino;
+	struct ext2_inode	inode;
+	char 		*buf;
+	ext2_file_t	e2_file;
+	unsigned int	got;
+	
+	ino = string_to_inode (dir);
+	if (!ino) {
+		printf ("string_to_inode failed: %s\n", dir);
+		return;
+	}
+	retval = ext2fs_read_inode (current_fs, ino, &inode);
+	if (retval) {
+		com_err ("restore", retval,
+			"while reading inode %u in dump_file", ino);
+		return;
+	}
+	buf = malloc(inode.i_size);
+        if (!buf) {
+                com_err("restore", errno, "while allocating buffer");
+		return;
+        }
+
+	retval = ext2fs_file_open(current_fs, ino, 0, &e2_file);
+	if (retval) {
+		com_err ("restore", retval, "while opening ext2 file");
+		return;
+	}
+	retval = ext2fs_file_read(e2_file, buf, inode.i_size, &got);
+	if (retval) 
+		com_err ("restore", retval, "while reading ext2 file");
+	retval = ext2fs_file_close(e2_file);
+	if (retval) {
+		com_err ("restore", retval, "while closing ext2 file");
+		return;
+	}
+
+	find_del (dir, buf, buf + inode.i_size);
+
+	retval = ext2fs_file_open(current_fs, ino, EXT2_FILE_WRITE, &e2_file);
+	if (retval) {
+		com_err ("restore", retval, "while opening ext2 file");
+		return;
+	}
+	retval = ext2fs_file_write(e2_file, buf, inode.i_size, &got);
+	if (retval) 
+		com_err ("restore", retval, "while reading ext2 file");
+	retval = ext2fs_file_close(e2_file);
+	if (retval) {
+		com_err ("restore", retval, "while closing ext2 file");
+		return;
+	}
+
+	find_dirs (dir, buf, buf + inode.i_size);
+
+	free (buf);
+	return;
+}
+
+static void find_dirs (char *dir, char *begin, char *end)
+{
+	char *buf = begin;
+	while (buf < end) {
+		char name[256];
+		struct ext2_dir_entry_2 *entry = 
+			(struct ext2_dir_entry_2 *) buf;
+		strncpy (name, entry->name, entry->name_len);
+		name[entry->name_len] = 0;
+		if (strcmp (name, ".") &&
+			strcmp (name, "..")) {
+			struct ext2_inode inode;
+			char path[10240];
+
+			ext2fs_read_inode (current_fs, entry->inode, &inode);
+			strncpy (path, dir, 10240);
+			if (strcmp (path, "/"))
+				strncat (path, "/", 10240);
+			strncat (path, name, 10240);
+			if (LINUX_S_ISDIR (inode.i_mode))
+				restore_dir (path);
+		}
+		buf += entry->rec_len;
+	}
+}
+
+void do_restore(int argc, char **argv)
+{
+	if (check_fs_open(argv[0])) return;
+	if (argc == 2)
+		sscanf (argv[1], "%x", &dtime);
+	else
+		dtime = 0;
+
+	restore_dir ("/");
+
+	ext2fs_mark_ib_dirty(current_fs);
+	ext2fs_mark_bb_dirty(current_fs);
+	current_fs->super->s_state &= ~EXT2_VALID_FS;
+	ext2fs_mark_super_dirty (current_fs);
+	return;
+}
+
