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