/* * Copyright 1996-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "fsck.h" #include "misc/malloc.h" #include "util/misc.h" #include #include #include #define ROLLBACK_FILE_START_MAGIC "_RollBackFileForReiserfsFSCK" static struct block_handler * rollback_blocks_array; static __u32 rollback_blocks_number = 0; static FILE * s_rollback_file = 0; static FILE * log_file; static int do_rollback = 0; static char * rollback_data; static unsigned int rollback_blocksize; void fsck_rollback_init (char * rollback_file, unsigned int *blocksize, FILE * log) { char * string; struct stat buf; if (rollback_file == NULL) return; stat(rollback_file, &buf); s_rollback_file = fopen (rollback_file, "w+"); if (s_rollback_file == NULL) { fprintf (stderr, "Cannot create file %s, work without " "a rollback file\n", rollback_file); return; } rollback_blocksize = *blocksize; string = ROLLBACK_FILE_START_MAGIC; fwrite (string, 28, 1, s_rollback_file); fwrite (&rollback_blocksize, sizeof(rollback_blocksize), 1, s_rollback_file); fwrite (&rollback_blocks_number, sizeof(rollback_blocks_number), 1, s_rollback_file); fflush(s_rollback_file); rollback_data = misc_getmem(rollback_blocksize); // printf("\ncheckmem1"); // fflush (stdout); // checkmem (rollback_data, misc_memsize((char *)rollback_data)); // printf(" OK"); log_file = log; if (log_file) fprintf (log_file, "rollback: file (%s) initialize\n", rollback_file); do_rollback = 0; } #if 0 static void erase_rollback_file (char * rollback_file) { close_rollback_file (); unlink (rollback_file); } #endif int fsck_rollback_prep (char * rollback_file, FILE * log) { char string [28]; struct stat buf; if (rollback_file == NULL) return -1; if (stat(rollback_file, &buf)) { fprintf (stderr, "Cannot stat rollback file (%s)\n", rollback_file); return -1; } s_rollback_file = fopen (rollback_file, "r+"); if (s_rollback_file == NULL) { fprintf (stderr, "Cannot open file (%s)\n", rollback_file); return -1; } fread (string, 28, 1, s_rollback_file); if (!strcmp (string, ROLLBACK_FILE_START_MAGIC)) { fprintf (stderr, "Specified file (%s) does not look like " "a rollback file\n", rollback_file); fclose (s_rollback_file); s_rollback_file = 0; return -1; } fread (&rollback_blocksize, sizeof (rollback_blocksize), 1, s_rollback_file); if (rollback_blocksize <= 0) { fprintf(stderr, "rollback: wrong rollback blocksize, exit\n"); return -1; } log_file = log; if (log_file) fprintf (log_file, "rollback: file (%s) opened\n", rollback_file); do_rollback = 1; return 0; } void fsck_rollback_fini () { if (s_rollback_file == 0) return; if (!do_rollback) { if (fseek (s_rollback_file, 28 + sizeof(int), SEEK_SET) == (off_t)-1) return; fwrite (&rollback_blocks_number, sizeof (rollback_blocksize), 1, s_rollback_file); if (log_file != 0) { fprintf (log_file, "rollback: %d blocks backed up\n", rollback_blocks_number); } } fclose (s_rollback_file); misc_freemem (rollback_data); misc_freemem (rollback_blocks_array); /* fprintf (stdout, "rollback: (%u) blocks saved, \n", rollback_blocks_number); for (i = 0; i < rollback_blocks_number; i++) fprintf(stdout, "device (%Lu), block number (%u)\n", rollback_blocks_array [i].device, rollback_blocks_array [i].blocknr); fprintf(stdout, "\n"); */ } void fsck_rollback (int fd_device, int fd_journal_device, FILE * progress) { long long int offset; struct stat buf; int descriptor; ssize_t retval; int count_failed = 0; int count_rollbacked = 0; int b_dev; int n_dev = 0; int n_journal_dev = 0; unsigned long total, done = 0; if (fd_device == 0) { fprintf(stderr, "rollback: unspecified device, exit\n"); return; } if (fd_journal_device) { if (!fstat (fd_journal_device, &buf)) { n_journal_dev = buf.st_rdev; } else { fprintf(stderr, "rollback: specified journal device " "cannot be stated\n"); } } if (!fstat (fd_device, &buf)) { n_dev = buf.st_rdev; } else { fprintf(stderr, "rollback: specified device cannot " "be stated, exit\n"); return; } rollback_data = misc_getmem (rollback_blocksize); // printf("\ncheckmem2"); // fflush (stdout); // checkmem (rollback_data, misc_memsize((char *)rollback_data)); // printf(" OK"); fread (&rollback_blocks_number, sizeof (rollback_blocks_number), 1, s_rollback_file); total = rollback_blocks_number; while (1) { if (!fsck_quiet(fs)) { util_misc_progress (progress, &done, rollback_blocks_number, 1, 0); } descriptor = 0; if ((retval = fread (&b_dev, sizeof (b_dev), 1, s_rollback_file)) <= 0) { if (retval) fprintf (stderr, "rollback: fread: %s\n", strerror (errno)); break; } if ((retval = fread (&offset, sizeof (offset), 1, s_rollback_file)) <= 0) { if (retval) fprintf (stderr, "rollback: fread: %s\n", strerror (errno)); break; } if ((retval = fread (rollback_data, rollback_blocksize, 1, s_rollback_file)) <= 0) { if (retval) fprintf (stderr, "rollback: fread: %s\n", strerror (errno)); break; } if (n_dev == b_dev) descriptor = fd_device; if ((n_journal_dev) && (n_journal_dev == b_dev)) descriptor = fd_journal_device; if (descriptor == 0) { fprintf(stderr, "rollback: block from unknown " "device, skip block\n"); count_failed ++; continue; } if (lseek (descriptor, offset, SEEK_SET) == (off_t)-1) { fprintf(stderr, "device cannot be lseeked, skip block\n"); count_failed ++; continue; } if (write (descriptor, rollback_data, rollback_blocksize) == -1) { fprintf (stderr, "rollback: write %d bytes returned error " "(block=%lld, dev=%d): %s\n", rollback_blocksize, offset/rollback_blocksize, b_dev, strerror (errno)); count_failed ++; } else { count_rollbacked ++; /*if you want to know what gets rollbacked, uncomment it*/ /* if (log_file != 0 && log_file != stdout) fprintf (log_file, "rollback: block %Lu of " "device %Lu was restored\n", (unsigned long long)offset/rollback_blocksize, b_dev); fprintf (stdout, "rollback: block (%Ld) written\n", (long long int)offset/rollback_blocksize); */ } } printf ("\n"); if (log_file != 0) { fprintf (log_file, "rollback: (%u) blocks restored\n", count_rollbacked); } } /* static void rollback__mark_block_saved (struct block_handler * rb_e) { if (rollback_blocks_array == NULL) rollback_blocks_array = misc_getmem (ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e)); if (rollback_blocks_number == misc_memsize ((void *)rollback_blocks_array) / sizeof (*rb_e)) { rollback_blocks_array = misc_expandmem (rollback_blocks_array, misc_memsize((void *)rollback_blocks_array), ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e)); } // checkmem ((char *)rollback_blocks_array, misc_memsize((char *)rollback_blocks_array)); rollback_blocks_array[rollback_blocks_number] = *rb_e; rollback_blocks_number ++; qsort (rollback_blocks_array, rollback_blocks_number, sizeof (*rb_e), rollback_compare); // printf("\ncheckmem3"); // fflush (stdout); // checkmem ((char *)rollback_blocks_array, misc_memsize((char *)rollback_blocks_array)); // printf(" OK"); } */