/* * Программа восстановления блоков удаленного файла. * Работает на канонической файловой системе 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
Назад | Содержание | Вперед