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