Пример 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++;

}

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

Используются технологии uCoz