date and time created 81/08/26 23:47:31 by mckusick
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Thu, 27 Aug 1981 14:47:31 +0000 (06:47 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Thu, 27 Aug 1981 14:47:31 +0000 (06:47 -0800)
SCCS-vsn: sbin/newfs/mkfs.c 1.1

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

diff --git a/usr/src/sbin/newfs/mkfs.c b/usr/src/sbin/newfs/mkfs.c
new file mode 100644 (file)
index 0000000..7976662
--- /dev/null
@@ -0,0 +1,789 @@
+static char *sccsid = "@(#)mkfs.c      1.1 (Berkeley) %G%";
+
+/*
+ * make file system for cylinder-group style file systems
+ *
+ * usage: mkfs fs proto
+ * or: mkfs size [ nsect ntrak cpg ]
+ */
+
+#define        NDIRECT (BSIZE/sizeof(struct direct))
+#define        MAXFN   500
+
+#define        setbit(a,i)     ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define        clrbit(a,i)     ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define        isset(a,i)      ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+
+#ifndef STANDALONE
+#include <stdio.h>
+#include <a.out.h>
+#endif
+
+#include "../h/param.h"
+#include "../h/ino.h"
+#include "../h/inode.h"
+#include "../h/fs.h"
+#include "../h/dir.h"
+
+time_t utime;
+
+#ifndef STANDALONE
+FILE   *fin;
+#else
+int    fin;
+#endif
+
+int    fsi;
+int    fso;
+char   *charp;
+char   buf[BSIZE];
+#ifndef STANDALONE
+struct exec head;
+#endif
+char   string[50];
+
+union {
+       struct fs fs;
+       char pad[BSIZE];
+} fsun;
+#define        sblock  fsun.fs
+struct csum *fscs;
+
+union {
+       struct cg cg;
+       char pad[BSIZE];
+} cgun;
+#define        acg     cgun.cg
+
+#define        howmany(x, y)   (((x)+((y)-1))/(y))
+#define        roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
+
+char   *fsys;
+char   *proto;
+int    error;
+ino_t  ino = ROOTINO - 1;
+long   getnum();
+daddr_t        alloc();
+
+struct dinode zino[MAXIPG];
+
+main(argc, argv)
+char *argv[];
+{
+       int f, c;
+       long i,n;
+
+       argc--, argv++;
+#ifndef STANDALONE
+       time(&utime);
+       if(argc < 2) {
+               printf("usage: mkfs sblock proto/size [ nsect ntrak cpg ]\n");
+               exit(1);
+       }
+       fsys = argv[0];
+       proto = argv[1];
+#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
+#ifndef STANDALONE
+       if (fin != NULL) {
+               getstr();
+               f = open(string, 0);
+               if (f < 0) {
+                       printf("%s: cannot open init\n", string);
+                       goto noinit;
+               }
+               read(f, (char *)&head, sizeof head);
+               c = head.a_text + head.a_data;
+               if (c > BSIZE)
+                       printf("%s: too big\n", string);
+               else {
+                       read(f, buf, c);
+                       wtfs(BBLOCK, BSIZE, buf);
+               }
+               close(f);
+noinit:
+               n = sblock.fs_size = getnum();
+               sblock.fs_ntrak = getnum();
+               sblock.fs_nsect = getnum();
+               sblock.fs_cpg = getnum();
+       } else
+#endif
+       {
+               charp = "d--777 0 0 $ ";
+               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');
+               }
+               sblock.fs_size = n;
+               if (argc > 2)
+                       sblock.fs_nsect = atoi(argv[2]);
+               else
+                       sblock.fs_nsect = 32;
+               if (argc > 3)
+                       sblock.fs_ntrak = atoi(argv[3]);
+               else
+                       sblock.fs_ntrak = 19;
+       }
+       /*
+        * Now have size for file system and nsect and ntrak.
+        * (And, if coming from prototype, cpg).
+        * Determine number of cylinders occupied by file system.
+        */
+       if (sblock.fs_ntrak <= 0)
+               printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1);
+       if (sblock.fs_nsect <= 0)
+               printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1);
+       if (sblock.fs_size <= 0)
+               printf("preposterous size %d\n", sblock.fs_size), exit(1);
+       if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG * NSPB) {
+               printf("cylinder too large (%d sectors)\n", 
+                   sblock.fs_ntrak * sblock.fs_nsect);
+               printf("maximum cylinder size: %d sectors\n",
+                   MAXBPG * NSPB);
+               exit(1);
+       }
+       sblock.fs_ncyl = n * NSPF / (sblock.fs_nsect * sblock.fs_ntrak);
+       if (n * NSPF > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) {
+               printf("%d sector(s) in last cylinder unused\n",
+                   n * NSPF - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak);
+               sblock.fs_ncyl++;
+       }
+       sblock.fs_magic = FS_MAGIC;
+       /*
+        * Validate specified/determined cpg.
+        */
+#define        CGTOOBIG(fs)    ((fs).fs_nsect*(fs).fs_ntrak*(fs).fs_cpg/NSPB > MAXBPG)
+       if (argc > 4 || fin) {
+               if (fin == NULL)
+                       sblock.fs_cpg = atoi(argv[4]);
+               if (CGTOOBIG(sblock)) {
+                       printf("cylinder group too large (%d blocks); ",
+                           sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB);
+                       printf("max: %d blocks\n", MAXBPG);
+                       exit(1);
+               }
+               if (sblock.fs_cpg > MAXCPG) {
+                       printf("cylinder groups are limited to %d cylinders\n",
+                           MAXCPG);
+                       exit(1);
+               }
+       } else {
+               sblock.fs_cpg = DESCPG;
+               while (CGTOOBIG(sblock))
+                       --sblock.fs_cpg;
+       }
+       /*
+        * Compute/validate number of cylinder groups.
+        */
+       sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
+       if (sblock.fs_ncyl % sblock.fs_cpg)
+               sblock.fs_ncg++;
+       if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF) {
+               printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n",
+                   sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg);
+               printf("as this would would have cyl groups whose size\n");
+               printf("is not a multiple of %d; choke!\n", FSIZE);
+               exit(1);
+       }
+       fscs = (struct csum *)
+           calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE));
+       /*
+        * Compute number of inode blocks per cylinder group.
+        * Start with one inode per NBPI bytes; adjust as necessary.
+        */
+       n = ((n * BSIZE) / NBPI) / INOPB;
+       if (n <= 0)
+               n = 1;
+       if (n > 65500/INOPB)
+               n = 65500/INOPB;
+       sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB;
+       if (sblock.fs_ipg < INOPB)
+               sblock.fs_ipg = INOPB;
+       if (sblock.fs_ipg > MAXIPG)
+               sblock.fs_ipg = MAXIPG;
+       while (sblock.fs_ipg * sblock.fs_ncyl > 65500)
+               sblock.fs_ipg -= INOPB;
+       sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
+       sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / (FSIZE / 512);
+       if (cgdmin(0,&sblock) >= sblock.fs_fpg)
+               printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
+                   cgdmin(0,&sblock)/FRAG, sblock.fs_fpg/FRAG), exit(1);
+       sblock.fs_nifree = sblock.fs_ipg * sblock.fs_ncg;
+       sblock.fs_cgsize = cgsize(&sblock);
+       sblock.fs_cssize = cssize(&sblock);
+       sblock.fs_sblkno = SBLOCK;
+       sblock.fs_fmod = 0;
+       sblock.fs_ronly = 0;
+
+       /*
+        * Dump out information about file system.
+        */
+       printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n",
+           fsys, sblock.fs_size*NSPF, sblock.fs_ncyl, sblock.fs_ntrak, sblock.fs_nsect);
+       printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n",
+           (float)sblock.fs_size*FSIZE*1e-6, sblock.fs_ncg, sblock.fs_cpg,
+           (float)sblock.fs_fpg*FSIZE*1e-6, sblock.fs_ipg);
+/*
+       printf("%7d size (%d blocks)\n", sblock.fs_size, sblock.fs_size/FRAG);
+       printf("%7d cylinder groups\n", sblock.fs_ncg);
+       printf("%7d cylinder group block size\n", sblock.fs_cgsize);
+       printf("%7d tracks\n", sblock.fs_ntrak);
+       printf("%7d sectors\n", sblock.fs_nsect);
+       printf("%7d sectors per cylinder\n", sblock.fs_spc);
+       printf("%7d cylinders\n", sblock.fs_ncyl);
+       printf("%7d cylinders per group\n", sblock.fs_cpg);
+       printf("%7d blocks per group\n", sblock.fs_fpg/FRAG);
+       printf("%7d inodes per group\n", sblock.fs_ipg);
+       if (sblock.fs_ncyl % sblock.fs_cpg) {
+               printf("%7d cylinders in last group\n",
+                   i = sblock.fs_ncyl % sblock.fs_cpg);
+               printf("%7d blocks in last group\n",
+                   i * sblock.fs_spc / NSPB);
+       }
+*/
+       /*
+        * Now build the cylinders group blocks and
+        * then print out indices of cylinder groups forwarded
+        * past bad blocks or other obstructions.
+        */
+       sblock.fs_nffree = 0;
+       sblock.fs_nbfree = 0;
+       for (c = 0; c < sblock.fs_ncg; c++)
+               initcg(c);
+       printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n",
+           SBLOCK, sblock.fs_fpg, SBLOCK+sblock.fs_fpg,
+           SBLOCK+(sblock.fs_ncg-1)*sblock.fs_fpg);
+       /*
+        * Now construct the initial file system, and
+        * then write out the super-block.
+        */
+       cfile((struct inode *)0);
+       sblock.fs_time = utime;
+       wtfs(SBLOCK, BSIZE, (char *)&sblock);
+       for (i = 0; i < cssize(&sblock); i += BSIZE)
+               wtfs(csaddr(&sblock) + i/BSIZE, BSIZE, ((char *)fscs)+i);
+       for (c = 0; c < sblock.fs_ncg; c++)
+               wtfs(cgsblock(c, &sblock), BSIZE, (char *)&sblock);
+#ifndef STANDALONE
+       exit(error);
+#endif
+}
+
+/*
+ * Initialize a cylinder group.
+ */
+initcg(c)
+       int c;
+{
+       daddr_t cbase, d, dmin, dmax;
+       long i, j, s;
+       register struct csum *cs;
+
+       /*
+        * Determine block bounds for cylinder group.
+        * Allow space for super block summary information in first
+        * cylinder group.
+        */
+       cbase = cgbase(c,&sblock);
+       dmax = cbase + sblock.fs_fpg;
+       if (dmax > sblock.fs_size)
+               dmax = sblock.fs_size;
+       d = cbase;
+       cs = fscs+c;
+tryagain:
+       for (i = cgdmin(c,&sblock) - FRAG; i >= 0; i -= FRAG)
+               if (badblk(d)) {
+                       d += i + FRAG;
+                       if (d + sblock.fs_ipg/INOPB >= dmax) {
+                               printf("bad blocks: cyl grp %d unusable\n", c);
+                               exit(1);
+                       }
+                       goto tryagain;
+               }
+       cs->cs_ndir = 0;
+       acg.cg_time = utime;
+       acg.cg_magic = CG_MAGIC;
+       acg.cg_cgx = c;
+       acg.cg_ncyl = sblock.fs_cpg;
+       acg.cg_niblk = sblock.fs_ipg;
+       acg.cg_ndblk = dmax - cbase;
+       acg.cg_ndir = 0;
+       acg.cg_nffree = 0;
+       acg.cg_nbfree = 0;
+       acg.cg_nifree = 0;
+       acg.cg_rotor = 0;
+       i = 0;
+       d = cgimin(c,&sblock);
+       while (i < sblock.fs_ipg) {
+               for (j = INOPB; j > 0; j--) {
+                       clrbit(acg.cg_iused, i);
+                       i++;
+               }
+               acg.cg_nifree += INOPB;
+               d++;
+       }
+       while (i < MAXIPG) {
+               clrbit(acg.cg_iused, i);
+               i++;
+       }
+       lseek(fso, cgimin(c,&sblock)*FSIZE, 0);
+       if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) !=
+           sblock.fs_ipg * sizeof (struct dinode))
+               printf("write error %D\n", tell(fso) / BSIZE);
+       for (i = 0; i < MAXCPG; i++)
+               for (j = 0; j < NRPOS; j++)
+                       acg.cg_b[i][j] = 0;
+       dmin = cgdmin(c,&sblock) - cbase;
+       if (c == 0) {
+               dmin += howmany(cssize(&sblock), BSIZE) * FRAG;
+       }
+       for (d = 0; d < dmin; d += FRAG)
+               clrblock(acg.cg_free, d/FRAG);
+       while ((d+FRAG) <= dmax - cbase) {
+               if (badblk(cbase+d))
+                       clrblock(acg.cg_free, d/FRAG);
+               else {
+                       setblock(acg.cg_free, d/FRAG);
+                       acg.cg_nbfree++;
+                       s = d * NSPF;
+                       acg.cg_b[s/sblock.fs_spc]
+                           [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++;
+               }
+               d += FRAG;
+       }
+       if (d < dmax - cbase)
+               if (badblk(d))
+                       for (; d < dmax - cbase; d++)
+                               clrbit(acg.cg_free, d);
+               else
+                       for (; d < dmax - cbase; d++) {
+                               setbit(acg.cg_free, d);
+                               acg.cg_nffree++;
+                       }
+       for (; d < MAXBPG; d++)
+               clrbit(acg.cg_free, d);
+       sblock.fs_nffree += acg.cg_nffree;
+       sblock.fs_nbfree += acg.cg_nbfree;
+       cs->cs_nifree = acg.cg_nifree;
+       cs->cs_nbfree = acg.cg_nbfree;
+       wtfs(cgtod(c, &sblock), BSIZE, (char *)&acg);
+}
+
+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<NDADDR; i++)
+               in.i_un.i_f.i_db[i] = (daddr_t)0;
+       for(i=0; i<NIADDR; i++)
+               in.i_un.i_f.i_ib[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, i);
+               }
+               close(f);
+               break;
+
+       case IFBLK:
+       case IFCHR:
+               /*
+                * special file
+                * content is maj/min types
+                */
+
+               i = getnum() & 0377;
+               f = getnum() & 0377;
+               in.i_un.i_d.i_rdev = makedev(i, 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;
+                       if (in.i_size >= FSIZE) {
+                               printf("can't handle direct of > %d entries\n",
+                                   NDIRECT/FRAG);
+                               exit(1);
+                       }
+                       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, roundup(dbc,FSIZE));
+       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, size, bf)
+daddr_t bno;
+int size;
+char *bf;
+{
+       int n;
+
+       lseek(fsi, bno*FSIZE, 0);
+       n = read(fsi, bf, size);
+       if(n != size) {
+               printf("read error: %ld\n", bno);
+               exit(1);
+       }
+}
+
+wtfs(bno, size, bf)
+daddr_t bno;
+int size;
+char *bf;
+{
+       int n;
+
+       lseek(fso, bno*FSIZE, 0);
+       n = write(fso, bf, size);
+       if(n != size) {
+               printf("write error: %D\n", bno);
+               exit(1);
+       }
+}
+
+daddr_t
+alloc(size)
+int size;
+{
+       int c, i, s, frag;
+       daddr_t d;
+
+       c = 0;
+       rdfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg);
+       if (acg.cg_nbfree == 0) {
+               printf("first cylinder group ran out of space\n");
+               return (0);
+       }
+       for (d = 0; d < acg.cg_ndblk; d += FRAG)
+               if (isblock(acg.cg_free, d/FRAG))
+                       goto goth;
+       printf("internal error: can't find block in cyl 0\n");
+       return (0);
+goth:
+       clrblock(acg.cg_free, d/FRAG);
+       acg.cg_nbfree--;
+       sblock.fs_nbfree--;
+       fscs[0].cs_nbfree--;
+       s = d * NSPF;
+       acg.cg_b[s/sblock.fs_spc][s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]--;
+       if (size != BSIZE) {
+               frag = howmany(size, FSIZE);
+               acg.cg_nffree += FRAG - frag;
+               sblock.fs_nffree += FRAG - frag;
+               for (i = frag; i < FRAG; i++)
+                       setbit(acg.cg_free, d+i);
+       }
+       wtfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg);
+       return (d);
+}
+
+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, BSIZE);
+}
+
+newblk(adbc, db, aibc, ib, size)
+int *adbc, *aibc;
+char *db;
+daddr_t *ib;
+int size;
+{
+       int i;
+       daddr_t bno;
+
+       bno = alloc(size);
+       wtfs(bno, size, db);
+       for(i=0; i<size; 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
+}
+
+iput(ip, aibc, ib)
+struct inode *ip;
+int *aibc;
+daddr_t *ib;
+{
+       struct dinode *dp;
+       daddr_t d;
+       int i, c = ip->i_number / sblock.fs_ipg;
+
+       rdfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg);
+       acg.cg_nifree--;
+       setbit(acg.cg_iused, ip->i_number);
+       wtfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg);
+       sblock.fs_nifree--;
+       fscs[0].cs_nifree--;
+       if(ip->i_number >= sblock.fs_ipg) {
+               printf("mkfs: cant handle more than one cg of inodes (yet)\n");
+               exit(1);
+       }
+       if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
+               if(error == 0)
+                       printf("ilist too small\n");
+               error = 1;
+               return;
+       }
+       d = itod(ip->i_number,&sblock);
+       rdfs(d, BSIZE, 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 >= NDADDR)
+                               break;
+                       ip->i_un.i_f.i_db[i] = ib[i];
+               }
+               if(*aibc >= NDADDR) {
+                       ip->i_un.i_f.i_ib[0] = alloc(BSIZE);
+                       for(i=0; i<NINDIR-NDADDR; i++) {
+                               ib[i] = ib[i+NDADDR];
+                               ib[i+NDADDR] = (daddr_t)0;
+                       }
+                       wtfs(ip->i_un.i_f.i_ib[0], (char *)ib);
+               }
+
+       case IFBLK:
+       case IFCHR:
+               ltol3(dp->di_addr, ip->i_un.i_f.i_db, NDADDR+NIADDR);
+               break;
+
+       default:
+               printf("bad mode %o\n", ip->i_mode);
+               exit(1);
+       }
+       wtfs(d, BSIZE, buf);
+}
+
+badblk(bno)
+daddr_t bno;
+{
+
+       return(0);
+}