Whamcloud - gitweb
Many files:
[tools/e2fsprogs.git] / misc / badblocks.c
index c7f1d46..66e352b 100644 (file)
@@ -64,13 +64,11 @@ static int v_flag = 0;                      /* verbose */
 static int w_flag = 0;                 /* do r/w test: 0=no, 1=yes,
                                         * 2=non-destructive */
 static int s_flag = 0;                 /* show progress of test */
+static int force = 0;                  /* force check of mounted device */
 
-static char *blkbuf;           /* Allocation array for bad block testing */
-
-
-static void usage(void)
+static void usage(NOARGS)
 {
-       fprintf(stderr, _("Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwn]\n [-c blocks_at_once] [-p num_passes] device [blocks_count] [start_count]\n"),
+       fprintf(stderr, _("Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n [-c blocks_at_once] [-p num_passes] device [blocks_count [start_count]]\n"),
                 program_name);
        exit (1);
 }
@@ -82,6 +80,9 @@ static FILE *out;
 static blk_t next_bad = 0;
 static ext2_badblocks_iterate bb_iter = NULL;
 
+/* Everything is STDC, these days */
+#define NOARGS void
+
 /*
  * This routine reports a new bad block.  If the bad block has already
  * been seen before, then it returns 0; otherwise it returns 1.
@@ -110,14 +111,14 @@ static int bb_output (unsigned long bad)
        return 1;
 }
 
-static void print_status (void)
+static void print_status(NOARGS)
 {
        fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks);
        fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
        fflush (stderr);
 }
 
-static void alarm_intr (int alnum)
+static void alarm_intr(int alnum)
 {
        signal (SIGALRM, alarm_intr);
        alarm(1);
@@ -130,14 +131,14 @@ static void alarm_intr (int alnum)
 
 static void *terminate_addr = NULL;
 
-static void terminate_intr (int signo)
+static void terminate_intr(int signo)
 {
        if (terminate_addr)
                longjmp(terminate_addr,1);
        exit(1);
 }
 
-static void capture_terminate (jmp_buf term_addr)
+static void capture_terminate(jmp_buf term_addr)
 {
        terminate_addr = term_addr;
        signal (SIGHUP, terminate_intr);
@@ -148,7 +149,7 @@ static void capture_terminate (jmp_buf term_addr)
        signal (SIGUSR2, terminate_intr);
 }
 
-static void uncapture_terminate()
+static void uncapture_terminate(NOARGS)
 {
        terminate_addr = NULL;
        signal (SIGHUP, SIG_DFL);
@@ -411,14 +412,14 @@ static unsigned int test_nd (int dev, unsigned long blocks_count,
        char *blkbuf, *save_ptr, *test_ptr, *read_ptr;
        char * ptr;
        int try, i;
-       long got, used2, written;
+       long got, used2, written, save_currently_testing;
        struct saved_blk_record *test_record;
-       int     num_saved;
+       /* This is static to prevent being clobbered by the longjmp */
+       static int num_saved;
        jmp_buf terminate_env;
        errcode_t errcode;
-       /* These are static to prevent being clobbered by the longjmp */
-       static long buf_used = 0;
-       static unsigned int bb_count = 0;
+       long buf_used;
+       unsigned int bb_count;
 
        errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter);
        if (errcode) {
@@ -463,8 +464,8 @@ static unsigned int test_nd (int dev, unsigned long blocks_count,
                /*
                 * Abnormal termination by a signal is handled here.
                 */
-
-               fprintf(stderr, _("Interrupt caught, cleaning up\n"));
+               signal (SIGALRM, SIG_IGN);
+               fprintf(stderr, _("\nInterrupt caught, cleaning up\n"));
 
                save_ptr = blkbuf;
                for (i=0; i < num_saved; i++) {
@@ -480,6 +481,7 @@ static unsigned int test_nd (int dev, unsigned long blocks_count,
        capture_terminate(terminate_env);
 
        buf_used = 0;
+       bb_count = 0;
        save_ptr = blkbuf;
        test_ptr = blkbuf + (blocks_at_once * block_size);
        currently_testing = from_count;
@@ -541,6 +543,7 @@ static unsigned int test_nd (int dev, unsigned long blocks_count,
                        continue;
 
                flush_bufs(dev);
+               save_currently_testing = currently_testing;
 
                /*
                 * for each contiguous block that we read into the
@@ -597,6 +600,7 @@ static unsigned int test_nd (int dev, unsigned long blocks_count,
                buf_used = 0;
                save_ptr = blkbuf;
                test_ptr = blkbuf + (blocks_at_once * block_size);
+               currently_testing = save_currently_testing;
        }
        num_blocks = 0;
        alarm(0);
@@ -613,6 +617,32 @@ static unsigned int test_nd (int dev, unsigned long blocks_count,
        return bb_count;
 }
 
+static void check_mount(char *device_name)
+{
+       errcode_t       retval;
+       int             mount_flags;
+
+       retval = ext2fs_check_if_mounted(device_name, &mount_flags);
+       if (retval) {
+               com_err("ext2fs_check_if_mount", retval,
+                       _("while determining whether %s is mounted."),
+                       device_name);
+               return;
+       }
+       if (!(mount_flags & EXT2_MF_MOUNTED))
+               return;
+
+       fprintf(stderr, _("%s is mounted; "), device_name);
+       if (force) {
+               fprintf(stderr, _("badblocks forced anyway.  "
+                       "Hope /etc/mtab is incorrect.\n"));
+               return;
+       }
+       fprintf(stderr, _("it's not safe to run badblocks!\n"));
+       exit(1);
+}
+
+
 int main (int argc, char ** argv)
 {
        int c;
@@ -632,7 +662,6 @@ int main (int argc, char ** argv)
        unsigned int (*test_func)(int dev, unsigned long blocks_count,
                                  int block_size, unsigned long from_count,
                                  unsigned long blocks_at_once);
-       size_t  buf_size;
 
        setbuf(stdout, NULL);
        setbuf(stderr, NULL);
@@ -645,7 +674,7 @@ int main (int argc, char ** argv)
        
        if (argc && *argv)
                program_name = *argv;
-       while ((c = getopt (argc, argv, "b:i:o:svwnc:p:h:")) != EOF) {
+       while ((c = getopt (argc, argv, "b:fi:o:svwnc:p:h:")) != EOF) {
                switch (c) {
                case 'b':
                        block_size = strtoul (optarg, &tmp, 0);
@@ -655,6 +684,9 @@ int main (int argc, char ** argv)
                                exit (1);
                        }
                        break;
+               case 'f':
+                       force++;
+                       break;
                case 'i':
                        input_file = optarg;
                        break;
@@ -731,12 +763,20 @@ int main (int argc, char ** argv)
        }
        if (optind <= argc-1) {
                from_count = strtoul (argv[optind], &tmp, 0);
+               if (*tmp) {
+                       com_err (program_name, 0, _("bad starting block - %s"),
+                                argv[optind]);
+                       exit (1);
+               }
        } else from_count = 0;
        if (from_count >= blocks_count) {
            com_err (program_name, 0, _("bad blocks range: %lu-%lu"),
                     from_count, blocks_count);
            exit (1);
        }
+       if (w_flag)
+               check_mount(device_name);
+       
        dev = open (device_name, w_flag ? O_RDWR : O_RDONLY);
        if (dev == -1)
        {
@@ -791,7 +831,7 @@ int main (int argc, char ** argv)
 
        if (in) {
                for(;;) {
-                       switch(fscanf (in, "%lu\n", &next_bad)) {
+                       switch(fscanf (in, "%u\n", &next_bad)) {
                                case 0:
                                        com_err (program_name, 0, "input file - bad format");
                                        exit (1);