home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / unix / bsd / 4751 < prev    next >
Encoding:
Text File  |  1992-08-26  |  19.5 KB  |  723 lines

  1. Path: sparky!uunet!dtix!darwin.sura.net!jvnc.net!yale.edu!yale!gumby!destroyer!ncar!ico!jbsys.com!jbev
  2. From: jbev@iscden.jbsys.com (Jim Bevier - J B Systems)
  3. Newsgroups: comp.unix.bsd
  4. Subject: Bad sector scanning program!
  5. Message-ID: <1992Aug26.234622.15781@jbsys.com>
  6. Date: 26 Aug 92 23:46:22 GMT
  7. Sender: jbev@jbsys.com (Jim Bevier - J B Systems)
  8. Organization: J B Systems on HiPeak, Morrison, Co.
  9. Lines: 712
  10.  
  11. I have updated bad144.c to recognize a -s option.  This will scan
  12. the 386bsd partition (rwd0c).  It will list the sector numbers that
  13. you can then use to input to bad144 with the -a -c options.  I 
  14. thought this might be useful to others.  The best time to run
  15. this scan is after you have written the label to the disk, but
  16. before making the newfs.  However, it can be run at anytime.
  17. I plan to update these changes later to automatically add any
  18. defects found to the bad sector table.  For now, it just scans.
  19. It reads a track at a time until an error is found.  It then
  20. rereads the track to find the defective sector.  It also prints
  21. out your disk label table showing offset and size in both sectors
  22. and cylinders.  Type bad144 -s wd0.  Here is what the output looks like:
  23.  
  24. device /dev/rwd0 is a ESDI disk
  25. rwd0a ROOT   offset:  196365 ( 247), size:  508800 ( 640), type = 4.2BSD
  26. rwd0b SWAP   offset:  705165 ( 887), size:   63600 (  80), type = swap
  27. rwd0c 386BSD offset:  196365 ( 247), size: 1120155 (1409), type = unused
  28. rwd0d DISK   offset:       0 (   0), size: 1316520 (1656), type = unused
  29. rwd0e DOS?   offset:       0 (   0), size:  196365 ( 247), type = unused
  30. rwd0h USR    offset:  768765 ( 967), size:  546165 ( 687), type = 4.2BSD
  31. secs: 53, tracks: 15, cyl: 1656, sec/cyl: 795, start: 196365, end: 1316341
  32. Starting scan of /dev/rwd0c at cylinder 247
  33.  247( 196365)
  34.  
  35. The scan stops before the bad track table.  That is the end of patition c
  36. less 1 cylinder plus 126 sectors.
  37.  
  38. The bad tracking will not work without a fix to wd.c.  This was posted
  39. earlier to the net.  Apply this patch:
  40.  
  41. ---- snip snip ----
  42. *** wd.c.ORIG    Wed Aug 19 15:43:21 1992
  43. --- wd.c    Wed Aug 19 16:16:18 1992
  44. ***************
  45. *** 402,407 ****
  46. --- 402,408 ----
  47.               cylin = blknum / secpercyl;
  48.               head = (blknum % secpercyl) / secpertrk;
  49.               sector = blknum % secpertrk;
  50. +             du->dk_flags |= DKFL_SINGLE;
  51.   #ifdef    WDDEBUG
  52.                   printf("new = %d\n", blknum);
  53.   #endif
  54. ---- snip snip ----
  55. from:
  56. UUCP: {hplabs!hp-sdd ucsd nosc}!crash!fpm
  57. ARPA: crash!fpm@nosc.mil
  58. INET: fpm@crash.cts.com
  59.  
  60. Following is the updated bad144.c program.  Let me know what you think.
  61. I think this will also work for a second disk drive.  If you find any
  62. errors or think of any other changes, let me know.
  63.  
  64. Cheers,
  65.  
  66. Jim Bevier
  67. jbev@jbsys.com
  68.  
  69. ---- snip snip ----
  70. /*
  71.  * Copyright (c) 1980,1986,1988 Regents of the University of California.
  72.  * All rights reserved.
  73.  *
  74.  * Redistribution and use in source and binary forms, with or without
  75.  * modification, are permitted provided that the following conditions
  76.  * are met:
  77.  * 1. Redistributions of source code must retain the above copyright
  78.  *    notice, this list of conditions and the following disclaimer.
  79.  * 2. Redistributions in binary form must reproduce the above copyright
  80.  *    notice, this list of conditions and the following disclaimer in the
  81.  *    documentation and/or other materials provided with the distribution.
  82.  * 3. All advertising materials mentioning features or use of this software
  83.  *    must display the following acknowledgement:
  84.  *    This product includes software developed by the University of
  85.  *    California, Berkeley and its contributors.
  86.  * 4. Neither the name of the University nor the names of its contributors
  87.  *    may be used to endorse or promote products derived from this software
  88.  *    without specific prior written permission.
  89.  *
  90.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  91.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  92.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  93.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  94.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  95.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  96.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  97.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  98.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  99.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  100.  * SUCH DAMAGE.
  101.  */
  102.  
  103. #ifndef lint
  104. char copyright[] =
  105. "@(#) Copyright (c) 1980,1986,1988 Regents of the University of California.\n\
  106.  All rights reserved.\n";
  107. #endif not lint
  108.  
  109. #ifndef lint
  110. static char sccsid[] = "@(#)bad144.c    5.19 (Berkeley) 4/11/91";
  111. #endif not lint
  112.  
  113. /*
  114.  * bad144
  115.  *
  116.  * This program prints and/or initializes a bad block record for a pack,
  117.  * in the format used by the DEC standard 144.
  118.  * It can also add bad sector(s) to the record, moving the sector
  119.  * replacements as necessary.
  120.  *
  121.  * It is preferable to write the bad information with a standard formatter,
  122.  * but this program will do.
  123.  * 
  124.  * RP06 sectors are marked as bad by inverting the format bit in the
  125.  * header; on other drives the valid-sector bit is cleared.
  126.  */
  127.  
  128. #define DKTYPENAMES
  129.  
  130. #include <sys/param.h>
  131. #include <sys/dkbad.h>
  132. #include <sys/ioctl.h>
  133. #include <ufs/fs.h>
  134. #include <sys/file.h>
  135. #include <sys/disklabel.h>
  136.  
  137. #include <stdio.h>
  138. #include <paths.h>
  139. #include <string.h>
  140.  
  141. #define RETRIES    10        /* number of retries on reading old sectors */
  142. #ifdef __386BSD__
  143. #define    RAWPART    "d"        /* disk partition containing badsector tables */
  144. #else
  145. #define    RAWPART    "c"        /* disk partition containing badsector tables */
  146. #endif
  147.  
  148. int    fflag, add, copy, verbose, nflag, sflag;
  149. int    compare();
  150. int    dups;
  151. int    badfile = -1;        /* copy of badsector table to use, -1 if any */
  152. #define MAXSECSIZE    1024
  153. struct    dkbad curbad, oldbad;
  154. #define    DKBAD_MAGIC    0x4321
  155.  
  156. char *buf;
  157. char    label[BBSIZE];
  158. daddr_t    size, getold(), badsn();
  159. struct    disklabel *dp;
  160. char    name[BUFSIZ];
  161. char    *malloc();
  162. off_t    lseek();
  163. int    bstart, bend;        /* start and ending block numbers */
  164. char    *p;            /* temp dev name pointer */
  165. char    devname[BUFSIZ];
  166. main(argc, argv)
  167.     int argc;
  168.     char *argv[];
  169. {
  170.     register struct bt_bad *bt;
  171.     daddr_t    sn, bn[126];
  172.     int i, j, f, nbad, new, bad, errs;
  173.  
  174.         setbuf(stdout, NULL);
  175.     argc--, argv++;
  176.     while (argc > 0 && **argv == '-') {
  177.         (*argv)++;
  178.         while (**argv) {
  179.             switch (**argv) {
  180.                 case 'a':
  181.                 add++;
  182.                 break;
  183.                 case 'c':
  184.                 copy++;
  185.                 break;
  186.                 case 'v':
  187.                 verbose++;
  188.                 break;
  189.                 case 'n':
  190.                 nflag++;
  191.                 verbose++;
  192.                 break;
  193.                 case 's':        /* scan partition */
  194.                 sflag++;
  195.                 verbose++;
  196.                 break;
  197.                 default:
  198.                 if (**argv >= '0' && **argv <= '4') {
  199.                     badfile = **argv - '0';
  200.                     break;
  201.                 }
  202.                 goto usage;
  203.             }
  204.             (*argv)++;
  205.         }
  206.         argc--, argv++;
  207.     }
  208.     if (argc < 1) {
  209. usage:
  210.         fprintf(stderr,
  211.           "usage: bad144 [ -f ] disk [ snum [ bn ... ] ]\n");
  212.         fprintf(stderr,
  213.           "to read or overwrite bad-sector table, e.g.: bad144 hp0\n");
  214.         fprintf(stderr,
  215.           "or bad144 -a [ -f ] [ -c ] disk  bn ...\n");
  216.         fprintf(stderr, "where options are:\n");
  217.         fprintf(stderr, "\t-a  add new bad sectors to the table\n");
  218.         fprintf(stderr, "\t-f  reformat listed sectors as bad\n");
  219.         fprintf(stderr, "\t-c  copy original sector to replacement\n");
  220.         fprintf(stderr, "\t-s  scan partition for bad sectors\n");
  221.         exit(1);
  222.     }
  223.     if (argv[0][0] != '/')
  224.         (void)sprintf(name, "%sr%s%s", _PATH_DEV, argv[0], RAWPART);
  225.     else
  226.         strcpy(name, argv[0]);
  227.     f = open(name, argc == 1? O_RDONLY : O_RDWR);
  228.     if (f < 0)
  229.         Perror(name);
  230.         p = rindex(name, '/');
  231.         strcpy(devname,++p);
  232.         devname[strlen(p)-1] = '\0';
  233.     /* obtain label and adjust to fit */
  234.     dp = (struct disklabel *)&label;
  235.     if (ioctl(f, DIOCGDINFO, dp) < 0)
  236.         Perror("ioctl DIOCGDINFO");
  237.     if (dp->d_magic != DISKMAGIC || dp->d_magic2 != DISKMAGIC
  238.         /* dkcksum(lp) != 0 */ ) {
  239.         fprintf(stderr, "Bad pack magic number (pack is unlabeled)\n");
  240.         exit(1);
  241.     }
  242.     if (dp->d_secsize > MAXSECSIZE || dp->d_secsize <= 0) {
  243.         fprintf(stderr, "Disk sector size too large/small (%d)\n",
  244.             dp->d_secsize);
  245.         exit(7);
  246.     }
  247. #ifdef __386BSD__
  248.     if (dp->d_type == DTYPE_SCSI) {
  249.         fprintf(stderr, "SCSI disks don't use bad144!\n");
  250.         exit(1);
  251.     }
  252.     /* are we inside a DOS partition? */
  253.     if (verbose) {
  254. static char * parts[] = {
  255.     "ROOT  ",
  256.     "SWAP  ",
  257.     "386BSD",
  258.     "DISK  ",
  259.     "DOS?  ",
  260.     "USR2  ",
  261.     "USR1  ",
  262.     "USR   "
  263.     };
  264.         printf("device /dev/%s is a %s disk\n",
  265.          devname, dktypenames[dp->d_type]);
  266.         j = dp->d_secpercyl;
  267.         for (i=0; i < dp->d_npartitions; i++) {
  268.             if (dp->d_partitions[i].p_size == 0)continue;
  269.         printf("%s%c %s offset: %7d (%4d), size: %7d (%4d), type = %s\n",
  270.          devname, 'a'+i, parts[i], dp->d_partitions[i].p_offset,
  271.           dp->d_partitions[i].p_offset/j,
  272.          dp->d_partitions[i].p_size,
  273.          dp->d_partitions[i].p_size/j,
  274.          fstypenames[dp->d_partitions[i].p_fstype]);
  275.         }
  276.     }
  277.     if (dp->d_partitions[0].p_offset) {
  278.         /* yes, rules change. assume bad tables at end of partition C,
  279.            which maps all of DOS partition we are within -wfj */
  280.         size = dp->d_partitions[2].p_offset +
  281.                dp->d_partitions[2].p_size;
  282.     } else
  283. #endif
  284.     size = dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders; 
  285.     bstart = 0;
  286.     if (dp->d_partitions[2].p_size) {
  287.      bstart = dp->d_partitions[2].p_offset;
  288.     }
  289.     /* determine where to stop scanning */
  290.     bend = dp->d_partitions[2].p_size + dp->d_partitions[2].p_offset;
  291.     bend -= (dp->d_nsectors + 126);
  292.     if (verbose) {
  293.   printf("secs: %d, tracks: %d, cyl: %d, sec/cyl: %d, start: %d, end: %d\n",
  294.     dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders,
  295.      dp->d_secpercyl, bstart, bend);
  296.     }
  297.     if (sflag) {        /* search for bad sectors */
  298.         int curr_sec, tries, n;
  299.         int spc = dp->d_secpercyl;
  300.         int ss = dp->d_secsize;
  301.         int trk = dp->d_nsectors;
  302.         int step;
  303.         
  304.         if (buf == (char *)NULL) {
  305.             buf = malloc((unsigned)(trk*ss));
  306.             if (buf == (char *)NULL) {
  307.             fprintf(stderr, "Out of memory\n");
  308.             exit(20);
  309.             }
  310.         }
  311.  
  312.         printf("Starting scan of /dev/%sc at cylinder %d\n",
  313.          devname, bstart/spc);
  314.         /* seek to start of parition c, we are in d */
  315.         for (tries = 0; tries < RETRIES; tries++) {
  316.             if (lseek(f, bstart * ss, L_SET) < 0) {
  317.             Perror("lseek");
  318.             } else
  319.             break;
  320.         }
  321.         step = trk;
  322.         for (curr_sec = bstart; curr_sec < bend; curr_sec += step) {
  323.             int gotone = 0;
  324.  
  325.             if (verbose) {
  326.             if ((curr_sec % spc) == 0)
  327.                 printf("\r%4d(%7d)", curr_sec/spc, curr_sec);
  328.             }
  329.             for (tries = 0; tries < RETRIES; tries++) {
  330.             if (lseek(f, curr_sec * ss, L_SET) < 0) {
  331. fprintf(stderr, "\nbad144: can't seek sector, %d\n", curr_sec);
  332.                 gotone = 1;
  333.             } else
  334.                 break;
  335.             }
  336.             if (gotone) {
  337. fprintf(stderr, "\nbad144: bad sector (seek), %d\n", curr_sec);
  338.             step = 1;
  339.             continue;
  340.             }
  341.             if (step == trk) {
  342.             if ((n = read(f, buf, (ss * trk))) == (ss * trk)) {
  343.                 continue;
  344.             }
  345.             }
  346.             /* switch to single sector reads */
  347.             lseek(f, curr_sec * ss, L_SET);
  348.             step = 1;
  349.             for (tries = 0; tries < RETRIES; tries++) {
  350.             if ((n = read(f, buf, ss)) != ss) {
  351. fprintf(stderr, "\nbad144: can't read sector, %d\n", curr_sec);
  352.                 gotone = 1;
  353.                 lseek(f, curr_sec * ss, L_SET);
  354.             } else {
  355.                 if ((curr_sec % trk) == 0) {
  356.                 step = trk;
  357.                 }
  358.                 break;
  359.             }
  360.             }
  361.             if (gotone) {
  362. fprintf(stderr, "\nbad144: bad sector (read), %d\n", curr_sec);
  363.             continue;
  364.             }
  365.         }
  366.     }
  367.     argc--;
  368.     argv++;
  369.     if (argc == 0) {
  370.         sn = getold(f, &oldbad);
  371.         printf("\nbad block information at sector %d in %s:\n",
  372.             sn, name);
  373.         switch (oldbad.bt_flag) {
  374.  
  375.         case (u_short)-1:
  376.             printf("alignment cartridge\n");
  377.             break;
  378.  
  379.         case DKBAD_MAGIC:
  380.             break;
  381.  
  382.         default:
  383.             printf("bt_flag=%x(16)?\n", oldbad.bt_flag);
  384.             break;
  385.         }
  386.         bt = oldbad.bt_bad;
  387.         for (i = 0; i < 126; i++) {
  388.             bad = (bt->bt_cyl<<16) + bt->bt_trksec;
  389.             if (bad < 0)
  390.                 break;
  391.             printf("sn=%d, cn=%d, tn=%d, sn=%d\n", badsn(bt),
  392.                 bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
  393.             bt++;
  394.         }
  395.         (void) checkold(&oldbad);
  396.         exit(0);
  397.     }
  398.     if (add) {
  399.         /*
  400.          * Read in the old badsector table.
  401.          * Verify that it makes sense, and the bad sectors
  402.          * are in order.  Copy the old table to the new one.
  403.          */
  404.         (void) getold(f, &oldbad);
  405.         i = checkold(&oldbad);
  406.         if (verbose)
  407.             printf("Had %d bad sectors, adding %d\n", i, argc);
  408.         if (i + argc > 126) {
  409.             printf("bad144: not enough room for %d more sectors\n",
  410.                 argc);
  411.             printf("limited to 126 by information format\n");
  412.             exit(1);
  413.         }
  414.         curbad = oldbad;
  415.     } else {
  416.         curbad.bt_csn = atoi(*argv++);
  417.         argc--;
  418.         curbad.bt_mbz = 0;
  419.         curbad.bt_flag = DKBAD_MAGIC;
  420.         if (argc > 126) {
  421.             printf("bad144: too many bad sectors specified\n");
  422.             printf("limited to 126 by information format\n");
  423.             exit(1);
  424.         }
  425.         i = 0;
  426.     }
  427.     errs = 0;
  428.     new = argc;
  429.     while (argc > 0) {
  430.         daddr_t sn = atoi(*argv++);
  431.         argc--;
  432.         if (sn < 0 || sn >= size) {
  433.             printf("%d: out of range [0,%d) for disk %s\n",
  434.                 sn, size, dp->d_typename);
  435.             errs++;
  436.             continue;
  437.         }
  438.         bn[i] = sn;
  439.         curbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks);
  440.         sn %= (dp->d_nsectors*dp->d_ntracks);
  441.         curbad.bt_bad[i].bt_trksec =
  442.             ((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors);
  443.         i++;
  444.     }
  445.     if (errs)
  446.         exit(1);
  447.     nbad = i;
  448.     while (i < 126) {
  449.         curbad.bt_bad[i].bt_trksec = -1;
  450.         curbad.bt_bad[i].bt_cyl = -1;
  451.         i++;
  452.     }
  453.     if (add) {
  454.         /*
  455.          * Sort the new bad sectors into the list.
  456.          * Then shuffle the replacement sectors so that
  457.          * the previous bad sectors get the same replacement data.
  458.          */
  459.         qsort((char *)curbad.bt_bad, nbad, sizeof (struct bt_bad),
  460.             compare);
  461.         if (dups) {
  462.             fprintf(stderr,
  463. "bad144: bad sectors have been duplicated; can't add existing sectors\n");
  464.             exit(3);
  465.         }
  466.         shift(f, nbad, nbad-new);
  467.     }
  468.     if (badfile == -1)
  469.         i = 0;
  470.     else
  471.         i = badfile * 2;
  472.     for (; i < 10 && i < dp->d_nsectors; i += 2) {
  473.         if (lseek(f, dp->d_secsize * (size - dp->d_nsectors + i),
  474.             L_SET) < 0)
  475.             Perror("lseek");
  476.         if (verbose)
  477.             printf("write badsect file at %d\n",
  478.                 size - dp->d_nsectors + i);
  479.         if (nflag == 0 && write(f, (caddr_t)&curbad, sizeof(curbad)) !=
  480.             sizeof(curbad)) {
  481.             char msg[80];
  482.             (void)sprintf(msg, "bad144: write bad sector file %d",
  483.                 i/2);
  484.             perror(msg);
  485.         }
  486.         if (badfile != -1)
  487.             break;
  488.     }
  489. #ifdef DIOCSBAD
  490.     if (nflag == 0 && ioctl(f, DIOCSBAD, (caddr_t)&curbad) < 0)
  491.         fprintf(stderr,
  492.     "Can't sync bad-sector file; reboot for changes to take effect\n");
  493. #endif
  494.     if ((dp->d_flags & D_BADSECT) == 0 && nflag == 0) {
  495.         dp->d_flags |= D_BADSECT;
  496.         if (ioctl(f, DIOCWDINFO, dp) < 0) {
  497.             perror("label");
  498.             fprintf(stderr, "Can't write disklabel to enable bad secctor handling by the drive\n");
  499.             exit(1);
  500.         }
  501.     }
  502.     exit(0);
  503. }
  504.  
  505. daddr_t
  506. getold(f, bad)
  507. struct dkbad *bad;
  508. {
  509.     register int i;
  510.     daddr_t sn;
  511.     char msg[80];
  512.  
  513.     if (badfile == -1)
  514.         i = 0;
  515.     else
  516.         i = badfile * 2;
  517.     for (; i < 10 && i < dp->d_nsectors; i += 2) {
  518.         sn = size - dp->d_nsectors + i;
  519.         if (lseek(f, sn * dp->d_secsize, L_SET) < 0)
  520.             Perror("lseek");
  521.         if (read(f, (char *) bad, dp->d_secsize) == dp->d_secsize) {
  522.             if (i > 0)
  523.                 printf("Using bad-sector file %d\n", i/2);
  524.             return(sn);
  525.         }
  526.         (void)sprintf(msg, "bad144: read bad sector file at sn %d", sn);
  527.         perror(msg);
  528.         if (badfile != -1)
  529.             break;
  530.     }
  531.     fprintf(stderr, "bad144: %s: can't read bad block info\n", name);
  532.     exit(1);
  533.     /*NOTREACHED*/
  534. }
  535.  
  536. checkold()
  537. {
  538.     register int i;
  539.     register struct bt_bad *bt;
  540.     daddr_t sn, lsn;
  541.     int errors = 0, warned = 0;
  542.  
  543.     if (oldbad.bt_flag != DKBAD_MAGIC) {
  544.         fprintf(stderr, "bad144: %s: bad flag in bad-sector table\n",
  545.             name);
  546.         errors++;
  547.     }
  548.     if (oldbad.bt_mbz != 0) {
  549.         fprintf(stderr, "bad144: %s: bad magic number\n", name);
  550.         errors++;
  551.     }
  552.     bt = oldbad.bt_bad;
  553.     for (i = 0; i < 126; i++, bt++) {
  554.         if (bt->bt_cyl == 0xffff && bt->bt_trksec == 0xffff)
  555.             break;
  556.         if ((bt->bt_cyl >= dp->d_ncylinders) ||
  557.             ((bt->bt_trksec >> 8) >= dp->d_ntracks) ||
  558.             ((bt->bt_trksec & 0xff) >= dp->d_nsectors)) {
  559.             fprintf(stderr,
  560.              "bad144: cyl/trk/sect out of range in existing entry: ");
  561.             fprintf(stderr, "sn=%d, cn=%d, tn=%d, sn=%d\n",
  562.                 badsn(bt), bt->bt_cyl, bt->bt_trksec>>8,
  563.                 bt->bt_trksec & 0xff);
  564.             errors++;
  565.         }
  566.         sn = (bt->bt_cyl * dp->d_ntracks +
  567.             (bt->bt_trksec >> 8)) *
  568.             dp->d_nsectors + (bt->bt_trksec & 0xff);
  569.         if (i > 0 && sn < lsn && !warned) {
  570.             fprintf(stderr,
  571.             "bad144: bad sector file is out of order\n");
  572.             errors++;
  573.             warned++;
  574.         }
  575.         if (i > 0 && sn == lsn) {
  576.             fprintf(stderr,
  577.             "bad144: bad sector file contains duplicates (sn %d)\n",
  578.             sn);
  579.             errors++;
  580.         }
  581.         lsn = sn;
  582.     }
  583.     if (errors)
  584.         exit(1);
  585.     return (i);
  586. }
  587.  
  588. /*
  589.  * Move the bad sector replacements
  590.  * to make room for the new bad sectors.
  591.  * new is the new number of bad sectors, old is the previous count.
  592.  */
  593. shift(f, new, old)
  594. {
  595.     daddr_t repl;
  596.  
  597.     /*
  598.      * First replacement is last sector of second-to-last track.
  599.      */
  600.     repl = size - dp->d_nsectors - 1;
  601.     new--; old--;
  602.     while (new >= 0 && new != old) {
  603.         if (old < 0 ||
  604.             compare(&curbad.bt_bad[new], &oldbad.bt_bad[old]) > 0) {
  605.             /*
  606.              * Insert new replacement here-- copy original
  607.              * sector if requested and possible,
  608.              * otherwise write a zero block.
  609.              */
  610.             if (!copy ||
  611.                 !blkcopy(f, badsn(&curbad.bt_bad[new]), repl - new))
  612.                 blkzero(f, repl - new);
  613.         } else {
  614.             if (blkcopy(f, repl - old, repl - new) == 0)
  615.                 fprintf(stderr,
  616.                 "Can't copy replacement sector %d to %d\n",
  617.                 repl-old, repl-new);
  618.             old--;
  619.         }
  620.         new--;
  621.     }
  622. }
  623.  
  624. /*
  625.  *  Copy disk sector s1 to s2.
  626.  */
  627. blkcopy(f, s1, s2)
  628. daddr_t s1, s2;
  629. {
  630.     register tries, n;
  631.  
  632.     if (buf == (char *)NULL) {
  633.         buf = malloc((unsigned)dp->d_secsize);
  634.         if (buf == (char *)NULL) {
  635.             fprintf(stderr, "Out of memory\n");
  636.             exit(20);
  637.         }
  638.     }
  639.     for (tries = 0; tries < RETRIES; tries++) {
  640.         if (lseek(f, dp->d_secsize * s1, L_SET) < 0)
  641.             Perror("lseek");
  642.         if ((n = read(f, buf, dp->d_secsize)) == dp->d_secsize)
  643.             break;
  644.     }
  645.     if (n != dp->d_secsize) {
  646.         fprintf(stderr, "bad144: can't read sector, %d: ", s1);
  647.         if (n < 0)
  648.             perror((char *)0);
  649.         return(0);
  650.     }
  651.     if (lseek(f, dp->d_secsize * s2, L_SET) < 0)
  652.         Perror("lseek");
  653.     if (verbose)
  654.         printf("copying %d to %d\n", s1, s2);
  655.     if (nflag == 0 && write(f, buf, dp->d_secsize) != dp->d_secsize) {
  656.         fprintf(stderr,
  657.             "bad144: can't write replacement sector, %d: ", s2);
  658.         perror((char *)0);
  659.         return(0);
  660.     }
  661.     return(1);
  662. }
  663.  
  664. char *zbuf;
  665.  
  666. blkzero(f, sn)
  667. daddr_t sn;
  668. {
  669.  
  670.     if (zbuf == (char *)NULL) {
  671.         zbuf = malloc((unsigned)dp->d_secsize);
  672.         if (zbuf == (char *)NULL) {
  673.             fprintf(stderr, "Out of memory\n");
  674.             exit(20);
  675.         }
  676.     }
  677.     if (lseek(f, dp->d_secsize * sn, L_SET) < 0)
  678.         Perror("lseek");
  679.     if (verbose)
  680.         printf("zeroing %d\n", sn);
  681.     if (nflag == 0 && write(f, zbuf, dp->d_secsize) != dp->d_secsize) {
  682.         fprintf(stderr,
  683.             "bad144: can't write replacement sector, %d: ", sn);
  684.         perror((char *)0);
  685.     }
  686. }
  687.  
  688. compare(b1, b2)
  689. register struct bt_bad *b1, *b2;
  690. {
  691.     if (b1->bt_cyl > b2->bt_cyl)
  692.         return(1);
  693.     if (b1->bt_cyl < b2->bt_cyl)
  694.         return(-1);
  695.     if (b1->bt_trksec == b2->bt_trksec)
  696.         dups++;
  697.     return (b1->bt_trksec - b2->bt_trksec);
  698. }
  699.  
  700. daddr_t
  701. badsn(bt)
  702. register struct bt_bad *bt;
  703. {
  704.     return ((bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * dp->d_nsectors
  705.         + (bt->bt_trksec&0xff));
  706. }
  707.  
  708. Perror(op)
  709.     char *op;
  710. {
  711.  
  712.     fprintf(stderr, "bad144: "); perror(op);
  713.     exit(4);
  714. }
  715.  
  716. ---- snip snip ----
  717.  
  718. -- 
  719. +=+     From the mountains of Colorado:   jbev@jbsys.com      +=+
  720. +=+           when it's not snowing, the sun is shining       +=+
  721. +=+     Jim Bevier    -   J B Systems   (303)-697-1038        +=+
  722. +=+         10136 Horizon View, Morrison, CO 80465            +=+
  723.