| // Disk layout: | |
| // [ boot block | sb block | log | inode blocks | free bit map | data blocks ] | |
| int nbitmap = FSSIZE/(BSIZE*8) + 1; | |
| int ninodeblocks = NINODES / IPB + 1; | |
| int nlog = LOGSIZE; | |
| int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap) | |
| int nblocks; // Number of data blocks | |
| int fsfd; | |
| struct superblock sb; | |
| char zeroes[BSIZE]; | |
| uint freeinode = 1; | |
| uint freeblock; | |
| void balloc(int); | |
| void wsect(uint, void*); | |
| void winode(uint, struct dinode*); | |
| void rinode(uint inum, struct dinode *ip); | |
| 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; | |
| } | |
| int | |
| main(int argc, char *argv[]) | |
| { | |
| int i, cc, fd; | |
| uint rootino, inum, off; | |
| struct dirent de; | |
| char buf[BSIZE]; | |
| struct dinode din; | |
| static_assert(sizeof(int) == 4, "Integers must be 4 bytes!"); | |
| if(argc < 2){ | |
| fprintf(stderr, "Usage: mkfs fs.img files...\n"); | |
| exit(1); | |
| } | |
| assert((BSIZE % sizeof(struct dinode)) == 0); | |
| assert((BSIZE % sizeof(struct dirent)) == 0); | |
| fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); | |
| if(fsfd < 0){ | |
| perror(argv[1]); | |
| exit(1); | |
| } | |
| // 1 fs block = 1 disk sector | |
| nmeta = 2 + nlog + ninodeblocks + nbitmap; | |
| nblocks = FSSIZE - nmeta; | |
| sb.size = xint(FSSIZE); | |
| sb.nblocks = xint(nblocks); | |
| sb.ninodes = xint(NINODES); | |
| sb.nlog = xint(nlog); | |
| sb.logstart = xint(2); | |
| sb.inodestart = xint(2+nlog); | |
| sb.bmapstart = xint(2+nlog+ninodeblocks); | |
| printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n", | |
| nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE); | |
| freeblock = nmeta; // the first free block that we can allocate | |
| for(i = 0; i < FSSIZE; i++) | |
| wsect(i, zeroes); | |
| memset(buf, 0, sizeof(buf)); | |
| memmove(buf, &sb, sizeof(sb)); | |
| wsect(1, buf); | |
| rootino = ialloc(T_DIR); | |
| assert(rootino == ROOTINO); | |
| 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); | |
| } | |
| // Skip leading _ in name when writing to file system. | |
| // The binaries are named _rm, _cat, etc. to keep the | |
| // build operating system from trying to execute them | |
| // in place of system binaries like rm and cat. | |
| if(argv[i][0] == '_') | |
| ++argv[i]; | |
| 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); | |
| } | |
| // fix size of root inode dir | |
| rinode(rootino, &din); | |
| off = xint(din.size); | |
| off = ((off/BSIZE) + 1) * BSIZE; | |
| din.size = xint(off); | |
| winode(rootino, &din); | |
| balloc(freeblock); | |
| exit(0); | |
| } | |
| void | |
| wsect(uint sec, void *buf) | |
| { | |
| if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){ | |
| perror("lseek"); | |
| exit(1); | |
| } | |
| if(write(fsfd, buf, BSIZE) != BSIZE){ | |
| perror("write"); | |
| exit(1); | |
| } | |
| } | |
| void | |
| winode(uint inum, struct dinode *ip) | |
| { | |
| char buf[BSIZE]; | |
| uint bn; | |
| struct dinode *dip; | |
| bn = IBLOCK(inum, sb); | |
| rsect(bn, buf); | |
| dip = ((struct dinode*)buf) + (inum % IPB); | |
| *dip = *ip; | |
| wsect(bn, buf); | |
| } | |
| void | |
| rinode(uint inum, struct dinode *ip) | |
| { | |
| char buf[BSIZE]; | |
| uint bn; | |
| struct dinode *dip; | |
| bn = IBLOCK(inum, sb); | |
| rsect(bn, buf); | |
| dip = ((struct dinode*)buf) + (inum % IPB); | |
| *ip = *dip; | |
| } | |
| void | |
| rsect(uint sec, void *buf) | |
| { | |
| if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){ | |
| perror("lseek"); | |
| exit(1); | |
| } | |
| if(read(fsfd, buf, BSIZE) != BSIZE){ | |
| 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; | |
| } | |
| void | |
| balloc(int used) | |
| { | |
| uchar buf[BSIZE]; | |
| int i; | |
| printf("balloc: first %d blocks have been allocated\n", used); | |
| assert(used < BSIZE*8); | |
| bzero(buf, BSIZE); | |
| for(i = 0; i < used; i++){ | |
| buf[i/8] = buf[i/8] | (0x1 << (i%8)); | |
| } | |
| printf("balloc: write bitmap block at sector %d\n", sb.bmapstart); | |
| wsect(sb.bmapstart, buf); | |
| } | |
| void | |
| iappend(uint inum, void *xp, int n) | |
| { | |
| char *p = (char*)xp; | |
| uint fbn, off, n1; | |
| struct dinode din; | |
| char buf[BSIZE]; | |
| uint indirect[NINDIRECT]; | |
| uint x; | |
| rinode(inum, &din); | |
| off = xint(din.size); | |
| // printf("append inum %d at off %d sz %d\n", inum, off, n); | |
| while(n > 0){ | |
| fbn = off / BSIZE; | |
| assert(fbn < MAXFILE); | |
| if(fbn < NDIRECT){ | |
| if(xint(din.addrs[fbn]) == 0){ | |
| din.addrs[fbn] = xint(freeblock++); | |
| } | |
| x = xint(din.addrs[fbn]); | |
| } else { | |
| if(xint(din.addrs[NDIRECT]) == 0){ | |
| din.addrs[NDIRECT] = xint(freeblock++); | |
| } | |
| rsect(xint(din.addrs[NDIRECT]), (char*)indirect); | |
| if(indirect[fbn - NDIRECT] == 0){ | |
| indirect[fbn - NDIRECT] = xint(freeblock++); | |
| wsect(xint(din.addrs[NDIRECT]), (char*)indirect); | |
| } | |
| x = xint(indirect[fbn-NDIRECT]); | |
| } | |
| n1 = min(n, (fbn + 1) * BSIZE - off); | |
| rsect(x, buf); | |
| bcopy(p, buf + off - (fbn * BSIZE), n1); | |
| wsect(x, buf); | |
| n -= n1; | |
| off += n1; | |
| p += n1; | |
| } | |
| din.size = xint(off); | |
| winode(inum, &din); | |
| } | |
Xet Storage Details
- Size:
- 6.14 kB
- Xet hash:
- d5c9a70c2f7367b536b98d3255bd0ba7546fc2de662c58f52bc312a5772637e2
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.