diff options
Diffstat (limited to 'usr.sbin/fdformat')
-rw-r--r-- | usr.sbin/fdformat/Makefile | 14 | ||||
-rw-r--r-- | usr.sbin/fdformat/Makefile.depend | 18 | ||||
-rw-r--r-- | usr.sbin/fdformat/fdformat.1 | 180 | ||||
-rw-r--r-- | usr.sbin/fdformat/fdformat.c | 360 |
4 files changed, 572 insertions, 0 deletions
diff --git a/usr.sbin/fdformat/Makefile b/usr.sbin/fdformat/Makefile new file mode 100644 index 0000000..59cd124 --- /dev/null +++ b/usr.sbin/fdformat/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../fdread + +PROG= fdformat +SRCS= fdformat.c fdutil.c + +CFLAGS+= -I${.CURDIR}/../fdread + +.if ${MACHINE} == "pc98" +CFLAGS+= -DPC98 +.endif + +.include <bsd.prog.mk> diff --git a/usr.sbin/fdformat/Makefile.depend b/usr.sbin/fdformat/Makefile.depend new file mode 100644 index 0000000..3646e2e --- /dev/null +++ b/usr.sbin/fdformat/Makefile.depend @@ -0,0 +1,18 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + gnu/lib/csu \ + gnu/lib/libgcc \ + include \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/fdformat/fdformat.1 b/usr.sbin/fdformat/fdformat.1 new file mode 100644 index 0000000..596b09b --- /dev/null +++ b/usr.sbin/fdformat/fdformat.1 @@ -0,0 +1,180 @@ +.\" Copyright (C) 1993, 1994, 1995, 2001 by Joerg Wunsch, Dresden +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, +.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 25, 2001 +.Dt FDFORMAT 1 +.Os +.Sh NAME +.Nm fdformat +.Nd format floppy disks +.Sh SYNOPSIS +.Nm +.Op Fl F Ar fill +.Op Fl f Ar fmt +.Op Fl s Ar fmtstr +.Op Fl nqvy +.Ar device +.Sh DESCRIPTION +The +.Nm +utility formats a floppy disk at +.Ar device , +where +.Ar device +may either be given as a full path +name of a device node for a floppy disk drive +(e.g.\& +.Pa /dev/fd0 ) , +or using an abbreviated name that will be looked up +under +.Pa /dev +(e.g.\& +.Dq Li fd0 ) . +.Pp +The options are as follows: +.Bl -tag -width ".Fl s Ar fmtstr" +.It Fl F Ar fill +Use +.Ar fill +as the fill byte for newly formatted sectors. +The +.Ar fill +argument +must be a number in the range 0 through 255 using common C +language notation. +The default value is +.Dq Li 0xf6 . +.It Fl f Ar fmt +Specify the density settings for a +.Ar fmt +kilobyte format, as described in +.Xr fdcontrol 8 . +.It Fl s Ar fmtstr +Specify the density settings using explicit parameters, as +described in +.Xr fdcontrol 8 . +.It Fl n +Do not verify floppy after formatting. +.It Fl q +Suppress any normal output from the command, and do not ask the +user for a confirmation whether to format the floppy disk at +.Ar device . +.It Fl v +Do not format, verify only. +.It Fl y +Do not ask for confirmation whether to format the floppy disk but +still report formatting status. +.El +.Pp +For non-autoselecting subdevices, neither +.Fl f Ar fmt +nor +.Fl s Ar fmtstr +may be specified, since the preconfigured media density settings +from the kernel driver will always be used. +However, if +.Ar device +is a device with automatic media density selection (see +.Xr fdc 4 ) , +both methods can be used to override the density settings for the +newly formatted medium (without permanently changing the density +settings of +.Ar device ) . +.Pp +If the +.Fl q +flag has not been specified, the user is asked for a confirmation +of the intended formatting process. +In order to continue, an answer +of +.Ql y +must be given. +.Pp +Note that +.Nm +does only perform low-level formatting. +In order to create +a file system on the medium, see the commands +.Xr newfs 8 +for a +.Tn UFS +file system, or +.Xr newfs_msdos 8 +for an +.Tn MS-DOS +(FAT) +file system. +.Sh EXIT STATUS +An exit status of 0 is returned upon successful operation. +Exit status +1 is returned on any errors during floppy formatting, and an exit status +of 2 reflects invalid arguments given to the program (along with an +appropriate information written to diagnostic output). +.Sh DIAGNOSTICS +Unless +.Fl q +has been specified, a single letter is printed to standard output +to inform the user about the progress of work. +First, an +.Ql F +is printed when the track is being formatted, then a +.Ql V +while it is being verified, and if an error has been detected, it +will finally change to +.Ql E . +Detailed status information (cylinder, head and sector number, and the +exact cause of the error) will be printed for up to 10 errors after the +entire formatting process has completed. +.Sh SEE ALSO +.Xr fdc 4 , +.Xr fdcontrol 8 , +.Xr newfs 8 , +.Xr newfs_msdos 8 +.Sh HISTORY +The +.Nm +utility +has been developed for +.Bx 386 0.1 +and upgraded to the new +.Xr fdc 4 +floppy disk driver. +It later became part of the +.Fx 1.1 +system. +Starting with +.Fx 5.0 , +it uses the unified density specifications as described in +.Xr fdcontrol 8 . +.Sh AUTHORS +.An -nosplit +The program has been contributed by +.An J\(:org Wunsch , +Dresden, with changes by +.An Serge Vakulenko +and +.An Andrey A. Chernov , +Moscow. diff --git a/usr.sbin/fdformat/fdformat.c b/usr.sbin/fdformat/fdformat.c new file mode 100644 index 0000000..341a161 --- /dev/null +++ b/usr.sbin/fdformat/fdformat.c @@ -0,0 +1,360 @@ +/* + * Copyright (C) 1992-1994,2001 by Joerg Wunsch, Dresden + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/fdcio.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> + +#include "fdutil.h" + +static void +format_track(int fd, int cyl, int secs, int head, int rate, + int gaplen, int secsize, int fill, int interleave, + int offset) +{ + struct fd_formb f; + int i, j, il[FD_MAX_NSEC + 1]; + + memset(il, 0, sizeof il); + for(j = 0, i = 1 + offset; i <= secs + offset; i++) { + while(il[(j % secs) + 1]) + j++; + il[(j % secs) + 1] = i; + j += interleave; + } + + f.format_version = FD_FORMAT_VERSION; + f.head = head; + f.cyl = cyl; + f.transfer_rate = rate; + + f.fd_formb_secshift = secsize; + f.fd_formb_nsecs = secs; + f.fd_formb_gaplen = gaplen; + f.fd_formb_fillbyte = fill; + for(i = 0; i < secs; i++) { + f.fd_formb_cylno(i) = cyl; + f.fd_formb_headno(i) = head; + f.fd_formb_secno(i) = il[i+1]; + f.fd_formb_secsize(i) = secsize; + } + (void)ioctl(fd, FD_FORM, (caddr_t)&f); +} + +static int +verify_track(int fd, int track, int tracksize) +{ + static char *buf; + static int bufsz; + int fdopts = -1, ofdopts, rv = 0; + + if (ioctl(fd, FD_GOPTS, &fdopts) < 0) + warn("warning: ioctl(FD_GOPTS)"); + else { + ofdopts = fdopts; + fdopts |= FDOPT_NORETRY; + (void)ioctl(fd, FD_SOPTS, &fdopts); + } + + if (bufsz < tracksize) + buf = realloc(buf, bufsz = tracksize); + if (buf == 0) + errx(EX_UNAVAILABLE, "out of memory"); + if (lseek (fd, (long) track * tracksize, 0) < 0) + rv = -1; + /* try twice reading it, without using the normal retrier */ + else if (read (fd, buf, tracksize) != tracksize + && read (fd, buf, tracksize) != tracksize) + rv = -1; + if (fdopts != -1) + (void)ioctl(fd, FD_SOPTS, &ofdopts); + return (rv); +} + +static void +usage (void) +{ + errx(EX_USAGE, + "usage: fdformat [-F fill] [-f fmt] [-s fmtstr] [-nqvy] device"); +} + +static int +yes (void) +{ + char reply[256], *p; + + reply[sizeof(reply) - 1] = 0; + for (;;) { + fflush(stdout); + if (!fgets (reply, sizeof(reply) - 1, stdin)) + return (0); + for (p=reply; *p==' ' || *p=='\t'; ++p) + continue; + if (*p=='y' || *p=='Y') + return (1); + if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') + return (0); + printf("Answer `yes' or `no': "); + } +} + +int +main(int argc, char **argv) +{ + enum fd_drivetype type; + struct fd_type fdt, newft, *fdtp; + struct stat sb; +#define MAXPRINTERRS 10 + struct fdc_status fdcs[MAXPRINTERRS]; + int format, fill, quiet, verify, verify_only, confirm; + int fd, c, i, track, error, tracks_per_dot, bytes_per_track, errs; + int flags; + char *fmtstring, *device; + const char *name, *descr; + + format = quiet = verify_only = confirm = 0; + verify = 1; + fill = 0xf6; + fmtstring = 0; + + while((c = getopt(argc, argv, "F:f:nqs:vy")) != -1) + switch(c) { + case 'F': /* fill byte */ + if (getnum(optarg, &fill)) { + fprintf(stderr, + "Bad argument %s to -F option; must be numeric\n", + optarg); + usage(); + } + break; + + case 'f': /* format in kilobytes */ + if (getnum(optarg, &format)) { + fprintf(stderr, + "Bad argument %s to -f option; must be numeric\n", + optarg); + usage(); + } + break; + + case 'n': /* don't verify */ + verify = 0; + break; + + case 'q': /* quiet */ + quiet = 1; + break; + + case 's': /* format string with detailed options */ + fmtstring = optarg; + break; + + case 'v': /* verify only */ + verify = 1; + verify_only = 1; + break; + + case 'y': /* confirm */ + confirm = 1; + break; + + default: + usage(); + } + + if(optind != argc - 1) + usage(); + + if (stat(argv[optind], &sb) == -1 && errno == ENOENT) { + /* try prepending _PATH_DEV */ + device = malloc(strlen(argv[optind]) + sizeof(_PATH_DEV) + 1); + if (device == 0) + errx(EX_UNAVAILABLE, "out of memory"); + strcpy(device, _PATH_DEV); + strcat(device, argv[optind]); + if (stat(device, &sb) == -1) { + free(device); + device = argv[optind]; /* let it fail below */ + } + } else { + device = argv[optind]; + } + + if ((fd = open(device, O_RDWR | O_NONBLOCK)) < 0) + err(EX_OSERR, "open(%s)", device); + + /* + * Device initialization. + * + * First, get the device type descriptor. This tells us about + * the media geometry data we need to format a medium. It also + * lets us know quickly whether the device name actually points + * to a floppy disk drive. + * + * Then, obtain any drive options. We're mainly interested to + * see whether we're currently working on a device with media + * density autoselection (FDOPT_AUTOSEL). Then, we add the + * device option to tell the kernel not to log media errors, + * since we can handle them ourselves. If the device does + * media density autoselection, we then need to set the device + * type appropriately, since by opening with O_NONBLOCK we + * told the driver to bypass media autoselection (otherwise we + * wouldn't stand a chance to format an unformatted or damaged + * medium). We do not attempt to set the media type on any + * other devices since this is a privileged operation. For the + * same reason, specifying -f and -s options is only possible + * for autoselecting devices. + * + * Finally, we are ready to turn off O_NONBLOCK, and start to + * actually format something. + */ + if(ioctl(fd, FD_GTYPE, &fdt) < 0) + errx(EX_OSERR, "not a floppy disk: %s", device); + if (ioctl(fd, FD_GDTYPE, &type) == -1) + err(EX_OSERR, "ioctl(FD_GDTYPE)"); + if (format) { + getname(type, &name, &descr); + fdtp = get_fmt(format, type); + if (fdtp == 0) + errx(EX_USAGE, + "unknown format %d KB for drive type %s", + format, name); + fdt = *fdtp; + } + if (fmtstring) { + parse_fmt(fmtstring, type, fdt, &newft); + fdt = newft; + } + if (ioctl(fd, FD_STYPE, &fdt) < 0) + err(EX_OSERR, "ioctl(FD_STYPE)"); + if ((flags = fcntl(fd, F_GETFL, 0)) == -1) + err(EX_OSERR, "fcntl(F_GETFL)"); + flags &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) == -1) + err(EX_OSERR, "fcntl(F_SETFL)"); + + bytes_per_track = fdt.sectrac * (128 << fdt.secsize); + + /* XXX 20/40 = 0.5 */ + tracks_per_dot = (fdt.tracks * fdt.heads + 20) / 40; + + if (verify_only) { + if(!quiet) + printf("Verify %dK floppy `%s'.\n", + fdt.tracks * fdt.heads * bytes_per_track / 1024, + device); + } + else if(!quiet && !confirm) { + printf("Format %dK floppy `%s'? (y/n): ", + fdt.tracks * fdt.heads * bytes_per_track / 1024, + device); + if(!yes()) { + printf("Not confirmed.\n"); + return (EX_UNAVAILABLE); + } + } + + /* + * Formatting. + */ + if(!quiet) { + printf("Processing "); + for (i = 0; i < (fdt.tracks * fdt.heads) / tracks_per_dot; i++) + putchar('-'); + printf("\rProcessing "); + fflush(stdout); + } + + error = errs = 0; + + for (track = 0; track < fdt.tracks * fdt.heads; track++) { + if (!verify_only) { + format_track(fd, track / fdt.heads, fdt.sectrac, + track % fdt.heads, fdt.trans, fdt.f_gap, + fdt.secsize, fill, fdt.f_inter, + track % fdt.heads? fdt.offset_side2: 0); + if(!quiet && !((track + 1) % tracks_per_dot)) { + putchar('F'); + fflush(stdout); + } + } + if (verify) { + if (verify_track(fd, track, bytes_per_track) < 0) { + error = 1; + if (errs < MAXPRINTERRS && errno == EIO) { + if (ioctl(fd, FD_GSTAT, fdcs + errs) == + -1) + errx(EX_IOERR, + "floppy IO error, but no FDC status"); + errs++; + } + } + if(!quiet && !((track + 1) % tracks_per_dot)) { + if (!verify_only) + putchar('\b'); + if (error) { + putchar('E'); + error = 0; + } + else + putchar('V'); + fflush(stdout); + } + } + } + if(!quiet) + printf(" done.\n"); + + if (!quiet && errs) { + fflush(stdout); + fprintf(stderr, "Errors encountered:\nCyl Head Sect Error\n"); + for (i = 0; i < errs && i < MAXPRINTERRS; i++) { + fprintf(stderr, " %2d %2d %2d ", + fdcs[i].status[3], fdcs[i].status[4], + fdcs[i].status[5]); + printstatus(fdcs + i, 1); + putc('\n', stderr); + } + if (errs >= MAXPRINTERRS) + fprintf(stderr, "(Further errors not printed.)\n"); + } + + return errs != 0; +} |