123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <assert.h>
- #define stat xv6_stat // avoid clash with host struct stat
- #include "types.h"
- #include "fs.h"
- #include "stat.h"
- #include "param.h"
- #define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
- int nblocks = 985;
- int nlog = LOGSIZE;
- int ninodes = 200;
- int size = 1024;
- int fsfd;
- struct superblock sb;
- char zeroes[512];
- uint freeblock;
- uint usedblocks;
- uint bitblocks;
- uint freeinode = 1;
- 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[512];
- 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((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.size = xint(size);
- sb.nblocks = xint(nblocks); // so whole disk is size sectors
- sb.ninodes = xint(ninodes);
- sb.nlog = xint(nlog);
- bitblocks = size/(512*8) + 1;
- usedblocks = ninodes / IPB + 3 + bitblocks;
- freeblock = usedblocks;
- printf("used %d (bit %d ninode %zu) free %u log %u total %d\n", usedblocks,
- bitblocks, ninodes/IPB + 1, freeblock, nlog, nblocks+usedblocks+nlog);
- assert(nblocks + usedblocks + nlog == size);
- for(i = 0; i < nblocks + usedblocks + nlog; 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(usedblocks);
- 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;
- }
- void
- balloc(int used)
- {
- uchar buf[512];
- int i;
- printf("balloc: first %d blocks have been allocated\n", used);
- assert(used < 512*8);
- bzero(buf, 512);
- for(i = 0; i < used; i++){
- buf[i/8] = buf[i/8] | (0x1 << (i%8));
- }
- printf("balloc: write bitmap block at sector %zu\n", ninodes/IPB + 3);
- wsect(ninodes / IPB + 3, buf);
- }
- #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];
- uint indirect[NINDIRECT];
- uint x;
- rinode(inum, &din);
- off = xint(din.size);
- while(n > 0){
- fbn = off / 512;
- assert(fbn < MAXFILE);
- if(fbn < NDIRECT){
- if(xint(din.addrs[fbn]) == 0){
- din.addrs[fbn] = xint(freeblock++);
- usedblocks++;
- }
- x = xint(din.addrs[fbn]);
- } else {
- if(xint(din.addrs[NDIRECT]) == 0){
- // printf("allocate indirect block\n");
- din.addrs[NDIRECT] = xint(freeblock++);
- usedblocks++;
- }
- // printf("read indirect block\n");
- rsect(xint(din.addrs[NDIRECT]), (char*)indirect);
- if(indirect[fbn - NDIRECT] == 0){
- indirect[fbn - NDIRECT] = xint(freeblock++);
- usedblocks++;
- wsect(xint(din.addrs[NDIRECT]), (char*)indirect);
- }
- x = xint(indirect[fbn-NDIRECT]);
- }
- n1 = min(n, (fbn + 1) * 512 - off);
- rsect(x, buf);
- bcopy(p, buf + off - (fbn * 512), n1);
- wsect(x, buf);
- n -= n1;
- off += n1;
- p += n1;
- }
- din.size = xint(off);
- winode(inum, &din);
- }
|