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