Deleted Added
full compact
fdformat.c (79161) fdformat.c (87992)
1/*
2 * Copyright (C) 1992-1994,2001 by Joerg Wunsch, Dresden
3 * 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 unchanged lines hidden (view full) ---

18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 *
1/*
2 * Copyright (C) 1992-1994,2001 by Joerg Wunsch, Dresden
3 * 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 unchanged lines hidden (view full) ---

18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: head/usr.sbin/fdformat/fdformat.c 79161 2001-07-03 21:43:41Z joerg $
26 * $FreeBSD: head/usr.sbin/fdformat/fdformat.c 87992 2001-12-15 19:09:04Z joerg $
27 */
28
27 */
28
29/*
30 * FreeBSD:
31 * format a floppy disk
32 *
33 * Added FD_GTYPE ioctl, verifying, proportional indicators.
34 * Serge Vakulenko, vak@zebub.msk.su
35 * Sat Dec 18 17:45:47 MSK 1993
36 *
37 * Final adaptation, change format/verify logic, add separate
38 * format gap/interleave values
39 * Andrew A. Chernov, ache@astral.msk.su
40 * Thu Jan 27 00:47:24 MSK 1994
41 */
29#include <sys/types.h>
30#include <sys/fdcio.h>
31#include <sys/stat.h>
42
43#include <ctype.h>
44#include <err.h>
45#include <errno.h>
46#include <fcntl.h>
47#include <paths.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <strings.h>
32
33#include <ctype.h>
34#include <err.h>
35#include <errno.h>
36#include <fcntl.h>
37#include <paths.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <strings.h>
41#include <sysexits.h>
51#include <unistd.h>
52
42#include <unistd.h>
43
53#include <sys/fdcio.h>
54
55#include "fdutil.h"
56
57static void
58format_track(int fd, int cyl, int secs, int head, int rate,
44#include "fdutil.h"
45
46static void
47format_track(int fd, int cyl, int secs, int head, int rate,
59 int gaplen, int secsize, int fill,int interleave)
48 int gaplen, int secsize, int fill, int interleave,
49 int offset)
60{
61 struct fd_formb f;
50{
51 struct fd_formb f;
62 register int i,j;
63 int il[FD_MAX_NSEC + 1];
52 int i, j, il[FD_MAX_NSEC + 1];
64
53
65 memset(il,0,sizeof il);
66 for(j = 0, i = 1; i <= secs; i++) {
67 while(il[(j%secs)+1]) j++;
68 il[(j%secs)+1] = i;
54 memset(il, 0, sizeof il);
55 for(j = 0, i = 1 + offset; i <= secs + offset; i++) {
56 while(il[(j % secs) + 1])
57 j++;
58 il[(j % secs) + 1] = i;
69 j += interleave;
70 }
71
72 f.format_version = FD_FORMAT_VERSION;
73 f.head = head;
74 f.cyl = cyl;
75 f.transfer_rate = rate;
76
77 f.fd_formb_secshift = secsize;
78 f.fd_formb_nsecs = secs;
79 f.fd_formb_gaplen = gaplen;
80 f.fd_formb_fillbyte = fill;
81 for(i = 0; i < secs; i++) {
82 f.fd_formb_cylno(i) = cyl;
83 f.fd_formb_headno(i) = head;
84 f.fd_formb_secno(i) = il[i+1];
85 f.fd_formb_secsize(i) = secsize;
86 }
87 if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0)
59 j += interleave;
60 }
61
62 f.format_version = FD_FORMAT_VERSION;
63 f.head = head;
64 f.cyl = cyl;
65 f.transfer_rate = rate;
66
67 f.fd_formb_secshift = secsize;
68 f.fd_formb_nsecs = secs;
69 f.fd_formb_gaplen = gaplen;
70 f.fd_formb_fillbyte = fill;
71 for(i = 0; i < secs; i++) {
72 f.fd_formb_cylno(i) = cyl;
73 f.fd_formb_headno(i) = head;
74 f.fd_formb_secno(i) = il[i+1];
75 f.fd_formb_secsize(i) = secsize;
76 }
77 if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0)
88 err(1, "ioctl(FD_FORM)");
78 err(EX_OSERR, "ioctl(FD_FORM)");
89}
90
91static int
92verify_track(int fd, int track, int tracksize)
93{
79}
80
81static int
82verify_track(int fd, int track, int tracksize)
83{
94 static char *buf = 0;
95 static int bufsz = 0;
84 static char *buf;
85 static int bufsz;
96 int fdopts = -1, ofdopts, rv = 0;
97
98 if (ioctl(fd, FD_GOPTS, &fdopts) < 0)
99 warn("warning: ioctl(FD_GOPTS)");
100 else {
101 ofdopts = fdopts;
102 fdopts |= FDOPT_NORETRY;
103 (void)ioctl(fd, FD_SOPTS, &fdopts);
104 }
105
86 int fdopts = -1, ofdopts, rv = 0;
87
88 if (ioctl(fd, FD_GOPTS, &fdopts) < 0)
89 warn("warning: ioctl(FD_GOPTS)");
90 else {
91 ofdopts = fdopts;
92 fdopts |= FDOPT_NORETRY;
93 (void)ioctl(fd, FD_SOPTS, &fdopts);
94 }
95
106 if (bufsz < tracksize) {
107 if (buf)
108 free (buf);
109 bufsz = tracksize;
110 buf = 0;
111 }
112 if (! buf)
113 buf = malloc (bufsz);
114 if (! buf)
115 errx(2, "out of memory");
116 if (lseek (fd, (long) track*tracksize, 0) < 0)
96 if (bufsz < tracksize)
97 buf = realloc(buf, bufsz = tracksize);
98 if (buf == 0)
99 errx(EX_UNAVAILABLE, "out of memory");
100 if (lseek (fd, (long) track * tracksize, 0) < 0)
117 rv = -1;
118 /* try twice reading it, without using the normal retrier */
119 else if (read (fd, buf, tracksize) != tracksize
120 && read (fd, buf, tracksize) != tracksize)
121 rv = -1;
101 rv = -1;
102 /* try twice reading it, without using the normal retrier */
103 else if (read (fd, buf, tracksize) != tracksize
104 && read (fd, buf, tracksize) != tracksize)
105 rv = -1;
122 if(fdopts != -1)
106 if (fdopts != -1)
123 (void)ioctl(fd, FD_SOPTS, &ofdopts);
124 return (rv);
125}
126
107 (void)ioctl(fd, FD_SOPTS, &ofdopts);
108 return (rv);
109}
110
127static const char *
128makename(const char *arg, const char *suffix)
129{
130 static char namebuff[20]; /* big enough for "/dev/fd0a"... */
131
132 memset(namebuff, 0, 20);
133 if(*arg == '\0') /* ??? */
134 return arg;
135 if(*arg == '/') /* do not convert absolute pathnames */
136 return arg;
137 strcpy(namebuff, _PATH_DEV);
138 strncat(namebuff, arg, 3);
139 strcat(namebuff, suffix);
140 return namebuff;
141}
142
143static void
144usage (void)
145{
111static void
112usage (void)
113{
146 fprintf(stderr, "%s\n%s\n",
147 "usage: fdformat [-y] [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]",
148 " [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] device_name");
149 exit(2);
114 errx(EX_USAGE,
115 "usage: fdformat [-F fill] [-f fmt] [-s fmtstr] [-nqvy] device");
150}
151
152static int
153yes (void)
154{
116}
117
118static int
119yes (void)
120{
155 char reply [256], *p;
121 char reply[256], *p;
156
122
157 reply[sizeof(reply)-1] = 0;
123 reply[sizeof(reply) - 1] = 0;
158 for (;;) {
159 fflush(stdout);
124 for (;;) {
125 fflush(stdout);
160 if (! fgets (reply, sizeof(reply)-1, stdin))
126 if (!fgets (reply, sizeof(reply) - 1, stdin))
161 return (0);
162 for (p=reply; *p==' ' || *p=='\t'; ++p)
163 continue;
164 if (*p=='y' || *p=='Y')
165 return (1);
166 if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r')
167 return (0);
168 printf("Answer `yes' or `no': ");
169 }
170}
171
172int
173main(int argc, char **argv)
174{
127 return (0);
128 for (p=reply; *p==' ' || *p=='\t'; ++p)
129 continue;
130 if (*p=='y' || *p=='Y')
131 return (1);
132 if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r')
133 return (0);
134 printf("Answer `yes' or `no': ");
135 }
136}
137
138int
139main(int argc, char **argv)
140{
175 int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1;
176 int rate = -1, gaplen = -1, secsize = -1, steps = -1;
177 int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0, confirm = 0;
178 int fd, c, i, track, error, tracks_per_dot, bytes_per_track, errs;
179 int fdopts;
180 const char *device, *suffix;
181 struct fd_type fdt;
141 enum fd_drivetype type;
142 struct fd_type fdt, newft, *fdtp;
143 struct stat sb;
182#define MAXPRINTERRS 10
183 struct fdc_status fdcs[MAXPRINTERRS];
144#define MAXPRINTERRS 10
145 struct fdc_status fdcs[MAXPRINTERRS];
146 int format, fill, quiet, verify, verify_only, confirm;
147 int fd, c, i, track, error, tracks_per_dot, bytes_per_track, errs;
148 int fdopts, flags;
149 char *fmtstring, *device;
150 const char *name, *descr;
184
151
185 while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qyvn")) != -1)
152 format = quiet = verify_only = confirm = 0;
153 verify = 1;
154 fill = 0xf6;
155 fmtstring = 0;
156
157 while((c = getopt(argc, argv, "F:f:nqs:vy")) != -1)
186 switch(c) {
158 switch(c) {
187 case 'f': /* format in kilobytes */
188 format = atoi(optarg);
159 case 'F': /* fill byte */
160 if (getnum(optarg, &fill)) {
161 fprintf(stderr,
162 "Bad argument %s to -F option; must be numeric\n",
163 optarg);
164 usage();
165 }
189 break;
190
166 break;
167
191 case 'c': /* # of cyls */
192 cyls = atoi(optarg);
168 case 'f': /* format in kilobytes */
169 if (getnum(optarg, &format)) {
170 fprintf(stderr,
171 "Bad argument %s to -f option; must be numeric\n",
172 optarg);
173 usage();
174 }
193 break;
194
175 break;
176
195 case 's': /* # of secs per track */
196 secs = atoi(optarg);
177 case 'n': /* don't verify */
178 verify = 0;
197 break;
198
179 break;
180
199 case 'h': /* # of heads */
200 heads = atoi(optarg);
201 break;
202
203 case 'r': /* transfer rate, kilobyte/sec */
204 rate = atoi(optarg);
205 break;
206
207 case 'g': /* length of GAP3 to format with */
208 gaplen = atoi(optarg);
209 break;
210
211 case 'S': /* sector size shift factor (1 << S)*128 */
212 secsize = atoi(optarg);
213 break;
214
215 case 'F': /* fill byte, C-like notation allowed */
216 fill = (int)strtol(optarg, (char **)0, 0);
217 break;
218
219 case 't': /* steps per track */
220 steps = atoi(optarg);
221 break;
222
223 case 'i': /* interleave factor */
224 intleave = atoi(optarg);
225 break;
226
227 case 'q':
181 case 'q': /* quiet */
228 quiet = 1;
229 break;
230
182 quiet = 1;
183 break;
184
231 case 'y':
232 confirm = 1;
185 case 's': /* format string with detailed options */
186 fmtstring = optarg;
233 break;
234
187 break;
188
235 case 'n':
236 verify = 0;
237 break;
238
239 case 'v':
189 case 'v': /* verify only */
240 verify = 1;
241 verify_only = 1;
242 break;
243
190 verify = 1;
191 verify_only = 1;
192 break;
193
244 case '?': default:
194 case 'y': /* confirm */
195 confirm = 1;
196 break;
197
198 default:
245 usage();
246 }
247
248 if(optind != argc - 1)
249 usage();
250
199 usage();
200 }
201
202 if(optind != argc - 1)
203 usage();
204
251 switch(format) {
252 default:
253 errx(2, "bad floppy size: %dK", format);
254 case -1: suffix = ""; break;
255 case 360: suffix = ".360"; break;
256 case 640: suffix = ".640"; break;
257 case 720: suffix = ".720"; break;
258 case 800: suffix = ".800"; break;
259 case 820: suffix = ".820"; break;
260 case 1200: suffix = ".1200"; break;
261 case 1232: suffix = ".1232"; break;
262 case 1440: suffix = ".1440"; break;
263 case 1480: suffix = ".1480"; break;
264 case 1720: suffix = ".1720"; break;
205 if (stat(argv[optind], &sb) == -1 && errno == ENOENT) {
206 /* try prepending _PATH_DEV */
207 device = malloc(strlen(argv[optind] + sizeof _PATH_DEV + 1));
208 if (device == 0)
209 errx(EX_UNAVAILABLE, "out of memory");
210 strcpy(device, _PATH_DEV);
211 strcat(device, argv[optind]);
212 if (stat(device, &sb) == -1) {
213 free(device);
214 device = argv[optind]; /* let it fail below */
215 }
216 } else {
217 device = argv[optind];
265 }
266
218 }
219
267 device = makename(argv[optind], suffix);
220 if ((fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
221 err(EX_OSERR, "open(%s)", device);
268
222
269 if((fd = open(device, O_RDWR)) < 0)
270 err(1, "%s", device);
271
223 /*
224 * Device initialization.
225 *
226 * First, get the device type descriptor. This tells us about
227 * the media geometry data we need to format a medium. It also
228 * lets us know quickly whether the device name actually points
229 * to a floppy disk drive.
230 *
231 * Then, obtain any drive options. We're mainly interested to
232 * see whether we're currently working on a device with media
233 * density autoselection (FDOPT_AUTOSEL). Then, we add the
234 * device option to tell the kernel not to log media errors,
235 * since we can handle them ourselves. If the device does
236 * media density autoselection, we then need to set the device
237 * type appropriately, since by opening with O_NONBLOCK we
238 * told the driver to bypass media autoselection (otherwise we
239 * wouldn't stand a chance to format an unformatted or damaged
240 * medium). We do not attempt to set the media type on any
241 * other devices since this is a privileged operation. For the
242 * same reason, specifying -f and -s options is only possible
243 * for autoselecting devices.
244 *
245 * Finally, we are ready to turn off O_NONBLOCK, and start to
246 * actually format something.
247 */
272 if(ioctl(fd, FD_GTYPE, &fdt) < 0)
248 if(ioctl(fd, FD_GTYPE, &fdt) < 0)
273 errx(1, "not a floppy disk: %s", device);
274 fdopts = FDOPT_NOERRLOG;
249 errx(EX_OSERR, "not a floppy disk: %s", device);
250 if (ioctl(fd, FD_GDTYPE, &type) == -1)
251 err(EX_OSERR, "ioctl(FD_GDTYPE)");
252 if (ioctl(fd, FD_GOPTS, &fdopts) == -1)
253 err(EX_OSERR, "ioctl(FD_GOPTS)");
254 fdopts |= FDOPT_NOERRLOG;
275 if (ioctl(fd, FD_SOPTS, &fdopts) == -1)
255 if (ioctl(fd, FD_SOPTS, &fdopts) == -1)
276 err(1, "ioctl(FD_SOPTS, FDOPT_NOERRLOG)");
277
278 switch(rate) {
279 case -1: break;
280 case 250: fdt.trans = FDC_250KBPS; break;
281 case 300: fdt.trans = FDC_300KBPS; break;
282 case 500: fdt.trans = FDC_500KBPS; break;
283 default:
284 errx(2, "invalid transfer rate: %d", rate);
256 err(EX_OSERR, "ioctl(FD_SOPTS, FDOPT_NOERRLOG)");
257 if (format) {
258 getname(type, &name, &descr);
259 fdtp = get_fmt(format, type);
260 if (fdtp == 0)
261 errx(EX_USAGE,
262 "unknown format %d KB for drive type %s",
263 format, name);
264 fdt = *fdtp;
285 }
265 }
266 if (fmtstring) {
267 parse_fmt(fmtstring, type, fdt, &newft);
268 fdt = newft;
269 }
270 if (fdopts & FDOPT_AUTOSEL) {
271 if (ioctl(fd, FD_STYPE, &fdt) < 0)
272 err(EX_OSERR, "ioctl(FD_STYPE)");
273 } else if (fmtstring || format) {
274 errx(EX_USAGE,
275 "-f fmt or -s fmtstr is only allowed for autoselecting devices");
276 }
277 if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
278 err(EX_OSERR, "fcntl(F_GETFL)");
279 flags &= ~O_NONBLOCK;
280 if (fcntl(fd, F_SETFL, flags) == -1)
281 err(EX_OSERR, "fcntl(F_SETFL)");
286
282
287 if (cyls >= 0) fdt.tracks = cyls;
288 if (secs >= 0) fdt.sectrac = secs;
289 if (fdt.sectrac > FD_MAX_NSEC)
290 errx(2, "too many sectors per track, max value is %d", FD_MAX_NSEC);
291 if (heads >= 0) fdt.heads = heads;
292 if (gaplen >= 0) fdt.f_gap = gaplen;
293 if (secsize >= 0) fdt.secsize = secsize;
294 if (steps >= 0) fdt.steptrac = steps;
295 if (intleave >= 0) fdt.f_inter = intleave;
283 bytes_per_track = fdt.sectrac * (128 << fdt.secsize);
296
284
297 bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128;
298
299 /* XXX 20/40 = 0.5 */
300 tracks_per_dot = (fdt.tracks * fdt.heads + 20) / 40;
301
302 if (verify_only) {
303 if(!quiet)
304 printf("Verify %dK floppy `%s'.\n",
305 fdt.tracks * fdt.heads * bytes_per_track / 1024,
306 device);
307 }
308 else if(!quiet && !confirm) {
309 printf("Format %dK floppy `%s'? (y/n): ",
310 fdt.tracks * fdt.heads * bytes_per_track / 1024,
311 device);
285 /* XXX 20/40 = 0.5 */
286 tracks_per_dot = (fdt.tracks * fdt.heads + 20) / 40;
287
288 if (verify_only) {
289 if(!quiet)
290 printf("Verify %dK floppy `%s'.\n",
291 fdt.tracks * fdt.heads * bytes_per_track / 1024,
292 device);
293 }
294 else if(!quiet && !confirm) {
295 printf("Format %dK floppy `%s'? (y/n): ",
296 fdt.tracks * fdt.heads * bytes_per_track / 1024,
297 device);
312 if(! yes ()) {
298 if(!yes()) {
313 printf("Not confirmed.\n");
299 printf("Not confirmed.\n");
314 return 3;
300 return (EX_UNAVAILABLE);
315 }
316 }
317
318 /*
319 * Formatting.
320 */
321 if(!quiet) {
322 printf("Processing ");

--- 4 unchanged lines hidden (view full) ---

327 }
328
329 error = errs = 0;
330
331 for (track = 0; track < fdt.tracks * fdt.heads; track++) {
332 if (!verify_only) {
333 format_track(fd, track / fdt.heads, fdt.sectrac,
334 track % fdt.heads, fdt.trans, fdt.f_gap,
301 }
302 }
303
304 /*
305 * Formatting.
306 */
307 if(!quiet) {
308 printf("Processing ");

--- 4 unchanged lines hidden (view full) ---

313 }
314
315 error = errs = 0;
316
317 for (track = 0; track < fdt.tracks * fdt.heads; track++) {
318 if (!verify_only) {
319 format_track(fd, track / fdt.heads, fdt.sectrac,
320 track % fdt.heads, fdt.trans, fdt.f_gap,
335 fdt.secsize, fill, fdt.f_inter);
321 fdt.secsize, fill, fdt.f_inter,
322 track % fdt.heads? fdt.offset_side2: 0);
336 if(!quiet && !((track + 1) % tracks_per_dot)) {
337 putchar('F');
338 fflush(stdout);
339 }
340 }
341 if (verify) {
342 if (verify_track(fd, track, bytes_per_track) < 0) {
343 error = 1;
344 if (errs < MAXPRINTERRS && errno == EIO) {
345 if (ioctl(fd, FD_GSTAT, fdcs + errs) ==
346 -1)
323 if(!quiet && !((track + 1) % tracks_per_dot)) {
324 putchar('F');
325 fflush(stdout);
326 }
327 }
328 if (verify) {
329 if (verify_track(fd, track, bytes_per_track) < 0) {
330 error = 1;
331 if (errs < MAXPRINTERRS && errno == EIO) {
332 if (ioctl(fd, FD_GSTAT, fdcs + errs) ==
333 -1)
347 errx(1,
334 errx(EX_IOERR,
348 "floppy IO error, but no FDC status");
349 errs++;
350 }
351 }
352 if(!quiet && !((track + 1) % tracks_per_dot)) {
353 if (!verify_only)
354 putchar('\b');
355 if (error) {

--- 28 unchanged lines hidden ---
335 "floppy IO error, but no FDC status");
336 errs++;
337 }
338 }
339 if(!quiet && !((track + 1) % tracks_per_dot)) {
340 if (!verify_only)
341 putchar('\b');
342 if (error) {

--- 28 unchanged lines hidden ---