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