#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
-#include "fsck.h"
+#include <ctype.h>
+
+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;
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);
* numbers in the inodes, and builds the block allocation map.
*/
-void pass1(void)
+static void pass1(void)
{
uint16_t n;
struct dinode ino;
++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()) {
}
}
if (ino.i_addr[b] != 0)
- bitmap[swizzle16(ino.i_addr[b])] = 1;
+ bitset(swizzle16(ino.i_addr[b]));
}
/* Check the double indirect blocks */
}
}
if (buf[b] != 0)
- bitmap[swizzle16(buf[b])] = 1;
+ bitset(swizzle16(buf[b]));
}
}
/* Check the rest */
}
}
if (b != 0)
- bitmap[b] = 1;
+ bitset(b);
}
}
}
/* 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())
/* 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;
}
-
/* Pass 3 finds and fixes multiply allocated blocks. */
-
-void pass3(void)
+static void pass3(void)
{
uint16_t n;
struct dinode ino;
/*--- 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);
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()) {
}
}
} else
- bitmap[swizzle16(ino.i_addr[b])] = 1;
+ bitset(swizzle16(ino.i_addr[b]));
}
}
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()) {
}
}
} else
- bitmap[b] = 1;
+ bitset(b);
}
}
}
-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;
/* 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];
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;
/* 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);
/* 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;
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;
* 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;
*/
/*--- was blk_alloc ---*/
-
-blkno_t blk_alloc0(struct filesys *filesys)
+static blkno_t blk_alloc0(struct filesys *filesys)
{
blkno_t newno;
blkno_t *buf;
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) {
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");
}
}
-
-void iread(uint16_t ino, struct dinode *buf)
+static void iread(uint16_t ino, struct dinode *buf)
{
struct dinode *addr;
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;
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;
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;
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;
-}