date and time created 82/09/10 00:09:25 by mckusick
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Fri, 10 Sep 1982 15:09:25 +0000 (07:09 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Fri, 10 Sep 1982 15:09:25 +0000 (07:09 -0800)
SCCS-vsn: usr.sbin/mkproto/mkproto.c 4.1

usr/src/usr.sbin/mkproto/mkproto.c [new file with mode: 0644]

diff --git a/usr/src/usr.sbin/mkproto/mkproto.c b/usr/src/usr.sbin/mkproto/mkproto.c
new file mode 100644 (file)
index 0000000..52e65f2
--- /dev/null
@@ -0,0 +1,531 @@
+/* Copyright (c) 1982 Regents of the University of California */
+
+static char sccsid[] = "@(#)mkproto.c  4.1     (Berkeley)      %G%";
+
+/*
+ * Make a file system prototype.
+ * usage: mkproto filsys proto
+ */
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/inode.h>
+#include <sys/fs.h>
+#include <sys/dir.h>
+
+union {
+       struct  fs fs;
+       char    fsx[SBSIZE];
+} ufs;
+#define sblock ufs.fs
+union {
+       struct  cg cg;
+       char    cgx[MAXBSIZE];
+} ucg;
+#define        acg     ucg.cg
+struct fs *fs;
+struct csum *fscs;
+int    fso, fsi;
+FILE   *proto;
+char   token[BUFSIZ];
+int    errs;
+int    ino = 10;
+long   getnum();
+char   *strcpy();
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int i;
+
+       if (argc != 3) {
+               fprintf(stderr, "usage: mkproto filsys proto\n");
+               exit(1);
+       }
+       fso = open(argv[1], 1);
+       fsi = open(argv[1], 0);
+       if (fso < 0 || fsi < 0) {
+               perror(argv[1]);
+               exit(1);
+       }
+       fs = &sblock;
+       rdfs(SBLOCK, SBSIZE, (char *)fs);
+       fscs = (struct csum *)calloc(1, fs->fs_cssize);
+       for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize)
+               rdfs(fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)),
+                       (int)(fs->fs_cssize - i < fs->fs_bsize ?
+                           fs->fs_cssize - i : fs->fs_bsize),
+                       ((char *)fscs) + i);
+       proto = fopen(argv[2], "r");
+       descend((struct inode *)0);
+       wtfs(SBLOCK, SBSIZE, (char *)fs);
+       for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize)
+               wtfs(fsbtodb(&sblock, fs->fs_csaddr + numfrags(&sblock, i)),
+                       (int)(fs->fs_cssize - i < fs->fs_bsize ?
+                           fs->fs_cssize - i : fs->fs_bsize),
+                       ((char *)fscs) + i);
+       exit(errs);
+}
+
+descend(par)
+       struct inode *par;
+{
+       struct inode in;
+       int ibc = 0;
+       int i, f, c;
+       struct dinode *dip, inos[MAXBSIZE / sizeof (struct dinode)];
+       daddr_t ib[MAXBSIZE / sizeof (daddr_t)];
+       char buf[MAXBSIZE];
+
+       getstr();
+       in.i_mode = gmode(token[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
+       in.i_mode |= gmode(token[1], "-u", 0, ISUID, 0, 0);
+       in.i_mode |= gmode(token[2], "-g", 0, ISGID, 0, 0);
+       for (i = 3; i < 6; i++) {
+               c = token[i];
+               if (c < '0' || c > '7') {
+                       printf("%c/%s: bad octal mode digit\n", c, token);
+                       errs++;
+                       c = 0;
+               }
+               in.i_mode |= (c-'0')<<(15-3*i);
+       }
+       in.i_uid = getnum(); in.i_gid = getnum();
+       for (i = 0; i < fs->fs_bsize; i++)
+               buf[i] = 0;
+       for (i = 0; i < NINDIR(fs); i++)
+               ib[i] = (daddr_t)0;
+       in.i_nlink = 1;
+       in.i_size = 0;
+       for (i = 0; i < NDADDR; i++)
+               in.i_db[i] = (daddr_t)0;
+       for (i = 0; i < NIADDR; i++)
+               in.i_ib[i] = (daddr_t)0;
+       if (par != (struct inode *)0) {
+               ialloc(&in);
+       } else {
+               par = &in;
+               i = itod(fs, ROOTINO);
+               rdfs(fsbtodb(fs, i), fs->fs_bsize, (char *)inos);
+               dip = &inos[ROOTINO % INOPB(fs)];
+               in.i_number = ROOTINO;
+               in.i_nlink = dip->di_nlink;
+               in.i_size = dip->di_size;
+               in.i_db[0] = dip->di_db[0];
+               rdfs(fsbtodb(fs, in.i_db[0]), fs->fs_bsize, buf);
+       }
+
+       switch (in.i_mode&IFMT) {
+
+       case IFREG:
+               getstr();
+               f = open(token, 0);
+               if (f < 0) {
+                       printf("%s: cannot open\n", token);
+                       errs++;
+                       break;
+               }
+               while ((i = read(f, buf, (int)fs->fs_bsize)) > 0) {
+                       in.i_size += i;
+                       newblk(buf, &ibc, ib, (int)blksize(fs, &in, ibc));
+               }
+               close(f);
+               break;
+
+       case IFBLK:
+       case IFCHR:
+               /*
+                * special file
+                * content is maj/min types
+                */
+
+               i = getnum() & 0377;
+               f = getnum() & 0377;
+               in.i_dev = (i << 8) | f;
+               break;
+
+       case IFDIR:
+               /*
+                * directory
+                * put in extra links
+                * call recursively until
+                * name of "$" found
+                */
+
+               if (in.i_number != ROOTINO) {
+                       par->i_nlink++;
+                       in.i_nlink++;
+                       entry(&in, in.i_number, ".", buf);
+                       entry(&in, par->i_number, "..", buf);
+               }
+               for (;;) {
+                       getstr();
+                       if (token[0]=='$' && token[1]=='\0')
+                               break;
+                       entry(&in, (ino_t)(ino+1), token, buf);
+                       descend(&in);
+               }
+               if (in.i_number != ROOTINO)
+                       newblk(buf, &ibc, ib, (int)blksize(fs, &in, 0));
+               else
+                       wtfs(fsbtodb(fs, in.i_db[0]), (int)fs->fs_bsize, buf);
+               break;
+       }
+       iput(&in, &ibc, ib);
+}
+
+/*ARGSUSED*/
+gmode(c, s, m0, m1, m2, m3)
+       char c, *s;
+{
+       int i;
+
+       for (i = 0; s[i]; i++)
+               if (c == s[i])
+                       return((&m0)[i]);
+       printf("%c/%s: bad mode\n", c, token);
+       errs++;
+       return(0);
+}
+
+long
+getnum()
+{
+       int i, c;
+       long n;
+
+       getstr();
+       n = 0;
+       i = 0;
+       for (i = 0; c=token[i]; i++) {
+               if (c<'0' || c>'9') {
+                       printf("%s: bad number\n", token);
+                       errs++;
+                       return((long)0);
+               }
+               n = n*10 + (c-'0');
+       }
+       return(n);
+}
+
+getstr()
+{
+       int i, c;
+
+loop:
+       switch (c = getc(proto)) {
+
+       case ' ':
+       case '\t':
+       case '\n':
+               goto loop;
+
+       case EOF:
+               printf("Unexpected EOF\n");
+               exit(1);
+
+       case ':':
+               while (getc(proto) != '\n')
+                       ;
+               goto loop;
+
+       }
+       i = 0;
+       do {
+               token[i++] = c;
+               c = getc(proto);
+       } while (c != ' ' && c != '\t' && c != '\n' && c != '\0');
+       token[i] = 0;
+}
+
+entry(ip, inum, str, buf)
+       struct inode *ip;
+       ino_t inum;
+       char *str;
+       char *buf;
+{
+       register struct direct *dp, *odp;
+       int oldsize, newsize, freespace;
+
+       odp = dp = (struct direct *)buf;
+       while ((int)dp - (int)buf < ip->i_size) {
+               odp = dp;
+               dp = (struct direct *)((int)dp + dp->d_reclen);
+       }
+       if (odp != dp)
+               oldsize = DIRSIZ(odp);
+       else
+               oldsize = 0;
+       freespace = odp->d_reclen - oldsize;
+       dp = (struct direct *)((int)odp + oldsize);
+       dp->d_ino = inum;
+       dp->d_namlen = strlen(str);
+       newsize = DIRSIZ(dp);
+       if (freespace >= newsize) {
+               odp->d_reclen = oldsize;
+               dp->d_reclen = freespace;
+       } else {
+               dp = (struct direct *)((int)odp + odp->d_reclen);
+               if ((int)dp - (int)buf >= fs->fs_bsize) {
+                       printf("directory too large\n");
+                       exit(1);
+               }
+               dp->d_ino = inum;
+               dp->d_namlen = strlen(str);
+               dp->d_reclen = DIRBLKSIZ;
+       }
+       strcpy(dp->d_name, str);
+       ip->i_size = (int)dp - (int)buf + newsize;
+}
+
+newblk(buf, aibc, ib, size)
+       int *aibc;
+       char *buf;
+       daddr_t *ib;
+       int size;
+{
+       int i;
+       daddr_t bno;
+
+       bno = alloc(size);
+       wtfs(fsbtodb(fs, bno), (int)fs->fs_bsize, buf);
+       for (i = 0; i < fs->fs_bsize; i++)
+               buf[i] = 0;
+       ib[(*aibc)++] = bno;
+       if (*aibc >= NINDIR(fs)) {
+               printf("indirect block full\n");
+               errs++;
+               *aibc = 0;
+       }
+}
+
+iput(ip, aibc, ib)
+       struct inode *ip;
+       int *aibc;
+       daddr_t *ib;
+{
+       daddr_t d;
+       int i;
+       struct dinode buf[MAXBSIZE / sizeof (struct dinode)];
+
+       ip->i_atime = ip->i_mtime = ip->i_ctime = time((long *)0);
+       switch (ip->i_mode&IFMT) {
+
+       case IFDIR:
+       case IFREG:
+               for (i = 0; i < *aibc; i++) {
+                       if (i >= NDADDR)
+                               break;
+                       ip->i_db[i] = ib[i];
+               }
+               if (*aibc > NDADDR) {
+                       ip->i_ib[0] = alloc((int)fs->fs_bsize);
+                       for (i = 0; i < NINDIR(fs) - NDADDR; i++) {
+                               ib[i] = ib[i+NDADDR];
+                               ib[i+NDADDR] = (daddr_t)0;
+                       }
+                       wtfs(fsbtodb(fs, ip->i_ib[0]),
+                           (int)fs->fs_bsize, (char *)ib);
+               }
+               break;
+
+       case IFBLK:
+       case IFCHR:
+               break;
+
+       default:
+               printf("bad mode %o\n", ip->i_mode);
+               exit(1);
+       }
+       d = fsbtodb(fs, itod(fs, ip->i_number));
+       rdfs(d, (int)fs->fs_bsize, (char *)buf);
+       buf[itoo(fs, ip->i_number)].di_ic = ip->i_ic;
+       wtfs(d, (int)fs->fs_bsize, (char *)buf);
+}
+
+daddr_t
+alloc(size)
+       int size;
+{
+       int i, frag;
+       daddr_t d;
+       static int cg = 0;
+
+again:
+       rdfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize,
+           (char *)&acg);
+       if (acg.cg_magic != CG_MAGIC) {
+               printf("cg %d: bad magic number\n", cg);
+               return (0);
+       }
+       if (acg.cg_cs.cs_nbfree == 0) {
+               cg++;
+               if (cg >= fs->fs_ncg) {
+                       printf("ran out of space\n");
+                       return (0);
+               }
+               goto again;
+       }
+       for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
+               if (isblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag))
+                       goto goth;
+       printf("internal error: can't find block in cyl %d\n", cg);
+       return (0);
+goth:
+       clrblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag);
+       acg.cg_cs.cs_nbfree--;
+       sblock.fs_cstotal.cs_nbfree--;
+       fscs[cg].cs_nbfree--;
+       acg.cg_btot[cbtocylno(&sblock, d)]--;
+       acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--;
+       if (size != sblock.fs_bsize) {
+               frag = howmany(size, sblock.fs_fsize);
+               fscs[cg].cs_nffree += sblock.fs_frag - frag;
+               sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
+               acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
+               acg.cg_frsum[sblock.fs_frag - frag]++;
+               for (i = frag; i < sblock.fs_frag; i++)
+                       setbit(acg.cg_free, d + i);
+       }
+       wtfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize,
+           (char *)&acg);
+       return (acg.cg_cgx * fs->fs_fpg + d);
+}
+
+/*
+ * Allocate an inode on the disk
+ */
+ialloc(ip)
+       register struct inode *ip;
+{
+       struct dinode buf[MAXBSIZE / sizeof (struct dinode)];
+       daddr_t d;
+       int c;
+
+       ip->i_number = ++ino;
+       c = itog(&sblock, ip->i_number);
+       rdfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize,
+           (char *)&acg);
+       if (acg.cg_magic != CG_MAGIC) {
+               printf("cg %d: bad magic number\n", c);
+               exit(1);
+       }
+       if (ip->i_mode & IFDIR) {
+               acg.cg_cs.cs_ndir++;
+               sblock.fs_cstotal.cs_ndir++;
+               fscs[c].cs_ndir++;
+       }
+       acg.cg_cs.cs_nifree--;
+       setbit(acg.cg_iused, ip->i_number);
+       wtfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize,
+           (char *)&acg);
+       sblock.fs_cstotal.cs_nifree--;
+       fscs[c].cs_nifree--;
+       if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
+               printf("fsinit: inode value out of range (%d).\n",
+                   ip->i_number);
+               exit(1);
+       }
+       return (ip->i_number);
+}
+
+/*
+ * read a block from the file system
+ */
+rdfs(bno, size, bf)
+       int bno, size;
+       char *bf;
+{
+       int n;
+
+       if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) {
+               printf("seek error: %ld\n", bno);
+               perror("rdfs");
+               exit(1);
+       }
+       n = read(fsi, bf, size);
+       if(n != size) {
+               printf("read error: %ld\n", bno);
+               perror("rdfs");
+               exit(1);
+       }
+}
+
+/*
+ * write a block to the file system
+ */
+wtfs(bno, size, bf)
+       int bno, size;
+       char *bf;
+{
+       int n;
+
+       lseek(fso, bno * DEV_BSIZE, 0);
+       if (lseek(fso, bno * DEV_BSIZE, 0) < 0) {
+               printf("seek error: %ld\n", bno);
+               perror("wtfs");
+               exit(1);
+       }
+       n = write(fso, bf, size);
+       if(n != size) {
+               printf("write error: %D\n", bno);
+               perror("wtfs");
+               exit(1);
+       }
+}
+/*
+ * check if a block is available
+ */
+isblock(fs, cp, h)
+       struct fs *fs;
+       unsigned char *cp;
+       int h;
+{
+       unsigned char mask;
+
+       switch (fs->fs_frag) {
+       case 8:
+               return (cp[h] == 0xff);
+       case 4:
+               mask = 0x0f << ((h & 0x1) << 2);
+               return ((cp[h >> 1] & mask) == mask);
+       case 2:
+               mask = 0x03 << ((h & 0x3) << 1);
+               return ((cp[h >> 2] & mask) == mask);
+       case 1:
+               mask = 0x01 << (h & 0x7);
+               return ((cp[h >> 3] & mask) == mask);
+       default:
+               fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
+               return (0);
+       }
+       /*NOTREACHED*/
+}
+
+/*
+ * take a block out of the map
+ */
+clrblock(fs, cp, h)
+       struct fs *fs;
+       unsigned char *cp;
+       int h;
+{
+       switch ((fs)->fs_frag) {
+       case 8:
+               cp[h] = 0;
+               return;
+       case 4:
+               cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
+               return;
+       case 2:
+               cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
+               return;
+       case 1:
+               cp[h >> 3] &= ~(0x01 << (h & 0x7));
+               return;
+       default:
+               fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
+               return;
+       }
+}
+