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 %u) 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 wsect(1, &sb); 94 95 rootino = ialloc(T_DIR); 96 assert(rootino == ROOTINO); 97 98 bzero(&de, sizeof(de)); 99 de.inum = xshort(rootino); 100 strcpy(de.name, "."); 101 iappend(rootino, &de, sizeof(de)); 102 103 bzero(&de, sizeof(de)); 104 de.inum = xshort(rootino); 105 strcpy(de.name, ".."); 106 iappend(rootino, &de, sizeof(de)); 107 108 for(i = 2; i < argc; i++){ 109 assert(index(argv[i], '/') == 0); 110 111 if((fd = open(argv[i], 0)) < 0){ 112 perror(argv[i]); 113 exit(1); 114 } 115 116 // Skip leading _ in name when writing to file system. 117 // The binaries are named _rm, _cat, etc. to keep the 118 // build operating system from trying to execute them 119 // in place of system binaries like rm and cat. 120 if(argv[i][0] == '_') 121 ++argv[i]; 122 123 inum = ialloc(T_FILE); 124 125 bzero(&de, sizeof(de)); 126 de.inum = xshort(inum); 127 strncpy(de.name, argv[i], DIRSIZ); 128 iappend(rootino, &de, sizeof(de)); 129 130 while((cc = read(fd, buf, sizeof(buf))) > 0) 131 iappend(inum, buf, cc); 132 133 close(fd); 134 } 135 136 // fix size of root inode dir 137 rinode(rootino, &din); 138 off = xint(din.size); 139 off = ((off/BSIZE) + 1) * BSIZE; 140 din.size = xint(off); 141 winode(rootino, &din); 142 143 balloc(usedblocks); 144 145 exit(0); 146 } 147 148 void 149 wsect(uint sec, void *buf) 150 { 151 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ 152 perror("lseek"); 153 exit(1); 154 } 155 if(write(fsfd, buf, 512) != 512){ 156 perror("write"); 157 exit(1); 158 } 159 } 160 161 uint 162 i2b(uint inum) 163 { 164 return (inum / IPB) + 2; 165 } 166 167 void 168 winode(uint inum, struct dinode *ip) 169 { 170 char buf[512]; 171 uint bn; 172 struct dinode *dip; 173 174 bn = i2b(inum); 175 rsect(bn, buf); 176 dip = ((struct dinode*) buf) + (inum % IPB); 177 *dip = *ip; 178 wsect(bn, buf); 179 } 180 181 void 182 rinode(uint inum, struct dinode *ip) 183 { 184 char buf[512]; 185 uint bn; 186 struct dinode *dip; 187 188 bn = i2b(inum); 189 rsect(bn, buf); 190 dip = ((struct dinode*) buf) + (inum % IPB); 191 *ip = *dip; 192 } 193 194 void 195 rsect(uint sec, void *buf) 196 { 197 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ 198 perror("lseek"); 199 exit(1); 200 } 201 if(read(fsfd, buf, 512) != 512){ 202 perror("read"); 203 exit(1); 204 } 205 } 206 207 uint 208 ialloc(ushort type) 209 { 210 uint inum = freeinode++; 211 struct dinode din; 212 213 bzero(&din, sizeof(din)); 214 din.type = xshort(type); 215 din.nlink = xshort(1); 216 din.size = xint(0); 217 winode(inum, &din); 218 return inum; 219 } 220 221 void 222 balloc(int used) 223 { 224 uchar buf[512]; 225 int i; 226 227 printf("balloc: first %d blocks have been allocated\n", used); 228 assert(used < 512); 229 bzero(buf, 512); 230 for(i = 0; i < used; i++) { 231 buf[i/8] = buf[i/8] | (0x1 << (i%8)); 232 } 233 printf("balloc: write bitmap block at sector %u\n", ninodes/IPB + 3); 234 wsect(ninodes / IPB + 3, buf); 235 } 236 237 #define min(a, b) ((a) < (b) ? (a) : (b)) 238 239 void 240 iappend(uint inum, void *xp, int n) 241 { 242 char *p = (char*) xp; 243 uint fbn, off, n1; 244 struct dinode din; 245 char buf[512]; 246 uint indirect[NINDIRECT]; 247 uint x; 248 249 rinode(inum, &din); 250 251 off = xint(din.size); 252 while(n > 0){ 253 fbn = off / 512; 254 assert(fbn < MAXFILE); 255 if(fbn < NDIRECT) { 256 if(xint(din.addrs[fbn]) == 0) { 257 din.addrs[fbn] = xint(freeblock++); 258 usedblocks++; 259 } 260 x = xint(din.addrs[fbn]); 261 } else { 262 if(xint(din.addrs[NDIRECT]) == 0) { 263 // printf("allocate indirect block\n"); 264 din.addrs[NDIRECT] = xint(freeblock++); 265 usedblocks++; 266 } 267 // printf("read indirect block\n"); 268 rsect(xint(din.addrs[NDIRECT]), (char*) indirect); 269 if(indirect[fbn - NDIRECT] == 0) { 270 indirect[fbn - NDIRECT] = xint(freeblock++); 271 usedblocks++; 272 wsect(xint(din.addrs[NDIRECT]), (char*) indirect); 273 } 274 x = xint(indirect[fbn-NDIRECT]); 275 } 276 n1 = min(n, (fbn + 1) * 512 - off); 277 rsect(x, buf); 278 bcopy(p, buf + off - (fbn * 512), n1); 279 wsect(x, buf); 280 n -= n1; 281 off += n1; 282 p += n1; 283 } 284 din.size = xint(off); 285 winode(inum, &din); 286 } 287