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