1*14556Ssam #ifndef lint 2*14556Ssam static char sccsid[] = "@(#)mkproto.c 4.4 (Berkeley) 08/11/83"; 3*14556Ssam #endif 48142Smckusick 58142Smckusick /* 68142Smckusick * Make a file system prototype. 78142Smckusick * usage: mkproto filsys proto 88142Smckusick */ 98142Smckusick #include <stdio.h> 108142Smckusick #include <sys/param.h> 118142Smckusick #include <sys/inode.h> 128142Smckusick #include <sys/fs.h> 138142Smckusick #include <sys/dir.h> 148142Smckusick 158142Smckusick union { 168142Smckusick struct fs fs; 178142Smckusick char fsx[SBSIZE]; 188142Smckusick } ufs; 198142Smckusick #define sblock ufs.fs 208142Smckusick union { 218142Smckusick struct cg cg; 228142Smckusick char cgx[MAXBSIZE]; 238142Smckusick } ucg; 248142Smckusick #define acg ucg.cg 258142Smckusick struct fs *fs; 268142Smckusick struct csum *fscs; 278142Smckusick int fso, fsi; 288142Smckusick FILE *proto; 298142Smckusick char token[BUFSIZ]; 308142Smckusick int errs; 318142Smckusick int ino = 10; 328142Smckusick long getnum(); 338142Smckusick char *strcpy(); 348142Smckusick 358142Smckusick main(argc, argv) 368142Smckusick int argc; 378142Smckusick char *argv[]; 388142Smckusick { 398142Smckusick int i; 408142Smckusick 418142Smckusick if (argc != 3) { 428142Smckusick fprintf(stderr, "usage: mkproto filsys proto\n"); 438142Smckusick exit(1); 448142Smckusick } 458142Smckusick fso = open(argv[1], 1); 468142Smckusick fsi = open(argv[1], 0); 478142Smckusick if (fso < 0 || fsi < 0) { 488142Smckusick perror(argv[1]); 498142Smckusick exit(1); 508142Smckusick } 518142Smckusick fs = &sblock; 528142Smckusick rdfs(SBLOCK, SBSIZE, (char *)fs); 538142Smckusick fscs = (struct csum *)calloc(1, fs->fs_cssize); 548142Smckusick for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) 558142Smckusick rdfs(fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)), 568142Smckusick (int)(fs->fs_cssize - i < fs->fs_bsize ? 578142Smckusick fs->fs_cssize - i : fs->fs_bsize), 588142Smckusick ((char *)fscs) + i); 598142Smckusick proto = fopen(argv[2], "r"); 608142Smckusick descend((struct inode *)0); 618142Smckusick wtfs(SBLOCK, SBSIZE, (char *)fs); 628142Smckusick for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize) 638142Smckusick wtfs(fsbtodb(&sblock, fs->fs_csaddr + numfrags(&sblock, i)), 648142Smckusick (int)(fs->fs_cssize - i < fs->fs_bsize ? 658142Smckusick fs->fs_cssize - i : fs->fs_bsize), 668142Smckusick ((char *)fscs) + i); 678142Smckusick exit(errs); 688142Smckusick } 698142Smckusick 708142Smckusick descend(par) 718142Smckusick struct inode *par; 728142Smckusick { 738142Smckusick struct inode in; 748142Smckusick int ibc = 0; 758142Smckusick int i, f, c; 768142Smckusick struct dinode *dip, inos[MAXBSIZE / sizeof (struct dinode)]; 778142Smckusick daddr_t ib[MAXBSIZE / sizeof (daddr_t)]; 788142Smckusick char buf[MAXBSIZE]; 798142Smckusick 808142Smckusick getstr(); 818142Smckusick in.i_mode = gmode(token[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); 828142Smckusick in.i_mode |= gmode(token[1], "-u", 0, ISUID, 0, 0); 838142Smckusick in.i_mode |= gmode(token[2], "-g", 0, ISGID, 0, 0); 848142Smckusick for (i = 3; i < 6; i++) { 858142Smckusick c = token[i]; 868142Smckusick if (c < '0' || c > '7') { 878142Smckusick printf("%c/%s: bad octal mode digit\n", c, token); 888142Smckusick errs++; 898142Smckusick c = 0; 908142Smckusick } 918142Smckusick in.i_mode |= (c-'0')<<(15-3*i); 928142Smckusick } 938142Smckusick in.i_uid = getnum(); in.i_gid = getnum(); 948142Smckusick for (i = 0; i < fs->fs_bsize; i++) 958142Smckusick buf[i] = 0; 968142Smckusick for (i = 0; i < NINDIR(fs); i++) 978142Smckusick ib[i] = (daddr_t)0; 988142Smckusick in.i_nlink = 1; 998142Smckusick in.i_size = 0; 1008142Smckusick for (i = 0; i < NDADDR; i++) 1018142Smckusick in.i_db[i] = (daddr_t)0; 1028142Smckusick for (i = 0; i < NIADDR; i++) 1038142Smckusick in.i_ib[i] = (daddr_t)0; 1048142Smckusick if (par != (struct inode *)0) { 1058142Smckusick ialloc(&in); 1068142Smckusick } else { 1078142Smckusick par = ∈ 1088142Smckusick i = itod(fs, ROOTINO); 1098142Smckusick rdfs(fsbtodb(fs, i), fs->fs_bsize, (char *)inos); 1108142Smckusick dip = &inos[ROOTINO % INOPB(fs)]; 1118142Smckusick in.i_number = ROOTINO; 1128142Smckusick in.i_nlink = dip->di_nlink; 1138142Smckusick in.i_size = dip->di_size; 1148142Smckusick in.i_db[0] = dip->di_db[0]; 1158142Smckusick rdfs(fsbtodb(fs, in.i_db[0]), fs->fs_bsize, buf); 1168142Smckusick } 1178142Smckusick 1188142Smckusick switch (in.i_mode&IFMT) { 1198142Smckusick 1208142Smckusick case IFREG: 1218142Smckusick getstr(); 1228142Smckusick f = open(token, 0); 1238142Smckusick if (f < 0) { 1248142Smckusick printf("%s: cannot open\n", token); 1258142Smckusick errs++; 1268142Smckusick break; 1278142Smckusick } 1288142Smckusick while ((i = read(f, buf, (int)fs->fs_bsize)) > 0) { 1298142Smckusick in.i_size += i; 1308142Smckusick newblk(buf, &ibc, ib, (int)blksize(fs, &in, ibc)); 1318142Smckusick } 1328142Smckusick close(f); 1338142Smckusick break; 1348142Smckusick 1358142Smckusick case IFBLK: 1368142Smckusick case IFCHR: 1378142Smckusick /* 1388142Smckusick * special file 1398142Smckusick * content is maj/min types 1408142Smckusick */ 1418142Smckusick 1428142Smckusick i = getnum() & 0377; 1438142Smckusick f = getnum() & 0377; 1448511Smckusick in.i_rdev = (i << 8) | f; 1458142Smckusick break; 1468142Smckusick 1478142Smckusick case IFDIR: 1488142Smckusick /* 1498142Smckusick * directory 1508142Smckusick * put in extra links 1518142Smckusick * call recursively until 1528142Smckusick * name of "$" found 1538142Smckusick */ 1548142Smckusick 1558142Smckusick if (in.i_number != ROOTINO) { 1568142Smckusick par->i_nlink++; 1578142Smckusick in.i_nlink++; 1588142Smckusick entry(&in, in.i_number, ".", buf); 1598142Smckusick entry(&in, par->i_number, "..", buf); 1608142Smckusick } 1618142Smckusick for (;;) { 1628142Smckusick getstr(); 1638142Smckusick if (token[0]=='$' && token[1]=='\0') 1648142Smckusick break; 1658142Smckusick entry(&in, (ino_t)(ino+1), token, buf); 1668142Smckusick descend(&in); 1678142Smckusick } 1688142Smckusick if (in.i_number != ROOTINO) 1698142Smckusick newblk(buf, &ibc, ib, (int)blksize(fs, &in, 0)); 1708142Smckusick else 1718142Smckusick wtfs(fsbtodb(fs, in.i_db[0]), (int)fs->fs_bsize, buf); 1728142Smckusick break; 1738142Smckusick } 1748142Smckusick iput(&in, &ibc, ib); 1758142Smckusick } 1768142Smckusick 1778142Smckusick /*ARGSUSED*/ 1788142Smckusick gmode(c, s, m0, m1, m2, m3) 1798142Smckusick char c, *s; 1808142Smckusick { 1818142Smckusick int i; 1828142Smckusick 1838142Smckusick for (i = 0; s[i]; i++) 1848142Smckusick if (c == s[i]) 1858142Smckusick return((&m0)[i]); 1868142Smckusick printf("%c/%s: bad mode\n", c, token); 1878142Smckusick errs++; 1888142Smckusick return(0); 1898142Smckusick } 1908142Smckusick 1918142Smckusick long 1928142Smckusick getnum() 1938142Smckusick { 1948142Smckusick int i, c; 1958142Smckusick long n; 1968142Smckusick 1978142Smckusick getstr(); 1988142Smckusick n = 0; 1998142Smckusick i = 0; 2008142Smckusick for (i = 0; c=token[i]; i++) { 2018142Smckusick if (c<'0' || c>'9') { 2028142Smckusick printf("%s: bad number\n", token); 2038142Smckusick errs++; 2048142Smckusick return((long)0); 2058142Smckusick } 2068142Smckusick n = n*10 + (c-'0'); 2078142Smckusick } 2088142Smckusick return(n); 2098142Smckusick } 2108142Smckusick 2118142Smckusick getstr() 2128142Smckusick { 2138142Smckusick int i, c; 2148142Smckusick 2158142Smckusick loop: 2168142Smckusick switch (c = getc(proto)) { 2178142Smckusick 2188142Smckusick case ' ': 2198142Smckusick case '\t': 2208142Smckusick case '\n': 2218142Smckusick goto loop; 2228142Smckusick 2238142Smckusick case EOF: 2248142Smckusick printf("Unexpected EOF\n"); 2258142Smckusick exit(1); 2268142Smckusick 2278142Smckusick case ':': 2288142Smckusick while (getc(proto) != '\n') 2298142Smckusick ; 2308142Smckusick goto loop; 2318142Smckusick 2328142Smckusick } 2338142Smckusick i = 0; 2348142Smckusick do { 2358142Smckusick token[i++] = c; 2368142Smckusick c = getc(proto); 2378142Smckusick } while (c != ' ' && c != '\t' && c != '\n' && c != '\0'); 2388142Smckusick token[i] = 0; 2398142Smckusick } 2408142Smckusick 2418142Smckusick entry(ip, inum, str, buf) 2428142Smckusick struct inode *ip; 2438142Smckusick ino_t inum; 2448142Smckusick char *str; 2458142Smckusick char *buf; 2468142Smckusick { 2478142Smckusick register struct direct *dp, *odp; 24812214Ssam int oldsize, newsize, spacefree; 2498142Smckusick 2508142Smckusick odp = dp = (struct direct *)buf; 2518142Smckusick while ((int)dp - (int)buf < ip->i_size) { 2528142Smckusick odp = dp; 2538142Smckusick dp = (struct direct *)((int)dp + dp->d_reclen); 2548142Smckusick } 2558142Smckusick if (odp != dp) 2568142Smckusick oldsize = DIRSIZ(odp); 2578142Smckusick else 2588142Smckusick oldsize = 0; 25912214Ssam spacefree = odp->d_reclen - oldsize; 2608142Smckusick dp = (struct direct *)((int)odp + oldsize); 2618142Smckusick dp->d_ino = inum; 2628142Smckusick dp->d_namlen = strlen(str); 2638142Smckusick newsize = DIRSIZ(dp); 26412214Ssam if (spacefree >= newsize) { 2658142Smckusick odp->d_reclen = oldsize; 26612214Ssam dp->d_reclen = spacefree; 2678142Smckusick } else { 2688142Smckusick dp = (struct direct *)((int)odp + odp->d_reclen); 2698142Smckusick if ((int)dp - (int)buf >= fs->fs_bsize) { 2708142Smckusick printf("directory too large\n"); 2718142Smckusick exit(1); 2728142Smckusick } 2738142Smckusick dp->d_ino = inum; 2748142Smckusick dp->d_namlen = strlen(str); 2758142Smckusick dp->d_reclen = DIRBLKSIZ; 2768142Smckusick } 2778142Smckusick strcpy(dp->d_name, str); 2788142Smckusick ip->i_size = (int)dp - (int)buf + newsize; 2798142Smckusick } 2808142Smckusick 2818142Smckusick newblk(buf, aibc, ib, size) 2828142Smckusick int *aibc; 2838142Smckusick char *buf; 2848142Smckusick daddr_t *ib; 2858142Smckusick int size; 2868142Smckusick { 2878142Smckusick int i; 2888142Smckusick daddr_t bno; 2898142Smckusick 2908142Smckusick bno = alloc(size); 2918142Smckusick wtfs(fsbtodb(fs, bno), (int)fs->fs_bsize, buf); 2928142Smckusick for (i = 0; i < fs->fs_bsize; i++) 2938142Smckusick buf[i] = 0; 2948142Smckusick ib[(*aibc)++] = bno; 2958142Smckusick if (*aibc >= NINDIR(fs)) { 2968142Smckusick printf("indirect block full\n"); 2978142Smckusick errs++; 2988142Smckusick *aibc = 0; 2998142Smckusick } 3008142Smckusick } 3018142Smckusick 3028142Smckusick iput(ip, aibc, ib) 3038142Smckusick struct inode *ip; 3048142Smckusick int *aibc; 3058142Smckusick daddr_t *ib; 3068142Smckusick { 3078142Smckusick daddr_t d; 3088142Smckusick int i; 3098142Smckusick struct dinode buf[MAXBSIZE / sizeof (struct dinode)]; 3108142Smckusick 3118142Smckusick ip->i_atime = ip->i_mtime = ip->i_ctime = time((long *)0); 3128142Smckusick switch (ip->i_mode&IFMT) { 3138142Smckusick 3148142Smckusick case IFDIR: 3158142Smckusick case IFREG: 3168142Smckusick for (i = 0; i < *aibc; i++) { 3178142Smckusick if (i >= NDADDR) 3188142Smckusick break; 3198142Smckusick ip->i_db[i] = ib[i]; 3208142Smckusick } 3218142Smckusick if (*aibc > NDADDR) { 3228142Smckusick ip->i_ib[0] = alloc((int)fs->fs_bsize); 3238142Smckusick for (i = 0; i < NINDIR(fs) - NDADDR; i++) { 3248142Smckusick ib[i] = ib[i+NDADDR]; 3258142Smckusick ib[i+NDADDR] = (daddr_t)0; 3268142Smckusick } 3278142Smckusick wtfs(fsbtodb(fs, ip->i_ib[0]), 3288142Smckusick (int)fs->fs_bsize, (char *)ib); 3298142Smckusick } 3308142Smckusick break; 3318142Smckusick 3328142Smckusick case IFBLK: 3338142Smckusick case IFCHR: 3348142Smckusick break; 3358142Smckusick 3368142Smckusick default: 3378142Smckusick printf("bad mode %o\n", ip->i_mode); 3388142Smckusick exit(1); 3398142Smckusick } 3408142Smckusick d = fsbtodb(fs, itod(fs, ip->i_number)); 3418142Smckusick rdfs(d, (int)fs->fs_bsize, (char *)buf); 3428142Smckusick buf[itoo(fs, ip->i_number)].di_ic = ip->i_ic; 3438142Smckusick wtfs(d, (int)fs->fs_bsize, (char *)buf); 3448142Smckusick } 3458142Smckusick 3468142Smckusick daddr_t 3478142Smckusick alloc(size) 3488142Smckusick int size; 3498142Smckusick { 3508142Smckusick int i, frag; 3518142Smckusick daddr_t d; 3528142Smckusick static int cg = 0; 3538142Smckusick 3548142Smckusick again: 3558142Smckusick rdfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize, 3568142Smckusick (char *)&acg); 3578142Smckusick if (acg.cg_magic != CG_MAGIC) { 3588142Smckusick printf("cg %d: bad magic number\n", cg); 3598142Smckusick return (0); 3608142Smckusick } 3618142Smckusick if (acg.cg_cs.cs_nbfree == 0) { 3628142Smckusick cg++; 3638142Smckusick if (cg >= fs->fs_ncg) { 3648142Smckusick printf("ran out of space\n"); 3658142Smckusick return (0); 3668142Smckusick } 3678142Smckusick goto again; 3688142Smckusick } 3698142Smckusick for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 3708142Smckusick if (isblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag)) 3718142Smckusick goto goth; 3728142Smckusick printf("internal error: can't find block in cyl %d\n", cg); 3738142Smckusick return (0); 3748142Smckusick goth: 3758142Smckusick clrblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag); 3768142Smckusick acg.cg_cs.cs_nbfree--; 3778142Smckusick sblock.fs_cstotal.cs_nbfree--; 3788142Smckusick fscs[cg].cs_nbfree--; 3798142Smckusick acg.cg_btot[cbtocylno(&sblock, d)]--; 3808142Smckusick acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--; 3818142Smckusick if (size != sblock.fs_bsize) { 3828142Smckusick frag = howmany(size, sblock.fs_fsize); 3838142Smckusick fscs[cg].cs_nffree += sblock.fs_frag - frag; 3848142Smckusick sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 3858142Smckusick acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 3868142Smckusick acg.cg_frsum[sblock.fs_frag - frag]++; 3878142Smckusick for (i = frag; i < sblock.fs_frag; i++) 3888142Smckusick setbit(acg.cg_free, d + i); 3898142Smckusick } 3908142Smckusick wtfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize, 3918142Smckusick (char *)&acg); 3928142Smckusick return (acg.cg_cgx * fs->fs_fpg + d); 3938142Smckusick } 3948142Smckusick 3958142Smckusick /* 3968142Smckusick * Allocate an inode on the disk 3978142Smckusick */ 3988142Smckusick ialloc(ip) 3998142Smckusick register struct inode *ip; 4008142Smckusick { 4018142Smckusick struct dinode buf[MAXBSIZE / sizeof (struct dinode)]; 4028142Smckusick daddr_t d; 4038142Smckusick int c; 4048142Smckusick 4058142Smckusick ip->i_number = ++ino; 4068142Smckusick c = itog(&sblock, ip->i_number); 4078142Smckusick rdfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize, 4088142Smckusick (char *)&acg); 4098142Smckusick if (acg.cg_magic != CG_MAGIC) { 4108142Smckusick printf("cg %d: bad magic number\n", c); 4118142Smckusick exit(1); 4128142Smckusick } 4138142Smckusick if (ip->i_mode & IFDIR) { 4148142Smckusick acg.cg_cs.cs_ndir++; 4158142Smckusick sblock.fs_cstotal.cs_ndir++; 4168142Smckusick fscs[c].cs_ndir++; 4178142Smckusick } 4188142Smckusick acg.cg_cs.cs_nifree--; 4198142Smckusick setbit(acg.cg_iused, ip->i_number); 4208142Smckusick wtfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize, 4218142Smckusick (char *)&acg); 4228142Smckusick sblock.fs_cstotal.cs_nifree--; 4238142Smckusick fscs[c].cs_nifree--; 4248142Smckusick if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 4258142Smckusick printf("fsinit: inode value out of range (%d).\n", 4268142Smckusick ip->i_number); 4278142Smckusick exit(1); 4288142Smckusick } 4298142Smckusick return (ip->i_number); 4308142Smckusick } 4318142Smckusick 4328142Smckusick /* 4338142Smckusick * read a block from the file system 4348142Smckusick */ 4358142Smckusick rdfs(bno, size, bf) 4368142Smckusick int bno, size; 4378142Smckusick char *bf; 4388142Smckusick { 4398142Smckusick int n; 4408142Smckusick 4418142Smckusick if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) { 4428142Smckusick printf("seek error: %ld\n", bno); 4438142Smckusick perror("rdfs"); 4448142Smckusick exit(1); 4458142Smckusick } 4468142Smckusick n = read(fsi, bf, size); 4478142Smckusick if(n != size) { 4488142Smckusick printf("read error: %ld\n", bno); 4498142Smckusick perror("rdfs"); 4508142Smckusick exit(1); 4518142Smckusick } 4528142Smckusick } 4538142Smckusick 4548142Smckusick /* 4558142Smckusick * write a block to the file system 4568142Smckusick */ 4578142Smckusick wtfs(bno, size, bf) 4588142Smckusick int bno, size; 4598142Smckusick char *bf; 4608142Smckusick { 4618142Smckusick int n; 4628142Smckusick 4638142Smckusick lseek(fso, bno * DEV_BSIZE, 0); 4648142Smckusick if (lseek(fso, bno * DEV_BSIZE, 0) < 0) { 4658142Smckusick printf("seek error: %ld\n", bno); 4668142Smckusick perror("wtfs"); 4678142Smckusick exit(1); 4688142Smckusick } 4698142Smckusick n = write(fso, bf, size); 4708142Smckusick if(n != size) { 4718142Smckusick printf("write error: %D\n", bno); 4728142Smckusick perror("wtfs"); 4738142Smckusick exit(1); 4748142Smckusick } 4758142Smckusick } 4768142Smckusick /* 4778142Smckusick * check if a block is available 4788142Smckusick */ 4798142Smckusick isblock(fs, cp, h) 4808142Smckusick struct fs *fs; 4818142Smckusick unsigned char *cp; 4828142Smckusick int h; 4838142Smckusick { 4848142Smckusick unsigned char mask; 4858142Smckusick 4868142Smckusick switch (fs->fs_frag) { 4878142Smckusick case 8: 4888142Smckusick return (cp[h] == 0xff); 4898142Smckusick case 4: 4908142Smckusick mask = 0x0f << ((h & 0x1) << 2); 4918142Smckusick return ((cp[h >> 1] & mask) == mask); 4928142Smckusick case 2: 4938142Smckusick mask = 0x03 << ((h & 0x3) << 1); 4948142Smckusick return ((cp[h >> 2] & mask) == mask); 4958142Smckusick case 1: 4968142Smckusick mask = 0x01 << (h & 0x7); 4978142Smckusick return ((cp[h >> 3] & mask) == mask); 4988142Smckusick default: 4998142Smckusick fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 5008142Smckusick return (0); 5018142Smckusick } 5028142Smckusick /*NOTREACHED*/ 5038142Smckusick } 5048142Smckusick 5058142Smckusick /* 5068142Smckusick * take a block out of the map 5078142Smckusick */ 5088142Smckusick clrblock(fs, cp, h) 5098142Smckusick struct fs *fs; 5108142Smckusick unsigned char *cp; 5118142Smckusick int h; 5128142Smckusick { 5138142Smckusick switch ((fs)->fs_frag) { 5148142Smckusick case 8: 5158142Smckusick cp[h] = 0; 5168142Smckusick return; 5178142Smckusick case 4: 5188142Smckusick cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 5198142Smckusick return; 5208142Smckusick case 2: 5218142Smckusick cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 5228142Smckusick return; 5238142Smckusick case 1: 5248142Smckusick cp[h >> 3] &= ~(0x01 << (h & 0x7)); 5258142Smckusick return; 5268142Smckusick default: 5278142Smckusick fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 5288142Smckusick return; 5298142Smckusick } 5308142Smckusick } 5318142Smckusick 532