147082Smckusick /*- 247082Smckusick * Copyright (c) 1980, 1988, 1991 The Regents of the University of California. 347082Smckusick * All rights reserved. 447082Smckusick * 547082Smckusick * %sccs.include.redist.c% 622041Sdist */ 75329Smckusic 822041Sdist #ifndef lint 9*59925Storek static char sccsid[] = "@(#)traverse.c 5.25 (Berkeley) 05/11/93"; 1046584Storek #endif /* not lint */ 1122041Sdist 1257723Smckusick #include <sys/param.h> 1357723Smckusick #include <sys/time.h> 1457723Smckusick #include <sys/stat.h> 1550499Smckusick #ifdef sunos 1657723Smckusick #include <sys/vnode.h> 1757723Smckusick 1851605Sbostic #include <ufs/fs.h> 1957723Smckusick #include <ufs/fsdir.h> 2057723Smckusick #include <ufs/inode.h> 2150499Smckusick #else 2254070Smckusick #include <ufs/ffs/fs.h> 2351605Sbostic #include <ufs/ufs/dir.h> 2451605Sbostic #include <ufs/ufs/dinode.h> 2557723Smckusick #endif 2657723Smckusick 2746795Sbostic #include <protocols/dumprestore.h> 2857723Smckusick 2957723Smckusick #include <ctype.h> 3057723Smckusick #include <stdio.h> 3146795Sbostic #ifdef __STDC__ 3257723Smckusick #include <string.h> 3346795Sbostic #include <unistd.h> 3446795Sbostic #endif 3557723Smckusick 361426Sroot #include "dump.h" 371426Sroot 3846792Smckusick #define HASDUMPEDFILE 0x1 3946792Smckusick #define HASSUBDIRS 0x2 4046584Storek 41*59925Storek #ifdef FS_44INODEFMT 42*59925Storek typedef quad_t fsizeT; 43*59925Storek #else 44*59925Storek typedef long fsizeT; 45*59925Storek #endif 46*59925Storek 4757723Smckusick static int dirindir __P((ino_t ino, daddr_t blkno, int level, long *size)); 48*59925Storek static void dmpindir __P((ino_t ino, daddr_t blk, int level, fsizeT *size)); 4957723Smckusick static int searchdir __P((ino_t ino, daddr_t blkno, long size, long filesize)); 5057723Smckusick 5146584Storek /* 5246584Storek * This is an estimation of the number of TP_BSIZE blocks in the file. 5346584Storek * It estimates the number of blocks in files with holes by assuming 5446584Storek * that all of the blocks accounted for by di_blocks are data blocks 5546584Storek * (when some of the blocks are usually used for indirect pointers); 5646584Storek * hence the estimate may be high. 5746584Storek */ 5846792Smckusick long 5947058Smckusick blockest(dp) 6047058Smckusick register struct dinode *dp; 6146584Storek { 6246792Smckusick long blkest, sizeest; 6346584Storek 6446584Storek /* 6547058Smckusick * dp->di_size is the size of the file in bytes. 6647058Smckusick * dp->di_blocks stores the number of sectors actually in the file. 6746584Storek * If there are more sectors than the size would indicate, this just 6846584Storek * means that there are indirect blocks in the file or unused 6946584Storek * sectors in the last file block; we can safely ignore these 7046792Smckusick * (blkest = sizeest below). 7146584Storek * If the file is bigger than the number of sectors would indicate, 7246584Storek * then the file has holes in it. In this case we must use the 7346584Storek * block count to estimate the number of data blocks used, but 7446584Storek * we use the actual size for estimating the number of indirect 7546792Smckusick * dump blocks (sizeest vs. blkest in the indirect block 7646792Smckusick * calculation). 7746584Storek */ 7847058Smckusick blkest = howmany(dbtob(dp->di_blocks), TP_BSIZE); 7947058Smckusick sizeest = howmany(dp->di_size, TP_BSIZE); 8046792Smckusick if (blkest > sizeest) 8146792Smckusick blkest = sizeest; 8247058Smckusick if (dp->di_size > sblock->fs_bsize * NDADDR) { 8346584Storek /* calculate the number of indirect blocks on the dump tape */ 8446792Smckusick blkest += 8546792Smckusick howmany(sizeest - NDADDR * sblock->fs_bsize / TP_BSIZE, 8646584Storek TP_NINDIR); 8746584Storek } 8846792Smckusick return (blkest + 1); 8946584Storek } 9046584Storek 91*59925Storek /* Auxiliary macro to pick up files changed since previous dump. */ 92*59925Storek #ifdef FS_44INODEFMT 93*59925Storek #define CHANGEDSINCE(dp, t) \ 94*59925Storek ((dp)->di_mtime.ts_sec >= (t) || (dp)->di_ctime.ts_sec >= (t)) 95*59925Storek #else 96*59925Storek #define CHANGEDSINCE(dp, t) \ 97*59925Storek ((dp)->di_mtime >= (t) || (dp)->di_ctime >= (t)) 98*59925Storek #endif 99*59925Storek 100*59925Storek /* The WANTTODUMP macro decides whether a file should be dumped. */ 101*59925Storek #ifdef UF_NODUMP 102*59925Storek #define WANTTODUMP(dp) \ 103*59925Storek (CHANGEDSINCE(dp, spcl.c_ddate) && \ 104*59925Storek (nonodump || ((dp)->di_flags & UF_NODUMP) != UF_NODUMP)) 105*59925Storek #else 106*59925Storek #define WANTTODUMP(dp) CHANGEDSINCE(dp, spcl.c_ddate) 107*59925Storek #endif 108*59925Storek 10946792Smckusick /* 11046792Smckusick * Dump pass 1. 11146792Smckusick * 11246792Smckusick * Walk the inode list for a filesystem to find all allocated inodes 11346792Smckusick * that have been modified since the previous dump time. Also, find all 11446792Smckusick * the directories in the filesystem. 11546792Smckusick */ 11657723Smckusick int 11746792Smckusick mapfiles(maxino, tapesize) 11846792Smckusick ino_t maxino; 11946792Smckusick long *tapesize; 12046584Storek { 12146792Smckusick register int mode; 12246792Smckusick register ino_t ino; 12346792Smckusick register struct dinode *dp; 12446792Smckusick int anydirskipped = 0; 12546584Storek 126*59925Storek for (ino = ROOTINO; ino < maxino; ino++) { 12746792Smckusick dp = getino(ino); 12846792Smckusick if ((mode = (dp->di_mode & IFMT)) == 0) 12946792Smckusick continue; 13046792Smckusick SETINO(ino, usedinomap); 13146792Smckusick if (mode == IFDIR) 13246792Smckusick SETINO(ino, dumpdirmap); 133*59925Storek if (WANTTODUMP(dp)) { 13446792Smckusick SETINO(ino, dumpinomap); 135*59925Storek if (mode != IFREG && mode != IFDIR && mode != IFLNK) 13646792Smckusick *tapesize += 1; 137*59925Storek else 138*59925Storek *tapesize += blockest(dp); 13946792Smckusick continue; 14046792Smckusick } 14146792Smckusick if (mode == IFDIR) 14246792Smckusick anydirskipped = 1; 14346792Smckusick } 14446792Smckusick /* 14546792Smckusick * Restore gets very upset if the root is not dumped, 14646792Smckusick * so ensure that it always is dumped. 14746792Smckusick */ 14851374Smckusick SETINO(ROOTINO, dumpinomap); 14946792Smckusick return (anydirskipped); 15046584Storek } 15146584Storek 15246792Smckusick /* 15346792Smckusick * Dump pass 2. 15446792Smckusick * 15546792Smckusick * Scan each directory on the filesystem to see if it has any modified 15646792Smckusick * files in it. If it does, and has not already been added to the dump 15746792Smckusick * list (because it was itself modified), then add it. If a directory 15846792Smckusick * has not been modified itself, contains no modified files and has no 15946792Smckusick * subdirectories, then it can be deleted from the dump list and from 16046792Smckusick * the list of directories. By deleting it from the list of directories, 16146792Smckusick * its parent may now qualify for the same treatment on this or a later 16246792Smckusick * pass using this algorithm. 16346792Smckusick */ 16457723Smckusick int 16546792Smckusick mapdirs(maxino, tapesize) 16646792Smckusick ino_t maxino; 16746792Smckusick long *tapesize; 16846792Smckusick { 16946792Smckusick register struct dinode *dp; 17055390Smckusick register int i, isdir; 17125797Smckusick register char *map; 17246792Smckusick register ino_t ino; 17354070Smckusick long filesize; 17446792Smckusick int ret, change = 0; 1751426Sroot 176*59925Storek isdir = 0; /* XXX just to get gcc to shut up */ 177*59925Storek for (map = dumpdirmap, ino = 1; ino < maxino; ino++) { 178*59925Storek if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */ 17955390Smckusick isdir = *map++; 18046792Smckusick else 18155390Smckusick isdir >>= 1; 18255390Smckusick if ((isdir & 1) == 0 || TSTINO(ino, dumpinomap)) 18346792Smckusick continue; 18446792Smckusick dp = getino(ino); 18546792Smckusick filesize = dp->di_size; 18646792Smckusick for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) { 18746792Smckusick if (dp->di_db[i] != 0) 18846792Smckusick ret |= searchdir(ino, dp->di_db[i], 18955390Smckusick (long)dblksize(sblock, dp, i), 19055390Smckusick filesize); 19146792Smckusick if (ret & HASDUMPEDFILE) 19246792Smckusick filesize = 0; 19346792Smckusick else 19446792Smckusick filesize -= sblock->fs_bsize; 19546792Smckusick } 19646792Smckusick for (i = 0; filesize > 0 && i < NIADDR; i++) { 19746792Smckusick if (dp->di_ib[i] == 0) 19846792Smckusick continue; 19946792Smckusick ret |= dirindir(ino, dp->di_ib[i], i, &filesize); 20046792Smckusick } 20146792Smckusick if (ret & HASDUMPEDFILE) { 20255390Smckusick SETINO(ino, dumpinomap); 20355390Smckusick *tapesize += blockest(dp); 20446792Smckusick change = 1; 20546792Smckusick continue; 20646792Smckusick } 20746792Smckusick if ((ret & HASSUBDIRS) == 0) { 20846792Smckusick if (!TSTINO(ino, dumpinomap)) { 20946792Smckusick CLRINO(ino, dumpdirmap); 21046792Smckusick change = 1; 21146792Smckusick } 21246792Smckusick } 2131426Sroot } 21446792Smckusick return (change); 2151426Sroot } 2161426Sroot 21746792Smckusick /* 21846792Smckusick * Read indirect blocks, and pass the data blocks to be searched 21946792Smckusick * as directories. Quit as soon as any entry is found that will 22046792Smckusick * require the directory to be dumped. 22146792Smckusick */ 22257723Smckusick static int 22354070Smckusick dirindir(ino, blkno, ind_level, filesize) 22446792Smckusick ino_t ino; 22546792Smckusick daddr_t blkno; 22654070Smckusick int ind_level; 22754070Smckusick long *filesize; 2281426Sroot { 22946792Smckusick int ret = 0; 23046792Smckusick register int i; 23146792Smckusick daddr_t idblk[MAXNINDIR]; 2321426Sroot 23354070Smckusick bread(fsbtodb(sblock, blkno), (char *)idblk, (int)sblock->fs_bsize); 23454070Smckusick if (ind_level <= 0) { 23546792Smckusick for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) { 23646792Smckusick blkno = idblk[i]; 23746792Smckusick if (blkno != 0) 23846796Smckusick ret |= searchdir(ino, blkno, sblock->fs_bsize, 23954070Smckusick *filesize); 24046792Smckusick if (ret & HASDUMPEDFILE) 24146792Smckusick *filesize = 0; 24246792Smckusick else 24346792Smckusick *filesize -= sblock->fs_bsize; 2441426Sroot } 24546792Smckusick return (ret); 2465329Smckusic } 24754070Smckusick ind_level--; 24846792Smckusick for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) { 24946792Smckusick blkno = idblk[i]; 25046792Smckusick if (blkno != 0) 25154070Smckusick ret |= dirindir(ino, blkno, ind_level, filesize); 2525329Smckusic } 25346792Smckusick return (ret); 2541426Sroot } 2551426Sroot 25646792Smckusick /* 25746792Smckusick * Scan a disk block containing directory information looking to see if 25846792Smckusick * any of the entries are on the dump list and to see if the directory 25946792Smckusick * contains any subdirectories. 26046792Smckusick */ 26157723Smckusick static int 26246796Smckusick searchdir(ino, blkno, size, filesize) 26346792Smckusick ino_t ino; 26446792Smckusick daddr_t blkno; 26554070Smckusick register long size; 26654070Smckusick long filesize; 2675329Smckusic { 26846792Smckusick register struct direct *dp; 26955390Smckusick register long loc, ret = 0; 27046792Smckusick char dblk[MAXBSIZE]; 2715329Smckusic 27254070Smckusick bread(fsbtodb(sblock, blkno), dblk, (int)size); 27346796Smckusick if (filesize < size) 27446796Smckusick size = filesize; 27546792Smckusick for (loc = 0; loc < size; ) { 27646792Smckusick dp = (struct direct *)(dblk + loc); 27746792Smckusick if (dp->d_reclen == 0) { 27846792Smckusick msg("corrupted directory, inumber %d\n", ino); 27946792Smckusick break; 2805329Smckusic } 28146792Smckusick loc += dp->d_reclen; 28246792Smckusick if (dp->d_ino == 0) 28346792Smckusick continue; 28446792Smckusick if (dp->d_name[0] == '.') { 28546792Smckusick if (dp->d_name[1] == '\0') 28646792Smckusick continue; 28746792Smckusick if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') 28846792Smckusick continue; 2895329Smckusic } 29055390Smckusick if (TSTINO(dp->d_ino, dumpinomap)) { 29155390Smckusick ret |= HASDUMPEDFILE; 29255390Smckusick if (ret & HASSUBDIRS) 29355390Smckusick break; 29455390Smckusick } 29555390Smckusick if (TSTINO(dp->d_ino, dumpdirmap)) { 29655390Smckusick ret |= HASSUBDIRS; 29755390Smckusick if (ret & HASDUMPEDFILE) 29855390Smckusick break; 29955390Smckusick } 3005329Smckusic } 30155390Smckusick return (ret); 3025329Smckusic } 3035329Smckusic 30446792Smckusick /* 30546792Smckusick * Dump passes 3 and 4. 30646792Smckusick * 30746792Smckusick * Dump the contents of an inode to tape. 30846792Smckusick */ 30946584Storek void 31047058Smckusick dumpino(dp, ino) 31147058Smckusick register struct dinode *dp; 31246792Smckusick ino_t ino; 31317234Smckusick { 31454596Smckusick int ind_level, cnt; 315*59925Storek fsizeT size; 31654596Smckusick char buf[TP_BSIZE]; 3171426Sroot 31846792Smckusick if (newtape) { 3191426Sroot newtape = 0; 32046792Smckusick dumpmap(dumpinomap, TS_BITS, ino); 3211426Sroot } 32246792Smckusick CLRINO(ino, dumpinomap); 32347058Smckusick spcl.c_dinode = *dp; 3241426Sroot spcl.c_type = TS_INODE; 3251426Sroot spcl.c_count = 0; 32657723Smckusick switch (dp->di_mode & S_IFMT) { 32754596Smckusick 32857723Smckusick case 0: 32954596Smckusick /* 33054596Smckusick * Freed inode. 33154596Smckusick */ 33217234Smckusick return; 33354596Smckusick 33457723Smckusick case S_IFLNK: 33554596Smckusick /* 33654596Smckusick * Check for short symbolic link. 33754596Smckusick */ 33857723Smckusick #ifdef FS_44INODEFMT 33954596Smckusick if (dp->di_size > 0 && 34054596Smckusick dp->di_size < sblock->fs_maxsymlinklen) { 34154596Smckusick spcl.c_addr[0] = 1; 34254596Smckusick spcl.c_count = 1; 34354596Smckusick writeheader(ino); 34454596Smckusick bcopy((caddr_t)dp->di_shortlink, buf, 34554596Smckusick (u_long)dp->di_size); 34654596Smckusick buf[dp->di_size] = '\0'; 34754596Smckusick writerec(buf, 0); 34854596Smckusick return; 34954596Smckusick } 35057723Smckusick #endif 35154596Smckusick /* fall through */ 35254596Smckusick 35357723Smckusick case S_IFDIR: 35457723Smckusick case S_IFREG: 35554596Smckusick if (dp->di_size > 0) 35654596Smckusick break; 35754596Smckusick /* fall through */ 35854596Smckusick 35957723Smckusick case S_IFIFO: 36057723Smckusick case S_IFSOCK: 36157723Smckusick case S_IFCHR: 36257723Smckusick case S_IFBLK: 36346792Smckusick writeheader(ino); 3641426Sroot return; 36554596Smckusick 36654596Smckusick default: 36754596Smckusick msg("Warning: undefined file type 0%o\n", dp->di_mode & IFMT); 36854596Smckusick return; 3691426Sroot } 37047058Smckusick if (dp->di_size > NDADDR * sblock->fs_bsize) 37146792Smckusick cnt = NDADDR * sblock->fs_frag; 3724777Smckusic else 37347058Smckusick cnt = howmany(dp->di_size, sblock->fs_fsize); 37447058Smckusick blksout(&dp->di_db[0], cnt, ino); 37547058Smckusick if ((size = dp->di_size - NDADDR * sblock->fs_bsize) <= 0) 3764777Smckusic return; 37754070Smckusick for (ind_level = 0; ind_level < NIADDR; ind_level++) { 37854070Smckusick dmpindir(ino, dp->di_ib[ind_level], ind_level, &size); 3794777Smckusic if (size <= 0) 3804777Smckusic return; 3814777Smckusic } 3821426Sroot } 3831426Sroot 38446792Smckusick /* 38546792Smckusick * Read indirect blocks, and pass the data blocks to be dumped. 38646792Smckusick */ 38757723Smckusick static void 38854070Smckusick dmpindir(ino, blk, ind_level, size) 38946792Smckusick ino_t ino; 3904777Smckusic daddr_t blk; 39154070Smckusick int ind_level; 392*59925Storek fsizeT *size; 3931426Sroot { 3944777Smckusic int i, cnt; 3955329Smckusic daddr_t idblk[MAXNINDIR]; 3961426Sroot 3974777Smckusic if (blk != 0) 39854070Smckusick bread(fsbtodb(sblock, blk), (char *)idblk, (int) sblock->fs_bsize); 3994777Smckusic else 40054070Smckusick bzero((char *)idblk, (int)sblock->fs_bsize); 40154070Smckusick if (ind_level <= 0) { 4025329Smckusic if (*size < NINDIR(sblock) * sblock->fs_bsize) 4035329Smckusic cnt = howmany(*size, sblock->fs_fsize); 4044777Smckusic else 4055329Smckusic cnt = NINDIR(sblock) * sblock->fs_frag; 4065329Smckusic *size -= NINDIR(sblock) * sblock->fs_bsize; 40746792Smckusick blksout(&idblk[0], cnt, ino); 4084777Smckusic return; 4091426Sroot } 41054070Smckusick ind_level--; 4115329Smckusic for (i = 0; i < NINDIR(sblock); i++) { 41254070Smckusick dmpindir(ino, idblk[i], ind_level, size); 4134777Smckusic if (*size <= 0) 4144777Smckusic return; 4154777Smckusic } 4161426Sroot } 4171426Sroot 41846792Smckusick /* 41946792Smckusick * Collect up the data into tape record sized buffers and output them. 42046792Smckusick */ 42146584Storek void 42246792Smckusick blksout(blkp, frags, ino) 4234777Smckusic daddr_t *blkp; 4244777Smckusic int frags; 42546792Smckusick ino_t ino; 4264777Smckusic { 42746584Storek register daddr_t *bp; 4285329Smckusic int i, j, count, blks, tbperdb; 4294777Smckusic 4309403Smckusick blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); 43146584Storek tbperdb = sblock->fs_bsize >> tp_bshift; 4324777Smckusic for (i = 0; i < blks; i += TP_NINDIR) { 4334777Smckusic if (i + TP_NINDIR > blks) 4344777Smckusic count = blks; 4354777Smckusic else 4364777Smckusic count = i + TP_NINDIR; 4374777Smckusic for (j = i; j < count; j++) 4385329Smckusic if (blkp[j / tbperdb] != 0) 4394777Smckusic spcl.c_addr[j - i] = 1; 4404777Smckusic else 4414777Smckusic spcl.c_addr[j - i] = 0; 4424777Smckusic spcl.c_count = count - i; 44346792Smckusick writeheader(ino); 44446584Storek bp = &blkp[i / tbperdb]; 44546584Storek for (j = i; j < count; j += tbperdb, bp++) 44646584Storek if (*bp != 0) 4475329Smckusic if (j + tbperdb <= count) 44854070Smckusick dumpblock(*bp, (int)sblock->fs_bsize); 4494777Smckusic else 45046792Smckusick dumpblock(*bp, (count - j) * TP_BSIZE); 4514777Smckusic spcl.c_type = TS_ADDR; 4524777Smckusic } 4534777Smckusic } 4544777Smckusic 45546792Smckusick /* 45646792Smckusick * Dump a map to the tape. 45746792Smckusick */ 45846584Storek void 45946792Smckusick dumpmap(map, type, ino) 4605329Smckusic char *map; 46146792Smckusick int type; 46246792Smckusick ino_t ino; 4631426Sroot { 46446792Smckusick register int i; 4651426Sroot char *cp; 4661426Sroot 46746792Smckusick spcl.c_type = type; 46846792Smckusick spcl.c_count = howmany(mapsize * sizeof(char), TP_BSIZE); 46946792Smckusick writeheader(ino); 4705329Smckusic for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE) 47154596Smckusick writerec(cp, 0); 4721426Sroot } 4731426Sroot 47446792Smckusick /* 47546792Smckusick * Write a header record to the dump tape. 47646792Smckusick */ 47746584Storek void 47846792Smckusick writeheader(ino) 47946792Smckusick ino_t ino; 4801426Sroot { 48146792Smckusick register long sum, cnt, *lp; 4821426Sroot 4831426Sroot spcl.c_inumber = ino; 4848368Smckusick spcl.c_magic = NFS_MAGIC; 4851426Sroot spcl.c_checksum = 0; 48646792Smckusick lp = (long *)&spcl; 48746792Smckusick sum = 0; 48846792Smckusick cnt = sizeof(union u_spcl) / (4 * sizeof(long)); 48946792Smckusick while (--cnt >= 0) { 49046792Smckusick sum += *lp++; 49146792Smckusick sum += *lp++; 49246792Smckusick sum += *lp++; 49346792Smckusick sum += *lp++; 49424168Smckusick } 49546792Smckusick spcl.c_checksum = CHECKSUM - sum; 49654596Smckusick writerec((char *)&spcl, 1); 4971426Sroot } 4981426Sroot 4994702Smckusic struct dinode * 50046792Smckusick getino(inum) 50146792Smckusick ino_t inum; 5024702Smckusic { 5034702Smckusic static daddr_t minino, maxino; 50446792Smckusick static struct dinode inoblock[MAXINOPB]; 5054702Smckusic 50646792Smckusick curino = inum; 50746792Smckusick if (inum >= minino && inum < maxino) 50846792Smckusick return (&inoblock[inum - minino]); 50954070Smckusick bread(fsbtodb(sblock, itod(sblock, inum)), (char *)inoblock, 51054070Smckusick (int)sblock->fs_bsize); 51146792Smckusick minino = inum - (inum % INOPB(sblock)); 5125329Smckusic maxino = minino + INOPB(sblock); 51346792Smckusick return (&inoblock[inum - minino]); 5144702Smckusic } 5154702Smckusic 51646792Smckusick /* 51746792Smckusick * Read a chunk of data from the disk. 51846792Smckusick * Try to recover from hard errors by reading in sector sized pieces. 51946792Smckusick * Error recovery is attempted at most BREADEMAX times before seeking 52046792Smckusick * consent from the operator to continue. 52146792Smckusick */ 5221426Sroot int breaderrors = 0; 5231426Sroot #define BREADEMAX 32 5241426Sroot 52546584Storek void 52646792Smckusick bread(blkno, buf, size) 52746792Smckusick daddr_t blkno; 52846792Smckusick char *buf; 52946792Smckusick int size; 5301426Sroot { 53146792Smckusick int cnt, i; 53234359Skarels extern int errno; 5331426Sroot 53415095Smckusick loop: 53554070Smckusick if ((int)lseek(diskfd, ((off_t)blkno << dev_bshift), 0) < 0) 5361426Sroot msg("bread: lseek fails\n"); 53746792Smckusick if ((cnt = read(diskfd, buf, size)) == size) 53815095Smckusick return; 53946792Smckusick if (blkno + (size / dev_bsize) > fsbtodb(sblock, sblock->fs_size)) { 54015095Smckusick /* 54115095Smckusick * Trying to read the final fragment. 54215095Smckusick * 54315095Smckusick * NB - dump only works in TP_BSIZE blocks, hence 54430560Smckusick * rounds `dev_bsize' fragments up to TP_BSIZE pieces. 54515095Smckusick * It should be smarter about not actually trying to 54615095Smckusick * read more than it can get, but for the time being 54715095Smckusick * we punt and scale back the read only when it gets 54815095Smckusick * us into trouble. (mkm 9/25/83) 54915095Smckusick */ 55046792Smckusick size -= dev_bsize; 55115095Smckusick goto loop; 5521426Sroot } 55350905Smckusick if (cnt == -1) 55450905Smckusick msg("read error from %s: %s: [block %d]: count=%d\n", 55550905Smckusick disk, strerror(errno), blkno, size); 55650905Smckusick else 55750905Smckusick msg("short read error from %s: [block %d]: count=%d, got=%d\n", 55850905Smckusick disk, blkno, size, cnt); 55946584Storek if (++breaderrors > BREADEMAX) { 56015095Smckusick msg("More than %d block read errors from %d\n", 56115095Smckusick BREADEMAX, disk); 56215095Smckusick broadcast("DUMP IS AILING!\n"); 56315095Smckusick msg("This is an unrecoverable error.\n"); 56415095Smckusick if (!query("Do you want to attempt to continue?")){ 56555288Sbostic dumpabort(0); 56615095Smckusick /*NOTREACHED*/ 56715095Smckusick } else 56815095Smckusick breaderrors = 0; 56915095Smckusick } 57034359Skarels /* 57134359Skarels * Zero buffer, then try to read each sector of buffer separately. 57234359Skarels */ 57346792Smckusick bzero(buf, size); 57446792Smckusick for (i = 0; i < size; i += dev_bsize, buf += dev_bsize, blkno++) { 57554070Smckusick if ((int)lseek(diskfd, ((off_t)blkno << dev_bshift), 0) < 0) 57634359Skarels msg("bread: lseek2 fails!\n"); 57754070Smckusick if ((cnt = read(diskfd, buf, (int)dev_bsize)) == dev_bsize) 57850905Smckusick continue; 57950905Smckusick if (cnt == -1) { 58050905Smckusick msg("read error from %s: %s: [sector %d]: count=%d\n", 58150905Smckusick disk, strerror(errno), blkno, dev_bsize); 58250905Smckusick continue; 58350905Smckusick } 58450905Smckusick msg("short read error from %s: [sector %d]: count=%d, got=%d\n", 58550905Smckusick disk, blkno, dev_bsize, cnt); 58634359Skarels } 5871426Sroot } 588