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