Bell 32V development
authorTom London <tbl@research.uucp>
Mon, 11 Dec 1978 00:31:30 +0000 (19:31 -0500)
committerTom London <tbl@research.uucp>
Mon, 11 Dec 1978 00:31:30 +0000 (19:31 -0500)
Work on file usr/src/cmd/mkfs.c

Co-Authored-By: John Reiser <jfr@research.uucp>
Synthesized-from: 32v

usr/src/cmd/mkfs.c [new file with mode: 0644]

diff --git a/usr/src/cmd/mkfs.c b/usr/src/cmd/mkfs.c
new file mode 100644 (file)
index 0000000..cf66b7b
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * Make a file system prototype.
+ * usage: mkfs filsys proto/size [ m n ]
+ */
+#define        NIPB    (BSIZE/sizeof(struct dinode))
+#define        NINDIR  (BSIZE/sizeof(daddr_t))
+#define        NDIRECT (BSIZE/sizeof(struct direct))
+#define        LADDR   10
+#define        MAXFN   500
+#define        itoo(x) (int)((x+15)&07)
+#ifndef STANDALONE
+#include <stdio.h>
+#include <a.out.h>
+#endif
+#include <sys/param.h>
+#include <sys/ino.h>
+#include <sys/inode.h>
+#include <sys/filsys.h>
+#include <sys/fblk.h>
+#include <sys/dir.h>
+time_t utime;
+#ifndef STANDALONE
+FILE   *fin;
+#else
+int    fin;
+#endif
+int    fsi;
+int    fso;
+char   *charp;
+char   buf[BSIZE];
+union {
+       struct fblk fb;
+       char pad1[BSIZE];
+} fbuf;
+#ifndef STANDALONE
+struct exec head;
+#endif
+char   string[50];
+union {
+       struct filsys fs;
+       char pad2[BSIZE];
+} filsys;
+char   *fsys;
+char   *proto;
+int    f_n     = MAXFN;
+int    f_m     = 3;
+int    error;
+ino_t  ino;
+long   getnum();
+daddr_t        alloc();
+
+main(argc, argv)
+char *argv[];
+{
+       int f, c;
+       long n;
+
+#ifndef STANDALONE
+       time(&utime);
+       if(argc < 3) {
+               printf("usage: mkfs filsys proto/size [ m n ]\n");
+               exit(1);
+       }
+       fsys = argv[1];
+       proto = argv[2];
+#else
+       {
+               static char protos[60];
+
+               printf("file sys size: ");
+               gets(protos);
+               proto = protos;
+       }
+#endif
+#ifdef STANDALONE
+       {
+               char fsbuf[100];
+
+               do {
+                       printf("file system: ");
+                       gets(fsbuf);
+                       fso = open(fsbuf, 1);
+                       fsi = open(fsbuf, 0);
+               } while (fso < 0 || fsi < 0);
+       }
+       fin = NULL;
+       argc = 0;
+#else
+       fso = creat(fsys, 0666);
+       if(fso < 0) {
+               printf("%s: cannot create\n", fsys);
+               exit(1);
+       }
+       fsi = open(fsys, 0);
+       if(fsi < 0) {
+               printf("%s: cannot open\n", fsys);
+               exit(1);
+       }
+       fin = fopen(proto, "r");
+#endif
+       if(fin == NULL) {
+               n = 0;
+               for(f=0; c=proto[f]; f++) {
+                       if(c<'0' || c>'9') {
+                               printf("%s: cannot open\n", proto);
+                               exit(1);
+                       }
+                       n = n*10 + (c-'0');
+               }
+               filsys.s_fsize = n;
+               n = n/25;
+               if(n <= 0)
+                       n = 1;
+               if(n > 65500/NIPB)
+                       n = 65500/NIPB;
+               filsys.s_isize = n + 2;
+               printf("isize = %D\n", n*NIPB);
+               charp = "d--777 0 0 $ ";
+               goto f3;
+       }
+
+#ifndef STANDALONE
+       /*
+        * get name of boot load program
+        * and read onto block 0
+        */
+
+       getstr();
+       f = open(string, 0);
+       if(f < 0) {
+               printf("%s: cannot  open init\n", string);
+               goto f2;
+       }
+       read(f, (char *)&head, sizeof head);
+       if(head.a_magic != A_MAGIC1) {
+               printf("%s: bad format\n", string);
+               goto f1;
+       }
+       c = head.a_text + head.a_data;
+       if(c > BSIZE) {
+               printf("%s: too big\n", string);
+               goto f1;
+       }
+       read(f, buf, c);
+       wtfs((long)0, buf);
+
+f1:
+       close(f);
+
+       /*
+        * get total disk size
+        * and inode block size
+        */
+
+f2:
+       filsys.s_fsize = getnum();
+       n = getnum();
+       n /= NIPB;
+       filsys.s_isize = n + 3;
+
+#endif
+f3:
+       if(argc >= 5) {
+               f_m = atoi(argv[3]);
+               f_n = atoi(argv[4]);
+               if(f_n <= 0 || f_n >= MAXFN)
+                       f_n = MAXFN;
+               if(f_m <= 0 || f_m > f_n)
+                       f_m = 3;
+       }
+       filsys.s_m = f_m;
+       filsys.s_n = f_n;
+       printf("m/n = %d %d\n", f_m, f_n);
+       if(filsys.s_isize >= filsys.s_fsize) {
+               printf("%ld/%ld: bad ratio\n", filsys.s_fsize, filsys.s_isize-2);
+               exit(1);
+       }
+       filsys.s_tfree = 0;
+       filsys.s_tinode = 0;
+       for(c=0; c<BSIZE; c++)
+               buf[c] = 0;
+       for(n=2; n!=filsys.s_isize; n++) {
+               wtfs(n, buf);
+               filsys.s_tinode += NIPB;
+       }
+       ino = 0;
+
+       bflist();
+
+       cfile((struct inode *)0);
+
+       filsys.s_time = utime;
+       wtfs((long)1, (char *)&filsys);
+       exit(error);
+}
+
+cfile(par)
+struct inode *par;
+{
+       struct inode in;
+       int dbc, ibc;
+       char db[BSIZE];
+       daddr_t ib[NINDIR];
+       int i, f, c;
+
+       /*
+        * get mode, uid and gid
+        */
+
+       getstr();
+       in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
+       in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0);
+       in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0);
+       for(i=3; i<6; i++) {
+               c = string[i];
+               if(c<'0' || c>'7') {
+                       printf("%c/%s: bad octal mode digit\n", c, string);
+                       error = 1;
+                       c = 0;
+               }
+               in.i_mode |= (c-'0')<<(15-3*i);
+       }
+       in.i_uid = getnum();
+       in.i_gid = getnum();
+
+       /*
+        * general initialization prior to
+        * switching on format
+        */
+
+       ino++;
+       in.i_number = ino;
+       for(i=0; i<BSIZE; i++)
+               db[i] = 0;
+       for(i=0; i<NINDIR; i++)
+               ib[i] = (daddr_t)0;
+       in.i_nlink = 1;
+       in.i_size = 0;
+       for(i=0; i<NADDR; i++)
+               in.i_un.i_addr[i] = (daddr_t)0;
+       if(par == (struct inode *)0) {
+               par = &in;
+               in.i_nlink--;
+       }
+       dbc = 0;
+       ibc = 0;
+       switch(in.i_mode&IFMT) {
+
+       case IFREG:
+               /*
+                * regular file
+                * contents is a file name
+                */
+
+               getstr();
+               f = open(string, 0);
+               if(f < 0) {
+                       printf("%s: cannot open\n", string);
+                       error = 1;
+                       break;
+               }
+               while((i=read(f, db, BSIZE)) > 0) {
+                       in.i_size += i;
+                       newblk(&dbc, db, &ibc, ib);
+               }
+               close(f);
+               break;
+
+       case IFBLK:
+       case IFCHR:
+               /*
+                * special file
+                * content is maj/min types
+                */
+
+               i = getnum() & 0377;
+               f = getnum() & 0377;
+               in.i_un.i_addr[0] = (i<<8) | f;
+               break;
+
+       case IFDIR:
+               /*
+                * directory
+                * put in extra links
+                * call recursively until
+                * name of "$" found
+                */
+
+               par->i_nlink++;
+               in.i_nlink++;
+               entry(in.i_number, ".", &dbc, db, &ibc, ib);
+               entry(par->i_number, "..", &dbc, db, &ibc, ib);
+               in.i_size = 2*sizeof(struct direct);
+               for(;;) {
+                       getstr();
+                       if(string[0]=='$' && string[1]=='\0')
+                               break;
+                       entry(ino+1, string, &dbc, db, &ibc, ib);
+                       in.i_size += sizeof(struct direct);
+                       cfile(&in);
+               }
+               break;
+       }
+       if(dbc != 0)
+               newblk(&dbc, db, &ibc, ib);
+       iput(&in, &ibc, ib);
+}
+
+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, string);
+       error = 1;
+       return(0);
+}
+
+long
+getnum()
+{
+       int i, c;
+       long n;
+
+       getstr();
+       n = 0;
+       i = 0;
+       for(i=0; c=string[i]; i++) {
+               if(c<'0' || c>'9') {
+                       printf("%s: bad number\n", string);
+                       error = 1;
+                       return((long)0);
+               }
+               n = n*10 + (c-'0');
+       }
+       return(n);
+}
+
+getstr()
+{
+       int i, c;
+
+loop:
+       switch(c=getch()) {
+
+       case ' ':
+       case '\t':
+       case '\n':
+               goto loop;
+
+       case '\0':
+               printf("EOF\n");
+               exit(1);
+
+       case ':':
+               while(getch() != '\n');
+               goto loop;
+
+       }
+       i = 0;
+
+       do {
+               string[i++] = c;
+               c = getch();
+       } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0');
+       string[i] = '\0';
+}
+
+rdfs(bno, bf)
+daddr_t bno;
+char *bf;
+{
+       int n;
+
+       lseek(fsi, bno*BSIZE, 0);
+       n = read(fsi, bf, BSIZE);
+       if(n != BSIZE) {
+               printf("read error: %ld\n", bno);
+               exit(1);
+       }
+}
+
+wtfs(bno, bf)
+daddr_t bno;
+char *bf;
+{
+       int n;
+
+       lseek(fso, bno*BSIZE, 0);
+       n = write(fso, bf, BSIZE);
+       if(n != BSIZE) {
+               printf("write error: %D\n", bno);
+               exit(1);
+       }
+}
+
+daddr_t
+alloc()
+{
+       int i;
+       daddr_t bno;
+
+       filsys.s_tfree--;
+       bno = filsys.s_free[--filsys.s_nfree];
+       if(bno == 0) {
+               printf("out of free space\n");
+               exit(1);
+       }
+       if(filsys.s_nfree <= 0) {
+               rdfs(bno, (char *)&fbuf);
+               filsys.s_nfree = fbuf.df_nfree;
+               for(i=0; i<NICFREE; i++)
+                       filsys.s_free[i] = fbuf.df_free[i];
+       }
+       return(bno);
+}
+
+bfree(bno)
+daddr_t bno;
+{
+       int i;
+
+       filsys.s_tfree++;
+       if(filsys.s_nfree >= NICFREE) {
+               fbuf.df_nfree = filsys.s_nfree;
+               for(i=0; i<NICFREE; i++)
+                       fbuf.df_free[i] = filsys.s_free[i];
+               wtfs(bno, (char *)&fbuf);
+               filsys.s_nfree = 0;
+       }
+       filsys.s_free[filsys.s_nfree++] = bno;
+}
+
+entry(inum, str, adbc, db, aibc, ib)
+ino_t inum;
+char *str;
+int *adbc, *aibc;
+char *db;
+daddr_t *ib;
+{
+       struct direct *dp;
+       int i;
+
+       dp = (struct direct *)db;
+       dp += *adbc;
+       (*adbc)++;
+       dp->d_ino = inum;
+       for(i=0; i<DIRSIZ; i++)
+               dp->d_name[i] = 0;
+       for(i=0; i<DIRSIZ; i++)
+               if((dp->d_name[i] = str[i]) == 0)
+                       break;
+       if(*adbc >= NDIRECT)
+               newblk(adbc, db, aibc, ib);
+}
+
+newblk(adbc, db, aibc, ib)
+int *adbc, *aibc;
+char *db;
+daddr_t *ib;
+{
+       int i;
+       daddr_t bno;
+
+       bno = alloc();
+       wtfs(bno, db);
+       for(i=0; i<BSIZE; i++)
+               db[i] = 0;
+       *adbc = 0;
+       ib[*aibc] = bno;
+       (*aibc)++;
+       if(*aibc >= NINDIR) {
+               printf("indirect block full\n");
+               error = 1;
+               *aibc = 0;
+       }
+}
+
+getch()
+{
+
+#ifndef STANDALONE
+       if(charp)
+#endif
+               return(*charp++);
+#ifndef STANDALONE
+       return(getc(fin));
+#endif
+}
+
+bflist()
+{
+       struct inode in;
+       daddr_t ib[NINDIR];
+       int ibc;
+       char flg[MAXFN];
+       int adr[MAXFN];
+       int i, j;
+       daddr_t f, d;
+
+       for(i=0; i<f_n; i++)
+               flg[i] = 0;
+       i = 0;
+       for(j=0; j<f_n; j++) {
+               while(flg[i])
+                       i = (i+1)%f_n;
+               adr[j] = i+1;
+               flg[i]++;
+               i = (i+f_m)%f_n;
+       }
+
+       ino++;
+       in.i_number = ino;
+       in.i_mode = IFREG;
+       in.i_uid = 0;
+       in.i_gid = 0;
+       in.i_nlink = 0;
+       in.i_size = 0;
+       for(i=0; i<NADDR; i++)
+               in.i_un.i_addr[i] = (daddr_t)0;
+
+       for(i=0; i<NINDIR; i++)
+               ib[i] = (daddr_t)0;
+       ibc = 0;
+       bfree((daddr_t)0);
+       d = filsys.s_fsize-1;
+       while(d%f_n)
+               d++;
+       for(; d > 0; d -= f_n)
+       for(i=0; i<f_n; i++) {
+               f = d - adr[i];
+               if(f < filsys.s_fsize && f >= filsys.s_isize)
+                       if(badblk(f)) {
+                               if(ibc >= NINDIR) {
+                                       printf("too many bad blocks\n");
+                                       error = 1;
+                                       ibc = 0;
+                               }
+                               ib[ibc] = f;
+                               ibc++;
+                       } else
+                               bfree(f);
+       }
+       iput(&in, &ibc, ib);
+}
+
+iput(ip, aibc, ib)
+struct inode *ip;
+int *aibc;
+daddr_t *ib;
+{
+       struct dinode *dp;
+       daddr_t d;
+       int i;
+
+       filsys.s_tinode--;
+       d = itod(ip->i_number);
+       if(d >= filsys.s_isize) {
+               if(error == 0)
+                       printf("ilist too small\n");
+               error = 1;
+               return;
+       }
+       rdfs(d, buf);
+       dp = (struct dinode *)buf;
+       dp += itoo(ip->i_number);
+
+       dp->di_mode = ip->i_mode;
+       dp->di_nlink = ip->i_nlink;
+       dp->di_uid = ip->i_uid;
+       dp->di_gid = ip->i_gid;
+       dp->di_size = ip->i_size;
+       dp->di_atime = utime;
+       dp->di_mtime = utime;
+       dp->di_ctime = utime;
+
+       switch(ip->i_mode&IFMT) {
+
+       case IFDIR:
+       case IFREG:
+               for(i=0; i<*aibc; i++) {
+                       if(i >= LADDR)
+                               break;
+                       ip->i_un.i_addr[i] = ib[i];
+               }
+               if(*aibc >= LADDR) {
+                       ip->i_un.i_addr[LADDR] = alloc();
+                       for(i=0; i<NINDIR-LADDR; i++) {
+                               ib[i] = ib[i+LADDR];
+                               ib[i+LADDR] = (daddr_t)0;
+                       }
+                       wtfs(ip->i_un.i_addr[LADDR], (char *)ib);
+               }
+
+       case IFBLK:
+       case IFCHR:
+               ltol3(dp->di_addr, ip->i_un.i_addr, NADDR);
+               break;
+
+       default:
+               printf("bad mode %o\n", ip->i_mode);
+               exit(1);
+       }
+       wtfs(d, buf);
+}
+
+badblk(bno)
+daddr_t bno;
+{
+
+       return(0);
+}