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 int nblocks = (995-LOGSIZE); 17 int nlog = LOGSIZE; 18 int ninodes = 200; 19 int size = 1024; 20 21 int fsfd; 22 struct superblock sb; 23 char zeroes[512]; 24 uint freeblock; 25 uint usedblocks; 26 uint bitblocks; 27 uint freeinode = 1; 28 29 void balloc(int); 30 void wsect(uint, void*); 31 void winode(uint, struct dinode*); 32 void rinode(uint inum, struct dinode *ip); 33 void rsect(uint sec, void *buf); 34 uint ialloc(ushort type); 35 void iappend(uint inum, void *p, int n); 36 37 // convert to intel byte order 38 ushort 39 xshort(ushort x) 40 { 41 ushort y; 42 uchar *a = (uchar*)&y; 43 a[0] = x; 44 a[1] = x >> 8; 45 return y; 46 } 47 48 uint 49 xint(uint x) 50 { 51 uint y; 52 uchar *a = (uchar*)&y; 53 a[0] = x; 54 a[1] = x >> 8; 55 a[2] = x >> 16; 56 a[3] = x >> 24; 57 return y; 58 } 59 60 int 61 main(int argc, char *argv[]) 62 { 63 int i, cc, fd; 64 uint rootino, inum, off; 65 struct dirent de; 66 char buf[512]; 67 struct dinode din; 68 69 70 static_assert(sizeof(int) == 4, "Integers must be 4 bytes!"); 71 72 if(argc < 2){ 73 fprintf(stderr, "Usage: mkfs fs.img files...\n"); 74 exit(1); 75 } 76 77 assert((512 % sizeof(struct dinode)) == 0); 78 assert((512 % sizeof(struct dirent)) == 0); 79 80 fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); 81 if(fsfd < 0){ 82 perror(argv[1]); 83 exit(1); 84 } 85 86 sb.size = xint(size); 87 sb.nblocks = xint(nblocks); // so whole disk is size sectors 88 sb.ninodes = xint(ninodes); 89 sb.nlog = xint(nlog); 90 91 bitblocks = size/(512*8) + 1; 92 usedblocks = ninodes / IPB + 3 + bitblocks; 93 freeblock = usedblocks; 94 95 printf("used %d (bit %d ninode %zu) free %u log %u total %d\n", usedblocks, 96 bitblocks, ninodes/IPB + 1, freeblock, nlog, nblocks+usedblocks+nlog); 97 98 assert(nblocks + usedblocks + nlog == size); 99 100 for(i = 0; i < nblocks + usedblocks + nlog; i++) 101 wsect(i, zeroes); 102 103 memset(buf, 0, sizeof(buf)); 104 memmove(buf, &sb, sizeof(sb)); 105 wsect(1, buf); 106 107 rootino = ialloc(T_DIR); 108 assert(rootino == ROOTINO); 109 110 bzero(&de, sizeof(de)); 111 de.inum = xshort(rootino); 112 strcpy(de.name, "."); 113 iappend(rootino, &de, sizeof(de)); 114 115 bzero(&de, sizeof(de)); 116 de.inum = xshort(rootino); 117 strcpy(de.name, ".."); 118 iappend(rootino, &de, sizeof(de)); 119 120 for(i = 2; i < argc; i++){ 121 assert(index(argv[i], '/') == 0); 122 123 if((fd = open(argv[i], 0)) < 0){ 124 perror(argv[i]); 125 exit(1); 126 } 127 128 // Skip leading _ in name when writing to file system. 129 // The binaries are named _rm, _cat, etc. to keep the 130 // build operating system from trying to execute them 131 // in place of system binaries like rm and cat. 132 if(argv[i][0] == '_') 133 ++argv[i]; 134 135 inum = ialloc(T_FILE); 136 137 bzero(&de, sizeof(de)); 138 de.inum = xshort(inum); 139 strncpy(de.name, argv[i], DIRSIZ); 140 iappend(rootino, &de, sizeof(de)); 141 142 while((cc = read(fd, buf, sizeof(buf))) > 0) 143 iappend(inum, buf, cc); 144 145 close(fd); 146 } 147 148 // fix size of root inode dir 149 rinode(rootino, &din); 150 off = xint(din.size); 151 off = ((off/BSIZE) + 1) * BSIZE; 152 din.size = xint(off); 153 winode(rootino, &din); 154 155 balloc(usedblocks); 156 157 exit(0); 158 } 159 160 void 161 wsect(uint sec, void *buf) 162 { 163 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ 164 perror("lseek"); 165 exit(1); 166 } 167 if(write(fsfd, buf, 512) != 512){ 168 perror("write"); 169 exit(1); 170 } 171 } 172 173 uint 174 i2b(uint inum) 175 { 176 return (inum / IPB) + 2; 177 } 178 179 void 180 winode(uint inum, struct dinode *ip) 181 { 182 char buf[512]; 183 uint bn; 184 struct dinode *dip; 185 186 bn = i2b(inum); 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[512]; 197 uint bn; 198 struct dinode *dip; 199 200 bn = i2b(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 * 512L, 0) != sec * 512L){ 210 perror("lseek"); 211 exit(1); 212 } 213 if(read(fsfd, buf, 512) != 512){ 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[512]; 237 int i; 238 239 printf("balloc: first %d blocks have been allocated\n", used); 240 assert(used < 512*8); 241 bzero(buf, 512); 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 %zu\n", ninodes/IPB + 3); 246 wsect(ninodes / IPB + 3, 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[512]; 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 / 512; 266 assert(fbn < MAXFILE); 267 if(fbn < NDIRECT){ 268 if(xint(din.addrs[fbn]) == 0){ 269 din.addrs[fbn] = xint(freeblock++); 270 usedblocks++; 271 } 272 x = xint(din.addrs[fbn]); 273 } else { 274 if(xint(din.addrs[NDIRECT]) == 0){ 275 // printf("allocate indirect block\n"); 276 din.addrs[NDIRECT] = xint(freeblock++); 277 usedblocks++; 278 } 279 // printf("read indirect block\n"); 280 rsect(xint(din.addrs[NDIRECT]), (char*)indirect); 281 if(indirect[fbn - NDIRECT] == 0){ 282 indirect[fbn - NDIRECT] = xint(freeblock++); 283 usedblocks++; 284 wsect(xint(din.addrs[NDIRECT]), (char*)indirect); 285 } 286 x = xint(indirect[fbn-NDIRECT]); 287 } 288 n1 = min(n, (fbn + 1) * 512 - off); 289 rsect(x, buf); 290 bcopy(p, buf + off - (fbn * 512), n1); 291 wsect(x, buf); 292 n -= n1; 293 off += n1; 294 p += n1; 295 } 296 din.size = xint(off); 297 winode(inum, &din); 298 } 299