Annotation of coherent/d/etc/badscan.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * badscan.c
        !             3:  * 2/7/91
        !             4:  * Usage: badscan [-v] [-o proto] [-b boot] device count
        !             5:  *     device    device to be scanned (e.g. /dev/rat0a)
        !             6:  *     count     size of file system to be scanned
        !             7:  *     sdev      master boot record for device size info (e.g. /dev/at0x)
        !             8:  * Options:
        !             9:  *     -b boot   use "boot" for boot in prototype file (default: /conf/boot)
        !            10:  *     -o proto  output file name for prototype file  (default: stdout)
        !            11:  *     -v        verbose messages as to the percentage of file system scanned
        !            12:  *
        !            13:  * Due to Inetco's braindamaged notion of removing stdio from everything, this
        !            14:  * does not #include <stdio.h> and uses sys write() calls to fd 1 and fd 2 in
        !            15:  * lieu of stdout and stderr.  This should be fixed when someone gets the urge.
        !            16:  *
        !            17:  * $Log:       /newbits/etc/badscan.c,v $
        !            18:  * Revision 1.6        91/02/22  12:14:25      bin
        !            19:  * updated version provided by stevesf for v311
        !            20:  * 
        !            21:  * Revision 1.7        91/02/07  12:36:00      bin
        !            22:  * steve 2/7/91
        !            23:  * Following norm's suggestion, SCSI badscan now issues warning but
        !            24:  * the continues with block-by-block scan of device.
        !            25:  * 
        !            26:  * Revision 1.6        91/02/07  09:58:21      bin
        !            27:  * steve 2/7/91
        !            28:  * Added include of <sys/devices.h>, changed explicitly declared floppy
        !            29:  * and hard disk major device manifest constants accordingly.
        !            30:  * Added check for major==SCSI; if so, print "SCSI devices do not require
        !            31:  * badscan" and exit successfully.
        !            32:  * Added "badscan:" at start of fatal() messages.
        !            33:  * Added comment moaning about Inetco avoiding stdio.
        !            34:  * 
        !            35:  * Revision 1.5        90/04/20  09:01:50      bin
        !            36:  * steve 4/20/90
        !            37:  * Previous version failed on floppy disks because HDGETA ioctl only works
        !            38:  * on hard disks.  Now it checks the major number, does HDGETA to find
        !            39:  * tracksize on hard disk and uses tracksize=1 (sector by sector scan)
        !            40:  * on floppies.  Future: should add FDGETA ioctl to floppy driver and
        !            41:  * let badscan (and mkfs) find default floppy size automatically.
        !            42:  * 
        !            43:  * Revision 1.4        90/04/19  14:08:36      bin
        !            44:  * steve 4/19/90
        !            45:  * Change -v messages slightly for use during install;
        !            46:  * use '\r' instead of '\n', overwrite with "Done\n" when finished.
        !            47:  * 
        !            48:  * Revision 1.3        90/03/27  08:33:48      bin
        !            49:  * steve 03/27/90
        !            50:  * Mark entire bad track as bad rather than reading each sector in track.
        !            51:  * 
        !            52:  * Revision 1.2        90/03/22  09:57:41      root
        !            53:  * Find sectors per track with ioctl rather than assuming 17.
        !            54:  * Rearranged code, changed fatal error messages, changed screwy spacing.
        !            55:  *     steve 3/22/90
        !            56:  * 
        !            57:  * 88/03/23    Allan Cornish   /usr/src/cmd/etc/badscan.c
        !            58:  * Reads are no longer attempted past logical end of partition,
        !            59:  * when a logical track straddles the partition boundary.
        !            60:  *
        !            61:  * 88/01/27    Jim Belton      /usr/src/cmd/etc/badscan.c
        !            62:  * Fixed bug for counts >= 32K by declaring atol().
        !            63:  *
        !            64:  * 86/11/03    Joe Iu
        !            65:  * Added -o and -b options, where the protofile and the boot file name
        !            66:  * can be specified by the user explicitly.
        !            67:  *
        !            68:  * 85/12/03    Allan Cornish
        !            69:  * Multi-sector read algorithm adjusted to ensure track alignment,
        !            70:  * even on track 0 where master boot block is not included in partition.
        !            71:  *
        !            72:  * 85/11/16    Allan Cornish
        !            73:  * Added track reads, with block by block retry on error.
        !            74:  *
        !            75:  * 85/11/13    Allan Cornish
        !            76:  * Added estimate of time remaining to each progress report.
        !            77:  *
        !            78:  * 85/11/06    Allan Cornish
        !            79:  * Added -v flag to report progress every 10 percent of scan.
        !            80:  *
        !            81:  * 88/07/11     Jim Napier
        !            82:  * Modified sput() to retry write if returns zero.  This was causing an
        !            83:  * invalid prototype file to be created when using the Seagate ST-251
        !            84:  * hard disk which contains bad blocks.
        !            85:  */
        !            86: 
        !            87: #include <sys/stat.h>
        !            88: #include <sys/devices.h>
        !            89: #include <sys/fdisk.h>
        !            90: #include <sys/hdioctl.h>
        !            91: 
        !            92: #define        BUFSIZ  512
        !            93: #define        MAXUINT ((unsigned)65535L)
        !            94: #define        NULL    ((char *)0)
        !            95: #define        TRUE    (0 == 0)
        !            96: 
        !            97: /*
        !            98:  * External functions.
        !            99:  */
        !           100: extern long    atol();
        !           101: extern char    *malloc();
        !           102: 
        !           103: /*
        !           104:  * Forward referenced functions.
        !           105:  */
        !           106: void           bad();
        !           107: void           fatal();
        !           108: void           lput();
        !           109: void           sput();
        !           110: void           usage();
        !           111: 
        !           112: /*
        !           113:  * Global variables.
        !           114:  */
        !           115: char           *bfile = "/conf/boot";
        !           116: int            bflag;
        !           117: int            oflag;
        !           118: struct stat    sb;
        !           119: int            vflag;
        !           120: 
        !           121: /**
        !           122:  * main        - validate number and type of arguments.
        !           123:  *             - scan device (arg1) for bad blocks until lim (arg2) reached.
        !           124:  *             - generate a mkfs prototype file on standard output or the
        !           125:  *               designated protofile.
        !           126:  */
        !           127: main(argc, argv) register int argc; register char *argv[];
        !           128: {
        !           129:        register int n;
        !           130:        long bno;
        !           131:        long incr;
        !           132:        long lim;
        !           133:        long t0, t1;
        !           134:        int percent;
        !           135:        int nspt;
        !           136:        char *buf;
        !           137:        hdparm_t hdparms;
        !           138:        unsigned int tracksize;
        !           139:        unsigned long base;
        !           140: 
        !           141:        /*
        !           142:         * Read options declared.
        !           143:         */
        !           144:        while((--argc > 0) && ((*++argv)[0] == '-')) {
        !           145: 
        !           146:                if((*argv)[2] != '\0')
        !           147:                        usage();
        !           148: 
        !           149:                switch((*argv)[1]) {
        !           150: 
        !           151:                case 'v':
        !           152:                        if(vflag)
        !           153:                                usage();
        !           154:                        vflag = TRUE;
        !           155:                        break;
        !           156: 
        !           157:                case 'o':
        !           158:                        if(oflag  ||  (--argc <= 0))
        !           159:                                usage();
        !           160:                        oflag = TRUE;
        !           161: 
        !           162:                        /*
        !           163:                         * Open protofile to store badscan information.
        !           164:                         */
        !           165:                        close(1);
        !           166:                        if(creat(*++argv, 0644) == -1)
        !           167:                                fatal("cannot create ", *argv);
        !           168:                        break;
        !           169: 
        !           170:                case 'b':
        !           171:                        if(bflag  ||  (--argc <= 0))
        !           172:                                usage();
        !           173: 
        !           174:                        bflag = TRUE;
        !           175:                        /*
        !           176:                         * Set boot file name.
        !           177:                         */
        !           178:                        bfile = *++argv;
        !           179:                        break;
        !           180: 
        !           181:                default:
        !           182:                        usage();
        !           183:                        break;
        !           184:                }
        !           185:        }
        !           186: 
        !           187:        /*
        !           188:         * Check to ensure that only arg1 and arg2 are available.
        !           189:         */
        !           190:        if (argc != 2)
        !           191:                usage();
        !           192: 
        !           193:        /*
        !           194:         * The first argument not associated with an option must be a
        !           195:         * character or block special file.
        !           196:         */
        !           197:        if (stat(argv[0], &sb) < 0)
        !           198:                fatal("cannot stat: ", argv[0]);
        !           199:        sb.st_mode &= S_IFMT;
        !           200:        if ((sb.st_mode != S_IFCHR) && (sb.st_mode != S_IFBLK))
        !           201:                fatal("not a device special file: ", argv[0]);
        !           202:        if ((n = major(sb.st_rdev)) == SCSI_MAJOR)
        !           203:                sput(2, "badscan: warning: SCSI devices do not require badscan\n");
        !           204:        else if (n != AT_MAJOR && n != FL_MAJOR)
        !           205:                fatal("not a disk device: ", argv[0]);
        !           206: 
        !           207:        /*
        !           208:         * Open the special file (arg1).
        !           209:         * Find the size of a track.
        !           210:         */
        !           211:        close(0);
        !           212:        if (open(argv[0], 0) == -1)
        !           213:                fatal("cannot open: ", argv[0]);
        !           214:        if (n == AT_MAJOR) {
        !           215:                /* Get hard disk track size with ioctl. */
        !           216:                if (ioctl(0, HDGETA, (char *)&hdparms) == -1)
        !           217:                        fatal("cannot get disk device parameters: ", argv[0]);
        !           218:                tracksize = hdparms.nspt;
        !           219:        } else {
        !           220:                /* Badscan a floppy disk or a SCSI disk. */
        !           221:                /* Floppy ioctl FDGETA should be implemented but is not (yet). */
        !           222: #if    0
        !           223:                /* Kludge: this code knows floppy minor to tracksize mapping. */
        !           224:                n = minor(sb.st_rdev) & 7;
        !           225:                if (n < 3)              /* minor 0, 1, 2, 8, 9, 10, ... */
        !           226:                        tracksize = 8;
        !           227:                else if (n < 6)         /* minor 3, 4, 5, 11, 12, 13, ... */
        !           228:                        tracksize = 9;
        !           229:                else if (n == 6)        /* minor 6, 14, ... */
        !           230:                        tracksize = 15;
        !           231:                else                    /* minor 7, 15, ... */
        !           232:                        fatal("unsupported minor number", argv[0]);
        !           233: #else
        !           234:                /* Scan block by block for now. */
        !           235:                tracksize = 1;
        !           236: #endif
        !           237:        }
        !           238: 
        !           239:        /*
        !           240:         * Allocate a track buffer.
        !           241:         */
        !           242:        if (tracksize > MAXUINT/BUFSIZ || (buf = malloc(tracksize * BUFSIZ)) == NULL)
        !           243:                fatal("cannot allocate track buffer", "");
        !           244: 
        !           245:        /*
        !           246:         * Validate and evaluate length (arg2)
        !           247:         */
        !           248:        lim = atol(argv[1]);
        !           249:        if (lim <= 0) {
        !           250: 
        !           251:                register struct hdisk_s *hp;
        !           252:                int f2;
        !           253: 
        !           254:                if ((f2 = open(argv[1], 0)) < 0)
        !           255:                        fatal("bad size: ", argv[1]);
        !           256:                if (read(f2, buf, 512) != 512)
        !           257:                        fatal("cannot read: ", argv[1]);
        !           258:                close(f2);
        !           259:                hp = buf;
        !           260:                if (hp->hd_sig != HDSIG)
        !           261:                        fatal("bad partition table: ", argv[1]);
        !           262:                lim  = hp->hd_partn[ sb.st_rdev & 3 ].p_size;
        !           263:                base = hp->hd_partn[ sb.st_rdev & 3 ].p_base;
        !           264:                nspt = tracksize - base % tracksize;
        !           265:                if (lim <= 0)
        !           266:                        fatal("null partition: ", argv[1]);
        !           267:        }
        !           268: 
        !           269:        /*
        !           270:         * Create header for mkfs prototype file.
        !           271:         */
        !           272:        sput(1, bfile);
        !           273:        sput(1, "\n");
        !           274:        lput(1, lim);
        !           275:        sput(1, " ");
        !           276:        lput(1, (lim/6 + 7) & ~7L);     /* ensure ninode is multiple of 8 */
        !           277:        percent = 10;
        !           278:        incr = lim / 10;
        !           279:        time(&t0);
        !           280: 
        !           281:        /*
        !           282:         * Scan for bad blocks.
        !           283:         * The first and last tracks may have less than tracksize sectors.
        !           284:         */
        !           285:        for (bno=0; bno < lim; (bno += nspt), (nspt = tracksize)) {
        !           286: 
        !           287:                /*
        !           288:                 * Try a track read first.
        !           289:                 */
        !           290:                lseek(0, bno * BUFSIZ, 0);
        !           291: 
        !           292:                /*
        !           293:                 * Avoid reading past end of partition.
        !           294:                 */
        !           295:                if (bno + nspt > lim)
        !           296:                        nspt = lim - bno;
        !           297: 
        !           298:                /* Mark each block in a bad track as bad. */
        !           299:                if (read(0, buf, (nspt * BUFSIZ)) != (nspt * BUFSIZ))
        !           300:                        for (n=0; n < nspt; ++n)
        !           301:                                bad(bno+n);
        !           302: 
        !           303:                /*
        !           304:                 * Periodically generate reports
        !           305:                 */
        !           306:                if (vflag && (bno >= incr) && (bno < lim)) {
        !           307: 
        !           308:                        /*
        !           309:                         * Estimate seconds remaining to next 1/10 minute.
        !           310:                         */
        !           311:                        time(&t1);
        !           312:                        t1 = (t1 - t0) * (100 - percent);
        !           313:                        t1 += percent - 1;
        !           314:                        t1 /= percent;
        !           315:                        t1 += 5;
        !           316: 
        !           317:                        lput(2, (long) percent);
        !           318:                        sput(2, "% done: ");
        !           319:                        if (t1 <  6000)
        !           320:                                sput(2, " ");
        !           321:                        if (t1 <   600)
        !           322:                                sput(2, " ");
        !           323:                        lput(2, t1 / 60);
        !           324:                        sput(2, ".");
        !           325:                        lput(2, (t1 % 60) / 6);
        !           326:                        sput(2, " minutes remaining...\r");
        !           327: 
        !           328:                        percent += 10;
        !           329:                        incr =  (lim * percent) / 100;
        !           330:                }
        !           331:        }
        !           332:        sput(2, "Done.                               \n");
        !           333:        sput(1, "\nd--755 0 0\n$\n");
        !           334:        exit(0);
        !           335: }
        !           336: 
        !           337: /**
        !           338:  * void
        !           339:  * bad(n)
        !           340:  * long        n;
        !           341:  *     Input:  n       - bad block location.
        !           342:  *     Action: Flag block n as being bad.
        !           343:  *     Return: None.
        !           344:  *     Note:   None.
        !           345:  */
        !           346: void
        !           347: bad(n) register long n;
        !           348: {
        !           349:        static int  nbad =  0;
        !           350:        static long last = -1;
        !           351: 
        !           352:        if ((last+1) != n)
        !           353:                nbad = 0;
        !           354:        last = n;
        !           355:        if ((nbad & 7) == 0)
        !           356:                sput(1, "\n%b");
        !           357:        sput(1, " ");
        !           358:        lput(1, n);
        !           359:        ++nbad;
        !           360: }
        !           361: 
        !           362: /**
        !           363:  * void
        !           364:  * fatal(s1, s2)
        !           365:  * char        * s1, *s2;
        !           366:  *     Input:  s1, s2  - pointer to error message strings.
        !           367:  *     Action: Print fatal message, terminate with extreme prejudice.
        !           368:  *     Return: Never return. Always exit.
        !           369:  *     Note:   None.
        !           370:  */
        !           371: void
        !           372: fatal(s1, s2) char * s1, * s2;
        !           373: {
        !           374:        sput(2, "badscan: ");
        !           375:        sput(2, s1);
        !           376:        sput(2, s2);
        !           377:        sput(2, "\n");
        !           378:        exit(1);
        !           379: }
        !           380: 
        !           381: /**
        !           382:  * void
        !           383:  * lput(fd, num)
        !           384:  * int fd;
        !           385:  * unsigned long num;
        !           386:  *
        !           387:  *     Input:  fd      - output file descriptor.
        !           388:  *             num     -
        !           389:  *     Action: Convert long num to ascii string sent to file fd.
        !           390:  *     Return: None.
        !           391:  *     Note:   None.
        !           392:  */
        !           393: void
        !           394: lput(fd, num) int      fd; unsigned long num;
        !           395: {
        !           396:        register char * cp;
        !           397:        static char buf[16];
        !           398: 
        !           399:        cp = &buf[15];
        !           400: 
        !           401:        /*
        !           402:         * Compute character equivalent value of long num.
        !           403:         */
        !           404:        do {
        !           405:                *--cp = (num % 10) + '0';
        !           406:        } while (num /= 10);
        !           407:        sput(fd, cp);
        !           408: }
        !           409: 
        !           410: /**
        !           411:  * void
        !           412:  * sput(fd, s)
        !           413:  * int fd;
        !           414:  * char        * s;
        !           415:  *
        !           416:  *     Input:  fd      - output file descriptor.
        !           417:  *             s       - pointer to character string.
        !           418:  *     Action: Write string s to file descriptor fd.
        !           419:  *     Return: None.
        !           420:  *     Note:   None.
        !           421:  */
        !           422: void
        !           423: sput(fd, s) int        fd; register char * s;
        !           424: {
        !           425:        register char * cp;
        !           426:        int i,j;
        !           427: 
        !           428:        /*
        !           429:         * Get location of end of string.
        !           430:         */
        !           431:        for (cp = s; *cp != '\0'; ++cp)
        !           432:                ;
        !           433:        
        !           434:        /* WRITE WITH RETRY IF WRITE() RETURNS 0 */
        !           435:        i = cp-s;
        !           436:        while ((j = write(fd, s, i)) == 0) ;
        !           437:          
        !           438: }
        !           439: 
        !           440: /**
        !           441:  * void
        !           442:  * usage()
        !           443:  *     Input:  None.
        !           444:  *     Action: Display command format.
        !           445:  *     return: None.
        !           446:  *     Note:   None.
        !           447:  */
        !           448: void
        !           449: usage()
        !           450: {
        !           451:        fatal(  "Usage: badscan [-v] [-o proto] [-b boot] dev size\n",
        !           452:                "       badscan [-v] [-o proto] [-b boot] dev sdev");
        !           453: }
        !           454: 
        !           455: /* end of badscan.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.