📄 fsck1.c
字号:
return(chkdots(ino, pos, dp, ino == ROOT_INODE ? ino : ftop->st_next->st_dir->d_inum)); } if (!chkname(ino, dp)) return(0); if (bitset(dirmap, (bit_nr) dp->d_inum)) { printf("link to directory discovered in "); printpath(1, 0); printf("name = '"); printname(dp->d_name); printf("', dir ino = %u)", dp->d_inum); return !Remove(dp); } return(descendtree(dp));}/* Check a zone of a directory by checking all the entries in the zone. * The zone is split up into chunks to not allocate too much stack. */int chkdirzone(ino, ip, pos, zno)ino_t ino;d_inode *ip;off_t pos;zone_nr zno;{ dir_struct dirblk[CDIRECT]; register dir_struct *dp; register n = SCALE * (NR_DIR_ENTRIES / CDIRECT), dirty; register long offset = zaddr(zno); register off_t size = 0; do { devread(offset, (char *) dirblk, DIRCHUNK); dirty = 0; for (dp = dirblk; dp < &dirblk[CDIRECT]; dp++) { if (dp->d_inum != NO_ENTRY && !chkentry(ino, pos, dp)) dirty = 1; pos += DIR_ENTRY_SIZE; if (dp->d_inum != NO_ENTRY) size = pos; } if (dirty) devwrite(offset, (char *) dirblk, DIRCHUNK); offset += DIRCHUNK; } while (--n); if (size > ip->i_size) { printf("size not updated of directory "); printpath(2, 0); if (yes(". extend")) { setbit(spec_imap, (bit_nr) ino); ip->i_size = size; devwrite(inoaddr(ino), (char *) ip, INODE_SIZE); } } return(1);}/* There is something wrong with the given zone. Print some details. */void errzone(mess, zno, level, pos)char *mess;zone_nr zno;int level;off_t pos;{ printf("%s zone in ", mess); printpath(1, 0); printf("zno = %u, type = ", zno); switch (level) { case 0: printf("DATA"); break; case 1: printf("SINGLE INDIRECT"); break; case 2: printf("DOUBLE INDIRECT"); break; default: printf("VERY INDIRECT"); } printf(", pos = %ld)\n", pos);}/* Found the given zone in the given inode. Check it, and if ok, mark it * in the zone bitmap. */int markzone(ino, zno, level, pos)ino_t ino;zone_nr zno;int level;off_t pos;{ register bit_nr bit = (bit_nr) zno - FIRST + 1; ztype[level]++; if (zno < FIRST || zno >= sb.s_nzones) { errzone("out-of-range", zno, level, pos); return(0); } if (bitset(zmap, bit)) { setbit(spec_zmap, bit); errzone("duplicate", zno, level, pos); return(0); } nfreezone--; if (bitset(spec_zmap, bit)) errzone("found", zno, level, pos); setbit(zmap, bit); return(1);}/* Check an indirect zone by checking all of its entries. * The zone is split up into chunks to not allocate too much stack. */int chkindzone(ino, ip, pos, zno, level)ino_t ino;d_inode *ip;off_t *pos;zone_nr zno;int level;{ zone_nr indirect[CINDIR]; register n = NR_INDIRECTS / CINDIR; register long offset = zaddr(zno); do { devread(offset, (char *) indirect, INDCHUNK); if (!chkzones(ino, ip, pos, indirect, CINDIR, level - 1)) return(0); offset += INDCHUNK; } while (--n && *pos < ip->i_size); return(1);}/* Return the size of a gap in the file, represented by a null zone number * at some level of indirection. */off_t jump(level)int level;{ off_t power = ZONE_SIZE; if (level != 0) do power *= NR_INDIRECTS; while (--level); return(power);}/* Check a zone, which may be either a normal data zone, a directory zone, * or an indirect zone. */int zonechk(ino, ip, pos, zno, level)ino_t ino;d_inode *ip;off_t *pos;zone_nr zno;int level;{ if (level == 0) { if ((ip->i_mode & I_TYPE) == I_DIRECTORY && !chkdirzone(ino, ip, *pos, zno)) return(0); *pos += ZONE_SIZE; return(1); } else return chkindzone(ino, ip, pos, zno, level);}/* Check a list of zones given by `zlist'. */int chkzones(ino, ip, pos, zlist, len, level)ino_t ino;d_inode *ip;off_t *pos;zone_nr *zlist;int len;int level;{ register ok = 1, i; /* The check on the position in the next loop is commented out, since FS * now requires valid zone numbers in each level that is necessary and FS * always deleted all the zones in the double indirect block. */ for (i = 0; i < len /* && *pos < ip->i_size */ ; i++) if (zlist[i] == NO_ZONE) *pos += jump(level); else if (!markzone(ino, zlist[i], level, *pos)) { *pos += jump(level); ok = 0; } else if (!zonechk(ino, ip, pos, zlist[i], level)) ok = 0; return(ok);}/* Check a file or a directory. */int chkfile(ino, ip)ino_t ino;d_inode *ip;{ register ok, i, level; off_t pos = 0; ok = chkzones(ino, ip, &pos, (zone_nr *)&ip->i_zone[0], NR_DZONE_NUM, 0); for (i = NR_DZONE_NUM, level = 1; i < NR_ZONE_NUMS; i++, level++) ok &= chkzones(ino, ip, &pos, (zone_nr *)&ip->i_zone[i], 1, level); return(ok);}/* Check a directory by checking the contents. Check if . and .. are present. */int chkdirectory(ino, ip)ino_t ino;d_inode *ip;{ register ok; setbit(dirmap, (bit_nr) ino); if (ip->i_size > MAXDIRSIZE) { printf("warning: huge directory: "); printpath(2, 1); } ok = chkfile(ino, ip); if (!(ftop->st_presence & DOT)) { printf(". missing in "); printpath(2, 1); ok = 0; } if (!(ftop->st_presence & DOTDOT)) { printf(".. missing in "); printpath(2, 1); ok = 0; } return(ok);}#ifdef I_SYMBOLIC_LINK/* Check the validity of a symbolic link. */int chklink(ino, ip)ino_t ino;d_inode *ip;{ int ok; ok = chkfile(ino, ip); if (ip->i_size <= 0 || ip->i_size > BLOCK_SIZE) { if (ip->i_size == 0) printf("empty symbolic link "); else printf("symbolic link too large (size %ld) ", ip->i_size); printpath(2, 1); ok = 0; } return(ok);}#endif/* Check the validity of a special file. */int chkspecial(ino, ip)ino_t ino;d_inode *ip;{ int i, ok; ok = 1; if ((dev_t) ip->i_zone[0] == NO_DEV) { printf("illegal device number %u for special file ", ip->i_zone[0]); printpath(2, 1); ok = 0; } /* FS will not use the remaining "zone numbers" but 1.6.11++ will panic if * they are nonzero, since this should not happen. */ for (i = 1; i < NR_ZONE_NUMS; i++) if (ip->i_zone[i] != NO_ZONE) { printf("nonzero zone number %u for special file ", ip->i_zone[i]); printpath(2, 1); ok = 0; } return(ok);}/* Check the mode and contents of an inode. */int chkmode(ino, ip)ino_t ino;d_inode *ip;{ switch (ip->i_mode & I_TYPE) { case I_REGULAR: nregular++; return chkfile(ino, ip); case I_DIRECTORY: ndirectory++; return chkdirectory(ino, ip); case I_BLOCK_SPECIAL: nblkspec++; return chkspecial(ino, ip); case I_CHAR_SPECIAL: ncharspec++; return chkspecial(ino, ip); case I_NAMED_PIPE: npipe++; return chkfile(ino, ip);#ifdef I_SYMBOLIC_LINK case I_SYMBOLIC_LINK: nsyml++; return chklink(ino, ip);#endif default: nbadinode++; printf("bad mode of "); printpath(1, 0); printf("mode = %o)", ip->i_mode); return(0); }}/* Check an inode. */int chkinode(ino, ip)ino_t ino;d_inode *ip;{ if (ino == ROOT_INODE && (ip->i_mode & I_TYPE) != I_DIRECTORY) { printf("root inode is not a directory "); printf("(ino = %u, mode = %o)\n", ino, ip->i_mode); fatal(""); } if (ip->i_nlinks == 0) { printf("link count zero of "); printpath(2, 0); return(0); } nfreeinode--; setbit(imap, (bit_nr) ino); if ((unsigned) ip->i_nlinks > LINK_MAX) { printf("link count too big in "); printpath(1, 0); printf("cnt = %u)\n", (unsigned) ip->i_nlinks); count[ino] -= LINK_MAX; setbit(spec_imap, (bit_nr) ino); } else count[ino] -= (unsigned) ip->i_nlinks; return chkmode(ino, ip);}/* Check the directory entry pointed to by dp, by checking the inode. */int descendtree(dp)dir_struct *dp;{ d_inode inode; register ino_t ino = dp->d_inum; register visited; struct stack stk; stk.st_dir = dp; stk.st_next = ftop; ftop = &stk; if (bitset(spec_imap, (bit_nr) ino)) { printf("found inode %u: ", ino); printpath(0, 1); } visited = bitset(imap, (bit_nr) ino); if (!visited || listing) { devread(inoaddr(ino), (char *) &inode, INODE_SIZE); if (listing) list(ino, &inode); if (!visited && !chkinode(ino, &inode)) { setbit(spec_imap, (bit_nr) ino); if (yes("remove")) { count[ino] += inode.i_nlinks - 1; clrbit(imap, (bit_nr) ino); devwrite(inoaddr(ino), nullbuf, INODE_SIZE); memset((void *) dp, 0, sizeof(dir_struct)); ftop = ftop->st_next; return(0); } } } ftop = ftop->st_next; return(1);}/* Check the file system tree. */void chktree(){ dir_struct dir; nfreeinode = sb.s_ninodes; nfreezone = N_DATA; dir.d_inum = ROOT_INODE; dir.d_name[0] = 0; if (!descendtree(&dir)) fatal("bad root inode"); putchar('\n');}/* Print the totals of all the objects found. */void printtotal(){ printf("blocksize = %5d ", BLOCK_SIZE); printf("zonesize = %5d\n", ZONE_SIZE); printf("\n"); pr("%6u Regular file%s\n", nregular, "", "s"); pr("%6u Director%s\n", ndirectory, "y", "ies"); pr("%6u Block special file%s\n", nblkspec, "", "s"); pr("%6u Character special file%s\n", ncharspec, "", "s"); if (nbadinode != 0) pr("%6u Bad inode%s\n", nbadinode, "", "s"); pr("%6u Free inode%s\n", nfreeinode, "", "s"); pr("%6u Named pipe%s\n", npipe, "", "s"); pr("%6u Symbolic link%s\n", nsyml, "", "s");/* Don't print some fields. printf("\n"); pr("%6u Data zone%s\n", ztype[0], "", "s"); pr("%6u Single indirect zone%s\n", ztype[1], "", "s"); pr("%6u Double indirect zone%s\n", ztype[2], "", "s");*/ pr("%6u Free zone%s\n", nfreezone, "", "s");}/* Check the device which name is given by `f'. The inodes listed by `clist' * should be listed separately, and the inodes listed by `ilist' and the zones * listed by `zlist' should be watched for while checking the file system. */void chkdev(f, clist, ilist, zlist)char *f, **clist, **ilist, **zlist;{ if (automatic) repair = 1; device = f; initvars(); devopen(); getsuper(); chksuper(); lsi(clist); getbitmaps(); fillbitmap(spec_imap, (bit_nr) 1, (bit_nr) sb.s_ninodes + 1, ilist); fillbitmap(spec_zmap, (bit_nr) FIRST, (bit_nr) sb.s_nzones, zlist); getcount(); chktree(); chkmap(zmap, spec_zmap, (bit_nr) FIRST - 1, BLK_ZMAP, N_ZMAP, "zone"); chkcount(); chkmap(imap, spec_imap, (bit_nr) 0, BLK_IMAP, N_IMAP, "inode"); chkilist(); printtotal(); putbitmaps(); freecount(); devclose(); if (changed) printf("----- FILE SYSTEM HAS BEEN MODIFIED -----\n\n");}int main(argc, argv)int argc;char **argv;{ register char **clist = 0, **ilist = 0, **zlist = 0; register devgiven = 0; register char *arg; if ((1 << BITSHIFT) != 8 * sizeof(bitchunk_t)) { printf("Fsck was compiled with the wrong BITSHIFT!\n"); exit(1); } sync(); prog = *argv++; while ((arg = *argv++) != 0) if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0) switch (arg[1]) { case 'a': automatic ^= 1; break; case 'c': clist = getlist(&argv, "inode"); break; case 'i': ilist = getlist(&argv, "inode"); break; case 'z': zlist = getlist(&argv, "zone"); break; case 'r': repair ^= 1; break; case 'l': listing ^= 1; break; case 's': listsuper ^= 1; break; default: printf("%s: unknown flag '%s'\n", prog, arg); } else { chkdev(arg, clist, ilist, zlist); clist = 0; ilist = 0; zlist = 0; devgiven = 1; } if (!devgiven) { printf("Usage: fsck1 [-acilrsz] file\n"); exit(1); } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -