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