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