]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fdformat: Add new switches -f/--from, -t/--to, -r/--repair
authorJaromir Capik <jcapik@redhat.com>
Mon, 28 Jul 2014 18:47:09 +0000 (20:47 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 29 Jul 2014 11:44:04 +0000 (13:44 +0200)
This commit introduces a support for user configurable
from/to track and a basic repair mode for broken floppies.
It also fixes a recently introduced bug that causes
a line breakage when printing the track number.

Signed-off-by: Karel Zak <kzak@redhat.com>
disk-utils/Makemodule.am
disk-utils/fdformat.8
disk-utils/fdformat.c

index c6183f5ca55387c600a42bf75865558d28119231..995e085529907476b343e5261277652637c281e1 100644 (file)
@@ -110,6 +110,7 @@ if BUILD_FDFORMAT
 usrsbin_exec_PROGRAMS += fdformat
 dist_man_MANS += disk-utils/fdformat.8
 fdformat_SOURCES = disk-utils/fdformat.c
+fdformat_LDADD = $(LDADD) libcommon.la
 endif
 
 if BUILD_BLOCKDEV
index df4153f23774ecd5fef85acd614212837c6f8b57..797f50f5ccab403b577df12e86b5d337e3533b8c 100644 (file)
@@ -1,6 +1,6 @@
 .\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
 .\" May be distributed under the GNU General Public License
-.TH FDFORMAT 8 "July 2011" "util-linux" "System Administration"
+.TH FDFORMAT 8 "July 2014" "util-linux" "System Administration"
 .SH NAME
 fdformat \- low-level format a floppy disk
 .SH SYNOPSIS
@@ -45,6 +45,15 @@ autodetected earlier.  In this case, use
 to load the disk parameters.
 .SH OPTIONS
 .TP
+\fB\-f\fR, \fB\-\-from\fR \fIN\fR
+Start at the track \fIN\fR (default is 0).
+.TP
+\fB\-t\fR, \fB\-\-to\fR \fIN\fR
+Stop at the track \fIN\fR (default is 0).
+.TP
+\fB\-r\fR, \fB\-\-repair\fR \fIN\fR
+Try to repair tracks failed during the verification (max \fIN\fR retries).
+.TP
 \fB\-n\fR, \fB\-\-no-verify\fR
 Skip the verification that is normally performed after the formatting.
 .TP
index e6ae8e43145c0147b092179ea0232510736b1bee..dc98de522d28bac9de580d34ca9db8ddd3117453 100644 (file)
 #include <unistd.h>
 
 #include "c.h"
+#include "strutils.h"
 #include "closestream.h"
 #include "nls.h"
 #include "xalloc.h"
 
+#define SECTOR_SIZE 512
+
 struct floppy_struct param;
 
-#define SECTOR_SIZE 512
 
-static void format_disk(int ctrl)
+static void format_begin(int ctrl)
 {
-       struct format_descr descr;
-       unsigned int track;
+       if (ioctl(ctrl, FDFMTBEG, NULL) < 0)
+               err(EXIT_FAILURE, "ioctl: FDFMTBEG");
+}
+
+static void format_end(int ctrl)
+{
+       if (ioctl(ctrl, FDFMTEND, NULL) < 0)
+               err(EXIT_FAILURE, "ioctl: FDFMTEND");
+}
+
+static void format_track_head(int ctrl, struct format_descr *descr)
+{
+       if (ioctl(ctrl, FDFMTTRK, (long) descr) < 0)
+               err(EXIT_FAILURE, "ioctl: FDFMTTRK");
+}
+
+static void seek_track_head(int ctrl, struct format_descr *descr)
+{
+       lseek(ctrl, (descr->track * param.head + descr->head) * param.sect * SECTOR_SIZE, SEEK_SET);
+}
+
+static void format_disk(int ctrl, unsigned int track_from, unsigned int track_to)
+{
+       struct format_descr current;
 
        printf(_("Formatting ... "));
        fflush(stdout);
-       if (ioctl(ctrl, FDFMTBEG, NULL) < 0)
-               err(EXIT_FAILURE, "ioctl: FDFMTBEG");
-       for (track = 0; track < param.track; track++) {
-               descr.track = track;
-               descr.head = 0;
-               if (ioctl(ctrl, FDFMTTRK, (long) &descr) < 0)
-                       err(EXIT_FAILURE, "ioctl: FDFMTTRK");
-
-               printf("%3ud\b\b\b", track);
-               fflush(stdout);
-               if (param.head == 2) {
-                       descr.head = 1;
-                       if (ioctl(ctrl, FDFMTTRK, (long)&descr) < 0)
-                               err(EXIT_FAILURE, "ioctl: FDFMTTRK");
+
+       format_begin(ctrl);
+
+       for (current.track = track_from; current.track <= track_to; current.track++) {
+               for (current.head = 0; current.head < param.head; current.head++) {
+                       printf("%3u/%u\b\b\b\b\b", current.track, current.head);
+                       fflush(stdout);
+                       format_track_head(ctrl, &current);
                }
        }
-       if (ioctl(ctrl, FDFMTEND, NULL) < 0)
-               err(EXIT_FAILURE, "ioctl: FDFMTEND");
+
+       format_end(ctrl);
+
        printf(_("done\n"));
 }
 
-static void verify_disk(char *name)
+static void verify_disk(int ctrl, unsigned int track_from, unsigned int track_to, unsigned int repair)
 {
        unsigned char *data;
-       unsigned int cyl;
-       int fd, cyl_size, count;
+       struct format_descr current;
+       int track_size, count;
+       unsigned int retries_left;
 
-       cyl_size = param.sect * param.head * 512;
-       data = xmalloc(cyl_size);
+       track_size = param.sect * SECTOR_SIZE;
+       data = xmalloc(track_size);
        printf(_("Verifying ... "));
        fflush(stdout);
-       if ((fd = open(name, O_RDONLY)) < 0)
-               err(EXIT_FAILURE, _("cannot open %s"), name);
-       for (cyl = 0; cyl < param.track; cyl++) {
-               int read_bytes;
-
-               printf("%u3d\b\b\b", cyl);
-               fflush(stdout);
-               read_bytes = read(fd, data, cyl_size);
-               if (read_bytes != cyl_size) {
-                       if (read_bytes < 0)
-                               perror(_("Read: "));
-                       fprintf(stderr,
-                               _("Problem reading cylinder %d,"
-                                 " expected %d, read %d\n"),
-                               cyl, cyl_size, read_bytes);
-                       free(data);
-                       exit(EXIT_FAILURE);
-               }
-               for (count = 0; count < cyl_size; count++)
-                       if (data[count] != FD_FILL_BYTE) {
-                               printf(_("bad data in cyl %d\n"
-                                        "Continuing ... "), cyl);
-                               fflush(stdout);
+
+       current.track = track_from;
+       current.head = 0;
+       seek_track_head (ctrl, &current);
+
+       for (current.track = track_from; current.track <= track_to; current.track++) {
+               for (current.head = 0; current.head < param.head; current.head++) {
+                       int read_bytes;
+
+                       printf("%3u\b\b\b", current.track);
+                       fflush(stdout);
+
+                       retries_left = repair;
+                       do {
+                               read_bytes = read(ctrl, data, track_size);
+                               if (read_bytes != track_size) {
+                                       if (retries_left) {
+                                               format_begin(ctrl);
+                                               format_track_head(ctrl, &current);
+                                               format_end(ctrl);
+                                               seek_track_head (ctrl, &current);
+                                               retries_left--;
+                                               if (retries_left)
+                                                       continue;
+                                       }
+                                       if (read_bytes < 0)
+                                               perror(_("Read: "));
+                                       fprintf(stderr,
+                                               _("Problem reading track/head %u/%u,"
+                                                 " expected %d, read %d\n"),
+                                               current.track, current.head, track_size, read_bytes);
+                                       free(data);
+                                       exit(EXIT_FAILURE);
+                               }
+                               for (count = 0; count < track_size; count++)
+                                       if (data[count] != FD_FILL_BYTE) {
+                                               if (retries_left) {
+                                                       format_begin(ctrl);
+                                                       format_track_head(ctrl, &current);
+                                                       format_end(ctrl);
+                                                       seek_track_head (ctrl, &current);
+                                                       retries_left--;
+                                                       if (retries_left)
+                                                               continue;
+                                               }
+                                               printf(_("bad data in track/head %u/%u\n"
+                                                        "Continuing ... "), current.track, current.head);
+                                               fflush(stdout);
+                                               break;
+                                       }
                                break;
-                       }
+                       } while (retries_left);
+               }
        }
+
        free(data);
        printf(_("done\n"));
-       if (close(fd) < 0)
-               err(EXIT_FAILURE, "close");
 }
 
 static void __attribute__ ((__noreturn__)) usage(FILE * out)
@@ -96,9 +143,13 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
                program_invocation_short_name);
 
        fprintf(out, _("\nOptions:\n"
-                      " -n, --no-verify  disable the verification after the format\n"
-                      " -V, --version    output version information and exit\n"
-                      " -h, --help       display this help and exit\n\n"));
+                      " -f, --from <N>    start at the track N (default 0)\n"
+                      " -t, --to <N>      stop at the track N\n"
+                      " -r, --repair <N>  try to repair tracks failed during\n"
+                      "                   the verification (max N retries)\n"
+                      " -n, --no-verify   disable the verification after the format\n"
+                      " -V, --version     output version information and exit\n"
+                      " -h, --help        display this help and exit\n\n"));
 
        exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
 }
