Пример 29

/*
 *      Программа восстановления блоков удаленного файла.
 *      Работает на канонической файловой системе 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 www.abyss-group.narod.ru
Си в UNIX

Назад | Содержание | Вперед

Hosted by uCoz