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