📄 fsck1.c
字号:
/* Hacks for version 1.6 */ #define INODES_PER_BLOCK V1_INODES_PER_BLOCK#define INODE_SIZE V1_INODE_SIZE#define WORDS_PER_BLOCK (BLOCK_SIZE / (int) sizeof(bitchunk_t))#define MAX_ZONES (V1_NR_DZONES+V1_INDIRECTS+(long)V1_INDIRECTS*V1_INDIRECTS)#define NR_DZONE_NUM V1_NR_DZONES#define NR_INDIRECTS V1_INDIRECTS#define NR_ZONE_NUMS V1_NR_TZONES#define ZONE_NUM_SIZE V1_ZONE_NUM_SIZE#define bit_nr u16_t /* perhaps bit_t should be used, although slower */#define Bit_nr U16_t#define block_nr block_t#define d_inode d1_inode#define d_inum d_ino#define dir_struct struct direct#define i_mode d1_mode#define i_nlinks d1_nlinks#define i_size d1_size#define i_zone d1_zone#define zone_nr zone1_t#define Zone_nr Zone1_t/* fsck - file system checker Author: Robbert van Renesse *//* Modified by Norbert Schlenker* Removed vestiges of standalone/DOS versions:* - various unused variables and buffers removed* - now uses library functions rather than private internal routines* - bytewise structure copies replaced by structure assignment* - fixed one bug with 14 character file names* - other small tweaks for speed** Modified by Lars Fredriksen at the request of Andy Tanenbaum, 90-03-10.* Removed -m option, by which fsck could be told to make a file* system on a 360K floppy. The code had limited utility, was buggy,* and failed due to a bug in the ACK C compiler. Use mkfs instead!*/#include <sys/types.h>#include <sys/dir.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <minix/config.h>#include <minix/const.h>#include <minix/type.h>#include "../../fs/const.h"#include "../../fs/inode.h"#include "../../fs/type.h"#include <minix/fslib.h>#undef printf /* defined as printk in "../fs/const.h" */#include <stdio.h>#define BITSHIFT 4 /* = log2(#bits(int)) */#define MAXPRINT 8 /* max. number of error lines in chkmap */#define MAXDIRSIZE 5000 /* max. size of a reasonable directory */#define CINDIR 128 /* number of indirect zno's read at a time */#define CDIRECT 16 /* number of dir entries read at a time */#define BITMASK ((1 << BITSHIFT) - 1)#define setbit(w, b) (w[(b) >> BITSHIFT] |= 1 << ((b) & BITMASK))#define clrbit(w, b) (w[(b) >> BITSHIFT] &= ~(1 << ((b) & BITMASK)))#define bitset(w, b) (w[(b) >> BITSHIFT] & (1 << ((b) & BITMASK)))#define ZONE_CT 360 /* default zones (when making file system) */#define INODE_CT 95 /* default inodes (when making file system) */#include "../../fs/super.h"struct super_block sb;#define STICKY_BIT 01000 /* not defined anywhere else *//* Ztob gives the block address of a zone * btoa gives the byte address of a block */#define ztob(z) ((block_nr) (z) << sb.s_log_zone_size)#define btoa(b) ((long) (b) * BLOCK_SIZE)#define SCALE ((int) ztob(1)) /* # blocks in a zone */#define FIRST ((zone_nr) sb.s_firstdatazone) /* as the name says *//* # blocks of each type */#define N_SUPER 1#define N_IMAP (sb.s_imap_blocks)#define N_ZMAP (sb.s_zmap_blocks)#define N_ILIST ((sb.s_ninodes+INODES_PER_BLOCK-1) / INODES_PER_BLOCK)#define N_DATA (sb.s_nzones - FIRST)/* Block address of each type */#define BLK_SUPER (SUPER_BLOCK)#define BLK_IMAP (BLK_SUPER + N_SUPER)#define BLK_ZMAP (BLK_IMAP + N_IMAP)#define BLK_ILIST (BLK_ZMAP + N_ZMAP)#define BLK_FIRST ztob(FIRST)#define ZONE_SIZE ((int) ztob(BLOCK_SIZE))#define NLEVEL (NR_ZONE_NUMS - NR_DZONE_NUM + 1)/* Byte address of a zone/of an inode */#define zaddr(z) btoa(ztob(z))#define inoaddr(i) ((long) (i - 1) * INODE_SIZE + btoa(BLK_ILIST))#define INDCHUNK (CINDIR * ZONE_NUM_SIZE)#define DIRCHUNK (CDIRECT * DIR_ENTRY_SIZE)char *prog, *device; /* program name (fsck), device name */int firstcnterr; /* is this the first inode ref cnt error? */bitchunk_t *imap, *spec_imap; /* inode bit maps */bitchunk_t *zmap, *spec_zmap; /* zone bit maps */bitchunk_t *dirmap; /* directory (inode) bit map */char rwbuf[BLOCK_SIZE]; /* one block buffer cache */block_nr thisblk; /* block in buffer cache */char nullbuf[BLOCK_SIZE]; /* null buffer */nlink_t *count; /* inode count */int changed; /* has the diskette been written to? */struct stack { dir_struct *st_dir; struct stack *st_next; char st_presence;} *ftop;int dev; /* file descriptor of the device */#define DOT 1#define DOTDOT 2/* Counters for each type of inode/zone. */int nfreeinode, nregular, ndirectory, nblkspec, ncharspec, nbadinode;int npipe, nsyml, nfreezone, ztype[NLEVEL];int repair, automatic, listing, listsuper; /* flags */int firstlist; /* has the listing header been printed? */unsigned part_offset; /* sector offset for this partition */char answer[] = "Answer questions with y or n. Then hit RETURN";_PROTOTYPE(int main, (int argc, char **argv));_PROTOTYPE(void initvars, (void));_PROTOTYPE(void fatal, (char *s));_PROTOTYPE(int eoln, (int c));_PROTOTYPE(int yes, (char *question));_PROTOTYPE(int atoo, (char *s));_PROTOTYPE(int input, (char *buf, int size));_PROTOTYPE(char *alloc, (unsigned nelem, unsigned elsize));_PROTOTYPE(void printname, (char *s));_PROTOTYPE(void printrec, (struct stack *sp));_PROTOTYPE(void printpath, (int mode, int nlcr));_PROTOTYPE(void devopen, (void));_PROTOTYPE(void devclose, (void));_PROTOTYPE(void devio, (block_nr bno, int dir));_PROTOTYPE(void devread, (long offset, char *buf, int size));_PROTOTYPE(void devwrite, (long offset, char *buf, int size));_PROTOTYPE(void pr, (char *fmt, int cnt, char *s, char *p));_PROTOTYPE(bit_nr getnumber, (char *s));_PROTOTYPE(char **getlist, (char ***argv, char *type));_PROTOTYPE(void lsuper, (void));_PROTOTYPE(void getsuper, (void));_PROTOTYPE(void chksuper, (void));_PROTOTYPE(void lsi, (char **clist));_PROTOTYPE(bitchunk_t *allocbitmap, (int nblk));_PROTOTYPE(void loadbitmap, (bitchunk_t *bitmap, block_nr bno, int nblk));_PROTOTYPE(void dumpbitmap, (bitchunk_t *bitmap, block_nr bno, int nblk));_PROTOTYPE(void fillbitmap, (bitchunk_t *bitmap, Bit_nr lwb, Bit_nr upb, char **list));_PROTOTYPE(void freebitmap, (bitchunk_t *p));_PROTOTYPE(void getbitmaps, (void));_PROTOTYPE(void putbitmaps, (void));_PROTOTYPE(void chkword, (unsigned w1, unsigned w2, Bit_nr bit, char *type, int *n, int *report));_PROTOTYPE(void chkmap, (bitchunk_t *cmap, bitchunk_t *dmap, Bit_nr bit, block_nr blkno, int nblk, char *type));_PROTOTYPE(void chkilist, (void));_PROTOTYPE(void getcount, (void));_PROTOTYPE(void counterror, (Ino_t ino));_PROTOTYPE(void chkcount, (void));_PROTOTYPE(void freecount, (void));_PROTOTYPE(void printperm, (Mode_t mode, int shift, int special, int overlay));_PROTOTYPE(void list, (Ino_t ino, d_inode *ip));_PROTOTYPE(int Remove, (dir_struct *dp));_PROTOTYPE(void make_printable_name, (char *dst, char *src, int n));_PROTOTYPE(int chkdots, (Ino_t ino, off_t pos, dir_struct *dp, Ino_t exp));_PROTOTYPE(int chkname, (Ino_t ino, dir_struct *dp));_PROTOTYPE(int chkentry, (Ino_t ino, off_t pos, dir_struct *dp));_PROTOTYPE(int chkdirzone, (Ino_t ino, d_inode *ip, off_t pos, Zone_nr zno));_PROTOTYPE(void errzone, (char *mess, Zone_nr zno, int level, off_t pos));_PROTOTYPE(int markzone, (Ino_t ino, Zone_nr zno, int level, off_t pos));_PROTOTYPE(int chkindzone, (Ino_t ino, d_inode *ip, off_t *pos, Zone_nr zno, int level));_PROTOTYPE(off_t jump, (int level));_PROTOTYPE(int zonechk, (Ino_t ino, d_inode *ip, off_t *pos, Zone_nr zno, int level));_PROTOTYPE(int chkzones, (Ino_t ino, d_inode *ip, off_t *pos, zone_nr *zlist, int len, int level));_PROTOTYPE(int chkfile, (Ino_t ino, d_inode *ip));_PROTOTYPE(int chkdirectory, (Ino_t ino, d_inode *ip));_PROTOTYPE(int chklink, (Ino_t ino, d_inode *ip));_PROTOTYPE(int chkmode, (Ino_t ino, d_inode *ip));_PROTOTYPE(int chkinode, (Ino_t ino, d_inode *ip));_PROTOTYPE(int chkspecial, (Ino_t ino, d_inode *ip) );_PROTOTYPE(int descendtree, (dir_struct *dp));_PROTOTYPE(void chktree, (void));_PROTOTYPE(void printtotal, (void));_PROTOTYPE(void chkdev, (char *f, char **clist, char **ilist, char **zlist));/* Initialize the variables used by this program. */void initvars(){ register level; nregular = ndirectory = nblkspec = ncharspec = nbadinode = npipe = nsyml = 0; for (level = 0; level < NLEVEL; level++) ztype[level] = 0; changed = 0; thisblk = NO_BLOCK; firstlist = 1; firstcnterr = 1;}/* Print the string `s' and exit. */void fatal(s)char *s;{ printf("%s\nfatal\n", s); exit(-1);}/* Test for end of line. */int eoln(c)int c;{ return(c == EOF || c == '\n' || c == '\r');}/* Ask a question and get the answer unless automatic is set. */int yes(question)char *question;{ register c, answer; if (!repair) { printf("\n"); return(0); } printf("%s? ", question); if (automatic) { printf("yes\n"); return(1); } fflush(stdout); if ((c = answer = getchar()) == 'q' || c == 'Q') exit(1); while (!eoln(c)) c = getchar(); return !(answer == 'n' || answer == 'N');}/* Convert string to integer. Representation is octal. */int atoo(s)register char *s;{ register int n = 0; while ('0' <= *s && *s < '8') { n <<= 3; n += *s++ - '0'; } return n;}/* If repairing the file system, print a prompt and get a string from user. */int input(buf, size)char *buf;int size;{ register char *p = buf; printf("\n"); if (repair) { printf("--> "); fflush(stdout); while (--size) { *p = getchar(); if (eoln(*p)) { *p = 0; return(p > buf); } p++; } *p = 0; while (!eoln(getchar())); return(1); } return(0);}/* Allocate some memory and zero it. */char *alloc(nelem, elsize)unsigned nelem, elsize;{ char *p; if ((p = (char *) malloc((size_t)nelem * elsize)) == 0) fatal("out of memory"); memset(p, 0, (size_t)nelem * elsize); return(p);}/* Print the name in a directory entry. */void printname(s)char *s;{ register n = NAME_MAX; int c; do { if ((c = *s) == 0) break; if (!isprint(c)) c = '?'; putchar(c); s++; } while (--n);}/* Print the pathname given by a linked list pointed to by `sp'. The * names are in reverse order. */void printrec(sp)struct stack *sp;{ if (sp->st_next != 0) { printrec(sp->st_next); putchar('/'); printname(sp->st_dir->d_name); }}/* Print the current pathname. */void printpath(mode, nlcr)int mode;int nlcr;{ if (ftop->st_next == 0) putchar('/'); else printrec(ftop); switch (mode) { case 1: printf(" (ino = %u, ", ftop->st_dir->d_inum); break; case 2: printf(" (ino = %u)", ftop->st_dir->d_inum); break; } if (nlcr) printf("\n");}/* Open the device. */void devopen(){ if ((dev = open(device, repair ? O_RDWR : O_RDONLY)) < 0) { perror(device); fatal(""); }}/* Close the device. */void devclose(){ if (close(dev) != 0) { perror("close"); fatal(""); }}/* Read or write a block. */void devio(bno, dir)block_nr bno;int dir;{ if (dir == READING && bno == thisblk) return; thisblk = bno; lseek(dev, (off_t) btoa(bno), SEEK_SET); if (dir == READING) { if (read(dev, rwbuf, BLOCK_SIZE) == BLOCK_SIZE) return; } else { if (write(dev, rwbuf, BLOCK_SIZE) == BLOCK_SIZE) return; } printf("%s: can't %s block %ld (error = 0x%x)\n", prog, dir == READING ? "read" : "write", (long) bno, errno); if (dir == READING) { printf("Continuing with a zero-filled block.\n"); memset(rwbuf, 0, BLOCK_SIZE); return; } fatal("");}/* Read `size' bytes from the disk starting at byte `offset'. */void devread(offset, buf, size)long offset;char *buf;int size;{ devio((block_nr) (offset / BLOCK_SIZE), READING); memmove(buf, &rwbuf[(int) (offset % BLOCK_SIZE)], (size_t)size);}/* Write `size' bytes to the disk starting at byte `offset'. */void devwrite(offset, buf, size)long offset;char *buf;int size;{ if (!repair) fatal("internal error (devwrite)"); if (size != BLOCK_SIZE) devio((block_nr) (offset / BLOCK_SIZE), READING); memmove(&rwbuf[(int) (offset % BLOCK_SIZE)], buf, (size_t)size); devio((block_nr) (offset / BLOCK_SIZE), WRITING); changed = 1;}/* Print a string with either a singular or a plural pronoun. */void pr(fmt, cnt, s, p)char *fmt, *s, *p;int cnt;{ printf(fmt, cnt, cnt == 1 ? s : p);}/* Convert string to number. */bit_nr getnumber(s)register char *s;{ register bit_nr n = 0; if (s == NULL) return NO_BIT; while (isdigit(*s)) n = (n << 1) + (n << 3) + *s++ - '0'; return (*s == '\0') ? n : NO_BIT;}/* See if the list pointed to by `argv' contains numbers. */char **getlist(argv, type)char ***argv, *type;{ register char **list = *argv; register empty = 1; while (getnumber(**argv) != NO_BIT) { (*argv)++; empty = 0; } if (empty) { printf("warning: no %s numbers given\n", type); return(NULL); } return(list);}/* Make a listing of the super block. If `repair' is set, ask the user * for changes. */void lsuper(){ char buf[80]; do { printf("ninodes = %u", sb.s_ninodes); if (input(buf, 80)) sb.s_ninodes = atol(buf); printf("nzones = %u", sb.s_nzones); if (input(buf, 80)) sb.s_nzones = atol(buf); printf("imap_blocks = %u", sb.s_imap_blocks); if (input(buf, 80)) sb.s_imap_blocks = atol(buf); printf("zmap_blocks = %u", sb.s_zmap_blocks); if (input(buf, 80)) sb.s_zmap_blocks = atol(buf); printf("firstdatazone = %u", sb.s_firstdatazone); if (input(buf, 80)) sb.s_firstdatazone = atol(buf); printf("log_zone_size = %u", sb.s_log_zone_size); if (input(buf, 80)) sb.s_log_zone_size = atol(buf); printf("maxsize = %lu", sb.s_max_size); if (input(buf, 80)) sb.s_max_size = atol(buf); if (yes("ok now")) { devwrite(btoa(BLK_SUPER), (char *) &sb, sizeof(sb)); return; } } while (yes("Do you want to try again")); if (repair) exit(0);}/* Get the super block from either disk or user. Do some initial checks. */void getsuper(){ devread(btoa(BLK_SUPER), (char *) &sb, sizeof(sb)); if (listsuper) lsuper(); if (sb.s_magic == SUPER_V2) fatal("Cannot handle V2 file systems"); if (sb.s_magic != SUPER_MAGIC) fatal("bad magic number in super block"); if ((short) sb.s_ninodes <= 0) fatal("no inodes"); if (sb.s_nzones <= 2) fatal("no zones"); if ((short) sb.s_imap_blocks <= 0) fatal("no imap"); if ((short) sb.s_zmap_blocks <= 0) fatal("no zmap");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -