xref: /csrg-svn/sbin/newfs/mkfs.c (revision 4788)
1*4788Smckusic static	char *sccsid = "@(#)mkfs.c	1.9 (Berkeley) 11/07/81";
24234Smckusick 
34234Smckusick /*
44234Smckusick  * make file system for cylinder-group style file systems
54234Smckusick  *
64234Smckusick  * usage: mkfs fs proto
74234Smckusick  * or: mkfs size [ nsect ntrak cpg ]
84234Smckusick  */
94234Smckusick 
104234Smckusick #define	NDIRECT	(BSIZE/sizeof(struct direct))
114234Smckusick #define	MAXFN	500
124234Smckusick 
134234Smckusick #ifndef STANDALONE
144234Smckusick #include <stdio.h>
154234Smckusick #include <a.out.h>
164234Smckusick #endif
174234Smckusick 
184234Smckusick #include "../h/param.h"
194234Smckusick #include "../h/inode.h"
204234Smckusick #include "../h/fs.h"
214234Smckusick #include "../h/dir.h"
224234Smckusick 
234234Smckusick time_t	utime;
244234Smckusick 
254234Smckusick #ifndef STANDALONE
264234Smckusick FILE 	*fin;
274234Smckusick #else
284234Smckusick int	fin;
294234Smckusick #endif
304234Smckusick 
314234Smckusick int	fsi;
324234Smckusick int	fso;
334234Smckusick char	*charp;
344234Smckusick char	buf[BSIZE];
354234Smckusick #ifndef STANDALONE
364234Smckusick struct exec head;
374234Smckusick #endif
384234Smckusick char	string[50];
394234Smckusick 
404234Smckusick union {
414234Smckusick 	struct fs fs;
424234Smckusick 	char pad[BSIZE];
434234Smckusick } fsun;
444234Smckusick #define	sblock	fsun.fs
454234Smckusick struct	csum *fscs;
464234Smckusick 
474234Smckusick union {
484234Smckusick 	struct cg cg;
494234Smckusick 	char pad[BSIZE];
504234Smckusick } cgun;
514234Smckusick #define	acg	cgun.cg
524234Smckusick 
534234Smckusick #define	howmany(x, y)	(((x)+((y)-1))/(y))
544234Smckusick #define	roundup(x, y)	((((x)+((y)-1))/(y))*(y))
554234Smckusick 
564234Smckusick char	*fsys;
574234Smckusick char	*proto;
584234Smckusick int	error;
594234Smckusick ino_t	ino = ROOTINO - 1;
604234Smckusick long	getnum();
614234Smckusick daddr_t	alloc();
624234Smckusick 
634234Smckusick struct	dinode zino[MAXIPG];
644234Smckusick 
654234Smckusick main(argc, argv)
664234Smckusick char *argv[];
674234Smckusick {
684234Smckusick 	int f, c;
694234Smckusick 	long i,n;
704234Smckusick 
714234Smckusick 	argc--, argv++;
724234Smckusick #ifndef STANDALONE
734234Smckusick 	time(&utime);
744234Smckusick 	if(argc < 2) {
754234Smckusick 		printf("usage: mkfs sblock proto/size [ nsect ntrak cpg ]\n");
764234Smckusick 		exit(1);
774234Smckusick 	}
784234Smckusick 	fsys = argv[0];
794234Smckusick 	proto = argv[1];
804234Smckusick #else
814234Smckusick 	{
824234Smckusick 		static char protos[60];
834234Smckusick 
844234Smckusick 		printf("file sys size: ");
854234Smckusick 		gets(protos);
864234Smckusick 		proto = protos;
874234Smckusick 	}
884234Smckusick #endif
894234Smckusick #ifdef STANDALONE
904234Smckusick 	{
914234Smckusick 		char fsbuf[100];
924234Smckusick 
934234Smckusick 		do {
944234Smckusick 			printf("file system: ");
954234Smckusick 			gets(fsbuf);
964234Smckusick 			fso = open(fsbuf, 1);
974234Smckusick 			fsi = open(fsbuf, 0);
984234Smckusick 		} while (fso < 0 || fsi < 0);
994234Smckusick 	}
1004234Smckusick 	fin = NULL;
1014234Smckusick 	argc = 0;
1024234Smckusick #else
1034234Smckusick 	fso = creat(fsys, 0666);
1044234Smckusick 	if(fso < 0) {
1054234Smckusick 		printf("%s: cannot create\n", fsys);
1064234Smckusick 		exit(1);
1074234Smckusick 	}
1084234Smckusick 	fsi = open(fsys, 0);
1094234Smckusick 	if(fsi < 0) {
1104234Smckusick 		printf("%s: cannot open\n", fsys);
1114234Smckusick 		exit(1);
1124234Smckusick 	}
1134234Smckusick 	fin = fopen(proto, "r");
1144234Smckusick #endif
1154234Smckusick #ifndef STANDALONE
1164234Smckusick 	if (fin != NULL) {
1174234Smckusick 		getstr();
1184234Smckusick 		f = open(string, 0);
1194234Smckusick 		if (f < 0) {
1204234Smckusick 			printf("%s: cannot open init\n", string);
1214234Smckusick 			goto noinit;
1224234Smckusick 		}
1234234Smckusick 		read(f, (char *)&head, sizeof head);
1244234Smckusick 		c = head.a_text + head.a_data;
1254234Smckusick 		if (c > BSIZE)
1264234Smckusick 			printf("%s: too big\n", string);
1274234Smckusick 		else {
1284234Smckusick 			read(f, buf, c);
1294234Smckusick 			wtfs(BBLOCK, BSIZE, buf);
1304234Smckusick 		}
1314234Smckusick 		close(f);
1324234Smckusick noinit:
1334234Smckusick 		n = sblock.fs_size = getnum();
1344234Smckusick 		sblock.fs_ntrak = getnum();
1354234Smckusick 		sblock.fs_nsect = getnum();
1364234Smckusick 		sblock.fs_cpg = getnum();
1374234Smckusick 	} else
1384234Smckusick #endif
1394234Smckusick 	{
1404234Smckusick 		charp = "d--777 0 0 $ ";
1414234Smckusick 		n = 0;
1424234Smckusick 		for (f=0; c=proto[f]; f++) {
1434234Smckusick 			if (c<'0' || c>'9') {
1444234Smckusick 				printf("%s: cannot open\n", proto);
1454234Smckusick 				exit(1);
1464234Smckusick 			}
1474234Smckusick 			n = n*10 + (c-'0');
1484234Smckusick 		}
1494234Smckusick 		sblock.fs_size = n;
1504234Smckusick 		if (argc > 2)
1514234Smckusick 			sblock.fs_nsect = atoi(argv[2]);
1524234Smckusick 		else
1534234Smckusick 			sblock.fs_nsect = 32;
1544234Smckusick 		if (argc > 3)
1554234Smckusick 			sblock.fs_ntrak = atoi(argv[3]);
1564234Smckusick 		else
1574234Smckusick 			sblock.fs_ntrak = 19;
1584234Smckusick 	}
1594234Smckusick 	/*
1604234Smckusick 	 * Now have size for file system and nsect and ntrak.
1614234Smckusick 	 * (And, if coming from prototype, cpg).
1624234Smckusick 	 * Determine number of cylinders occupied by file system.
1634234Smckusick 	 */
1644234Smckusick 	if (sblock.fs_ntrak <= 0)
1654234Smckusick 		printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1);
1664234Smckusick 	if (sblock.fs_nsect <= 0)
1674234Smckusick 		printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1);
1684234Smckusick 	if (sblock.fs_size <= 0)
1694234Smckusick 		printf("preposterous size %d\n", sblock.fs_size), exit(1);
1704234Smckusick 	if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG * NSPB) {
1714234Smckusick 		printf("cylinder too large (%d sectors)\n",
1724234Smckusick 		    sblock.fs_ntrak * sblock.fs_nsect);
1734234Smckusick 		printf("maximum cylinder size: %d sectors\n",
1744234Smckusick 		    MAXBPG * NSPB);
1754234Smckusick 		exit(1);
1764234Smckusick 	}
1774234Smckusick 	sblock.fs_ncyl = n * NSPF / (sblock.fs_nsect * sblock.fs_ntrak);
1784234Smckusick 	if (n * NSPF > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) {
1794234Smckusick 		printf("%d sector(s) in last cylinder unused\n",
1804234Smckusick 		    n * NSPF - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak);
1814234Smckusick 		sblock.fs_ncyl++;
1824234Smckusick 	}
1834234Smckusick 	sblock.fs_magic = FS_MAGIC;
1844234Smckusick 	/*
1854234Smckusick 	 * Validate specified/determined cpg.
1864234Smckusick 	 */
1874234Smckusick #define	CGTOOBIG(fs)	((fs).fs_nsect*(fs).fs_ntrak*(fs).fs_cpg/NSPB > MAXBPG)
1884234Smckusick 	if (argc > 4 || fin) {
1894234Smckusick 		if (fin == NULL)
1904234Smckusick 			sblock.fs_cpg = atoi(argv[4]);
1914234Smckusick 		if (CGTOOBIG(sblock)) {
1924234Smckusick 			printf("cylinder group too large (%d blocks); ",
1934234Smckusick 			    sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB);
1944234Smckusick 			printf("max: %d blocks\n", MAXBPG);
1954234Smckusick 			exit(1);
1964234Smckusick 		}
1974234Smckusick 		if (sblock.fs_cpg > MAXCPG) {
1984234Smckusick 			printf("cylinder groups are limited to %d cylinders\n",
1994234Smckusick 			    MAXCPG);
2004234Smckusick 			exit(1);
2014234Smckusick 		}
2024234Smckusick 	} else {
2034234Smckusick 		sblock.fs_cpg = DESCPG;
2044234Smckusick 		while (CGTOOBIG(sblock))
2054234Smckusick 			--sblock.fs_cpg;
2064234Smckusick 	}
2074234Smckusick 	/*
2084234Smckusick 	 * Compute/validate number of cylinder groups.
2094234Smckusick 	 */
2104234Smckusick 	sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
2114234Smckusick 	if (sblock.fs_ncyl % sblock.fs_cpg)
2124234Smckusick 		sblock.fs_ncg++;
2134234Smckusick 	if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF) {
2144234Smckusick 		printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n",
2154234Smckusick 		    sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg);
2164234Smckusick 		printf("as this would would have cyl groups whose size\n");
2174234Smckusick 		printf("is not a multiple of %d; choke!\n", FSIZE);
2184234Smckusick 		exit(1);
2194234Smckusick 	}
2204234Smckusick 	fscs = (struct csum *)
2214234Smckusick 	    calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE));
2224234Smckusick 	/*
2234234Smckusick 	 * Compute number of inode blocks per cylinder group.
2244234Smckusick 	 * Start with one inode per NBPI bytes; adjust as necessary.
2254234Smckusick 	 */
2264234Smckusick 	n = ((n * BSIZE) / NBPI) / INOPB;
2274234Smckusick 	if (n <= 0)
2284234Smckusick 		n = 1;
2294234Smckusick 	if (n > 65500/INOPB)
2304234Smckusick 		n = 65500/INOPB;
2314234Smckusick 	sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB;
2324234Smckusick 	if (sblock.fs_ipg < INOPB)
2334234Smckusick 		sblock.fs_ipg = INOPB;
2344234Smckusick 	if (sblock.fs_ipg > MAXIPG)
2354234Smckusick 		sblock.fs_ipg = MAXIPG;
2364234Smckusick 	while (sblock.fs_ipg * sblock.fs_ncyl > 65500)
2374234Smckusick 		sblock.fs_ipg -= INOPB;
2384234Smckusick 	sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
2394234Smckusick 	sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / (FSIZE / 512);
2404234Smckusick 	if (cgdmin(0,&sblock) >= sblock.fs_fpg)
2414234Smckusick 		printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
2424234Smckusick 		    cgdmin(0,&sblock)/FRAG, sblock.fs_fpg/FRAG), exit(1);
243*4788Smckusic 	sblock.fs_cstotal.cs_nifree = sblock.fs_ipg * sblock.fs_ncg;
2444234Smckusick 	sblock.fs_cgsize = cgsize(&sblock);
2454234Smckusick 	sblock.fs_cssize = cssize(&sblock);
2464234Smckusick 	sblock.fs_sblkno = SBLOCK;
2474234Smckusick 	sblock.fs_fmod = 0;
2484234Smckusick 	sblock.fs_ronly = 0;
2494234Smckusick 
2504234Smckusick 	/*
2514234Smckusick 	 * Dump out information about file system.
2524234Smckusick 	 */
2534234Smckusick 	printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n",
2544234Smckusick 	    fsys, sblock.fs_size*NSPF, sblock.fs_ncyl, sblock.fs_ntrak, sblock.fs_nsect);
2554234Smckusick 	printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n",
2564234Smckusick 	    (float)sblock.fs_size*FSIZE*1e-6, sblock.fs_ncg, sblock.fs_cpg,
2574234Smckusick 	    (float)sblock.fs_fpg*FSIZE*1e-6, sblock.fs_ipg);
2584234Smckusick /*
2594234Smckusick 	printf("%7d size (%d blocks)\n", sblock.fs_size, sblock.fs_size/FRAG);
2604234Smckusick 	printf("%7d cylinder groups\n", sblock.fs_ncg);
2614234Smckusick 	printf("%7d cylinder group block size\n", sblock.fs_cgsize);
2624234Smckusick 	printf("%7d tracks\n", sblock.fs_ntrak);
2634234Smckusick 	printf("%7d sectors\n", sblock.fs_nsect);
2644234Smckusick 	printf("%7d sectors per cylinder\n", sblock.fs_spc);
2654234Smckusick 	printf("%7d cylinders\n", sblock.fs_ncyl);
2664234Smckusick 	printf("%7d cylinders per group\n", sblock.fs_cpg);
2674234Smckusick 	printf("%7d blocks per group\n", sblock.fs_fpg/FRAG);
2684234Smckusick 	printf("%7d inodes per group\n", sblock.fs_ipg);
2694234Smckusick 	if (sblock.fs_ncyl % sblock.fs_cpg) {
2704234Smckusick 		printf("%7d cylinders in last group\n",
2714234Smckusick 		    i = sblock.fs_ncyl % sblock.fs_cpg);
2724234Smckusick 		printf("%7d blocks in last group\n",
2734234Smckusick 		    i * sblock.fs_spc / NSPB);
2744234Smckusick 	}
2754234Smckusick */
2764234Smckusick 	/*
2774234Smckusick 	 * Now build the cylinders group blocks and
2784234Smckusick 	 * then print out indices of cylinder groups forwarded
2794234Smckusick 	 * past bad blocks or other obstructions.
2804234Smckusick 	 */
281*4788Smckusic 	sblock.fs_cstotal.cs_ndir = 0;
282*4788Smckusic 	sblock.fs_cstotal.cs_nbfree = 0;
283*4788Smckusic 	sblock.fs_cstotal.cs_nifree = 0;
284*4788Smckusic 	sblock.fs_cstotal.cs_nffree = 0;
2854652Smckusic 	sblock.fs_cgrotor = 0;
2864652Smckusic 	for (i = 0; i < NRPOS; i++)
2874652Smckusic 		sblock.fs_postbl[i] = -1;
2884652Smckusic 	for (i = 0; i < sblock.fs_spc; i += (NSPF * FRAG))
2894652Smckusic 		/* void */;
2904652Smckusic 	for (i -= (NSPF * FRAG); i >= 0; i -= (NSPF * FRAG)) {
2914652Smckusic 		c = i % sblock.fs_nsect * NRPOS / sblock.fs_nsect;
2924652Smckusic 		sblock.fs_rotbl[i / (NSPF * FRAG)] = sblock.fs_postbl[c];
2934652Smckusic 		sblock.fs_postbl[c] = i / (NSPF * FRAG);
2944652Smckusic 	}
2954234Smckusick 	for (c = 0; c < sblock.fs_ncg; c++)
2964234Smckusick 		initcg(c);
2974234Smckusick 	printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n",
2984234Smckusick 	    SBLOCK, sblock.fs_fpg, SBLOCK+sblock.fs_fpg,
2994234Smckusick 	    SBLOCK+(sblock.fs_ncg-1)*sblock.fs_fpg);
3004234Smckusick 	/*
3014234Smckusick 	 * Now construct the initial file system, and
3024234Smckusick 	 * then write out the super-block.
3034234Smckusick 	 */
3044234Smckusick 	cfile((struct inode *)0);
3054234Smckusick 	sblock.fs_time = utime;
3064234Smckusick 	wtfs(SBLOCK, BSIZE, (char *)&sblock);
3074234Smckusick 	for (i = 0; i < cssize(&sblock); i += BSIZE)
3084234Smckusick 		wtfs(csaddr(&sblock) + i/BSIZE, BSIZE, ((char *)fscs)+i);
3094234Smckusick 	for (c = 0; c < sblock.fs_ncg; c++)
3104234Smckusick 		wtfs(cgsblock(c, &sblock), BSIZE, (char *)&sblock);
3114234Smckusick #ifndef STANDALONE
3124234Smckusick 	exit(error);
3134234Smckusick #endif
3144234Smckusick }
3154234Smckusick 
3164234Smckusick /*
3174234Smckusick  * Initialize a cylinder group.
3184234Smckusick  */
3194234Smckusick initcg(c)
3204234Smckusick 	int c;
3214234Smckusick {
3224234Smckusick 	daddr_t cbase, d, dmin, dmax;
3234234Smckusick 	long i, j, s;
3244234Smckusick 	register struct csum *cs;
3254234Smckusick 
3264234Smckusick 	/*
3274234Smckusick 	 * Determine block bounds for cylinder group.
3284234Smckusick 	 * Allow space for super block summary information in first
3294234Smckusick 	 * cylinder group.
3304234Smckusick 	 */
3314234Smckusick 	cbase = cgbase(c,&sblock);
3324234Smckusick 	dmax = cbase + sblock.fs_fpg;
3334234Smckusick 	if (dmax > sblock.fs_size)
3344234Smckusick 		dmax = sblock.fs_size;
3354465Smckusic 	dmin = cgdmin(c,&sblock) - cbase;
3364234Smckusick 	d = cbase;
3374234Smckusick 	cs = fscs+c;
3384234Smckusick 	acg.cg_time = utime;
3394234Smckusick 	acg.cg_magic = CG_MAGIC;
3404234Smckusick 	acg.cg_cgx = c;
3414234Smckusick 	acg.cg_ncyl = sblock.fs_cpg;
3424234Smckusick 	acg.cg_niblk = sblock.fs_ipg;
3434234Smckusick 	acg.cg_ndblk = dmax - cbase;
344*4788Smckusic 	acg.cg_cs.cs_ndir = 0;
345*4788Smckusic 	acg.cg_cs.cs_nffree = 0;
346*4788Smckusic 	acg.cg_cs.cs_nbfree = 0;
347*4788Smckusic 	acg.cg_cs.cs_nifree = 0;
3484465Smckusic 	acg.cg_rotor = dmin;
3494465Smckusic 	acg.cg_frotor = dmin;
3504257Smckusic 	acg.cg_irotor = 0;
3514465Smckusic 	for (i = 0; i < FRAG; i++) {
3524465Smckusic 		acg.cg_frsum[i] = 0;
3534465Smckusic 	}
3544465Smckusic 	for (i = 0; i < sblock.fs_ipg; ) {
3554234Smckusick 		for (j = INOPB; j > 0; j--) {
3564234Smckusick 			clrbit(acg.cg_iused, i);
3574234Smckusick 			i++;
3584234Smckusick 		}
359*4788Smckusic 		acg.cg_cs.cs_nifree += INOPB;
3604234Smckusick 	}
3614234Smckusick 	while (i < MAXIPG) {
3624234Smckusick 		clrbit(acg.cg_iused, i);
3634234Smckusick 		i++;
3644234Smckusick 	}
3654234Smckusick 	lseek(fso, cgimin(c,&sblock)*FSIZE, 0);
3664234Smckusick 	if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) !=
3674234Smckusick 	    sblock.fs_ipg * sizeof (struct dinode))
3684234Smckusick 		printf("write error %D\n", tell(fso) / BSIZE);
3694234Smckusick 	for (i = 0; i < MAXCPG; i++)
3704234Smckusick 		for (j = 0; j < NRPOS; j++)
3714234Smckusick 			acg.cg_b[i][j] = 0;
3724234Smckusick 	if (c == 0) {
3734234Smckusick 		dmin += howmany(cssize(&sblock), BSIZE) * FRAG;
3744234Smckusick 	}
3754234Smckusick 	for (d = 0; d < dmin; d += FRAG)
3764234Smckusick 		clrblock(acg.cg_free, d/FRAG);
3774234Smckusick 	while ((d+FRAG) <= dmax - cbase) {
3784251Smckusic 		setblock(acg.cg_free, d/FRAG);
379*4788Smckusic 		acg.cg_cs.cs_nbfree++;
3804251Smckusic 		s = d * NSPF;
3814251Smckusic 		acg.cg_b[s/sblock.fs_spc]
3824251Smckusic 		    [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++;
3834234Smckusick 		d += FRAG;
3844234Smckusick 	}
3854234Smckusick 	if (d < dmax - cbase)
3864251Smckusic 		for (; d < dmax - cbase; d++) {
3874251Smckusic 			setbit(acg.cg_free, d);
388*4788Smckusic 			acg.cg_cs.cs_nffree++;
3894251Smckusic 		}
3904234Smckusick 	for (; d < MAXBPG; d++)
3914234Smckusick 		clrbit(acg.cg_free, d);
392*4788Smckusic 	sblock.fs_dsize += acg.cg_ndblk - dmin;
393*4788Smckusic 	sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
394*4788Smckusic 	sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
395*4788Smckusic 	sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
396*4788Smckusic 	sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
397*4788Smckusic 	*cs = acg.cg_cs;
3984234Smckusick 	wtfs(cgtod(c, &sblock), BSIZE, (char *)&acg);
3994234Smckusick }
4004234Smckusick 
4014234Smckusick cfile(par)
4024234Smckusick struct inode *par;
4034234Smckusick {
4044234Smckusick 	struct inode in;
4054234Smckusick 	int dbc, ibc;
4064234Smckusick 	char db[BSIZE];
4074234Smckusick 	daddr_t ib[NINDIR];
4084234Smckusick 	int i, f, c;
4094234Smckusick 
4104234Smckusick 	/*
4114234Smckusick 	 * get mode, uid and gid
4124234Smckusick 	 */
4134234Smckusick 
4144234Smckusick 	getstr();
4154234Smckusick 	in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
4164234Smckusick 	in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0);
4174234Smckusick 	in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0);
4184234Smckusick 	for(i=3; i<6; i++) {
4194234Smckusick 		c = string[i];
4204234Smckusick 		if(c<'0' || c>'7') {
4214234Smckusick 			printf("%c/%s: bad octal mode digit\n", c, string);
4224234Smckusick 			error = 1;
4234234Smckusick 			c = 0;
4244234Smckusick 		}
4254234Smckusick 		in.i_mode |= (c-'0')<<(15-3*i);
4264234Smckusick 	}
4274234Smckusick 	in.i_uid = getnum();
4284234Smckusick 	in.i_gid = getnum();
4294251Smckusic 	in.i_atime = utime;
4304251Smckusic 	in.i_mtime = utime;
4314251Smckusic 	in.i_ctime = utime;
4324234Smckusick 
4334234Smckusick 	/*
4344234Smckusick 	 * general initialization prior to
4354234Smckusick 	 * switching on format
4364234Smckusick 	 */
4374234Smckusick 
4384234Smckusick 	ino++;
4394234Smckusick 	in.i_number = ino;
4404234Smckusick 	for(i=0; i<BSIZE; i++)
4414234Smckusick 		db[i] = 0;
4424234Smckusick 	for(i=0; i<NINDIR; i++)
4434234Smckusick 		ib[i] = (daddr_t)0;
4444234Smckusick 	in.i_nlink = 1;
4454234Smckusick 	in.i_size = 0;
4464234Smckusick 	for(i=0; i<NDADDR; i++)
4474251Smckusic 		in.i_db[i] = (daddr_t)0;
4484234Smckusick 	for(i=0; i<NIADDR; i++)
4494251Smckusic 		in.i_ib[i] = (daddr_t)0;
4504234Smckusick 	if(par == (struct inode *)0) {
4514234Smckusick 		par = &in;
4524234Smckusick 		in.i_nlink--;
4534234Smckusick 	}
4544234Smckusick 	dbc = 0;
4554234Smckusick 	ibc = 0;
4564234Smckusick 	switch(in.i_mode&IFMT) {
4574234Smckusick 
4584234Smckusick 	case IFREG:
4594234Smckusick 		/*
4604234Smckusick 		 * regular file
4614234Smckusick 		 * contents is a file name
4624234Smckusick 		 */
4634234Smckusick 
4644234Smckusick 		getstr();
4654234Smckusick 		f = open(string, 0);
4664234Smckusick 		if(f < 0) {
4674234Smckusick 			printf("%s: cannot open\n", string);
4684234Smckusick 			error = 1;
4694234Smckusick 			break;
4704234Smckusick 		}
4714234Smckusick 		while((i=read(f, db, BSIZE)) > 0) {
4724234Smckusick 			in.i_size += i;
4734427Smckusic 			newblk(&dbc, db, &ibc, ib, ibc < NDADDR ? i : BSIZE, 0);
4744234Smckusick 		}
4754234Smckusick 		close(f);
4764234Smckusick 		break;
4774234Smckusick 
4784234Smckusick 	case IFBLK:
4794234Smckusick 	case IFCHR:
4804234Smckusick 		/*
4814234Smckusick 		 * special file
4824234Smckusick 		 * content is maj/min types
4834234Smckusick 		 */
4844234Smckusick 
4854234Smckusick 		i = getnum() & 0377;
4864234Smckusick 		f = getnum() & 0377;
4874251Smckusic 		in.i_rdev = makedev(i, f);
4884234Smckusick 		break;
4894234Smckusick 
4904234Smckusick 	case IFDIR:
4914234Smckusick 		/*
4924234Smckusick 		 * directory
4934234Smckusick 		 * put in extra links
4944234Smckusick 		 * call recursively until
4954234Smckusick 		 * name of "$" found
4964234Smckusick 		 */
4974234Smckusick 
4984234Smckusick 		par->i_nlink++;
4994234Smckusick 		in.i_nlink++;
5004234Smckusick 		entry(in.i_number, ".", &dbc, db, &ibc, ib);
5014234Smckusick 		entry(par->i_number, "..", &dbc, db, &ibc, ib);
5024234Smckusick 		in.i_size = 2*sizeof(struct direct);
5034234Smckusick 		for(;;) {
5044234Smckusick 			getstr();
5054234Smckusick 			if(string[0]=='$' && string[1]=='\0')
5064234Smckusick 				break;
5074427Smckusic 			if (in.i_size >= BSIZE * NDADDR) {
5084234Smckusick 				printf("can't handle direct of > %d entries\n",
5094427Smckusic 				    NDIRECT * NDADDR);
5104234Smckusick 				exit(1);
5114234Smckusick 			}
5124234Smckusick 			entry(ino+1, string, &dbc, db, &ibc, ib);
5134234Smckusick 			in.i_size += sizeof(struct direct);
5144234Smckusick 			cfile(&in);
5154234Smckusick 		}
5164427Smckusic 		newblk(&dbc, db, &ibc, ib, roundup(dbc, FSIZE), IFDIR);
5174234Smckusick 		break;
5184234Smckusick 	}
5194234Smckusick 	iput(&in, &ibc, ib);
5204234Smckusick }
5214234Smckusick 
5224234Smckusick gmode(c, s, m0, m1, m2, m3)
5234234Smckusick char c, *s;
5244234Smckusick {
5254234Smckusick 	int i;
5264234Smckusick 
5274234Smckusick 	for(i=0; s[i]; i++)
5284234Smckusick 		if(c == s[i])
5294234Smckusick 			return((&m0)[i]);
5304234Smckusick 	printf("%c/%s: bad mode\n", c, string);
5314234Smckusick 	error = 1;
5324234Smckusick 	return(0);
5334234Smckusick }
5344234Smckusick 
5354234Smckusick long
5364234Smckusick getnum()
5374234Smckusick {
5384234Smckusick 	int i, c;
5394234Smckusick 	long n;
5404234Smckusick 
5414234Smckusick 	getstr();
5424234Smckusick 	n = 0;
5434234Smckusick 	i = 0;
5444234Smckusick 	for(i=0; c=string[i]; i++) {
5454234Smckusick 		if(c<'0' || c>'9') {
5464234Smckusick 			printf("%s: bad number\n", string);
5474234Smckusick 			error = 1;
5484234Smckusick 			return((long)0);
5494234Smckusick 		}
5504234Smckusick 		n = n*10 + (c-'0');
5514234Smckusick 	}
5524234Smckusick 	return(n);
5534234Smckusick }
5544234Smckusick 
5554234Smckusick getstr()
5564234Smckusick {
5574234Smckusick 	int i, c;
5584234Smckusick 
5594234Smckusick loop:
5604234Smckusick 	switch(c=getch()) {
5614234Smckusick 
5624234Smckusick 	case ' ':
5634234Smckusick 	case '\t':
5644234Smckusick 	case '\n':
5654234Smckusick 		goto loop;
5664234Smckusick 
5674234Smckusick 	case '\0':
5684234Smckusick 		printf("EOF\n");
5694234Smckusick 		exit(1);
5704234Smckusick 
5714234Smckusick 	case ':':
5724234Smckusick 		while(getch() != '\n');
5734234Smckusick 		goto loop;
5744234Smckusick 
5754234Smckusick 	}
5764234Smckusick 	i = 0;
5774234Smckusick 
5784234Smckusick 	do {
5794234Smckusick 		string[i++] = c;
5804234Smckusick 		c = getch();
5814234Smckusick 	} while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0');
5824234Smckusick 	string[i] = '\0';
5834234Smckusick }
5844234Smckusick 
5854234Smckusick rdfs(bno, size, bf)
5864234Smckusick daddr_t bno;
5874234Smckusick int size;
5884234Smckusick char *bf;
5894234Smckusick {
5904234Smckusick 	int n;
5914234Smckusick 
5924234Smckusick 	lseek(fsi, bno*FSIZE, 0);
5934234Smckusick 	n = read(fsi, bf, size);
5944234Smckusick 	if(n != size) {
5954234Smckusick 		printf("read error: %ld\n", bno);
5964234Smckusick 		exit(1);
5974234Smckusick 	}
5984234Smckusick }
5994234Smckusick 
6004234Smckusick wtfs(bno, size, bf)
6014234Smckusick daddr_t bno;
6024234Smckusick int size;
6034234Smckusick char *bf;
6044234Smckusick {
6054234Smckusick 	int n;
6064234Smckusick 
6074234Smckusick 	lseek(fso, bno*FSIZE, 0);
6084234Smckusick 	n = write(fso, bf, size);
6094234Smckusick 	if(n != size) {
6104234Smckusick 		printf("write error: %D\n", bno);
6114234Smckusick 		exit(1);
6124234Smckusick 	}
6134234Smckusick }
6144234Smckusick 
6154234Smckusick daddr_t
6164427Smckusic alloc(size, mode)
6174427Smckusic 	int size;
6184427Smckusic 	int mode;
6194234Smckusick {
6204234Smckusick 	int c, i, s, frag;
6214234Smckusick 	daddr_t d;
6224234Smckusick 
6234234Smckusick 	c = 0;
6244234Smckusick 	rdfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg);
625*4788Smckusic 	if (acg.cg_cs.cs_nbfree == 0) {
6264234Smckusick 		printf("first cylinder group ran out of space\n");
6274234Smckusick 		return (0);
6284234Smckusick 	}
6294234Smckusick 	for (d = 0; d < acg.cg_ndblk; d += FRAG)
6304234Smckusick 		if (isblock(acg.cg_free, d/FRAG))
6314234Smckusick 			goto goth;
6324234Smckusick 	printf("internal error: can't find block in cyl 0\n");
6334234Smckusick 	return (0);
6344234Smckusick goth:
6354234Smckusick 	clrblock(acg.cg_free, d/FRAG);
636*4788Smckusic 	acg.cg_cs.cs_nbfree--;
637*4788Smckusic 	sblock.fs_cstotal.cs_nbfree--;
6384234Smckusick 	fscs[0].cs_nbfree--;
6394427Smckusic 	if (mode & IFDIR) {
640*4788Smckusic 		acg.cg_cs.cs_ndir++;
641*4788Smckusic 		sblock.fs_cstotal.cs_ndir++;
6424427Smckusic 		fscs[0].cs_ndir++;
6434427Smckusic 	}
6444234Smckusick 	s = d * NSPF;
6454234Smckusick 	acg.cg_b[s/sblock.fs_spc][s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]--;
6464234Smckusick 	if (size != BSIZE) {
6474234Smckusick 		frag = howmany(size, FSIZE);
648*4788Smckusic 		fscs[0].cs_nffree += FRAG - frag;
649*4788Smckusic 		sblock.fs_cstotal.cs_nffree += FRAG - frag;
650*4788Smckusic 		acg.cg_cs.cs_nffree += FRAG - frag;
6514465Smckusic 		acg.cg_frsum[FRAG - frag]++;
6524234Smckusick 		for (i = frag; i < FRAG; i++)
6534234Smckusick 			setbit(acg.cg_free, d+i);
6544234Smckusick 	}
6554234Smckusick 	wtfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg);
6564234Smckusick 	return (d);
6574234Smckusick }
6584234Smckusick 
6594234Smckusick entry(inum, str, adbc, db, aibc, ib)
6604234Smckusick ino_t inum;
6614234Smckusick char *str;
6624234Smckusick int *adbc, *aibc;
6634234Smckusick char *db;
6644234Smckusick daddr_t *ib;
6654234Smckusick {
6664234Smckusick 	struct direct *dp;
6674234Smckusick 	int i;
6684234Smckusick 
6694427Smckusic 	if (*adbc == NDIRECT)
6704427Smckusic 		newblk(adbc, db, aibc, ib, BSIZE, 0);
6714234Smckusick 	dp = (struct direct *)db;
6724234Smckusick 	dp += *adbc;
6734234Smckusick 	(*adbc)++;
6744234Smckusick 	dp->d_ino = inum;
6754234Smckusick 	for(i=0; i<DIRSIZ; i++)
6764234Smckusick 		dp->d_name[i] = 0;
6774234Smckusick 	for(i=0; i<DIRSIZ; i++)
6784234Smckusick 		if((dp->d_name[i] = str[i]) == 0)
6794234Smckusick 			break;
6804234Smckusick }
6814234Smckusick 
6824427Smckusic newblk(adbc, db, aibc, ib, size, mode)
6834427Smckusic 	int *adbc, *aibc;
6844427Smckusic 	char *db;
6854427Smckusic 	daddr_t *ib;
6864427Smckusic 	int size;
6874427Smckusic 	int mode;
6884234Smckusick {
6894234Smckusick 	int i;
6904234Smckusick 	daddr_t bno;
6914234Smckusick 
6924427Smckusic 	bno = alloc(size, mode);
6934234Smckusick 	wtfs(bno, size, db);
6944234Smckusick 	for(i=0; i<size; i++)
6954234Smckusick 		db[i] = 0;
6964234Smckusick 	*adbc = 0;
6974234Smckusick 	ib[*aibc] = bno;
6984234Smckusick 	(*aibc)++;
6994234Smckusick 	if(*aibc >= NINDIR) {
7004234Smckusick 		printf("indirect block full\n");
7014234Smckusick 		error = 1;
7024234Smckusick 		*aibc = 0;
7034234Smckusick 	}
7044234Smckusick }
7054234Smckusick 
7064234Smckusick getch()
7074234Smckusick {
7084234Smckusick 
7094234Smckusick #ifndef STANDALONE
7104234Smckusick 	if(charp)
7114234Smckusick #endif
7124234Smckusick 		return(*charp++);
7134234Smckusick #ifndef STANDALONE
7144234Smckusick 	return(getc(fin));
7154234Smckusick #endif
7164234Smckusick }
7174234Smckusick 
7184234Smckusick iput(ip, aibc, ib)
7194234Smckusick struct inode *ip;
7204234Smckusick int *aibc;
7214234Smckusick daddr_t *ib;
7224234Smckusick {
7234234Smckusick 	struct dinode *dp;
7244234Smckusick 	daddr_t d;
7254234Smckusick 	int i, c = ip->i_number / sblock.fs_ipg;
7264234Smckusick 
7274234Smckusick 	rdfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg);
728*4788Smckusic 	acg.cg_cs.cs_nifree--;
7294234Smckusick 	setbit(acg.cg_iused, ip->i_number);
7304234Smckusick 	wtfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg);
731*4788Smckusic 	sblock.fs_cstotal.cs_nifree--;
7324234Smckusick 	fscs[0].cs_nifree--;
7334234Smckusick 	if(ip->i_number >= sblock.fs_ipg) {
7344234Smckusick 		printf("mkfs: cant handle more than one cg of inodes (yet)\n");
7354234Smckusick 		exit(1);
7364234Smckusick 	}
7374234Smckusick 	if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
7384234Smckusick 		if(error == 0)
7394234Smckusick 			printf("ilist too small\n");
7404234Smckusick 		error = 1;
7414234Smckusick 		return;
7424234Smckusick 	}
7434234Smckusick 	d = itod(ip->i_number,&sblock);
7444234Smckusick 	rdfs(d, BSIZE, buf);
7454251Smckusic 	for(i=0; i<*aibc; i++) {
7464251Smckusic 		if(i >= NDADDR)
7474251Smckusic 			break;
7484251Smckusic 		ip->i_db[i] = ib[i];
7494251Smckusic 	}
7504251Smckusic 	if(*aibc >= NDADDR) {
7514427Smckusic 		ip->i_ib[0] = alloc(BSIZE, 0);
7524251Smckusic 		for(i=0; i<NINDIR-NDADDR; i++) {
7534251Smckusic 			ib[i] = ib[i+NDADDR];
7544251Smckusic 			ib[i+NDADDR] = (daddr_t)0;
7554234Smckusick 		}
7564251Smckusic 		wtfs(ip->i_ib[0], (char *)ib);
7574234Smckusick 	}
7584251Smckusic 	((struct dinode *)buf+itoo(ip->i_number))->di_ic = ip->i_ic;
7594234Smckusick 	wtfs(d, BSIZE, buf);
7604234Smckusick }
761