fs.h --> ufs from sys
[unix-history] / usr / src / usr.sbin / bad144 / bad144.c
CommitLineData
761330fe 1/*
bc78840a
MK
2 * Copyright (c) 1980,1986,1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
761330fe
DF
16 */
17
18#ifndef lint
19char copyright[] =
bc78840a 20"@(#) Copyright (c) 1980,1986,1988 Regents of the University of California.\n\
761330fe
DF
21 All rights reserved.\n";
22#endif not lint
23
6cb1d6d5 24#ifndef lint
ac6387a5 25static char sccsid[] = "@(#)bad144.c 5.17 (Berkeley) %G%";
761330fe 26#endif not lint
52ff80b5
BJ
27
28/*
29 * bad144
30 *
31 * This program prints and/or initializes a bad block record for a pack,
32 * in the format used by the DEC standard 144.
d2b6f994
MK
33 * It can also add bad sector(s) to the record, moving the sector
34 * replacements as necessary.
52ff80b5
BJ
35 *
36 * It is preferable to write the bad information with a standard formatter,
d2b6f994 37 * but this program will do.
ace59b28 38 *
6cb1d6d5 39 * RP06 sectors are marked as bad by inverting the format bit in the
d2b6f994 40 * header; on other drives the valid-sector bit is cleared.
52ff80b5 41 */
01de500b 42#include <sys/param.h>
52ff80b5 43#include <sys/dkbad.h>
ace59b28 44#include <sys/ioctl.h>
ac6387a5 45#include <ufs/fs.h>
6cb1d6d5 46#include <sys/file.h>
7abf8d65 47#include <sys/disklabel.h>
347d81fa 48
52ff80b5 49#include <stdio.h>
7abf8d65 50#include <paths.h>
52ff80b5 51
7bfa7599 52#define RETRIES 10 /* number of retries on reading old sectors */
ce43fbef 53#define RAWPART "c" /* disk partition containing badsector tables */
7bfa7599
MK
54
55int fflag, add, copy, verbose, nflag;
d2b6f994 56int compare();
ce43fbef 57int dups;
d44874de 58int badfile = -1; /* copy of badsector table to use, -1 if any */
01de500b 59#define MAXSECSIZE 1024
01de500b
MK
60struct dkbad curbad, oldbad;
61#define DKBAD_MAGIC 0
01de500b
MK
62
63char label[BBSIZE];
d2b6f994 64daddr_t size, getold(), badsn();
01de500b 65struct disklabel *dp;
d2b6f994 66char name[BUFSIZ];
5d026fbb 67char *malloc();
aef5a985 68off_t lseek();
52ff80b5
BJ
69
70main(argc, argv)
71 int argc;
6cb1d6d5 72 char *argv[];
52ff80b5 73{
52ff80b5 74 register struct bt_bad *bt;
d2b6f994
MK
75 daddr_t sn, bn[126];
76 int i, f, nbad, new, bad, errs;
52ff80b5
BJ
77
78 argc--, argv++;
d2b6f994
MK
79 while (argc > 0 && **argv == '-') {
80 (*argv)++;
81 while (**argv) {
82 switch (**argv) {
01de500b 83#if vax
d2b6f994
MK
84 case 'f':
85 fflag++;
86 break;
01de500b 87#endif
d2b6f994
MK
88 case 'a':
89 add++;
90 break;
91 case 'c':
92 copy++;
93 break;
94 case 'v':
95 verbose++;
96 break;
7bfa7599
MK
97 case 'n':
98 nflag++;
aef5a985 99 verbose++;
7bfa7599 100 break;
01de500b 101 default:
d44874de
MK
102 if (**argv >= '0' && **argv <= '4') {
103 badfile = **argv - '0';
104 break;
105 }
01de500b 106 goto usage;
d2b6f994
MK
107 }
108 (*argv)++;
109 }
ace59b28 110 argc--, argv++;
ace59b28 111 }
01de500b
MK
112 if (argc < 1) {
113usage:
ace59b28 114 fprintf(stderr,
01de500b 115 "usage: bad144 [ -f ] disk [ snum [ bn ... ] ]\n");
d2b6f994 116 fprintf(stderr,
ce43fbef 117 "to read or overwrite bad-sector table, e.g.: bad144 hp0\n");
d2b6f994 118 fprintf(stderr,
01de500b 119 "or bad144 -a [ -f ] [ -c ] disk bn ...\n");
d2b6f994
MK
120 fprintf(stderr, "where options are:\n");
121 fprintf(stderr, "\t-a add new bad sectors to the table\n");
122 fprintf(stderr, "\t-f reformat listed sectors as bad\n");
123 fprintf(stderr, "\t-c copy original sector to replacement\n");
347d81fa
SL
124 exit(1);
125 }
01de500b 126 if (argv[0][0] != '/')
7abf8d65 127 (void)sprintf(name, "%s/r%s%s", _PATH_DEV, argv[0], RAWPART);
01de500b
MK
128 else
129 strcpy(name, argv[0]);
130 f = open(name, argc == 1? O_RDONLY : O_RDWR);
131 if (f < 0)
132 Perror(name);
133 if (read(f, label, sizeof(label)) < 0)
134 Perror("read");
135 for (dp = (struct disklabel *)(label + LABELOFFSET);
136 dp < (struct disklabel *)
137 (label + sizeof(label) - sizeof(struct disklabel));
138 dp = (struct disklabel *)((char *)dp + 64))
139 if (dp->d_magic == DISKMAGIC && dp->d_magic2 == DISKMAGIC)
140 break;
141 if (dp->d_magic != DISKMAGIC || dp->d_magic2 != DISKMAGIC) {
142 fprintf(stderr, "Bad pack magic number (pack is unlabeled)\n");
52ff80b5
BJ
143 exit(1);
144 }
01de500b
MK
145 if (dp->d_secsize > MAXSECSIZE || dp->d_secsize <= 0) {
146 fprintf(stderr, "Disk sector size too large/small (%d)\n",
147 dp->d_secsize);
148 exit(7);
149 }
347d81fa 150 size = dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders;
01de500b
MK
151 argc--;
152 argv++;
52ff80b5 153 if (argc == 0) {
bafbe71a 154 sn = getold(f, &oldbad);
95317c9f 155 printf("bad block information at sector %d in %s:\n",
d2b6f994 156 sn, name);
bafbe71a
MK
157 printf("cartridge serial number: %d(10)\n", oldbad.bt_csn);
158 switch (oldbad.bt_flag) {
347d81fa 159
0674a1df 160 case (u_short)-1:
52ff80b5
BJ
161 printf("alignment cartridge\n");
162 break;
347d81fa 163
01de500b 164 case DKBAD_MAGIC:
52ff80b5 165 break;
347d81fa 166
52ff80b5 167 default:
bafbe71a 168 printf("bt_flag=%x(16)?\n", oldbad.bt_flag);
52ff80b5
BJ
169 break;
170 }
bafbe71a 171 bt = oldbad.bt_bad;
d2b6f994 172 for (i = 0; i < 126; i++) {
52ff80b5
BJ
173 bad = (bt->bt_cyl<<16) + bt->bt_trksec;
174 if (bad < 0)
175 break;
d2b6f994 176 printf("sn=%d, cn=%d, tn=%d, sn=%d\n", badsn(bt),
52ff80b5
BJ
177 bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
178 bt++;
179 }
bafbe71a 180 (void) checkold(&oldbad);
6cb1d6d5 181 exit(0);
52ff80b5 182 }
d2b6f994
MK
183 if (add) {
184 /*
185 * Read in the old badsector table.
186 * Verify that it makes sense, and the bad sectors
187 * are in order. Copy the old table to the new one.
188 */
189 (void) getold(f, &oldbad);
bafbe71a 190 i = checkold(&oldbad);
d2b6f994 191 if (verbose)
01de500b 192 printf("Had %d bad sectors, adding %d\n", i, argc);
d2b6f994
MK
193 if (i + argc > 126) {
194 printf("bad144: not enough room for %d more sectors\n",
195 argc);
196 printf("limited to 126 by information format\n");
197 exit(1);
198 }
01de500b 199 curbad = oldbad;
d2b6f994 200 } else {
01de500b 201 curbad.bt_csn = atoi(*argv++);
d2b6f994 202 argc--;
01de500b
MK
203 curbad.bt_mbz = 0;
204 curbad.bt_flag = DKBAD_MAGIC;
d2b6f994
MK
205 if (argc > 126) {
206 printf("bad144: too many bad sectors specified\n");
207 printf("limited to 126 by information format\n");
208 exit(1);
209 }
210 i = 0;
52ff80b5
BJ
211 }
212 errs = 0;
d2b6f994 213 new = argc;
52ff80b5 214 while (argc > 0) {
d2b6f994 215 daddr_t sn = atoi(*argv++);
52ff80b5 216 argc--;
347d81fa 217 if (sn < 0 || sn >= size) {
01de500b
MK
218 printf("%d: out of range [0,%d) for disk %s\n",
219 sn, size, dp->d_typename);
52ff80b5 220 errs++;
d2b6f994 221 continue;
52ff80b5 222 }
d2b6f994 223 bn[i] = sn;
01de500b 224 curbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks);
347d81fa 225 sn %= (dp->d_nsectors*dp->d_ntracks);
01de500b 226 curbad.bt_bad[i].bt_trksec =
347d81fa 227 ((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors);
52ff80b5
BJ
228 i++;
229 }
d2b6f994
MK
230 if (errs)
231 exit(1);
232 nbad = i;
52ff80b5 233 while (i < 126) {
01de500b
MK
234 curbad.bt_bad[i].bt_trksec = -1;
235 curbad.bt_bad[i].bt_cyl = -1;
52ff80b5
BJ
236 i++;
237 }
d2b6f994
MK
238 if (add) {
239 /*
240 * Sort the new bad sectors into the list.
241 * Then shuffle the replacement sectors so that
242 * the previous bad sectors get the same replacement data.
243 */
01de500b 244 qsort((char *)curbad.bt_bad, nbad, sizeof (struct bt_bad),
aef5a985 245 compare);
ce43fbef
MK
246 if (dups) {
247 fprintf(stderr,
248"bad144: bad sectors have been duplicated; can't add existing sectors\n");
249 exit(3);
250 }
d2b6f994
MK
251 shift(f, nbad, nbad-new);
252 }
d44874de
MK
253 if (badfile == -1)
254 i = 0;
255 else
256 i = badfile * 2;
257 for (; i < 10 && i < dp->d_nsectors; i += 2) {
d2b6f994
MK
258 if (lseek(f, dp->d_secsize * (size - dp->d_nsectors + i),
259 L_SET) < 0)
260 Perror("lseek");
261 if (verbose)
262 printf("write badsect file at %d\n",
263 size - dp->d_nsectors + i);
01de500b
MK
264 if (nflag == 0 && write(f, (caddr_t)&curbad, sizeof(curbad)) !=
265 sizeof(curbad)) {
d2b6f994 266 char msg[80];
aef5a985
JL
267 (void)sprintf(msg, "bad144: write bad sector file %d",
268 i/2);
d2b6f994
MK
269 perror(msg);
270 }
d44874de
MK
271 if (badfile != -1)
272 break;
d2b6f994 273 }
01de500b
MK
274#ifdef vax
275 if (nflag == 0 && fflag)
7bfa7599 276 for (i = nbad - new; i < nbad; i++)
d2b6f994 277 format(f, bn[i]);
9ffd8bdd
MK
278#endif
279#ifdef DIOCSBAD
280 if (nflag == 0 && ioctl(f, DIOCSBAD, (caddr_t)&curbad) < 0)
281 fprintf(stderr,
282 "Can't sync bad-sector file; reboot for changes to take effect\n");
01de500b 283#endif
d2b6f994
MK
284 exit(0);
285}
ace59b28 286
d2b6f994
MK
287daddr_t
288getold(f, bad)
289struct dkbad *bad;
290{
291 register int i;
292 daddr_t sn;
293 char msg[80];
294
d44874de
MK
295 if (badfile == -1)
296 i = 0;
297 else
298 i = badfile * 2;
299 for (; i < 10 && i < dp->d_nsectors; i += 2) {
d2b6f994
MK
300 sn = size - dp->d_nsectors + i;
301 if (lseek(f, sn * dp->d_secsize, L_SET) < 0)
302 Perror("lseek");
01de500b 303 if (read(f, (char *) bad, dp->d_secsize) == dp->d_secsize) {
d2b6f994
MK
304 if (i > 0)
305 printf("Using bad-sector file %d\n", i/2);
306 return(sn);
ace59b28 307 }
01de500b 308 (void)sprintf(msg, "bad144: read bad sector file at sn %d", sn);
d2b6f994 309 perror(msg);
d44874de
MK
310 if (badfile != -1)
311 break;
d2b6f994 312 }
01de500b 313 fprintf(stderr, "bad144: %s: can't read bad block info\n", name);
d2b6f994 314 exit(1);
aef5a985 315 /*NOTREACHED*/
d2b6f994
MK
316}
317
318checkold()
319{
320 register int i;
321 register struct bt_bad *bt;
322 daddr_t sn, lsn;
7bfa7599 323 int errors = 0, warned = 0;
d2b6f994 324
01de500b 325 if (oldbad.bt_flag != DKBAD_MAGIC) {
d2b6f994
MK
326 fprintf(stderr, "bad144: %s: bad flag in bad-sector table\n",
327 name);
7bfa7599 328 errors++;
d2b6f994
MK
329 }
330 if (oldbad.bt_mbz != 0) {
331 fprintf(stderr, "bad144: %s: bad magic number\n", name);
7bfa7599 332 errors++;
d2b6f994 333 }
d2b6f994
MK
334 bt = oldbad.bt_bad;
335 for (i = 0; i < 126; i++, bt++) {
bafbe71a 336 if (bt->bt_cyl == 0xffff && bt->bt_trksec == 0xffff)
d2b6f994
MK
337 break;
338 if ((bt->bt_cyl >= dp->d_ncylinders) ||
339 ((bt->bt_trksec >> 8) >= dp->d_ntracks) ||
340 ((bt->bt_trksec & 0xff) >= dp->d_nsectors)) {
7bfa7599
MK
341 fprintf(stderr,
342 "bad144: cyl/trk/sect out of range in existing entry: ");
343 fprintf(stderr, "sn=%d, cn=%d, tn=%d, sn=%d\n",
344 badsn(bt), bt->bt_cyl, bt->bt_trksec>>8,
345 bt->bt_trksec & 0xff);
346 errors++;
d2b6f994
MK
347 }
348 sn = (bt->bt_cyl * dp->d_ntracks +
349 (bt->bt_trksec >> 8)) *
350 dp->d_nsectors + (bt->bt_trksec & 0xff);
ce43fbef 351 if (i > 0 && sn < lsn && !warned) {
bafbe71a
MK
352 fprintf(stderr,
353 "bad144: bad sector file is out of order\n");
7bfa7599
MK
354 errors++;
355 warned++;
d2b6f994 356 }
ce43fbef
MK
357 if (i > 0 && sn == lsn) {
358 fprintf(stderr,
bafbe71a
MK
359 "bad144: bad sector file contains duplicates (sn %d)\n",
360 sn);
ce43fbef
MK
361 errors++;
362 }
d2b6f994
MK
363 lsn = sn;
364 }
7bfa7599
MK
365 if (errors)
366 exit(1);
367 return (i);
d2b6f994
MK
368}
369
370/*
371 * Move the bad sector replacements
372 * to make room for the new bad sectors.
373 * new is the new number of bad sectors, old is the previous count.
374 */
375shift(f, new, old)
376{
377 daddr_t repl;
378
379 /*
380 * First replacement is last sector of second-to-last track.
381 */
382 repl = size - dp->d_nsectors - 1;
383 new--; old--;
384 while (new >= 0 && new != old) {
385 if (old < 0 ||
01de500b 386 compare(&curbad.bt_bad[new], &oldbad.bt_bad[old]) > 0) {
d2b6f994
MK
387 /*
388 * Insert new replacement here-- copy original
389 * sector if requested and possible,
390 * otherwise write a zero block.
391 */
392 if (!copy ||
01de500b 393 !blkcopy(f, badsn(&curbad.bt_bad[new]), repl - new))
d2b6f994
MK
394 blkzero(f, repl - new);
395 } else {
396 if (blkcopy(f, repl - old, repl - new) == 0)
397 fprintf(stderr,
398 "Can't copy replacement sector %d to %d\n",
399 repl-old, repl-new);
400 old--;
401 }
402 new--;
403 }
404}
405
5d026fbb
MK
406char *buf;
407
d2b6f994
MK
408/*
409 * Copy disk sector s1 to s2.
410 */
411blkcopy(f, s1, s2)
412daddr_t s1, s2;
413{
7bfa7599 414 register tries, n;
d2b6f994 415
5d026fbb 416 if (buf == (char *)NULL) {
aef5a985 417 buf = malloc((unsigned)dp->d_secsize);
5d026fbb
MK
418 if (buf == (char *)NULL) {
419 fprintf(stderr, "Out of memory\n");
420 exit(20);
421 }
422 }
d44874de
MK
423 for (tries = 0; tries < RETRIES; tries++) {
424 if (lseek(f, dp->d_secsize * s1, L_SET) < 0)
425 Perror("lseek");
aef5a985 426 if ((n = read(f, buf, dp->d_secsize)) == dp->d_secsize)
7bfa7599 427 break;
d44874de 428 }
aef5a985 429 if (n != dp->d_secsize) {
7bfa7599
MK
430 fprintf(stderr, "bad144: can't read sector, %d: ", s1);
431 if (n < 0)
aef5a985 432 perror((char *)0);
d2b6f994
MK
433 return(0);
434 }
435 if (lseek(f, dp->d_secsize * s2, L_SET) < 0)
436 Perror("lseek");
437 if (verbose)
438 printf("copying %d to %d\n", s1, s2);
aef5a985 439 if (nflag == 0 && write(f, buf, dp->d_secsize) != dp->d_secsize) {
d2b6f994 440 fprintf(stderr,
7bfa7599 441 "bad144: can't write replacement sector, %d: ", s2);
aef5a985 442 perror((char *)0);
d2b6f994
MK
443 return(0);
444 }
445 return(1);
446}
447
5d026fbb 448char *zbuf;
d2b6f994
MK
449
450blkzero(f, sn)
451daddr_t sn;
452{
453
5d026fbb 454 if (zbuf == (char *)NULL) {
aef5a985 455 zbuf = malloc((unsigned)dp->d_secsize);
5d026fbb
MK
456 if (zbuf == (char *)NULL) {
457 fprintf(stderr, "Out of memory\n");
458 exit(20);
459 }
460 }
d2b6f994
MK
461 if (lseek(f, dp->d_secsize * sn, L_SET) < 0)
462 Perror("lseek");
463 if (verbose)
464 printf("zeroing %d\n", sn);
aef5a985 465 if (nflag == 0 && write(f, zbuf, dp->d_secsize) != dp->d_secsize) {
d2b6f994 466 fprintf(stderr,
7bfa7599 467 "bad144: can't write replacement sector, %d: ", sn);
aef5a985 468 perror((char *)0);
d2b6f994
MK
469 }
470}
471
472compare(b1, b2)
473register struct bt_bad *b1, *b2;
474{
475 if (b1->bt_cyl > b2->bt_cyl)
476 return(1);
477 if (b1->bt_cyl < b2->bt_cyl)
478 return(-1);
ce43fbef
MK
479 if (b1->bt_trksec == b2->bt_trksec)
480 dups++;
5d026fbb 481 return (b1->bt_trksec - b2->bt_trksec);
d2b6f994
MK
482}
483
484daddr_t
485badsn(bt)
486register struct bt_bad *bt;
487{
488 return ((bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * dp->d_nsectors
489 + (bt->bt_trksec&0xff));
52ff80b5 490}
ace59b28 491
01de500b
MK
492#ifdef vax
493#include <machine/dkio.h>
494
ace59b28
SL
495struct rp06hdr {
496 short h_cyl;
497 short h_trksec;
498 short h_key1;
499 short h_key2;
500 char h_data[512];
501#define RP06_FMT 010000 /* 1 == 16 bit, 0 == 18 bit */
502};
6cb1d6d5
SL
503
504/*
505 * Most massbus and unibus drives
506 * have headers of this form
507 */
508struct hpuphdr {
509 u_short hpup_cyl;
7bfa7599
MK
510 u_char hpup_sect;
511 u_char hpup_track;
6cb1d6d5
SL
512 char hpup_data[512];
513#define HPUP_OKSECT 0xc000 /* this normally means sector is good */
7bfa7599 514#define HPUP_16BIT 0x1000 /* 1 == 16 bit format */
6cb1d6d5 515};
7bfa7599 516int rp06format(), hpupformat();
ace59b28
SL
517
518struct formats {
519 char *f_name; /* disk name */
520 int f_bufsize; /* size of sector + header */
6cb1d6d5 521 int f_bic; /* value to bic in hpup_cyl */
ace59b28
SL
522 int (*f_routine)(); /* routine for special handling */
523} formats[] = {
7bfa7599
MK
524 { "rp06", sizeof (struct rp06hdr), RP06_FMT, rp06format },
525 { "eagle", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
526 { "capricorn", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
527 { "rm03", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
528 { "rm05", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
529 { "9300", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
530 { "9766", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
6cb1d6d5 531 { 0, 0, 0, 0 }
ace59b28
SL
532};
533
aef5a985 534/*ARGSUSED*/
7bfa7599 535hpupformat(fp, dp, blk, buf, count)
aef5a985 536 struct formats *fp;
01de500b 537 struct disklabel *dp;
7bfa7599
MK
538 daddr_t blk;
539 char *buf;
540 int count;
541{
542 struct hpuphdr *hdr = (struct hpuphdr *)buf;
543 int sect;
544
545 if (count < sizeof(struct hpuphdr)) {
546 hdr->hpup_cyl = (HPUP_OKSECT | HPUP_16BIT) |
547 (blk / (dp->d_nsectors * dp->d_ntracks));
548 sect = blk % (dp->d_nsectors * dp->d_ntracks);
549 hdr->hpup_track = (u_char)(sect / dp->d_nsectors);
550 hdr->hpup_sect = (u_char)(sect % dp->d_nsectors);
551 }
552 return (0);
553}
554
aef5a985 555/*ARGSUSED*/
7bfa7599 556rp06format(fp, dp, blk, buf, count)
aef5a985 557 struct formats *fp;
01de500b 558 struct disklabel *dp;
7bfa7599
MK
559 daddr_t blk;
560 char *buf;
561 int count;
562{
563
564 if (count < sizeof(struct rp06hdr)) {
565 fprintf(stderr, "Can't read header on blk %d, can't reformat\n",
566 blk);
567 return (-1);
568 }
569 return (0);
570}
571
d2b6f994 572format(fd, blk)
ace59b28 573 int fd;
ace59b28
SL
574 daddr_t blk;
575{
576 register struct formats *fp;
7bfa7599
MK
577 static char *buf;
578 static char bufsize;
9ffd8bdd 579 struct format_op fop;
7bfa7599 580 int n;
ace59b28
SL
581
582 for (fp = formats; fp->f_name; fp++)
01de500b 583 if (strcmp(dp->d_typename, fp->f_name) == 0)
ace59b28
SL
584 break;
585 if (fp->f_name == 0) {
586 fprintf(stderr, "bad144: don't know how to format %s disks\n",
01de500b 587 dp->d_typename);
ace59b28
SL
588 exit(2);
589 }
7bfa7599
MK
590 if (buf && bufsize < fp->f_bufsize) {
591 free(buf);
592 buf = NULL;
593 }
594 if (buf == NULL)
aef5a985 595 buf = malloc((unsigned)fp->f_bufsize);
ace59b28
SL
596 if (buf == NULL) {
597 fprintf(stderr, "bad144: can't allocate sector buffer\n");
598 exit(3);
599 }
7bfa7599 600 bufsize = fp->f_bufsize;
ace59b28
SL
601 /*
602 * Here we do the actual formatting. All we really
603 * do is rewrite the sector header and flag the bad sector
604 * according to the format table description. If a special
605 * purpose format routine is specified, we allow it to
606 * process the sector as well.
607 */
d2b6f994
MK
608 if (verbose)
609 printf("format blk %d\n", blk);
9ffd8bdd
MK
610 bzero((char *)&fop, sizeof(fop));
611 fop.df_buf = buf;
612 fop.df_count = fp->f_bufsize;
613 fop.df_startblk = blk;
614 bzero(buf, fp->f_bufsize);
615 if (ioctl(fd, DIOCRFORMAT, &fop) < 0)
616 perror("bad144: read format");
617 if (fp->f_routine &&
618 (*fp->f_routine)(fp, dp, blk, buf, fop.df_count) != 0)
619 return;
6cb1d6d5
SL
620 if (fp->f_bic) {
621 struct hpuphdr *xp = (struct hpuphdr *)buf;
622
623 xp->hpup_cyl &= ~fp->f_bic;
624 }
7bfa7599
MK
625 if (nflag)
626 return;
9ffd8bdd
MK
627 bzero((char *)&fop, sizeof(fop));
628 fop.df_buf = buf;
629 fop.df_count = fp->f_bufsize;
630 fop.df_startblk = blk;
631 if (ioctl(fd, DIOCWFORMAT, &fop) < 0)
632 Perror("write format");
633 if (fop.df_count != fp->f_bufsize) {
d2b6f994 634 char msg[80];
aef5a985 635 (void)sprintf(msg, "bad144: write format %d", blk);
d2b6f994
MK
636 perror(msg);
637 }
ace59b28 638}
01de500b 639#endif
ace59b28 640
6cb1d6d5
SL
641Perror(op)
642 char *op;
ace59b28
SL
643{
644
6cb1d6d5
SL
645 fprintf(stderr, "bad144: "); perror(op);
646 exit(4);
ace59b28 647}