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