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