#include #include #include #include #include #include #include "types.h" #include "param.h" #include "fs.h" int nblocks = 1009; int ninodes = 100; int fsfd; struct superblock sb; char zeroes[512]; uint freeblock; uint freeinode = 1; void wsect(uint, void *); void winode(uint, struct dinode *); void rsect(uint sec, void *buf); uint ialloc(ushort type); void iappend(uint inum, void *p, int n); // convert to intel byte order ushort xshort(ushort x) { ushort y; uchar *a = (uchar *) &y; a[0] = x; a[1] = x >> 8; return y; } uint xint(uint x) { uint y; uchar *a = (uchar *) &y; a[0] = x; a[1] = x >> 8; a[2] = x >> 16; a[3] = x >> 24; return y; } main(int argc, char *argv[]) { int i, cc, fd; uint bn, rootino, inum; struct dirent de; char buf[512]; if(argc < 2){ fprintf(stderr, "Usage: mkfs fs.img files...\n"); exit(1); } assert((512 % sizeof(struct dinode)) == 0); assert((512 % sizeof(struct dirent)) == 0); fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); if(fsfd < 0){ perror(argv[1]); exit(1); } sb.nblocks = xint(nblocks); // so whole disk is 1024 sectors sb.ninodes = xint(ninodes); freeblock = ninodes / IPB + 2; for(i = 0; i < nblocks + (ninodes / IPB) + 3; i++) wsect(i, zeroes); wsect(1, &sb); rootino = ialloc(T_DIR); assert(rootino == 1); bzero(&de, sizeof(de)); de.inum = xshort(rootino); strcpy(de.name, "."); iappend(rootino, &de, sizeof(de)); bzero(&de, sizeof(de)); de.inum = xshort(rootino); strcpy(de.name, ".."); iappend(rootino, &de, sizeof(de)); for(i = 2; i < argc; i++){ assert(index(argv[i], '/') == 0); if((fd = open(argv[i], 0)) < 0){ perror(argv[i]); exit(1); } inum = ialloc(T_FILE); bzero(&de, sizeof(de)); de.inum = xshort(inum); strncpy(de.name, argv[i], DIRSIZ); iappend(rootino, &de, sizeof(de)); while((cc = read(fd, buf, sizeof(buf))) > 0) iappend(inum, buf, cc); close(fd); } exit(0); } void wsect(uint sec, void *buf) { if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ perror("lseek"); exit(1); } if(write(fsfd, buf, 512) != 512){ perror("write"); exit(1); } } uint i2b(uint inum) { return (inum / IPB) + 2; } void winode(uint inum, struct dinode *ip) { char buf[512]; uint bn; struct dinode *dip; bn = i2b(inum); rsect(bn, buf); dip = ((struct dinode *) buf) + (inum % IPB); *dip = *ip; wsect(bn, buf); } void rinode(uint inum, struct dinode *ip) { char buf[512]; uint bn; struct dinode *dip; bn = i2b(inum); rsect(bn, buf); dip = ((struct dinode *) buf) + (inum % IPB); *ip = *dip; } void rsect(uint sec, void *buf) { if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ perror("lseek"); exit(1); } if(read(fsfd, buf, 512) != 512){ perror("read"); exit(1); } } uint ialloc(ushort type) { uint inum = freeinode++; struct dinode din; bzero(&din, sizeof(din)); din.type = xshort(type); din.nlink = xshort(1); din.size = xint(0); winode(inum, &din); return inum; } #define min(a, b) ((a) < (b) ? (a) : (b)) void iappend(uint inum, void *xp, int n) { char *p = (char *) xp; uint fbn, off, n1; struct dinode din; char buf[512]; rinode(inum, &din); off = xint(din.size); while(n > 0){ fbn = off / 512; assert(fbn < NDIRECT); if(din.addrs[fbn] == 0) din.addrs[fbn] = xint(freeblock++); n1 = min(n, (fbn + 1) * 512 - off); rsect(xint(din.addrs[fbn]), buf); bcopy(p, buf + off - (fbn * 512), n1); wsect(xint(din.addrs[fbn]), buf); n -= n1; off += n1; p += n1; } din.size = xint(off); winode(inum, &din); }