1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * diskscan: 31*7c478bd9Sstevel@tonic-gate * performs a verification pass over a device specified on command line; 32*7c478bd9Sstevel@tonic-gate * display progress on stdout, and print bad sector numbers to stderr 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate #include <stdio.h> 35*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 36*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 37*7c478bd9Sstevel@tonic-gate #include <unistd.h> 38*7c478bd9Sstevel@tonic-gate #include <stropts.h> 39*7c478bd9Sstevel@tonic-gate #include <memory.h> 40*7c478bd9Sstevel@tonic-gate #include <ctype.h> 41*7c478bd9Sstevel@tonic-gate #include <malloc.h> 42*7c478bd9Sstevel@tonic-gate #include <signal.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate static void verexit(); /* signal handler and exit routine */ 50*7c478bd9Sstevel@tonic-gate static void report(); /* tell user how we're getting on */ 51*7c478bd9Sstevel@tonic-gate static void scandisk(char *device, int devfd, int writeflag); 52*7c478bd9Sstevel@tonic-gate static void report(char *what, int sector); 53*7c478bd9Sstevel@tonic-gate static void verexit(int code); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #define TRUE 1 56*7c478bd9Sstevel@tonic-gate #define FALSE 0 57*7c478bd9Sstevel@tonic-gate #define VER_WRITE 1 58*7c478bd9Sstevel@tonic-gate #define VER_READ 2 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate static char *progname; 61*7c478bd9Sstevel@tonic-gate static struct dk_geom dkg; /* physical device boot info */ 62*7c478bd9Sstevel@tonic-gate static char replybuf[64]; /* used for user replies to questions */ 63*7c478bd9Sstevel@tonic-gate static daddr_t unix_base; /* first sector of UNIX System partition */ 64*7c478bd9Sstevel@tonic-gate static daddr_t unix_size; /* # sectors in UNIX System partition */ 65*7c478bd9Sstevel@tonic-gate static long numbadrd = 0; /* number of bad sectors on read */ 66*7c478bd9Sstevel@tonic-gate static long numbadwr = 0; /* number of bad sectors on write */ 67*7c478bd9Sstevel@tonic-gate static char eol = '\n'; /* end-of-line char (if -n, we set to '\n') */ 68*7c478bd9Sstevel@tonic-gate static int print_warn = 1; /* should the warning message be printed? */ 69*7c478bd9Sstevel@tonic-gate static int do_scan = VER_READ; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate void 72*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) { 73*7c478bd9Sstevel@tonic-gate extern int optind; 74*7c478bd9Sstevel@tonic-gate int devfd; /* device file descriptor */ 75*7c478bd9Sstevel@tonic-gate struct stat statbuf; 76*7c478bd9Sstevel@tonic-gate struct part_info part_info; 77*7c478bd9Sstevel@tonic-gate int c; 78*7c478bd9Sstevel@tonic-gate int errflag = 0; 79*7c478bd9Sstevel@tonic-gate char *device; 80*7c478bd9Sstevel@tonic-gate progname = argv[0]; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate /* Don't buffer stdout - we don't want to see bursts */ 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate setbuf(stdout, NULL); 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "Wny")) != -1) 87*7c478bd9Sstevel@tonic-gate { 88*7c478bd9Sstevel@tonic-gate switch (c) { 89*7c478bd9Sstevel@tonic-gate case 'W': 90*7c478bd9Sstevel@tonic-gate do_scan = VER_WRITE; 91*7c478bd9Sstevel@tonic-gate break; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate case 'n': 94*7c478bd9Sstevel@tonic-gate eol = '\r'; 95*7c478bd9Sstevel@tonic-gate break; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate case 'y': 98*7c478bd9Sstevel@tonic-gate print_warn = 0; 99*7c478bd9Sstevel@tonic-gate break; 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate default: 102*7c478bd9Sstevel@tonic-gate ++errflag; 103*7c478bd9Sstevel@tonic-gate break; 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate if ((argc - optind) < 1) 108*7c478bd9Sstevel@tonic-gate errflag++; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate if (errflag) { 111*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 112*7c478bd9Sstevel@tonic-gate "\nUsage: %s [-W] [-n] [-y] <phys_device_name> \n", 113*7c478bd9Sstevel@tonic-gate progname); 114*7c478bd9Sstevel@tonic-gate exit(1); 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate device = argv[optind]; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate if (stat(device, &statbuf)) { 120*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 121*7c478bd9Sstevel@tonic-gate "%s: invalid device %s, stat failed\n", progname, device); 122*7c478bd9Sstevel@tonic-gate perror(""); 123*7c478bd9Sstevel@tonic-gate exit(4); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate if ((statbuf.st_mode & S_IFMT) != S_IFCHR) { 126*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 127*7c478bd9Sstevel@tonic-gate "%s: device %s is not character special\n", 128*7c478bd9Sstevel@tonic-gate progname, device); 129*7c478bd9Sstevel@tonic-gate exit(5); 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate if ((devfd = open(device, O_RDWR)) == -1) { 132*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 133*7c478bd9Sstevel@tonic-gate "%s: open of %s failed\n", progname, device); 134*7c478bd9Sstevel@tonic-gate perror(""); 135*7c478bd9Sstevel@tonic-gate exit(8); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate if ((ioctl(devfd, DKIOCGGEOM, &dkg)) == -1) { 139*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 140*7c478bd9Sstevel@tonic-gate "%s: unable to get disk geometry.\n", progname); 141*7c478bd9Sstevel@tonic-gate perror(""); 142*7c478bd9Sstevel@tonic-gate exit(9); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate if ((ioctl(devfd, DKIOCPARTINFO, &part_info)) == -1) { 145*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: unable to get partition info.\n", 146*7c478bd9Sstevel@tonic-gate progname); 147*7c478bd9Sstevel@tonic-gate perror(""); 148*7c478bd9Sstevel@tonic-gate exit(9); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate unix_base = part_info.p_start; 152*7c478bd9Sstevel@tonic-gate unix_size = part_info.p_length; 153*7c478bd9Sstevel@tonic-gate scandisk(device, devfd, do_scan); 154*7c478bd9Sstevel@tonic-gate exit(0); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate /* 158*7c478bd9Sstevel@tonic-gate * scandisk: 159*7c478bd9Sstevel@tonic-gate * attempt to read every sector of the drive; 160*7c478bd9Sstevel@tonic-gate * display bad sectors found on stderr 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate static void 164*7c478bd9Sstevel@tonic-gate scandisk(char *device, int devfd, int writeflag) 165*7c478bd9Sstevel@tonic-gate { 166*7c478bd9Sstevel@tonic-gate int trksiz = NBPSCTR * dkg.dkg_nsect; 167*7c478bd9Sstevel@tonic-gate char *verbuf; 168*7c478bd9Sstevel@tonic-gate daddr_t cursec; 169*7c478bd9Sstevel@tonic-gate int cylsiz = dkg.dkg_nsect * dkg.dkg_nhead; 170*7c478bd9Sstevel@tonic-gate int i; 171*7c478bd9Sstevel@tonic-gate char *rptr; 172*7c478bd9Sstevel@tonic-gate long tmpend = 0; 173*7c478bd9Sstevel@tonic-gate long tmpsec = 0; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* #define LIBMALLOC */ 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate #ifdef LIBMALLOC 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate extern int mallopt(); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* This adds 5k to the binary, but it's a lot prettier */ 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate /* make track buffer sector aligned */ 185*7c478bd9Sstevel@tonic-gate if (mallopt(M_GRAIN, 0x200)) { 186*7c478bd9Sstevel@tonic-gate perror("mallopt"); 187*7c478bd9Sstevel@tonic-gate exit(1); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate if ((verbuf = malloc(NBPSCTR * dkg.dkg_nsect)) == (char *)NULL) { 190*7c478bd9Sstevel@tonic-gate perror("malloc"); 191*7c478bd9Sstevel@tonic-gate exit(1); 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate #else 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate if ((verbuf = malloc(0x200 + NBPSCTR * dkg.dkg_nsect)) 197*7c478bd9Sstevel@tonic-gate == (char *)NULL) { 198*7c478bd9Sstevel@tonic-gate perror("malloc"); 199*7c478bd9Sstevel@tonic-gate exit(1); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate verbuf = (char *)(((unsigned long)verbuf + 0x00000200) & 0xfffffe00); 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate #endif 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate /* write pattern in track buffer */ 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate for (i = 0; i < trksiz; i++) 208*7c478bd9Sstevel@tonic-gate verbuf[i] = (char)0xe5; 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate /* Turn off retry, and set trap to turn them on again */ 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, verexit); 213*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, verexit); 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate if (writeflag == VER_READ) 216*7c478bd9Sstevel@tonic-gate goto do_readonly; 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* 219*7c478bd9Sstevel@tonic-gate * display warning only if -n arg not passed 220*7c478bd9Sstevel@tonic-gate * (otherwise the UI system will take care of it) 221*7c478bd9Sstevel@tonic-gate */ 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate if (print_warn == 1) { 224*7c478bd9Sstevel@tonic-gate (void) printf( 225*7c478bd9Sstevel@tonic-gate "\nCAUTION: ABOUT TO DO DESTRUCTIVE WRITE ON %s\n", device); 226*7c478bd9Sstevel@tonic-gate (void) printf(" THIS WILL DESTROY ANY DATA YOU HAVE ON\n"); 227*7c478bd9Sstevel@tonic-gate (void) printf(" THAT PARTITION OR SLICE.\n"); 228*7c478bd9Sstevel@tonic-gate (void) printf("Do you want to continue (y/n)? "); 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate rptr = fgets(replybuf, 64*sizeof (char), stdin); 231*7c478bd9Sstevel@tonic-gate if (!rptr || !((replybuf[0] == 'Y') || (replybuf[0] == 'y'))) 232*7c478bd9Sstevel@tonic-gate exit(10); 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate for (cursec = 0; cursec < unix_size; cursec += dkg.dkg_nsect) { 236*7c478bd9Sstevel@tonic-gate if (lseek(devfd, (long)cursec * NBPSCTR, 0) == -1) { 237*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 238*7c478bd9Sstevel@tonic-gate "Error seeking sector %ld Cylinder %ld\n", 239*7c478bd9Sstevel@tonic-gate cursec, cursec / cylsiz); 240*7c478bd9Sstevel@tonic-gate verexit(1); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* 244*7c478bd9Sstevel@tonic-gate * verify sector at a time only when 245*7c478bd9Sstevel@tonic-gate * the whole track write fails; 246*7c478bd9Sstevel@tonic-gate * (if we write a sector at a time, it takes forever) 247*7c478bd9Sstevel@tonic-gate */ 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate report("Writing", cursec); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate if (write(devfd, verbuf, trksiz) != trksiz) { 252*7c478bd9Sstevel@tonic-gate tmpend = cursec + dkg.dkg_nsect; 253*7c478bd9Sstevel@tonic-gate for (tmpsec = cursec; tmpsec < tmpend; tmpsec++) { 254*7c478bd9Sstevel@tonic-gate /* 255*7c478bd9Sstevel@tonic-gate * try writing to it once; if this fails, 256*7c478bd9Sstevel@tonic-gate * then announce the sector bad on stderr 257*7c478bd9Sstevel@tonic-gate */ 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate if (lseek 260*7c478bd9Sstevel@tonic-gate (devfd, (long)tmpsec * NBPSCTR, 0) == -1) { 261*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Error seeking " 262*7c478bd9Sstevel@tonic-gate "sector %ld Cylinder %ld\n", 263*7c478bd9Sstevel@tonic-gate tmpsec, cursec / cylsiz); 264*7c478bd9Sstevel@tonic-gate verexit(1); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate report("Writing", tmpsec); 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate if (write(devfd, verbuf, NBPSCTR) != NBPSCTR) { 270*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 271*7c478bd9Sstevel@tonic-gate "%ld\n", tmpsec + unix_base); 272*7c478bd9Sstevel@tonic-gate numbadwr++; 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate (void) putchar(eol); 279*7c478bd9Sstevel@tonic-gate do_readonly: 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate for (cursec = 0; cursec < unix_size; cursec += dkg.dkg_nsect) { 282*7c478bd9Sstevel@tonic-gate if (lseek(devfd, (long)cursec * NBPSCTR, 0) == -1) { 283*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 284*7c478bd9Sstevel@tonic-gate "Error seeking sector %ld Cylinder %ld\n", 285*7c478bd9Sstevel@tonic-gate cursec, cursec / cylsiz); 286*7c478bd9Sstevel@tonic-gate verexit(1); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * read a sector at a time only when 291*7c478bd9Sstevel@tonic-gate * the whole track write fails; 292*7c478bd9Sstevel@tonic-gate * (if we do a sector at a time read, it takes forever) 293*7c478bd9Sstevel@tonic-gate */ 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate report("Reading", cursec); 296*7c478bd9Sstevel@tonic-gate if (read(devfd, verbuf, trksiz) != trksiz) { 297*7c478bd9Sstevel@tonic-gate tmpend = cursec + dkg.dkg_nsect; 298*7c478bd9Sstevel@tonic-gate for (tmpsec = cursec; tmpsec < tmpend; tmpsec++) { 299*7c478bd9Sstevel@tonic-gate if (lseek(devfd, (long)tmpsec * NBPSCTR, 0) 300*7c478bd9Sstevel@tonic-gate == -1) { 301*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Error seeking" 302*7c478bd9Sstevel@tonic-gate " sector %ld Cylinder %ld\n", 303*7c478bd9Sstevel@tonic-gate tmpsec, cursec / cylsiz); 304*7c478bd9Sstevel@tonic-gate verexit(1); 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate report("Reading", tmpsec); 307*7c478bd9Sstevel@tonic-gate if (read(devfd, verbuf, NBPSCTR) != NBPSCTR) { 308*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%ld\n", 309*7c478bd9Sstevel@tonic-gate tmpsec + unix_base); 310*7c478bd9Sstevel@tonic-gate numbadrd++; 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate (void) printf("%c%c======== Diskscan complete ========%c", eol, 316*7c478bd9Sstevel@tonic-gate eol, eol); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if ((numbadrd > 0) || (numbadwr > 0)) { 319*7c478bd9Sstevel@tonic-gate (void) printf("%cFound %ld bad sector(s) on read," 320*7c478bd9Sstevel@tonic-gate " %ld bad sector(s) on write%c", 321*7c478bd9Sstevel@tonic-gate eol, numbadrd, numbadwr, eol); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate static void 326*7c478bd9Sstevel@tonic-gate verexit(int code) 327*7c478bd9Sstevel@tonic-gate { 328*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 329*7c478bd9Sstevel@tonic-gate exit(code); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * report where we are... 335*7c478bd9Sstevel@tonic-gate */ 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate static void 338*7c478bd9Sstevel@tonic-gate report(char *what, int sector) 339*7c478bd9Sstevel@tonic-gate { 340*7c478bd9Sstevel@tonic-gate (void) printf("%s sector %-7d of %-7ld%c", what, sector, 341*7c478bd9Sstevel@tonic-gate unix_size, eol); 342*7c478bd9Sstevel@tonic-gate } 343