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