mkfs.c (5815B)
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 "../include/types.h" 10 #include "../include/fs.h" 11 #include "../include/stat.h" 12 #include "../include/param.h" 13 14 #ifndef static_assert 15 # define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0) 16 #endif // static_assert 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 72 static_assert(sizeof(int) == 4, "Integers must be 4 bytes!"); 73 74 if(argc < 2){ 75 fprintf(stderr, "Usage: mkfs fs.img files...\n"); 76 exit(1); 77 } 78 79 assert((512 % sizeof(struct dinode)) == 0); 80 assert((512 % sizeof(struct dirent)) == 0); 81 82 fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); 83 if(fsfd < 0){ 84 perror(argv[1]); 85 exit(1); 86 } 87 88 sb.size = xint(size); 89 sb.nblocks = xint(nblocks); // so whole disk is size sectors 90 sb.ninodes = xint(ninodes); 91 sb.nlog = xint(nlog); 92 93 bitblocks = size/(512*8) + 1; 94 usedblocks = ninodes / IPB + 3 + bitblocks; 95 freeblock = usedblocks; 96 97 printf("used %d (bit %d ninode %zu) free %u log %u total %d\n", usedblocks, 98 bitblocks, ninodes/IPB + 1, freeblock, nlog, nblocks+usedblocks+nlog); 99 100 assert(nblocks + usedblocks + nlog == size); 101 102 for(i = 0; i < nblocks + usedblocks + nlog; i++) 103 wsect(i, zeroes); 104 105 memset(buf, 0, sizeof(buf)); 106 memmove(buf, &sb, sizeof(sb)); 107 wsect(1, buf); 108 109 rootino = ialloc(T_DIR); 110 assert(rootino == ROOTINO); 111 112 bzero(&de, sizeof(de)); 113 de.inum = xshort(rootino); 114 strcpy(de.name, "."); 115 iappend(rootino, &de, sizeof(de)); 116 117 bzero(&de, sizeof(de)); 118 de.inum = xshort(rootino); 119 strcpy(de.name, ".."); 120 iappend(rootino, &de, sizeof(de)); 121 122 for(i = 2; i < argc; i++){ 123 char *name = argv[i]; 124 125 if (!strncmp(name, "fs/", 3)) 126 name += 3; 127 128 assert(index(name, '/') == 0); 129 130 if((fd = open(argv[i], 0)) < 0){ 131 perror(argv[i]); 132 exit(1); 133 } 134 135 inum = ialloc(T_FILE); 136 137 bzero(&de, sizeof(de)); 138 de.inum = xshort(inum); 139 strncpy(de.name, name, DIRSIZ); 140 iappend(rootino, &de, sizeof(de)); 141 142 while((cc = read(fd, buf, sizeof(buf))) > 0) 143 iappend(inum, buf, cc); 144 145 close(fd); 146 } 147 148 // fix size of root inode dir 149 rinode(rootino, &din); 150 off = xint(din.size); 151 off = ((off/BSIZE) + 1) * BSIZE; 152 din.size = xint(off); 153 winode(rootino, &din); 154 155 balloc(usedblocks); 156 157 exit(0); 158 } 159 160 void 161 wsect(uint sec, void *buf) 162 { 163 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ 164 perror("lseek"); 165 exit(1); 166 } 167 if(write(fsfd, buf, 512) != 512){ 168 perror("write"); 169 exit(1); 170 } 171 } 172 173 uint 174 i2b(uint inum) 175 { 176 return (inum / IPB) + 2; 177 } 178 179 void 180 winode(uint inum, struct dinode *ip) 181 { 182 char buf[512]; 183 uint bn; 184 struct dinode *dip; 185 186 bn = i2b(inum); 187 rsect(bn, buf); 188 dip = ((struct dinode*)buf) + (inum % IPB); 189 *dip = *ip; 190 wsect(bn, buf); 191 } 192 193 void 194 rinode(uint inum, struct dinode *ip) 195 { 196 char buf[512]; 197 uint bn; 198 struct dinode *dip; 199 200 bn = i2b(inum); 201 rsect(bn, buf); 202 dip = ((struct dinode*)buf) + (inum % IPB); 203 *ip = *dip; 204 } 205 206 void 207 rsect(uint sec, void *buf) 208 { 209 if(lseek(fsfd, sec * 512L, 0) != sec * 512L){ 210 perror("lseek"); 211 exit(1); 212 } 213 if(read(fsfd, buf, 512) != 512){ 214 perror("read"); 215 exit(1); 216 } 217 } 218 219 uint 220 ialloc(ushort type) 221 { 222 uint inum = freeinode++; 223 struct dinode din; 224 225 bzero(&din, sizeof(din)); 226 din.type = xshort(type); 227 din.nlink = xshort(1); 228 din.size = xint(0); 229 winode(inum, &din); 230 return inum; 231 } 232 233 void 234 balloc(int used) 235 { 236 uchar buf[512]; 237 int i; 238 239 printf("balloc: first %d blocks have been allocated\n", used); 240 assert(used < 512*8); 241 bzero(buf, 512); 242 for(i = 0; i < used; i++){ 243 buf[i/8] = buf[i/8] | (0x1 << (i%8)); 244 } 245 printf("balloc: write bitmap block at sector %zu\n", ninodes/IPB + 3); 246 wsect(ninodes / IPB + 3, buf); 247 } 248 249 #define min(a, b) ((a) < (b) ? (a) : (b)) 250 251 void 252 iappend(uint inum, void *xp, int n) 253 { 254 char *p = (char*)xp; 255 uint fbn, off, n1; 256 struct dinode din; 257 char buf[512]; 258 uint indirect[NINDIRECT]; 259 uint x; 260 261 rinode(inum, &din); 262 263 off = xint(din.size); 264 while(n > 0){ 265 fbn = off / 512; 266 assert(fbn < MAXFILE); 267 if(fbn < NDIRECT){ 268 if(xint(din.addrs[fbn]) == 0){ 269 din.addrs[fbn] = xint(freeblock++); 270 usedblocks++; 271 } 272 x = xint(din.addrs[fbn]); 273 } else { 274 if(xint(din.addrs[NDIRECT]) == 0){ 275 // printf("allocate indirect block\n"); 276 din.addrs[NDIRECT] = xint(freeblock++); 277 usedblocks++; 278 } 279 // printf("read indirect block\n"); 280 rsect(xint(din.addrs[NDIRECT]), (char*)indirect); 281 if(indirect[fbn - NDIRECT] == 0){ 282 indirect[fbn - NDIRECT] = xint(freeblock++); 283 usedblocks++; 284 wsect(xint(din.addrs[NDIRECT]), (char*)indirect); 285 } 286 x = xint(indirect[fbn-NDIRECT]); 287 } 288 n1 = min(n, (fbn + 1) * 512 - off); 289 rsect(x, buf); 290 bcopy(p, buf + off - (fbn * 512), n1); 291 wsect(x, buf); 292 n -= n1; 293 off += n1; 294 p += n1; 295 } 296 din.size = xint(off); 297 winode(inum, &din); 298 }