From: Alan Cox Date: Sun, 22 Oct 2017 18:32:41 +0000 (+0100) Subject: fsck: Rework standalone fsck to use as native fsck X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=387a974cafd3b1535bbcb0648192c7a3fce69f00;p=FUZIX.git fsck: Rework standalone fsck to use as native fsck - Use bitmaps not bytemaps - Support yes() properly Not heavily tested yet! --- diff --git a/Applications/util/fsck.c b/Applications/util/fsck.c index 5a431736..a27c1406 100644 --- a/Applications/util/fsck.c +++ b/Applications/util/fsck.c @@ -5,55 +5,166 @@ #include #include #include -#include "fsck.h" +#include + +typedef uint16_t blkno_t; + +struct filesys { + uint16_t s_mounted; + uint16_t s_isize; + uint16_t s_fsize; + int16_t s_nfree; + blkno_t s_free[50]; + int16_t s_ninode; + uint16_t s_inode[50]; + uint8_t s_fmod; + uint8_t s_timeh; /* top bits of time */ + uint32_t s_time; + blkno_t s_tfree; + uint16_t s_tinode; + uint16_t s_mntpt; +}; + +#define ROOTINODE 1 +#define SMOUNTED 12742 /* Magic number to specify mounted filesystem */ +#define SMOUNTED_WRONGENDIAN 50737 /* byteflipped */ + +struct dinode { + uint16_t i_mode; + uint16_t i_nlink; + uint16_t i_uid; + uint16_t i_gid; + uint32_t i_size; + uint32_t i_atime; + uint32_t i_mtime; + uint32_t i_ctime; + blkno_t i_addr[20]; +}; /* Exactly 64 bytes long! */ + +#define F_REG 0100000 +#define F_DIR 040000 +#define F_PIPE 010000 +#define F_BDEV 060000 +#define F_CDEV 020000 + +#define F_MASK 0170000 + +struct direct { + uint16_t d_ino; + char d_name[30]; +}; #define MAXDEPTH 20 /* Maximum depth of directory tree to search */ /* This checks a filesystem */ -/* WARNING: This is a test version. Take a copy of the file system first. +static int dev = 0; +static struct filesys superblock; +static int swizzling = 0; /* Wrongendian ? */ +static long offset; +static int dev_fd; +static int dev_offset; + +static unsigned char *bitmap; +static int16_t *linkmap; +static char *daread(uint16_t blk); +static void dwrite(uint16_t blk, char *addr); +static void iread(uint16_t ino, struct dinode *buf); +static void iwrite(uint16_t ino, struct dinode *buf); +static void setblkno(struct dinode *ino, blkno_t num, blkno_t dnum); +static void ckdir(uint16_t inum, uint16_t pnum, char *name); +static void dirread(struct dinode *ino, uint16_t j, struct direct *dentry); +static void dirwrite(struct dinode *ino, uint16_t j, struct direct *dentry); +static void mkentry(uint16_t inum); +static blkno_t blk_alloc0(struct filesys *filesys); +static blkno_t getblkno(struct dinode *ino, blkno_t num); + +static void pass1(void); +static void pass2(void); +static void pass3(void); +static void pass4(void); +static void pass5(void); + +static int yes(void) +{ + static char buf[16]; + do { + if (fgets(buf, 15, stdin) == NULL) + exit(1); + if (isupper(*buf)) + *buf = tolower(*buf); + } while(*buf != 'n' && *buf != 'y'); + return (*buf == 'y') ? 1 : 0; +} - To fsck a file system it must be unmounted. To fsck the root fs boot with - the root fs read only, fsck, sync, reboot - - TODO: change the bitmap to use bits to save memory. 64K blocks is then 8K - of RAM which should mean we can fsck a full sized fs ok - */ +static void bitset(uint16_t b) +{ + bitmap[b >> 3] |= (1 << (b & 7)); +} + +static void bitclear(uint16_t b) +{ + bitmap[b >> 3] &= ~(1 << (b & 7)); +} -int dev = 0; -struct filesys superblock; -int swizzling = 0; /* Wrongendian ? */ -long offset; -int dev_fd; -int dev_offset; - -char *bitmap; -int16_t *linkmap; -char *daread(uint16_t blk); -void dwrite(uint16_t blk, char *addr); -void iread(uint16_t ino, struct dinode *buf); -void iwrite(uint16_t ino, struct dinode *buf); -void setblkno(struct dinode *ino, blkno_t num, blkno_t dnum); -void ckdir(uint16_t inum, uint16_t pnum, char *name); -void dirread(struct dinode *ino, uint16_t j, struct direct *dentry); -void dirwrite(struct dinode *ino, uint16_t j, struct direct *dentry); -void mkentry(uint16_t inum); -blkno_t getblkno(struct dinode *ino, blkno_t num); -blkno_t blk_alloc0(struct filesys *filesys); - -void pass1(void); -void pass2(void); -void pass3(void); -void pass4(void); -void pass5(void); - -int yes(void) +static int bittest(uint16_t b) { - printf("YESYES!\n"); - return 1; + return (bitmap[b >> 3] & (1 << (b & 7))) ? 1 : 0; +} + +static int fd_open(char *name) +{ + char *namecopy, *sd; + int bias = 0; + + namecopy = strdup(name); + sd = index(namecopy, ':'); + if (sd) { + *sd = 0; + sd++; + bias = atoi(sd); + } + + printf("Opening %s (offset %d)\n", namecopy, bias); + dev_offset = bias; + dev_fd = open(namecopy, O_RDWR | O_CREAT, 0666); + free(namecopy); + + if (dev_fd < 0) + return -1; + /* printf("fd=%d, dev_offset = %d\n", dev_fd, dev_offset); */ + return 0; } +static void panic(char *s) +{ + fprintf(stderr, "panic: %s\n", s); + exit(1); +} + +static uint16_t swizzle16(uint32_t v) +{ + int top = v & 0xFFFF0000UL; + if (top && top != 0xFFFF0000) { + fprintf(stderr, "swizzle16 given a 32bit input\n"); + exit(1); + } + if (swizzling) + return (v & 0xFF) << 8 | ((v & 0xFF00) >> 8); + else + return v; +} + +static uint32_t swizzle32(uint32_t v) +{ + if (!swizzling) + return v; + + return (v & 0xFF) << 24 | (v & 0xFF00) << 8 | (v & 0xFF0000) >> 8 | + (v & 0xFF000000) >> 24; +} + int main(int argc, char **argv) { char *buf; @@ -96,9 +207,12 @@ int main(int argc, char **argv) if (!yes()) exit(-1); - bitmap = calloc(swizzle16(superblock.s_fsize), sizeof(char)); + bitmap = calloc((swizzle16(superblock.s_fsize) + 7) / 8, sizeof(char)); linkmap = (int16_t *) calloc(8 * swizzle16(superblock.s_isize), sizeof(int16_t)); + printf("Memory pool %d bytes\n", + 16 * swizzle16(superblock.s_isize) + + swizzle16(superblock.s_fsize + 7) / 8); if (!bitmap || !linkmap) { fprintf(stderr, "Not enough memory.\n"); exit(-1); @@ -130,7 +244,7 @@ int main(int argc, char **argv) * numbers in the inodes, and builds the block allocation map. */ -void pass1(void) +static void pass1(void) { uint16_t n; struct dinode ino; @@ -166,7 +280,7 @@ void pass1(void) ++icount; /* Check size */ - if ((int32_t)swizzle32(ino.i_size) < 0) { + if (swizzle32(ino.i_size) < 0) { printf("Inode %d offset is negative with value of %ld. Fix? ", n, (long)swizzle32(ino.i_size)); if (yes()) { @@ -198,7 +312,7 @@ void pass1(void) } } if (ino.i_addr[b] != 0) - bitmap[swizzle16(ino.i_addr[b])] = 1; + bitset(swizzle16(ino.i_addr[b])); } /* Check the double indirect blocks */ @@ -216,7 +330,7 @@ void pass1(void) } } if (buf[b] != 0) - bitmap[swizzle16(buf[b])] = 1; + bitset(swizzle16(buf[b])); } } /* Check the rest */ @@ -232,7 +346,7 @@ void pass1(void) } } if (b != 0) - bitmap[b] = 1; + bitset(b); } } } @@ -250,12 +364,12 @@ void pass1(void) /* Clear inode free list, rebuild block free list using bit map. */ - -void pass2(void) +static void pass2(void) { blkno_t j; blkno_t oldtfree; int s; + int yes(); printf("Rebuild free list? "); if (!yes()) @@ -273,7 +387,7 @@ void pass2(void) /* Free each block, building the free list */ for (j = swizzle16(superblock.s_fsize) - 1; j >= swizzle16(superblock.s_isize); --j) { - if (bitmap[j] == 0) { + if (bittest(j) == 0) { if (swizzle16(superblock.s_nfree) == 50) { dwrite(j, (char *) &superblock.s_nfree); superblock.s_nfree = 0; @@ -293,10 +407,8 @@ void pass2(void) } - /* Pass 3 finds and fixes multiply allocated blocks. */ - -void pass3(void) +static void pass3(void) { uint16_t n; struct dinode ino; @@ -307,7 +419,7 @@ void pass3(void) /*--- was blk_alloc ---*/ for (b = swizzle16(superblock.s_isize); b < swizzle16(superblock.s_fsize); ++b) - bitmap[b] = 0; + bitclear(b); for (n = ROOTINODE; n < 8 * (swizzle16(superblock.s_isize) - 2); ++n) { iread(n, &ino); @@ -320,7 +432,7 @@ void pass3(void) for (b = 18; b < 20; ++b) { if (ino.i_addr[b] != 0) { - if (bitmap[swizzle16(ino.i_addr[b])] != 0) { + if (bittest(swizzle16(ino.i_addr[b])) != 0) { printf("Indirect block %d in inode %u value %u multiply allocated. Fix? ", b, n, swizzle16(ino.i_addr[b])); if (yes()) { @@ -334,7 +446,7 @@ void pass3(void) } } } else - bitmap[swizzle16(ino.i_addr[b])] = 1; + bitset(swizzle16(ino.i_addr[b])); } } @@ -343,7 +455,7 @@ void pass3(void) b = getblkno(&ino, bno); if (b != 0) { - if (bitmap[b] != 0) { + if (bittest(b)) { printf("Block %d in inode %u value %u multiply allocated. Fix? ", bno, n, b); if (yes()) { @@ -357,7 +469,7 @@ void pass3(void) } } } else - bitmap[b] = 1; + bitset(b); } } @@ -365,14 +477,14 @@ void pass3(void) } -int depth; +static int depth; /* * Pass 4 traverses the directory tree, fixing bad directory entries * and finding the actual number of references to each inode. */ -void pass4(void) +static void pass4(void) { depth = 0; linkmap[ROOTINODE] = 1; @@ -383,13 +495,13 @@ void pass4(void) /* This recursively checks the directories */ - -void ckdir(uint16_t inum, uint16_t pnum, char *name) +static void ckdir(uint16_t inum, uint16_t pnum, char *name) { struct dinode ino; struct direct dentry; uint16_t j; int c; + uint8_t i; int nentries; char ename[150]; @@ -410,15 +522,9 @@ void ckdir(uint16_t inum, uint16_t pnum, char *name) for (j = 0; j < nentries; ++j) { dirread(&ino, j, &dentry); -#if 1 /**HP**/ - { - int i; - - for (i = 0; i < 30; ++i) if (dentry.d_name[i] == '\0') break; - for ( ; i < 30; ++i) dentry.d_name[i] = '\0'; - dirwrite(&ino, j, &dentry); - } -#endif + for (i = 0; i < 30; ++i) if (dentry.d_name[i] == '\0') break; + for ( ; i < 30; ++i) dentry.d_name[i] = '\0'; + dirwrite(&ino, j, &dentry); if (dentry.d_ino == 0) continue; @@ -486,11 +592,11 @@ void ckdir(uint16_t inum, uint16_t pnum, char *name) /* Pass 5 compares the link counts found in pass 4 with the inodes. */ - -void pass5(void) +static void pass5(void) { uint16_t n; struct dinode ino; + int yes(); for (n = ROOTINODE; n < 8 * (swizzle16(superblock.s_isize) - 2); ++n) { iread(n, &ino); @@ -566,8 +672,7 @@ void pass5(void) /* This makes an entry in "lost+found" for inode n */ - -void mkentry(uint16_t inum) +static void mkentry(uint16_t inum) { struct dinode rootino; struct direct dentry; @@ -586,15 +691,13 @@ void mkentry(uint16_t inum) printf("Sorry... No empty slots in root directory.\n"); } -/* Beginning of fsck1.c */ - /* * Getblkno gets a pointer index, and a number of a block in the file. * It returns the number of the block on the disk. A value of zero * means an unallocated block. */ -blkno_t getblkno(struct dinode *ino, blkno_t num) +static blkno_t getblkno(struct dinode *ino, blkno_t num) { blkno_t indb; blkno_t dindb; @@ -630,8 +733,7 @@ blkno_t getblkno(struct dinode *ino, blkno_t num) * A return of zero means there were no blocks available to create an * indirect block. This should never happen in fsck. */ - -void setblkno(struct dinode *ino, blkno_t num, blkno_t dnum) +static void setblkno(struct dinode *ino, blkno_t num, blkno_t dnum) { blkno_t indb; blkno_t dindb; @@ -672,8 +774,7 @@ void setblkno(struct dinode *ino, blkno_t num, blkno_t dnum) */ /*--- was blk_alloc ---*/ - -blkno_t blk_alloc0(struct filesys *filesys) +static blkno_t blk_alloc0(struct filesys *filesys) { blkno_t newno; blkno_t *buf; @@ -706,8 +807,7 @@ blkno_t blk_alloc0(struct filesys *filesys) return (newno); } - -char *daread(uint16_t blk) +static char *daread(uint16_t blk) { static char da_buf[512]; if (lseek(dev_fd, offset + blk * 512L, 0) == -1) { @@ -721,8 +821,7 @@ char *daread(uint16_t blk) return da_buf; } - -void dwrite(uint16_t blk, char *addr) +static void dwrite(uint16_t blk, char *addr) { if (lseek(dev_fd, offset + blk * 512L, 0) == -1) { perror("lseek"); @@ -734,8 +833,7 @@ void dwrite(uint16_t blk, char *addr) } } - -void iread(uint16_t ino, struct dinode *buf) +static void iread(uint16_t ino, struct dinode *buf) { struct dinode *addr; @@ -743,8 +841,7 @@ void iread(uint16_t ino, struct dinode *buf) bcopy((char *) &addr[ino & 7], (char *) buf, sizeof(struct dinode)); } - -void iwrite(uint16_t ino, struct dinode *buf) +static void iwrite(uint16_t ino, struct dinode *buf) { struct dinode *addr; @@ -753,8 +850,7 @@ void iwrite(uint16_t ino, struct dinode *buf) dwrite((ino >> 3) + 2, (char *) addr); } - -void dirread(struct dinode *ino, uint16_t j, struct direct *dentry) +static void dirread(struct dinode *ino, uint16_t j, struct direct *dentry) { blkno_t blkno; char *buf; @@ -766,8 +862,7 @@ void dirread(struct dinode *ino, uint16_t j, struct direct *dentry) bcopy(buf + 32 * (j % 16), (char *) dentry, 32); } - -void dirwrite(struct dinode *ino, uint16_t j, struct direct *dentry) +static void dirwrite(struct dinode *ino, uint16_t j, struct direct *dentry) { blkno_t blkno; char *buf; @@ -780,55 +875,3 @@ void dirwrite(struct dinode *ino, uint16_t j, struct direct *dentry) dwrite(blkno, buf); } -int fd_open(char *name) -{ - char *namecopy, *sd; - int bias = 0; - - namecopy = strdup(name); - sd = index(namecopy, ':'); - if (sd) { - *sd = 0; - sd++; - bias = atoi(sd); - } - - printf("Opening %s (offset %d)\n", namecopy, bias); - dev_offset = bias; - dev_fd = open(namecopy, O_RDWR | O_CREAT, 0666); - free(namecopy); - - if (dev_fd < 0) - return -1; - /* printf("fd=%d, dev_offset = %d\n", dev_fd, dev_offset); */ - return 0; -} - - -void panic(char *s) -{ - fprintf(stderr, "panic: %s\n", s); - exit(1); -} - -uint16_t swizzle16(uint32_t v) -{ - int top = v & 0xFFFF0000UL; - if (top && top != 0xFFFF0000) { - fprintf(stderr, "swizzle16 given a 32bit input\n"); - exit(1); - } - if (swizzling) - return (v & 0xFF) << 8 | ((v & 0xFF00) >> 8); - else - return v; -} - -uint32_t swizzle32(uint32_t v) -{ - if (!swizzling) - return v; - - return (v & 0xFF) << 24 | (v & 0xFF00) << 8 | (v & 0xFF0000) >> 8 | - (v & 0xFF000000) >> 24; -}