1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)mkproto.c 4.3 (Berkeley) 05/03/83"; 4 5 /* 6 * Make a file system prototype. 7 * usage: mkproto filsys proto 8 */ 9 #include <stdio.h> 10 #include <sys/param.h> 11 #include <sys/inode.h> 12 #include <sys/fs.h> 13 #include <sys/dir.h> 14 15 union { 16 struct fs fs; 17 char fsx[SBSIZE]; 18 } ufs; 19 #define sblock ufs.fs 20 union { 21 struct cg cg; 22 char cgx[MAXBSIZE]; 23 } ucg; 24 #define acg ucg.cg 25 struct fs *fs; 26 struct csum *fscs; 27 int fso, fsi; 28 FILE *proto; 29 char token[BUFSIZ]; 30 int errs; 31 int ino = 10; 32 long getnum(); 33 char *strcpy(); 34 35 main(argc, argv) 36 int argc; 37 char *argv[]; 38 { 39 int i; 40 41 if (argc != 3) { 42 fprintf(stderr, "usage: mkproto filsys proto\n"); 43 exit(1); 44 } 45 fso = open(argv[1], 1); 46 fsi = open(argv[1], 0); 47 if (fso < 0 || fsi < 0) { 48 perror(argv[1]); 49 exit(1); 50 } 51 fs = &sblock; 52 rdfs(SBLOCK, SBSIZE, (char *)fs); 53 fscs = (struct csum *)calloc(1, fs->fs_cssize); 54 for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) 55 rdfs(fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)), 56 (int)(fs->fs_cssize - i < fs->fs_bsize ? 57 fs->fs_cssize - i : fs->fs_bsize), 58 ((char *)fscs) + i); 59 proto = fopen(argv[2], "r"); 60 descend((struct inode *)0); 61 wtfs(SBLOCK, SBSIZE, (char *)fs); 62 for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) 63 wtfs(fsbtodb(&sblock, fs->fs_csaddr + numfrags(&sblock, i)), 64 (int)(fs->fs_cssize - i < fs->fs_bsize ? 65 fs->fs_cssize - i : fs->fs_bsize), 66 ((char *)fscs) + i); 67 exit(errs); 68 } 69 70 descend(par) 71 struct inode *par; 72 { 73 struct inode in; 74 int ibc = 0; 75 int i, f, c; 76 struct dinode *dip, inos[MAXBSIZE / sizeof (struct dinode)]; 77 daddr_t ib[MAXBSIZE / sizeof (daddr_t)]; 78 char buf[MAXBSIZE]; 79 80 getstr(); 81 in.i_mode = gmode(token[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); 82 in.i_mode |= gmode(token[1], "-u", 0, ISUID, 0, 0); 83 in.i_mode |= gmode(token[2], "-g", 0, ISGID, 0, 0); 84 for (i = 3; i < 6; i++) { 85 c = token[i]; 86 if (c < '0' || c > '7') { 87 printf("%c/%s: bad octal mode digit\n", c, token); 88 errs++; 89 c = 0; 90 } 91 in.i_mode |= (c-'0')<<(15-3*i); 92 } 93 in.i_uid = getnum(); in.i_gid = getnum(); 94 for (i = 0; i < fs->fs_bsize; i++) 95 buf[i] = 0; 96 for (i = 0; i < NINDIR(fs); i++) 97 ib[i] = (daddr_t)0; 98 in.i_nlink = 1; 99 in.i_size = 0; 100 for (i = 0; i < NDADDR; i++) 101 in.i_db[i] = (daddr_t)0; 102 for (i = 0; i < NIADDR; i++) 103 in.i_ib[i] = (daddr_t)0; 104 if (par != (struct inode *)0) { 105 ialloc(&in); 106 } else { 107 par = ∈ 108 i = itod(fs, ROOTINO); 109 rdfs(fsbtodb(fs, i), fs->fs_bsize, (char *)inos); 110 dip = &inos[ROOTINO % INOPB(fs)]; 111 in.i_number = ROOTINO; 112 in.i_nlink = dip->di_nlink; 113 in.i_size = dip->di_size; 114 in.i_db[0] = dip->di_db[0]; 115 rdfs(fsbtodb(fs, in.i_db[0]), fs->fs_bsize, buf); 116 } 117 118 switch (in.i_mode&IFMT) { 119 120 case IFREG: 121 getstr(); 122 f = open(token, 0); 123 if (f < 0) { 124 printf("%s: cannot open\n", token); 125 errs++; 126 break; 127 } 128 while ((i = read(f, buf, (int)fs->fs_bsize)) > 0) { 129 in.i_size += i; 130 newblk(buf, &ibc, ib, (int)blksize(fs, &in, ibc)); 131 } 132 close(f); 133 break; 134 135 case IFBLK: 136 case IFCHR: 137 /* 138 * special file 139 * content is maj/min types 140 */ 141 142 i = getnum() & 0377; 143 f = getnum() & 0377; 144 in.i_rdev = (i << 8) | f; 145 break; 146 147 case IFDIR: 148 /* 149 * directory 150 * put in extra links 151 * call recursively until 152 * name of "$" found 153 */ 154 155 if (in.i_number != ROOTINO) { 156 par->i_nlink++; 157 in.i_nlink++; 158 entry(&in, in.i_number, ".", buf); 159 entry(&in, par->i_number, "..", buf); 160 } 161 for (;;) { 162 getstr(); 163 if (token[0]=='$' && token[1]=='\0') 164 break; 165 entry(&in, (ino_t)(ino+1), token, buf); 166 descend(&in); 167 } 168 if (in.i_number != ROOTINO) 169 newblk(buf, &ibc, ib, (int)blksize(fs, &in, 0)); 170 else 171 wtfs(fsbtodb(fs, in.i_db[0]), (int)fs->fs_bsize, buf); 172 break; 173 } 174 iput(&in, &ibc, ib); 175 } 176 177 /*ARGSUSED*/ 178 gmode(c, s, m0, m1, m2, m3) 179 char c, *s; 180 { 181 int i; 182 183 for (i = 0; s[i]; i++) 184 if (c == s[i]) 185 return((&m0)[i]); 186 printf("%c/%s: bad mode\n", c, token); 187 errs++; 188 return(0); 189 } 190 191 long 192 getnum() 193 { 194 int i, c; 195 long n; 196 197 getstr(); 198 n = 0; 199 i = 0; 200 for (i = 0; c=token[i]; i++) { 201 if (c<'0' || c>'9') { 202 printf("%s: bad number\n", token); 203 errs++; 204 return((long)0); 205 } 206 n = n*10 + (c-'0'); 207 } 208 return(n); 209 } 210 211 getstr() 212 { 213 int i, c; 214 215 loop: 216 switch (c = getc(proto)) { 217 218 case ' ': 219 case '\t': 220 case '\n': 221 goto loop; 222 223 case EOF: 224 printf("Unexpected EOF\n"); 225 exit(1); 226 227 case ':': 228 while (getc(proto) != '\n') 229 ; 230 goto loop; 231 232 } 233 i = 0; 234 do { 235 token[i++] = c; 236 c = getc(proto); 237 } while (c != ' ' && c != '\t' && c != '\n' && c != '\0'); 238 token[i] = 0; 239 } 240 241 entry(ip, inum, str, buf) 242 struct inode *ip; 243 ino_t inum; 244 char *str; 245 char *buf; 246 { 247 register struct direct *dp, *odp; 248 int oldsize, newsize, spacefree; 249 250 odp = dp = (struct direct *)buf; 251 while ((int)dp - (int)buf < ip->i_size) { 252 odp = dp; 253 dp = (struct direct *)((int)dp + dp->d_reclen); 254 } 255 if (odp != dp) 256 oldsize = DIRSIZ(odp); 257 else 258 oldsize = 0; 259 spacefree = odp->d_reclen - oldsize; 260 dp = (struct direct *)((int)odp + oldsize); 261 dp->d_ino = inum; 262 dp->d_namlen = strlen(str); 263 newsize = DIRSIZ(dp); 264 if (spacefree >= newsize) { 265 odp->d_reclen = oldsize; 266 dp->d_reclen = spacefree; 267 } else { 268 dp = (struct direct *)((int)odp + odp->d_reclen); 269 if ((int)dp - (int)buf >= fs->fs_bsize) { 270 printf("directory too large\n"); 271 exit(1); 272 } 273 dp->d_ino = inum; 274 dp->d_namlen = strlen(str); 275 dp->d_reclen = DIRBLKSIZ; 276 } 277 strcpy(dp->d_name, str); 278 ip->i_size = (int)dp - (int)buf + newsize; 279 } 280 281 newblk(buf, aibc, ib, size) 282 int *aibc; 283 char *buf; 284 daddr_t *ib; 285 int size; 286 { 287 int i; 288 daddr_t bno; 289 290 bno = alloc(size); 291 wtfs(fsbtodb(fs, bno), (int)fs->fs_bsize, buf); 292 for (i = 0; i < fs->fs_bsize; i++) 293 buf[i] = 0; 294 ib[(*aibc)++] = bno; 295 if (*aibc >= NINDIR(fs)) { 296 printf("indirect block full\n"); 297 errs++; 298 *aibc = 0; 299 } 300 } 301 302 iput(ip, aibc, ib) 303 struct inode *ip; 304 int *aibc; 305 daddr_t *ib; 306 { 307 daddr_t d; 308 int i; 309 struct dinode buf[MAXBSIZE / sizeof (struct dinode)]; 310 311 ip->i_atime = ip->i_mtime = ip->i_ctime = time((long *)0); 312 switch (ip->i_mode&IFMT) { 313 314 case IFDIR: 315 case IFREG: 316 for (i = 0; i < *aibc; i++) { 317 if (i >= NDADDR) 318 break; 319 ip->i_db[i] = ib[i]; 320 } 321 if (*aibc > NDADDR) { 322 ip->i_ib[0] = alloc((int)fs->fs_bsize); 323 for (i = 0; i < NINDIR(fs) - NDADDR; i++) { 324 ib[i] = ib[i+NDADDR]; 325 ib[i+NDADDR] = (daddr_t)0; 326 } 327 wtfs(fsbtodb(fs, ip->i_ib[0]), 328 (int)fs->fs_bsize, (char *)ib); 329 } 330 break; 331 332 case IFBLK: 333 case IFCHR: 334 break; 335 336 default: 337 printf("bad mode %o\n", ip->i_mode); 338 exit(1); 339 } 340 d = fsbtodb(fs, itod(fs, ip->i_number)); 341 rdfs(d, (int)fs->fs_bsize, (char *)buf); 342 buf[itoo(fs, ip->i_number)].di_ic = ip->i_ic; 343 wtfs(d, (int)fs->fs_bsize, (char *)buf); 344 } 345 346 daddr_t 347 alloc(size) 348 int size; 349 { 350 int i, frag; 351 daddr_t d; 352 static int cg = 0; 353 354 again: 355 rdfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize, 356 (char *)&acg); 357 if (acg.cg_magic != CG_MAGIC) { 358 printf("cg %d: bad magic number\n", cg); 359 return (0); 360 } 361 if (acg.cg_cs.cs_nbfree == 0) { 362 cg++; 363 if (cg >= fs->fs_ncg) { 364 printf("ran out of space\n"); 365 return (0); 366 } 367 goto again; 368 } 369 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 370 if (isblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag)) 371 goto goth; 372 printf("internal error: can't find block in cyl %d\n", cg); 373 return (0); 374 goth: 375 clrblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag); 376 acg.cg_cs.cs_nbfree--; 377 sblock.fs_cstotal.cs_nbfree--; 378 fscs[cg].cs_nbfree--; 379 acg.cg_btot[cbtocylno(&sblock, d)]--; 380 acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--; 381 if (size != sblock.fs_bsize) { 382 frag = howmany(size, sblock.fs_fsize); 383 fscs[cg].cs_nffree += sblock.fs_frag - frag; 384 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 385 acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 386 acg.cg_frsum[sblock.fs_frag - frag]++; 387 for (i = frag; i < sblock.fs_frag; i++) 388 setbit(acg.cg_free, d + i); 389 } 390 wtfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize, 391 (char *)&acg); 392 return (acg.cg_cgx * fs->fs_fpg + d); 393 } 394 395 /* 396 * Allocate an inode on the disk 397 */ 398 ialloc(ip) 399 register struct inode *ip; 400 { 401 struct dinode buf[MAXBSIZE / sizeof (struct dinode)]; 402 daddr_t d; 403 int c; 404 405 ip->i_number = ++ino; 406 c = itog(&sblock, ip->i_number); 407 rdfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize, 408 (char *)&acg); 409 if (acg.cg_magic != CG_MAGIC) { 410 printf("cg %d: bad magic number\n", c); 411 exit(1); 412 } 413 if (ip->i_mode & IFDIR) { 414 acg.cg_cs.cs_ndir++; 415 sblock.fs_cstotal.cs_ndir++; 416 fscs[c].cs_ndir++; 417 } 418 acg.cg_cs.cs_nifree--; 419 setbit(acg.cg_iused, ip->i_number); 420 wtfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize, 421 (char *)&acg); 422 sblock.fs_cstotal.cs_nifree--; 423 fscs[c].cs_nifree--; 424 if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 425 printf("fsinit: inode value out of range (%d).\n", 426 ip->i_number); 427 exit(1); 428 } 429 return (ip->i_number); 430 } 431 432 /* 433 * read a block from the file system 434 */ 435 rdfs(bno, size, bf) 436 int bno, size; 437 char *bf; 438 { 439 int n; 440 441 if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) { 442 printf("seek error: %ld\n", bno); 443 perror("rdfs"); 444 exit(1); 445 } 446 n = read(fsi, bf, size); 447 if(n != size) { 448 printf("read error: %ld\n", bno); 449 perror("rdfs"); 450 exit(1); 451 } 452 } 453 454 /* 455 * write a block to the file system 456 */ 457 wtfs(bno, size, bf) 458 int bno, size; 459 char *bf; 460 { 461 int n; 462 463 lseek(fso, bno * DEV_BSIZE, 0); 464 if (lseek(fso, bno * DEV_BSIZE, 0) < 0) { 465 printf("seek error: %ld\n", bno); 466 perror("wtfs"); 467 exit(1); 468 } 469 n = write(fso, bf, size); 470 if(n != size) { 471 printf("write error: %D\n", bno); 472 perror("wtfs"); 473 exit(1); 474 } 475 } 476 /* 477 * check if a block is available 478 */ 479 isblock(fs, cp, h) 480 struct fs *fs; 481 unsigned char *cp; 482 int h; 483 { 484 unsigned char mask; 485 486 switch (fs->fs_frag) { 487 case 8: 488 return (cp[h] == 0xff); 489 case 4: 490 mask = 0x0f << ((h & 0x1) << 2); 491 return ((cp[h >> 1] & mask) == mask); 492 case 2: 493 mask = 0x03 << ((h & 0x3) << 1); 494 return ((cp[h >> 2] & mask) == mask); 495 case 1: 496 mask = 0x01 << (h & 0x7); 497 return ((cp[h >> 3] & mask) == mask); 498 default: 499 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 500 return (0); 501 } 502 /*NOTREACHED*/ 503 } 504 505 /* 506 * take a block out of the map 507 */ 508 clrblock(fs, cp, h) 509 struct fs *fs; 510 unsigned char *cp; 511 int h; 512 { 513 switch ((fs)->fs_frag) { 514 case 8: 515 cp[h] = 0; 516 return; 517 case 4: 518 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 519 return; 520 case 2: 521 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 522 return; 523 case 1: 524 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 525 return; 526 default: 527 fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 528 return; 529 } 530 } 531 532