@@ -108,22 +159,40 @@ int main(int argc, char **argv)
        int ch;
        int ctrl;
        int verify = 1;
+       unsigned int repair = 0;
+       unsigned int track_from = 0;
+       unsigned int track_to = 0;
+       int has_user_defined_track_to = 0;
        struct stat st;
 
        static const struct option longopts[] = {
+               {"from", required_argument, NULL, 'f'},
+               {"to", required_argument, NULL, 't'},
+               {"repair", required_argument, NULL, 'r'},
                {"no-verify", no_argument, NULL, 'n'},
                {"version", no_argument, NULL, 'V'},
                {"help", no_argument, NULL, 'h'},
                {NULL, 0, NULL, 0}
        };
 
+
        setlocale(LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
        atexit(close_stdout);
 
-       while ((ch = getopt_long(argc, argv, "nVh", longopts, NULL)) != -1)
+       while ((ch = getopt_long(argc, argv, "f:t:r:nVh", longopts, NULL)) != -1)
                switch (ch) {
+               case 'f':
+                       track_from = strtou32_or_err(optarg, _("invalid argument - from"));
+                       break;
+               case 't':
+                       has_user_defined_track_to = 1;
+                       track_to = strtou32_or_err(optarg, _("invalid argument - to"));
+                       break;
+               case 'r':
+                       repair = strtou32_or_err(optarg, _("invalid argument - repair"));
+                       break;
                case 'n':
                        verify = 0;
                        break;
@@ -149,20 +218,33 @@ int main(int argc, char **argv)
        if (access(argv[0], W_OK) < 0)
                err(EXIT_FAILURE, _("cannot access file %s"), argv[0]);
 
-       ctrl = open(argv[0], O_WRONLY);
+       ctrl = open(argv[0], O_RDWR);
        if (ctrl < 0)
                err(EXIT_FAILURE, _("cannot open %s"), argv[0]);
-       if (ioctl(ctrl, FDGETPRM, (long)&param) < 0)
-               err(EXIT_FAILURE, _("Could not determine current format type"));
+       if (ioctl(ctrl, FDGETPRM, (long) &param) < 0)
+               err(EXIT_FAILURE, _("could not determine current format type"));
 
        printf(_("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n"),
-              (param.head == 2) ? _("Double") : _("Single"),
-              param.track, param.sect, param.size >> 1);
-       format_disk(ctrl);
-       if (close_fd(ctrl) != 0)
-               err(EXIT_FAILURE, _("write failed"));
+               (param.head == 2) ? _("Double") : _("Single"),
+               param.track, param.sect, param.size >> 1);
+
+       if (!has_user_defined_track_to)
+               track_to = param.track - 1;
+
+       if (track_from >= param.track)
+               err(EXIT_FAILURE, _("user defined start track exceeds the medium specific maximum"));
+       if (track_to >= param.track)
+               err(EXIT_FAILURE, _("user defined end track exceeds the medium specific maximum"));
+       if (track_from > track_to)
+               err(EXIT_FAILURE, _("user defined start track exceeds the user defined end track"));
+
+       format_disk(ctrl, track_from, track_to);
 
        if (verify)
-               verify_disk(argv[0]);
+               verify_disk(ctrl, track_from, track_to, repair);
+
+       if (close_fd(ctrl) != 0)
+               err(EXIT_FAILURE, _("close failed"));
+
        return EXIT_SUCCESS;
 }