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