📄 fsck1.c
字号:
if ((short) sb.s_firstdatazone <= 1) fatal("first data zone too small"); if ((short) sb.s_log_zone_size < 0) fatal("zone size < block size"); if (sb.s_max_size <= 0) fatal("max. file size <= 0");}/* Check the super block for reasonable contents. */void chksuper(){ register n; register off_t maxsize; n = bitmapsize((bit_t) sb.s_ninodes + 1); if (sb.s_magic != SUPER_MAGIC) fatal("bad magic number in super block"); if ((short) sb.s_imap_blocks < n) fatal("too few imap blocks"); if (sb.s_imap_blocks != n) { pr("warning: expected %d imap_block%s", n, "", "s"); printf(" instead of %d\n", sb.s_imap_blocks); } n = bitmapsize((bit_t) sb.s_nzones); if ((short) sb.s_zmap_blocks < n) fatal("too few zmap blocks"); if (sb.s_zmap_blocks != n) { pr("warning: expected %d zmap_block%s", n, "", "s"); printf(" instead of %d\n", sb.s_zmap_blocks); } if (sb.s_firstdatazone >= sb.s_nzones) fatal("first data zone too large"); if ((unsigned short) sb.s_log_zone_size >= 8 * sizeof(block_nr)) fatal("log_zone_size too large"); if (sb.s_log_zone_size > 8) printf("warning: large log_zone_size (%d)\n", sb.s_log_zone_size); n = (BLK_ILIST + N_ILIST + SCALE - 1) >> sb.s_log_zone_size; if ((short) sb.s_firstdatazone < n) fatal("first data zone too small"); if (sb.s_firstdatazone != n) { printf("warning: expected first data zone to be %d ", n); printf("instead of %u\n", sb.s_firstdatazone); } maxsize = MAX_FILE_POS; if (((maxsize - 1) >> sb.s_log_zone_size) / BLOCK_SIZE >= MAX_ZONES) maxsize = ((long) MAX_ZONES * BLOCK_SIZE) << sb.s_log_zone_size; if (sb.s_max_size != maxsize) { printf("warning: expected max size to be %ld ", maxsize); printf("instead of %ld\n", sb.s_max_size); }}/* Make a listing of the inodes given by `clist'. If `repair' is set, ask * the user for changes. */void lsi(clist)char **clist;{ register bit_nr bit; register ino_t ino; d_inode inode, *ip = &inode; char buf[80]; if (clist == 0) return; while ((bit = getnumber(*clist++)) != NO_BIT) { setbit(spec_imap, bit); ino = bit; do { devread(inoaddr(ino), (char *) ip, INODE_SIZE); printf("inode %u:\n", ino); printf(" mode = %06o", ip->i_mode); if (input(buf, 80)) ip->i_mode = atoo(buf); printf(" nlinks = %6u", ip->i_nlinks); if (input(buf, 80)) ip->i_nlinks = atol(buf); printf(" size = %6ld", ip->i_size); if (input(buf, 80)) ip->i_size = atol(buf); if (yes("Write this back")) { devwrite(inoaddr(ino), (char *) ip, INODE_SIZE); break; } } while (yes("Do you want to change it again")); }}/* Allocate `nblk' blocks worth of bitmap. */bitchunk_t *allocbitmap(nblk)int nblk;{ register bitchunk_t *bitmap; bitmap = (bitchunk_t *) alloc(nblk, BLOCK_SIZE); *bitmap |= 1; return(bitmap);}/* Load the bitmap starting at block `bno' from disk. */void loadbitmap(bitmap, bno, nblk)bitchunk_t *bitmap;block_nr bno;int nblk;{ register i; register bitchunk_t *p; p = bitmap; for (i = 0; i < nblk; i++, bno++, p += WORDS_PER_BLOCK) devread(btoa(bno), (char *) p, BLOCK_SIZE); *bitmap |= 1;}/* Write the bitmap starting at block `bno' to disk. */void dumpbitmap(bitmap, bno, nblk)bitchunk_t *bitmap;block_nr bno;int nblk;{ register i; register bitchunk_t *p = bitmap; for (i = 0; i < nblk; i++, bno++, p += WORDS_PER_BLOCK) devwrite(btoa(bno), (char *) p, BLOCK_SIZE);}/* Set the bits given by `list' in the bitmap. */void fillbitmap(bitmap, lwb, upb, list)bitchunk_t *bitmap;bit_nr lwb, upb;char **list;{ register bit_nr bit; if (list == 0) return; while ((bit = getnumber(*list++)) != NO_BIT) if (bit < lwb || bit >= upb) { if (bitmap == spec_imap) printf("inode number %u ", bit); else printf("zone number %u ", bit); printf("out of range (ignored)\n"); } else setbit(bitmap, bit - lwb + 1);}/* Deallocate the bitmap `p'. */void freebitmap(p)bitchunk_t *p;{ free((char *) p);}/* Get all the bitmaps used by this program. */void getbitmaps(){ imap = allocbitmap(N_IMAP); zmap = allocbitmap(N_ZMAP); spec_imap = allocbitmap(N_IMAP); spec_zmap = allocbitmap(N_ZMAP); dirmap = allocbitmap(N_IMAP);}/* Release all the space taken by the bitmaps. */void putbitmaps(){ freebitmap(imap); freebitmap(zmap); freebitmap(spec_imap); freebitmap(spec_zmap); freebitmap(dirmap);}/* `w1' and `w2' are differing words from two bitmaps that should be * identical. Print what's the matter with them. */void chkword(w1, w2, bit, type, n, report)unsigned w1, w2;char *type;bit_nr bit;int *n, *report;{ for (; (w1 | w2); w1 >>= 1, w2 >>= 1, bit++) if ((w1 ^ w2) & 1 && ++(*n) % MAXPRINT == 0 && *report && (!repair || automatic || yes("stop this listing"))) *report = 0; else if (*report) if ((w1 & 1) && !(w2 & 1)) printf("%s %u is missing\n", type, bit); else if (!(w1 & 1) && (w2 & 1)) printf("%s %u is not free\n", type, bit);}/* Check if the given (correct) bitmap is identical with the one that is * on the disk. If not, ask if the disk should be repaired. */void chkmap(cmap, dmap, bit, blkno, nblk, type)bitchunk_t *cmap, *dmap;bit_nr bit;block_nr blkno;int nblk;char *type;{ register bitchunk_t *p = dmap, *q = cmap; int report = 1, nerr = 0; int w = nblk * WORDS_PER_BLOCK; printf("Checking %s map\n", type); loadbitmap(dmap, blkno, nblk); do { if (*p != *q) chkword(*p, *q, bit, type, &nerr, &report); p++; q++; bit += 8 * sizeof(bitchunk_t); } while (--w > 0); if ((!repair || automatic) && !report) printf("etc. "); if (nerr > MAXPRINT || nerr > 10) printf("%d errors found. ", nerr); if (nerr != 0 && yes("install a new map")) dumpbitmap(cmap, blkno, nblk); if (nerr > 0) printf("\n");}/* See if the inodes that aren't allocated are cleared. */void chkilist(){ register ino_t ino = 1; mode_t mode; printf("Checking inode list\n"); do if (!bitset(imap, (bit_nr) ino)) { devread(inoaddr(ino), (char *) &mode, sizeof(mode)); if (mode != I_NOT_ALLOC) { printf("mode inode %u not cleared", ino); if (yes(". clear")) devwrite(inoaddr(ino), nullbuf, INODE_SIZE); } } while (++ino <= sb.s_ninodes); printf("\n");}/* Allocate an array to maintain the inode reference counts in. */void getcount(){ count = (nlink_t *) alloc(sb.s_ninodes + 1, sizeof(nlink_t));}/* The reference count for inode `ino' is wrong. Ask if it should be adjusted. */void counterror(ino)ino_t ino;{ d_inode inode; if (firstcnterr) { printf("INODE NLINK COUNT\n"); firstcnterr = 0; } devread(inoaddr(ino), (char *) &inode, INODE_SIZE); count[ino] += inode.i_nlinks; printf("%5u %5u %5u", ino, (unsigned) inode.i_nlinks, count[ino]); if (yes(" adjust")) { if ((inode.i_nlinks = count[ino]) == 0) { fatal("internal error (counterror)");/* This would be a patch inode.i_mode = I_NOT_ALLOC; clrbit(imap, (bit_nr) ino);*/ } devwrite(inoaddr(ino), (char *) &inode, INODE_SIZE); }}/* Check if the reference count of the inodes are correct. The array `count' * is maintained as follows: an entry indexed by the inode number is * incremented each time a link is found; when the inode is read the link * count in there is substracted from the corresponding entry in `count'. * Thus, when the whole file system has been traversed, all the entries * should be zero. */void chkcount(){ register ino_t ino; for (ino = 1; ino <= sb.s_ninodes; ino++) if (count[ino] != 0) counterror(ino); if (!firstcnterr) printf("\n");}/* Deallocate the `count' array. */void freecount(){ free((char *) count);}/* Print the inode permission bits given by mode and shift. */void printperm(mode, shift, special, overlay)mode_t mode;int shift;int special;int overlay;{ if (mode >> shift & R_BIT) putchar('r'); else putchar('-'); if (mode >> shift & W_BIT) putchar('w'); else putchar('-'); if (mode & special) putchar(overlay); else if (mode >> shift & X_BIT) putchar('x'); else putchar('-');}/* List the given inode. */void list(ino, ip)ino_t ino;d_inode *ip;{ if (firstlist) { firstlist = 0; printf(" inode permission link size name\n"); } printf("%6u ", ino); switch (ip->i_mode & I_TYPE) { case I_REGULAR: putchar('-'); break; case I_DIRECTORY: putchar('d'); break; case I_CHAR_SPECIAL: putchar('c'); break; case I_BLOCK_SPECIAL: putchar('b'); break; case I_NAMED_PIPE: putchar('p'); break;#ifdef I_SYMBOLIC_LINK case I_SYMBOLIC_LINK: putchar('l'); break;#endif default: putchar('?');} printperm(ip->i_mode, 6, I_SET_UID_BIT, 's'); printperm(ip->i_mode, 3, I_SET_GID_BIT, 's'); printperm(ip->i_mode, 0, STICKY_BIT, 't'); printf(" %3u ", ip->i_nlinks); switch (ip->i_mode & I_TYPE) { case I_CHAR_SPECIAL: case I_BLOCK_SPECIAL: printf(" %2x,%2x ", (dev_t) ip->i_zone[0] >> MAJOR & 0xFF, (dev_t) ip->i_zone[0] >> MINOR & 0xFF); break; default: printf("%7ld ", ip->i_size); } printpath(0, 1);}/* Remove an entry from a directory if ok with the user. * Don't name the function remove() - that is owned by ANSI, and chaos results * when it is a macro. */int Remove(dp)dir_struct *dp;{ setbit(spec_imap, (bit_nr) dp->d_inum); if (yes(". remove entry")) { count[dp->d_inum]--; memset((void *) dp, 0, sizeof(dir_struct)); return(1); } return(0);}/* Convert string so that embedded control characters are printable. */void make_printable_name(dst, src, n)register char *dst;register char *src;register int n;{ register int c; while (--n >= 0 && (c = *src++) != '\0') { if (isprint(c) && c != '\\') *dst++ = c; else { *dst++ = '\\'; switch (c) { case '\\': *dst++ = '\\'; break; case '\b': *dst++ = 'b'; break; case '\f': *dst++ = 'f'; break; case '\n': *dst++ = 'n'; break; case '\r': *dst++ = 'r'; break; case '\t': *dst++ = 't'; break; default: *dst++ = '0' + ((c >> 6) & 03); *dst++ = '0' + ((c >> 3) & 07); *dst++ = '0' + (c & 07); } } } *dst = '\0';}/* See if the `.' or `..' entry is as expected. */int chkdots(ino, pos, dp, exp)ino_t ino, exp;off_t pos;dir_struct *dp;{ char printable_name[4 * NAME_MAX + 1]; if (dp->d_inum != exp) { make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name)); printf("bad %s in ", printable_name); printpath(1, 0); printf("%s is linked to %u ", printable_name, dp->d_inum); printf("instead of %u)", exp); setbit(spec_imap, (bit_nr) ino); setbit(spec_imap, (bit_nr) dp->d_inum); setbit(spec_imap, (bit_nr) exp); if (yes(". repair")) { count[dp->d_inum]--; dp->d_inum = exp; count[exp]++; return(0); } } else if (pos != (dp->d_name[1] ? DIR_ENTRY_SIZE : 0)) { make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name)); printf("warning: %s has offset %ld in ", printable_name, pos); printpath(1, 0); printf("%s is linked to %u)\n", printable_name, dp->d_inum); setbit(spec_imap, (bit_nr) ino); setbit(spec_imap, (bit_nr) dp->d_inum); setbit(spec_imap, (bit_nr) exp); } return(1);}/* Check the name in a directory entry. */int chkname(ino, dp)ino_t ino;dir_struct *dp;{ register n = NAME_MAX + 1; register char *p = dp->d_name; if (*p == '\0') { printf("null name found in "); printpath(0, 0); setbit(spec_imap, (bit_nr) ino); if (Remove(dp)) return(0); } while (*p != '\0' && --n != 0) if (*p++ == '/') { printf("found a '/' in entry of directory "); printpath(1, 0); setbit(spec_imap, (bit_nr) ino); printf("entry = '"); printname(dp->d_name); printf("')"); if (Remove(dp)) return(0); break; } return(1);}/* Check a directory entry. Here the routine `descendtree' is called * recursively to check the file or directory pointed to by the entry. */int chkentry(ino, pos, dp)ino_t ino;off_t pos;dir_struct *dp;{ if (dp->d_inum < ROOT_INODE || dp->d_inum > sb.s_ninodes) { printf("bad inode found in directory "); printpath(1, 0); printf("ino found = %u, ", dp->d_inum); printf("name = '"); printname(dp->d_name); printf("')"); if (yes(". remove entry")) { memset((void *) dp, 0, sizeof(dir_struct)); return(0); } return(1); } if ((unsigned) count[dp->d_inum] == LINK_MAX) { printf("too many links to ino %u\n", dp->d_inum); printf("discovered at entry '"); printname(dp->d_name); printf("' in directory "); printpath(0, 1); if (Remove(dp)) return(0); } count[dp->d_inum]++; if (strcmp(dp->d_name, ".") == 0) { ftop->st_presence |= DOT; return(chkdots(ino, pos, dp, ino)); } if (strcmp(dp->d_name, "..") == 0) { ftop->st_presence |= DOTDOT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -