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