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 "param.h" 9 #include "fs.h" 10 11 int nblocks = 1008; 12 int ninodes = 100; 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 main(int argc, char *argv[]) 55 { 56 int i, cc, fd; 57 uint bn, 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 %d) free %d 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 == 1); 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 inum = ialloc(T_FILE); 116 117 bzero(&de, sizeof(de)); 118 de.inum = xshort(inum); 119 strncpy(de.name, argv[i], DIRSIZ); 120 iappend(rootino, &de, sizeof(de)); 121 122 while((cc = read(fd, buf, sizeof(buf))) > 0) 123 iappend(inum, buf, cc); 124 125 close(fd); 126 } 127 128 // fix size of root inode dir 129 rinode(rootino, &din); 130 off = xint(din.size); 131 off = ((off/BSIZE) + 1) * BSIZE; 132 din.size = xint(off); 133 winode(rootino, &din); 134 135 balloc(usedblocks); 136 137 exit(0); 138 } 139 140 void 141 wsect(uint sec, void *buf) 142 { 143 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ 144 perror("lseek"); 145 exit(1); 146 } 147 if(write(fsfd, buf, 512) != 512){ 148 perror("write"); 149 exit(1); 150 } 151 } 152 153 uint 154 i2b(uint inum) 155 { 156 return (inum / IPB) + 2; 157 } 158 159 void 160 winode(uint inum, struct dinode *ip) 161 { 162 char buf[512]; 163 uint bn; 164 struct dinode *dip; 165 166 bn = i2b(inum); 167 rsect(bn, buf); 168 dip = ((struct dinode*) buf) + (inum % IPB); 169 *dip = *ip; 170 wsect(bn, buf); 171 } 172 173 void 174 rinode(uint inum, struct dinode *ip) 175 { 176 char buf[512]; 177 uint bn; 178 struct dinode *dip; 179 180 bn = i2b(inum); 181 rsect(bn, buf); 182 dip = ((struct dinode*) buf) + (inum % IPB); 183 *ip = *dip; 184 } 185 186 void 187 rsect(uint sec, void *buf) 188 { 189 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ 190 perror("lseek"); 191 exit(1); 192 } 193 if(read(fsfd, buf, 512) != 512){ 194 perror("read"); 195 exit(1); 196 } 197 } 198 199 uint 200 ialloc(ushort type) 201 { 202 uint inum = freeinode++; 203 struct dinode din; 204 205 bzero(&din, sizeof(din)); 206 din.type = xshort(type); 207 din.nlink = xshort(1); 208 din.size = xint(0); 209 winode(inum, &din); 210 return inum; 211 } 212 213 void 214 balloc(int used) 215 { 216 uchar buf[512]; 217 int i; 218 219 printf("balloc: first %d blocks have been allocated\n", used); 220 assert(used < 512); 221 bzero(buf, 512); 222 for(i = 0; i < used; i++) { 223 buf[i/8] = buf[i/8] | (0x1 << (i%8)); 224 } 225 printf("balloc: write bitmap block at sector %d\n", ninodes/IPB + 3); 226 wsect(ninodes / IPB + 3, buf); 227 } 228 229 #define min(a, b) ((a) < (b) ? (a) : (b)) 230 231 void 232 iappend(uint inum, void *xp, int n) 233 { 234 char *p = (char*) xp; 235 uint fbn, off, n1; 236 struct dinode din; 237 char buf[512]; 238 uint indirect[NINDIRECT]; 239 uint x; 240 241 rinode(inum, &din); 242 243 off = xint(din.size); 244 while(n > 0){ 245 fbn = off / 512; 246 assert(fbn < MAXFILE); 247 if(fbn < NDIRECT) { 248 if(xint(din.addrs[fbn]) == 0) { 249 din.addrs[fbn] = xint(freeblock++); 250 usedblocks++; 251 } 252 x = xint(din.addrs[fbn]); 253 } else { 254 if(xint(din.addrs[INDIRECT]) == 0) { 255 printf("allocate indirect block\n"); 256 din.addrs[INDIRECT] = xint(freeblock++); 257 usedblocks++; 258 } 259 printf("read indirect block\n"); 260 rsect(xint(din.addrs[INDIRECT]), (char*) indirect); 261 if(indirect[fbn - NDIRECT] == 0) { 262 indirect[fbn - NDIRECT] = xint(freeblock++); 263 usedblocks++; 264 wsect(xint(din.addrs[INDIRECT]), (char*) indirect); 265 } 266 x = xint(indirect[fbn-NDIRECT]); 267 } 268 n1 = min(n, (fbn + 1) * 512 - off); 269 rsect(x, buf); 270 bcopy(p, buf + off - (fbn * 512), n1); 271 wsect(x, buf); 272 n -= n1; 273 off += n1; 274 p += n1; 275 } 276 din.size = xint(off); 277 winode(inum, &din); 278 } 279