/*
* Программа восстановления блоков удаленного файла.
* Работает на канонической файловой системе UNIX (ДЕМОС).
* Просматривает список свободных блоков диска.
*
* Эта программа позволяет восстановить блоки ТОЛЬКО ЧТО удаленного файла.
* Как только вы удалили нужный файл, немедленно прекратите любую
* работу на машине и даже отмонтируйте диск с удаленным файлом.
* Затем, находясь на ДРУГОМ диске, вызовите эту программу.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h> /* BSIZE */
#include <sys/filsys.h> /* struct filsys */
#include <sys/fblk.h> /* struct fblk */
#include <fcntl.h>
#include <ctype.h>
/*
#define BSIZE 1024 размер блока файловой системы
*/
int fd; /* raw disk */
int fdout; /* дескриптор для спасенных блоков на ДРУГОМ диске */
char blk[ BSIZE ], /* буфер для прочитанного блока */
sublk[ BSIZE ]; /* буфер для суперблока */
/* структура суперблока */
struct filsys *super = (struct filsys *) sublk;
/* счетчик */
long n = 0L;
main( ac, av ) char *av[];
{
daddr_t bno; /* номер блока из списка свободных */
extern daddr_t alloc();
if( ac < 2 ){
fprintf( stderr, "Usage: %s disk\n", av[0] );
exit(1);
}
if((fd = open( av[1], O_RDONLY )) < 0 ){
fprintf( stderr, "Can't read %s\n", av[1] );
exit(2);
}
sync(); /* syncronize */
printf( "Вы должны находиться на ДРУГОМ диске, нежели %s,\n", av[1] );
printf( "чтобы блоки файлов, в которые будут записаны спасаемые\n");
printf( "блоки, выделялись на другом устройстве и не портили\n" );
printf( "список свободных блоков на %s\n\n", av[1] );
fflush( stdout ); sleep(2);
/* прочесть суперблок */
lseek( fd, (long) BSIZE, 0 );
read( fd, sublk, BSIZE );
fprintf( stderr, "%ld free blocks at %s (%6.6s)\n" ,
super->s_tfree, av[1],
super->s_fpack );
/* Просмотр свободных блоков. Список свободных блоков
* имеет организацию LIFO (стек), поэтому блоки
* в списке могут идти не в том порядке,
* в котором они шли в файле. Учтите, что в файле
* кроме блоков, содержащих текст файла,
* бывают также косвенные адресные блоки !
*/
while((bno = alloc()) >= 0L ){
save( bno );
}
printf( "total %ld\n", n );
exit(0);
}
/* Извлечь очередной блок из списка свободных блоков */
daddr_t alloc(){
daddr_t bno;
if( super -> s_nfree <= 0 ) /* число адресов своб. блоков,
* хранимых в суперблоке */
goto nospace;
/* читаем номер блока из списка свободных */
bno = super -> s_free[ --super -> s_nfree ];
if( bno == (daddr_t) 0 )
goto nospace;
if( super -> s_nfree <= 0 ){
/* Продолжение списка - не в суперблоке,
* а в специальном дополнительном блоке файловой системы.
*/
printf( "Indirect block %ld\n", bno );
lseek( fd, (long) BSIZE * bno , 0 );
read ( fd, blk, BSIZE );
super -> s_nfree = ((struct fblk *)blk) -> df_nfree ;
memcpy( (char *) (super -> s_free),
(char *) (((struct fblk *) blk) -> df_free ),
sizeof( super->s_free));
}
if( super -> s_nfree <= 0 ||
super -> s_nfree > NICFREE ){
fprintf( stderr, "Bad free count %d\n", super->s_nfree );
goto nospace;
}
if( super -> s_tfree ) /* кол-во свободных блоков */
super -> s_tfree --;
return bno;
nospace:
super -> s_nfree = 0;
super -> s_tfree = 0;
return (-1L); /* конец списка */
}
/* пересылка участка памяти длиной n байт */
memcpy( to, from, n )
register char *to, *from;
register n;
{
while( n > 0 ){
*to++ = *from++;
n--;
}
}
save( bno ) daddr_t bno;
{
register i;
char answer[ 20 ];
printf( "block %ld-------------------\n", bno );
lseek( fd, bno * BSIZE , 0 );
read ( fd, blk, BSIZE );
for( i=0; i < BSIZE; i++ )
putchar(isprint(blk[i]) || isspace(blk[i]) ? blk[i] : '.' );
printf( "\n\7===> save block %ld ? ", bno );
fflush( stdout );
gets( answer );
if( *answer == 'y' || *answer == 'Y' ){
sprintf( answer, "#%012ld", n );
fdout = creat( answer, 0644 );
if( fdout < 0 ){
fprintf( stderr, "Can't create %s\n", answer );
exit(3);
}
write( fdout, blk, BSIZE );
close( fdout );
}
n++;
}
© Copyright А. Богатырев, 1992-95
Си в UNIX
Назад | Содержание | Вперед