home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / bad144 / bad144.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  16.3 KB  |  663 lines

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