root/mkfs/mkfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xshort
  2. xint
  3. main
  4. wsect
  5. winode
  6. rinode
  7. rsect
  8. ialloc
  9. balloc
  10. iappend
  11. die

   1 #include <stdio.h>
   2 #include <unistd.h>
   3 #include <stdlib.h>
   4 #include <string.h>
   5 #include <fcntl.h>
   6 #include <assert.h>
   7 
   8 #define stat xv6_stat  // avoid clash with host struct stat
   9 #include "kernel/types.h"
  10 #include "kernel/fs.h"
  11 #include "kernel/stat.h"
  12 #include "kernel/param.h"
  13 
  14 #ifndef static_assert
  15 #define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
  16 #endif
  17 
  18 #define NINODES 200
  19 
  20 // Disk layout:
  21 // [ boot block | sb block | log | inode blocks | free bit map | data blocks ]
  22 
  23 int nbitmap = FSSIZE/BPB + 1;
  24 int ninodeblocks = NINODES / IPB + 1;
  25 int nlog = LOGSIZE;
  26 int nmeta;    // Number of meta blocks (boot, sb, nlog, inode, bitmap)
  27 int nblocks;  // Number of data blocks
  28 
  29 int fsfd;
  30 struct superblock sb;
  31 char zeroes[BSIZE];
  32 uint freeinode = 1;
  33 uint freeblock;
  34 
  35 
  36 void balloc(int);
  37 void wsect(uint, void*);
  38 void winode(uint, struct dinode*);
  39 void rinode(uint inum, struct dinode *ip);
  40 void rsect(uint sec, void *buf);
  41 uint ialloc(ushort type);
  42 void iappend(uint inum, void *p, int n);
  43 void die(const char *);
  44 
  45 // convert to riscv byte order
  46 ushort
  47 xshort(ushort x)
  48 {
  49   ushort y;
  50   uchar *a = (uchar*)&y;
  51   a[0] = x;
  52   a[1] = x >> 8;
  53   return y;
  54 }
  55 
  56 uint
  57 xint(uint x)
  58 {
  59   uint y;
  60   uchar *a = (uchar*)&y;
  61   a[0] = x;
  62   a[1] = x >> 8;
  63   a[2] = x >> 16;
  64   a[3] = x >> 24;
  65   return y;
  66 }
  67 
  68 int
  69 main(int argc, char *argv[])
  70 {
  71   int i, cc, fd;
  72   uint rootino, inum, off;
  73   struct dirent de;
  74   char buf[BSIZE];
  75   struct dinode din;
  76 
  77 
  78   static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");
  79 
  80   if(argc < 2){
  81     fprintf(stderr, "Usage: mkfs fs.img files...\n");
  82     exit(1);
  83   }
  84 
  85   assert((BSIZE % sizeof(struct dinode)) == 0);
  86   assert((BSIZE % sizeof(struct dirent)) == 0);
  87 
  88   fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
  89   if(fsfd < 0)
  90     die(argv[1]);
  91 
  92   // 1 fs block = 1 disk sector
  93   nmeta = 2 + nlog + ninodeblocks + nbitmap;
  94   nblocks = FSSIZE - nmeta;
  95 
  96   sb.magic = FSMAGIC;
  97   sb.size = xint(FSSIZE);
  98   sb.nblocks = xint(nblocks);
  99   sb.ninodes = xint(NINODES);
 100   sb.nlog = xint(nlog);
 101   sb.logstart = xint(2);
 102   sb.inodestart = xint(2+nlog);
 103   sb.bmapstart = xint(2+nlog+ninodeblocks);
 104 
 105   printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
 106          nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);
 107 
 108   freeblock = nmeta;     // the first free block that we can allocate
 109 
 110   for(i = 0; i < FSSIZE; i++)
 111     wsect(i, zeroes);
 112 
 113   memset(buf, 0, sizeof(buf));
 114   memmove(buf, &sb, sizeof(sb));
 115   wsect(1, buf);
 116 
 117   rootino = ialloc(T_DIR);
 118   assert(rootino == ROOTINO);
 119 
 120   bzero(&de, sizeof(de));
 121   de.inum = xshort(rootino);
 122   strcpy(de.name, ".");
 123   iappend(rootino, &de, sizeof(de));
 124 
 125   bzero(&de, sizeof(de));
 126   de.inum = xshort(rootino);
 127   strcpy(de.name, "..");
 128   iappend(rootino, &de, sizeof(de));
 129 
 130   for(i = 2; i < argc; i++){
 131     // get rid of "user/"
 132     char *shortname;
 133     if(strncmp(argv[i], "user/", 5) == 0)
 134       shortname = argv[i] + 5;
 135     else
 136       shortname = argv[i];
 137     
 138     assert(index(shortname, '/') == 0);
 139 
 140     if((fd = open(argv[i], 0)) < 0)
 141       die(argv[i]);
 142 
 143     // Skip leading _ in name when writing to file system.
 144     // The binaries are named _rm, _cat, etc. to keep the
 145     // build operating system from trying to execute them
 146     // in place of system binaries like rm and cat.
 147     if(shortname[0] == '_')
 148       shortname += 1;
 149 
 150     assert(strlen(shortname) <= DIRSIZ);
 151     
 152     inum = ialloc(T_FILE);
 153 
 154     bzero(&de, sizeof(de));
 155     de.inum = xshort(inum);
 156     strncpy(de.name, shortname, DIRSIZ);
 157     iappend(rootino, &de, sizeof(de));
 158 
 159     while((cc = read(fd, buf, sizeof(buf))) > 0)
 160       iappend(inum, buf, cc);
 161 
 162     close(fd);
 163   }
 164 
 165   // fix size of root inode dir
 166   rinode(rootino, &din);
 167   off = xint(din.size);
 168   off = ((off/BSIZE) + 1) * BSIZE;
 169   din.size = xint(off);
 170   winode(rootino, &din);
 171 
 172   balloc(freeblock);
 173 
 174   exit(0);
 175 }
 176 
 177 void
 178 wsect(uint sec, void *buf)
 179 {
 180   if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE)
 181     die("lseek");
 182   if(write(fsfd, buf, BSIZE) != BSIZE)
 183     die("write");
 184 }
 185 
 186 void
 187 winode(uint inum, struct dinode *ip)
 188 {
 189   char buf[BSIZE];
 190   uint bn;
 191   struct dinode *dip;
 192 
 193   bn = IBLOCK(inum, sb);
 194   rsect(bn, buf);
 195   dip = ((struct dinode*)buf) + (inum % IPB);
 196   *dip = *ip;
 197   wsect(bn, buf);
 198 }
 199 
 200 void
 201 rinode(uint inum, struct dinode *ip)
 202 {
 203   char buf[BSIZE];
 204   uint bn;
 205   struct dinode *dip;
 206 
 207   bn = IBLOCK(inum, sb);
 208   rsect(bn, buf);
 209   dip = ((struct dinode*)buf) + (inum % IPB);
 210   *ip = *dip;
 211 }
 212 
 213 void
 214 rsect(uint sec, void *buf)
 215 {
 216   if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE)
 217     die("lseek");
 218   if(read(fsfd, buf, BSIZE) != BSIZE)
 219     die("read");
 220 }
 221 
 222 uint
 223 ialloc(ushort type)
 224 {
 225   uint inum = freeinode++;
 226   struct dinode din;
 227 
 228   bzero(&din, sizeof(din));
 229   din.type = xshort(type);
 230   din.nlink = xshort(1);
 231   din.size = xint(0);
 232   winode(inum, &din);
 233   return inum;
 234 }
 235 
 236 void
 237 balloc(int used)
 238 {
 239   uchar buf[BSIZE];
 240   int i;
 241 
 242   printf("balloc: first %d blocks have been allocated\n", used);
 243   assert(used < BPB);
 244   bzero(buf, BSIZE);
 245   for(i = 0; i < used; i++){
 246     buf[i/8] = buf[i/8] | (0x1 << (i%8));
 247   }
 248   printf("balloc: write bitmap block at sector %d\n", sb.bmapstart);
 249   wsect(sb.bmapstart, buf);
 250 }
 251 
 252 #define min(a, b) ((a) < (b) ? (a) : (b))
 253 
 254 void
 255 iappend(uint inum, void *xp, int n)
 256 {
 257   char *p = (char*)xp;
 258   uint fbn, off, n1;
 259   struct dinode din;
 260   char buf[BSIZE];
 261   uint indirect[NINDIRECT];
 262   uint x;
 263 
 264   rinode(inum, &din);
 265   off = xint(din.size);
 266   // printf("append inum %d at off %d sz %d\n", inum, off, n);
 267   while(n > 0){
 268     fbn = off / BSIZE;
 269     assert(fbn < MAXFILE);
 270     if(fbn < NDIRECT){
 271       if(xint(din.addrs[fbn]) == 0){
 272         din.addrs[fbn] = xint(freeblock++);
 273       }
 274       x = xint(din.addrs[fbn]);
 275     } else {
 276       if(xint(din.addrs[NDIRECT]) == 0){
 277         din.addrs[NDIRECT] = xint(freeblock++);
 278       }
 279       rsect(xint(din.addrs[NDIRECT]), (char*)indirect);
 280       if(indirect[fbn - NDIRECT] == 0){
 281         indirect[fbn - NDIRECT] = xint(freeblock++);
 282         wsect(xint(din.addrs[NDIRECT]), (char*)indirect);
 283       }
 284       x = xint(indirect[fbn-NDIRECT]);
 285     }
 286     n1 = min(n, (fbn + 1) * BSIZE - off);
 287     rsect(x, buf);
 288     bcopy(p, buf + off - (fbn * BSIZE), n1);
 289     wsect(x, buf);
 290     n -= n1;
 291     off += n1;
 292     p += n1;
 293   }
 294   din.size = xint(off);
 295   winode(inum, &din);
 296 }
 297 
 298 void
 299 die(const char *s)
 300 {
 301   perror(s);
 302   exit(1);
 303 }

/* [<][>][^][v][top][bottom][index][help] */