1 /* $NetBSD: fdformat.c,v 1.4 1997/10/18 14:48:22 lukem Exp $ */ 2 /*- 3 * Copyright (c) 1996 John T. Kohl. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35 /* 36 * fdformat: format a floppy diskette, using interface provided in 37 * <sys/fdio.h> 38 */ 39 #include <sys/types.h> 40 #include <sys/fdio.h> 41 #include <sys/ioctl.h> 42 43 #include <err.h> 44 #include <errno.h> 45 #include <fcntl.h> 46 #include <limits.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <unistd.h> 50 #include "pathnames.h" 51 52 char *fdb_array[2] = {_PATH_FLOPPYTAB, 0}; 53 54 #define MASK_NBPS 0x0001 55 #define MASK_NCYL 0x0002 56 #define MASK_NSPT 0x0004 57 #define MASK_NTRK 0x0008 58 #define MASK_STEPSPERCYL 0x0010 59 #define MASK_GAPLEN 0x0020 60 #define MASK_FILLBYTE 0x0040 61 #define MASK_XFER_RATE 0x0080 62 #define MASK_INTERLEAVE 0x0100 63 64 #define ALLPARMS (MASK_NBPS|MASK_NCYL|MASK_NSPT|MASK_NTRK|MASK_STEPSPERCYL|MASK_GAPLEN|MASK_FILLBYTE|MASK_XFER_RATE|MASK_INTERLEAVE) 65 66 int confirm(int); 67 int main __P((int, char **)); 68 void usage __P((void)); 69 int verify_track(int, int, int, struct fdformat_parms *, char *); 70 71 int 72 confirm(int def) 73 { 74 int ch; 75 76 printf(" Yes/no [%c]?", def ? 'y' : 'n'); 77 ch = getchar(); 78 switch (ch) { 79 case 'y': 80 case 'Y': 81 return 1; 82 case '\n': 83 return def; 84 case EOF: 85 case 'n': 86 case 'N': 87 default: 88 return 0; 89 } 90 } 91 92 int 93 verify_track(int fd, int cyl, int trk, struct fdformat_parms *parms, char *buf) 94 { 95 size_t tracksize; 96 off_t offset; 97 98 tracksize = parms->nbps * parms->nspt; /* bytes per track */ 99 offset = tracksize * (cyl * parms->ntrk + trk); /* track offset */ 100 101 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) { 102 putchar('E'); 103 return 1; 104 } 105 if (read(fd, buf, tracksize) != tracksize) { 106 putchar('E'); 107 return 1; 108 } else 109 putchar('V'); 110 return 0; 111 } 112 113 void 114 usage(void) 115 { 116 extern char *__progname; 117 118 errx(1,"Usage: %s [-f device] [-t type] [-n] [-B nbps] [-S nspt]\n\t[-T ntrk] [-C ncyl] [-P stepspercyl] [-G gaplen]\n\t[-F fillbyte] [-X xfer_rate] [-I interleave]\n", __progname); 119 } 120 121 #define numarg(which, maskn) \ 122 tmplong = strtol(optarg, &tmpcharp, 0); \ 123 if (*tmpcharp != '\0' || tmplong <= 0 || tmplong == LONG_MIN || tmplong == LONG_MAX) \ 124 errx(1, "invalid numerical argument %s for " # which, optarg); \ 125 parms.which = tmplong; \ 126 parmmask |= MASK_##maskn 127 128 #define getparm(structname, maskname) \ 129 if (cgetnum(fdbuf, # structname, &tmplong) == -1) \ 130 errx(1, "parameter " # structname " missing for type %s", \ 131 optarg); \ 132 parms.structname = tmplong; \ 133 parmmask |= MASK_ ## maskname 134 135 #define copyparm(which, mask) \ 136 if ((parmmask & MASK_##mask) == 0) \ 137 parms.which = fetchparms.which 138 139 int 140 main(int argc, char *argv[]) 141 { 142 char *fdbuf = NULL, *trackbuf = NULL; 143 int errcnt = 0; 144 int verify = 1; 145 int ch; 146 long tmplong; 147 int tmpint; 148 char *tmpcharp; 149 int parmmask = 0; 150 struct fdformat_parms parms, fetchparms; 151 struct fdformat_cmd cmd; 152 char *filename = _PATH_FLOPPY_DEV; 153 int fd; 154 int trk, cyl; 155 156 while ((ch = getopt(argc, argv, "f:t:nB:C:S:T:P:G:F:X:I:")) != -1) 157 switch (ch) { 158 case 't': /* disk type */ 159 switch (cgetent(&fdbuf, fdb_array, optarg)) { 160 case 0: 161 break; 162 case 1: 163 case -3: 164 errx(1, "tc= loop or missing entry entry in " 165 _PATH_FLOPPYTAB " for type %s", optarg); 166 break; 167 case -1: 168 errx(1, "unknown floppy disk type %s", optarg); 169 break; 170 default: 171 err(1, "problem accessing " _PATH_FLOPPYTAB); 172 break; 173 } 174 175 getparm(nbps, NBPS); 176 getparm(ncyl, NCYL); 177 getparm(nspt, NSPT); 178 getparm(ntrk, NTRK); 179 getparm(stepspercyl, STEPSPERCYL); 180 getparm(gaplen, GAPLEN); 181 getparm(fillbyte, FILLBYTE); 182 getparm(xfer_rate, XFER_RATE); 183 getparm(interleave, INTERLEAVE); 184 break; 185 case 'f': /* device name */ 186 filename = optarg; 187 break; 188 case 'n': /* no verify */ 189 verify = 0; 190 break; 191 case 'B': 192 numarg(nbps, NBPS); 193 break; 194 case 'C': 195 numarg(ncyl, NCYL); 196 break; 197 case 'S': 198 numarg(nspt, NSPT); 199 break; 200 case 'T': 201 numarg(ntrk, NTRK); 202 break; 203 case 'P': 204 numarg(stepspercyl, STEPSPERCYL); 205 break; 206 case 'G': 207 numarg(gaplen, GAPLEN); 208 break; 209 case 'F': /* special handling--0 is OK */ 210 /*numarg(fillbyte, FILLBYTE);*/ 211 tmplong = strtol(optarg, &tmpcharp, 0); 212 if (*tmpcharp != '\0' || tmplong < 0 || 213 tmplong == LONG_MIN || tmplong == LONG_MAX) 214 errx(1, "invalid numerical argument %s for fillbyte", optarg); 215 parms.fillbyte = tmplong; 216 parmmask |= MASK_FILLBYTE; 217 break; 218 case 'X': 219 numarg(xfer_rate, XFER_RATE); 220 break; 221 case 'I': 222 numarg(interleave, INTERLEAVE); 223 break; 224 case '?': 225 default: 226 usage(); 227 } 228 if (optind < argc) 229 usage(); 230 231 fd = open(filename, O_RDWR); 232 if (fd == -1) 233 err(1, "cannot open %s", filename); 234 if (ioctl(fd, FDIOCGETFORMAT, &fetchparms) == -1) { 235 if (errno == ENOTTY) 236 err(1, "device %s does not support floppy formatting", 237 filename); 238 else 239 err(1, "cannot fetch current floppy formatting parameters"); 240 } 241 242 copyparm(nbps, NBPS); 243 copyparm(ncyl, NCYL); 244 copyparm(nspt, NSPT); 245 copyparm(ntrk, NTRK); 246 copyparm(stepspercyl, STEPSPERCYL); 247 copyparm(gaplen, GAPLEN); 248 copyparm(fillbyte, FILLBYTE); 249 copyparm(xfer_rate, XFER_RATE); 250 copyparm(interleave, INTERLEAVE); 251 252 parms.fdformat_version = FDFORMAT_VERSION; 253 254 tmpint = FDOPT_NORETRY|FDOPT_SILENT; 255 if (ioctl(fd, FDIOCSETOPTS, &tmpint) == -1 || 256 ioctl(fd, FDIOCSETFORMAT, &parms) == -1) { 257 warn("cannot set requested formatting parameters"); 258 errx(1, "%d cylinders, %d tracks, %d sectors of %d bytes", 259 parms.ncyl, parms.ntrk, parms.nspt, parms.nbps); 260 } 261 262 printf("Ready to format %s with %d cylinders, %d tracks, %d sectors of %d bytes\n(%d KB)", 263 filename, parms.ncyl, parms.ntrk, parms.nspt, parms.nbps, 264 parms.ncyl * parms.ntrk * parms.nspt * parms.nbps / 1024); 265 if (!confirm(1)) 266 errx(1,"formatting abandoned--not confirmed."); 267 268 if (verify) 269 trackbuf = malloc(parms.nbps * parms.nspt); 270 271 cmd.formatcmd_version = FDFORMAT_VERSION; 272 for (cyl = 0; cyl < parms.ncyl; cyl++) { 273 cmd.cylinder = cyl; 274 for (trk = 0; trk < parms.ntrk; trk++) { 275 cmd.head = trk; 276 if (ioctl(fd, FDIOCFORMAT_TRACK, &cmd) == 0) { 277 putchar('F'); 278 if (verify) 279 putchar('\b'); 280 fflush(stdout); 281 if (verify) 282 errcnt += verify_track(fd, cyl, trk, 283 &parms, 284 trackbuf); 285 } else if (errno == EINVAL) { 286 putchar('\n'); 287 errx(1, "formatting botch at <%d,%d>", 288 cyl, trk); 289 } else if (errno == EIO) { 290 putchar('E'); 291 fflush(stdout); 292 errcnt++; 293 } 294 } 295 } 296 putchar('\n'); 297 if (errcnt) 298 errx(1,"%d track formatting errors", errcnt); 299 return 0; 300 } 301