xref: /csrg-svn/sbin/newfs/mkfs.c (revision 5324)
1*5324Smckusic static	char *sccsid = "@(#)mkfs.c	1.10 (Berkeley) 01/05/82";
24234Smckusick 
34234Smckusick /*
44234Smckusick  * make file system for cylinder-group style file systems
54234Smckusick  *
64234Smckusick  * usage: mkfs fs proto
7*5324Smckusic  * or: mkfs size [ bsize frag nsect ntrak cpg ]
84234Smckusick  */
94234Smckusick 
10*5324Smckusic #define	NDIRECT(fs)	((fs)->fs_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;
34*5324Smckusic char	buf[MAXBSIZE];
354234Smckusick #ifndef STANDALONE
364234Smckusick struct exec head;
374234Smckusick #endif
384234Smckusick char	string[50];
394234Smckusick 
404234Smckusick union {
414234Smckusick 	struct fs fs;
42*5324Smckusic 	char pad[MAXBSIZE];
434234Smckusick } fsun;
444234Smckusick #define	sblock	fsun.fs
454234Smckusick struct	csum *fscs;
464234Smckusick 
474234Smckusick union {
484234Smckusick 	struct cg cg;
49*5324Smckusic 	char pad[MAXBSIZE];
504234Smckusick } cgun;
514234Smckusick #define	acg	cgun.cg
524234Smckusick 
534234Smckusick char	*fsys;
544234Smckusick char	*proto;
554234Smckusick int	error;
564234Smckusick ino_t	ino = ROOTINO - 1;
574234Smckusick long	getnum();
584234Smckusick daddr_t	alloc();
594234Smckusick 
604234Smckusick struct	dinode zino[MAXIPG];
614234Smckusick 
624234Smckusick main(argc, argv)
63*5324Smckusic 	int argc;
64*5324Smckusic 	char *argv[];
654234Smckusick {
664234Smckusick 	int f, c;
674234Smckusick 	long i,n;
684234Smckusick 
694234Smckusick 	argc--, argv++;
704234Smckusick #ifndef STANDALONE
714234Smckusick 	time(&utime);
724234Smckusick 	if(argc < 2) {
73*5324Smckusic 		printf("usage: mkfs sblock proto/size [ bsize frag nsect ntrak cpg ]\n");
744234Smckusick 		exit(1);
754234Smckusick 	}
764234Smckusick 	fsys = argv[0];
774234Smckusick 	proto = argv[1];
784234Smckusick #else
794234Smckusick 	{
804234Smckusick 		static char protos[60];
814234Smckusick 
824234Smckusick 		printf("file sys size: ");
834234Smckusick 		gets(protos);
844234Smckusick 		proto = protos;
854234Smckusick 	}
864234Smckusick #endif
874234Smckusick #ifdef STANDALONE
884234Smckusick 	{
894234Smckusick 		char fsbuf[100];
904234Smckusick 
914234Smckusick 		do {
924234Smckusick 			printf("file system: ");
934234Smckusick 			gets(fsbuf);
944234Smckusick 			fso = open(fsbuf, 1);
954234Smckusick 			fsi = open(fsbuf, 0);
964234Smckusick 		} while (fso < 0 || fsi < 0);
974234Smckusick 	}
984234Smckusick 	fin = NULL;
994234Smckusick 	argc = 0;
1004234Smckusick #else
1014234Smckusick 	fso = creat(fsys, 0666);
1024234Smckusick 	if(fso < 0) {
1034234Smckusick 		printf("%s: cannot create\n", fsys);
1044234Smckusick 		exit(1);
1054234Smckusick 	}
1064234Smckusick 	fsi = open(fsys, 0);
1074234Smckusick 	if(fsi < 0) {
1084234Smckusick 		printf("%s: cannot open\n", fsys);
1094234Smckusick 		exit(1);
1104234Smckusick 	}
1114234Smckusick 	fin = fopen(proto, "r");
1124234Smckusick #endif
1134234Smckusick #ifndef STANDALONE
1144234Smckusick 	if (fin != NULL) {
1154234Smckusick 		getstr();
1164234Smckusick 		f = open(string, 0);
1174234Smckusick 		if (f < 0) {
1184234Smckusick 			printf("%s: cannot open init\n", string);
1194234Smckusick 			goto noinit;
1204234Smckusick 		}
1214234Smckusick 		read(f, (char *)&head, sizeof head);
1224234Smckusick 		c = head.a_text + head.a_data;
123*5324Smckusic 		if (c > MAXBSIZE)
1244234Smckusick 			printf("%s: too big\n", string);
1254234Smckusick 		else {
1264234Smckusick 			read(f, buf, c);
127*5324Smckusic 			wtfs(BBLOCK, MAXBSIZE, buf);
1284234Smckusick 		}
1294234Smckusick 		close(f);
1304234Smckusick noinit:
131*5324Smckusic 		n = getnum();
132*5324Smckusic 		sblock.fs_bsize = MAXBSIZE;
133*5324Smckusic 		sblock.fs_frag = MAXFRAG;
134*5324Smckusic 		sblock.fs_fsize = MAXBSIZE / MAXFRAG;
135*5324Smckusic 		sblock.fs_rotdelay = ROTDELAY;
136*5324Smckusic 		sblock.fs_minfree = MINFREE;
1374234Smckusick 		sblock.fs_ntrak = getnum();
1384234Smckusick 		sblock.fs_nsect = getnum();
1394234Smckusick 		sblock.fs_cpg = getnum();
1404234Smckusick 	} else
1414234Smckusick #endif
1424234Smckusick 	{
1434234Smckusick 		charp = "d--777 0 0 $ ";
1444234Smckusick 		n = 0;
1454234Smckusick 		for (f=0; c=proto[f]; f++) {
1464234Smckusick 			if (c<'0' || c>'9') {
1474234Smckusick 				printf("%s: cannot open\n", proto);
1484234Smckusick 				exit(1);
1494234Smckusick 			}
1504234Smckusick 			n = n*10 + (c-'0');
1514234Smckusick 		}
1524234Smckusick 		if (argc > 2)
153*5324Smckusic 			sblock.fs_bsize = atoi(argv[2]);
1544234Smckusick 		else
155*5324Smckusic 			sblock.fs_bsize = MAXBSIZE;
1564234Smckusick 		if (argc > 3)
157*5324Smckusic 			sblock.fs_fsize = atoi(argv[3]);
1584234Smckusick 		else
159*5324Smckusic 			sblock.fs_fsize = MAXBSIZE / MAXFRAG;
160*5324Smckusic 		if (argc > 4)
161*5324Smckusic 			sblock.fs_nsect = atoi(argv[4]);
162*5324Smckusic 		else
163*5324Smckusic 			sblock.fs_nsect = 32;
164*5324Smckusic 		if (argc > 5)
165*5324Smckusic 			sblock.fs_ntrak = atoi(argv[5]);
166*5324Smckusic 		else
1674234Smckusick 			sblock.fs_ntrak = 19;
168*5324Smckusic 		sblock.fs_frag = sblock.fs_bsize / sblock.fs_fsize;
169*5324Smckusic 		sblock.fs_rotdelay = ROTDELAY;
170*5324Smckusic 		sblock.fs_minfree = MINFREE;
1714234Smckusick 	}
1724234Smckusick 	/*
1734234Smckusick 	 * Now have size for file system and nsect and ntrak.
1744234Smckusick 	 * (And, if coming from prototype, cpg).
1754234Smckusick 	 * Determine number of cylinders occupied by file system.
1764234Smckusick 	 */
177*5324Smckusic 	if (sblock.fs_fsize < DEV_BSIZE) {
178*5324Smckusic 		printf("fragment size %d is too small, minimum is %d\n",
179*5324Smckusic 		    sblock.fs_fsize, DEV_BSIZE);
180*5324Smckusic 		exit(1);
181*5324Smckusic 	}
182*5324Smckusic 	if (sblock.fs_bsize < MINBSIZE) {
183*5324Smckusic 		printf("block size %d is too small, minimum is %d\n",
184*5324Smckusic 		    sblock.fs_bsize, MINBSIZE);
185*5324Smckusic 		exit(1);
186*5324Smckusic 	}
187*5324Smckusic 	sblock.fs_size = n = dbtofsb(&sblock, n);
1884234Smckusick 	if (sblock.fs_ntrak <= 0)
1894234Smckusick 		printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1);
1904234Smckusick 	if (sblock.fs_nsect <= 0)
1914234Smckusick 		printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1);
1924234Smckusick 	if (sblock.fs_size <= 0)
1934234Smckusick 		printf("preposterous size %d\n", sblock.fs_size), exit(1);
194*5324Smckusic 	if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG(&sblock) * NSPB(&sblock)) {
1954234Smckusick 		printf("cylinder too large (%d sectors)\n",
1964234Smckusick 		    sblock.fs_ntrak * sblock.fs_nsect);
1974234Smckusick 		printf("maximum cylinder size: %d sectors\n",
198*5324Smckusic 		    MAXBPG(&sblock) * NSPB(&sblock));
1994234Smckusick 		exit(1);
2004234Smckusick 	}
201*5324Smckusic 	sblock.fs_ncyl = n * NSPF(&sblock) / (sblock.fs_nsect * sblock.fs_ntrak);
202*5324Smckusic 	if (n * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) {
2034234Smckusick 		printf("%d sector(s) in last cylinder unused\n",
204*5324Smckusic 		    n * NSPF(&sblock) - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak);
2054234Smckusick 		sblock.fs_ncyl++;
2064234Smckusick 	}
2074234Smckusick 	sblock.fs_magic = FS_MAGIC;
2084234Smckusick 	/*
2094234Smckusick 	 * Validate specified/determined cpg.
2104234Smckusick 	 */
211*5324Smckusic #define	CGTOOBIG(fs) \
212*5324Smckusic    ((fs).fs_nsect * (fs).fs_ntrak * (fs).fs_cpg/NSPB(&sblock) > MAXBPG(&sblock))
213*5324Smckusic 	if (argc > 6 || fin) {
2144234Smckusick 		if (fin == NULL)
215*5324Smckusic 			sblock.fs_cpg = atoi(argv[6]);
2164234Smckusick 		if (CGTOOBIG(sblock)) {
2174234Smckusick 			printf("cylinder group too large (%d blocks); ",
218*5324Smckusic 			    sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB(&sblock));
219*5324Smckusic 			printf("max: %d blocks\n", MAXBPG(&sblock));
2204234Smckusick 			exit(1);
2214234Smckusick 		}
2224234Smckusick 		if (sblock.fs_cpg > MAXCPG) {
2234234Smckusick 			printf("cylinder groups are limited to %d cylinders\n",
2244234Smckusick 			    MAXCPG);
2254234Smckusick 			exit(1);
2264234Smckusick 		}
2274234Smckusick 	} else {
2284234Smckusick 		sblock.fs_cpg = DESCPG;
2294234Smckusick 		while (CGTOOBIG(sblock))
2304234Smckusick 			--sblock.fs_cpg;
2314234Smckusick 	}
2324234Smckusick 	/*
2334234Smckusick 	 * Compute/validate number of cylinder groups.
2344234Smckusick 	 */
2354234Smckusick 	sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
2364234Smckusick 	if (sblock.fs_ncyl % sblock.fs_cpg)
2374234Smckusick 		sblock.fs_ncg++;
238*5324Smckusic 	if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF(&sblock)) {
2394234Smckusick 		printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n",
2404234Smckusick 		    sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg);
2414234Smckusick 		printf("as this would would have cyl groups whose size\n");
242*5324Smckusic 		printf("is not a multiple of %d; choke!\n", sblock.fs_fsize);
2434234Smckusick 		exit(1);
2444234Smckusick 	}
2454234Smckusick 	fscs = (struct csum *)
246*5324Smckusic 	    calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum),
247*5324Smckusic 		sblock.fs_bsize));
2484234Smckusick 	/*
2494234Smckusick 	 * Compute number of inode blocks per cylinder group.
2504234Smckusick 	 * Start with one inode per NBPI bytes; adjust as necessary.
2514234Smckusick 	 */
252*5324Smckusic 	n = ((n * sblock.fs_fsize) / NBPI) / INOPB(&sblock);
2534234Smckusick 	if (n <= 0)
2544234Smckusick 		n = 1;
255*5324Smckusic 	sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB(&sblock);
256*5324Smckusic 	if (sblock.fs_ipg < INOPB(&sblock))
257*5324Smckusic 		sblock.fs_ipg = INOPB(&sblock);
2584234Smckusick 	if (sblock.fs_ipg > MAXIPG)
2594234Smckusick 		sblock.fs_ipg = MAXIPG;
2604234Smckusick 	sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
261*5324Smckusic 	sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) /
262*5324Smckusic 			(sblock.fs_fsize / SECTSIZE);
263*5324Smckusic 	if (cgdmin(0,&sblock) >= sblock.fs_fpg) {
2644234Smckusick 		printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
265*5324Smckusic 		    cgdmin(0,&sblock) / sblock.fs_frag,
266*5324Smckusic 		    sblock.fs_fpg / sblock.fs_frag);
267*5324Smckusic 		exit(1);
268*5324Smckusic 	}
2694788Smckusic 	sblock.fs_cstotal.cs_nifree = sblock.fs_ipg * sblock.fs_ncg;
2704234Smckusick 	sblock.fs_cgsize = cgsize(&sblock);
271*5324Smckusic 	sblock.fs_csaddr = cgdmin(0, &sblock);
272*5324Smckusic 	sblock.fs_cssize = sblock.fs_ncg * sizeof(struct csum);
2734234Smckusick 	sblock.fs_sblkno = SBLOCK;
2744234Smckusick 	sblock.fs_fmod = 0;
2754234Smckusick 	sblock.fs_ronly = 0;
2764234Smckusick 
2774234Smckusick 	/*
2784234Smckusick 	 * Dump out information about file system.
2794234Smckusick 	 */
2804234Smckusick 	printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n",
281*5324Smckusic 	    fsys, sblock.fs_size*NSPF(&sblock), sblock.fs_ncyl,
282*5324Smckusic 	    sblock.fs_ntrak, sblock.fs_nsect);
2834234Smckusick 	printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n",
284*5324Smckusic 	    (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg,
285*5324Smckusic 	    sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6,
286*5324Smckusic 	    sblock.fs_ipg);
2874234Smckusick /*
288*5324Smckusic 	printf("%7d size (%d blocks)\n",
289*5324Smckusic 		sblock.fs_size, sblock.fs_size / sblock.fs_frag);
2904234Smckusick 	printf("%7d cylinder groups\n", sblock.fs_ncg);
2914234Smckusick 	printf("%7d cylinder group block size\n", sblock.fs_cgsize);
2924234Smckusick 	printf("%7d tracks\n", sblock.fs_ntrak);
2934234Smckusick 	printf("%7d sectors\n", sblock.fs_nsect);
2944234Smckusick 	printf("%7d sectors per cylinder\n", sblock.fs_spc);
2954234Smckusick 	printf("%7d cylinders\n", sblock.fs_ncyl);
2964234Smckusick 	printf("%7d cylinders per group\n", sblock.fs_cpg);
297*5324Smckusic 	printf("%7d blocks per group\n", sblock.fs_fpg/sblock.fs_frag);
2984234Smckusick 	printf("%7d inodes per group\n", sblock.fs_ipg);
2994234Smckusick 	if (sblock.fs_ncyl % sblock.fs_cpg) {
3004234Smckusick 		printf("%7d cylinders in last group\n",
3014234Smckusick 		    i = sblock.fs_ncyl % sblock.fs_cpg);
3024234Smckusick 		printf("%7d blocks in last group\n",
303*5324Smckusic 		    i * sblock.fs_spc / NSPB(&sblock));
3044234Smckusick 	}
3054234Smckusick */
3064234Smckusick 	/*
3074234Smckusick 	 * Now build the cylinders group blocks and
3084234Smckusick 	 * then print out indices of cylinder groups forwarded
3094234Smckusick 	 * past bad blocks or other obstructions.
3104234Smckusick 	 */
3114788Smckusic 	sblock.fs_cstotal.cs_ndir = 0;
3124788Smckusic 	sblock.fs_cstotal.cs_nbfree = 0;
3134788Smckusic 	sblock.fs_cstotal.cs_nifree = 0;
3144788Smckusic 	sblock.fs_cstotal.cs_nffree = 0;
3154652Smckusic 	sblock.fs_cgrotor = 0;
3164652Smckusic 	for (i = 0; i < NRPOS; i++)
3174652Smckusic 		sblock.fs_postbl[i] = -1;
318*5324Smckusic 	for (i = 0; i < sblock.fs_spc; i += (NSPF(&sblock) * sblock.fs_frag))
3194652Smckusic 		/* void */;
320*5324Smckusic 	for (i -= (NSPF(&sblock) * sblock.fs_frag);
321*5324Smckusic 	     i >= 0;
322*5324Smckusic 	     i -= (NSPF(&sblock) * sblock.fs_frag)) {
3234652Smckusic 		c = i % sblock.fs_nsect * NRPOS / sblock.fs_nsect;
324*5324Smckusic 		sblock.fs_rotbl[i / (NSPF(&sblock) * sblock.fs_frag)] =
325*5324Smckusic 			sblock.fs_postbl[c];
326*5324Smckusic 		sblock.fs_postbl[c] = i / (NSPF(&sblock) * sblock.fs_frag);
3274652Smckusic 	}
3284234Smckusick 	for (c = 0; c < sblock.fs_ncg; c++)
3294234Smckusick 		initcg(c);
330*5324Smckusic 	if (sblock.fs_ncg == 1)
331*5324Smckusic 		printf("Warning, no super-block backups with only one cylinder group\n");
332*5324Smckusic 	else
333*5324Smckusic 		printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n",
334*5324Smckusic 		    SBLOCK, fsbtodb(&sblock, sblock.fs_fpg),
335*5324Smckusic 		    SBLOCK + fsbtodb(&sblock, sblock.fs_fpg),
336*5324Smckusic 		    SBLOCK + fsbtodb(&sblock, (sblock.fs_ncg - 1) *
337*5324Smckusic 			sblock.fs_fpg));
3384234Smckusick 	/*
3394234Smckusick 	 * Now construct the initial file system, and
3404234Smckusick 	 * then write out the super-block.
3414234Smckusick 	 */
3424234Smckusick 	cfile((struct inode *)0);
3434234Smckusick 	sblock.fs_time = utime;
344*5324Smckusic 	wtfs(SBLOCK, MAXBSIZE, (char *)&sblock);
345*5324Smckusic 	for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
346*5324Smckusic 		wtfs(fsbtodb(&sblock, sblock.fs_csaddr + i / sblock.fs_fsize),
347*5324Smckusic 			sblock.fs_bsize, ((char *)fscs) + i);
3484234Smckusick 	for (c = 0; c < sblock.fs_ncg; c++)
349*5324Smckusic 		wtfs(fsbtodb(&sblock, cgsblock(c, &sblock)),
350*5324Smckusic 			MAXBSIZE, (char *)&sblock);
3514234Smckusick #ifndef STANDALONE
3524234Smckusick 	exit(error);
3534234Smckusick #endif
3544234Smckusick }
3554234Smckusick 
3564234Smckusick /*
3574234Smckusick  * Initialize a cylinder group.
3584234Smckusick  */
3594234Smckusick initcg(c)
3604234Smckusick 	int c;
3614234Smckusick {
3624234Smckusick 	daddr_t cbase, d, dmin, dmax;
3634234Smckusick 	long i, j, s;
3644234Smckusick 	register struct csum *cs;
3654234Smckusick 
3664234Smckusick 	/*
3674234Smckusick 	 * Determine block bounds for cylinder group.
3684234Smckusick 	 * Allow space for super block summary information in first
3694234Smckusick 	 * cylinder group.
3704234Smckusick 	 */
3714234Smckusick 	cbase = cgbase(c,&sblock);
3724234Smckusick 	dmax = cbase + sblock.fs_fpg;
3734234Smckusick 	if (dmax > sblock.fs_size)
3744234Smckusick 		dmax = sblock.fs_size;
3754465Smckusic 	dmin = cgdmin(c,&sblock) - cbase;
3764234Smckusick 	d = cbase;
3774234Smckusick 	cs = fscs+c;
3784234Smckusick 	acg.cg_time = utime;
3794234Smckusick 	acg.cg_magic = CG_MAGIC;
3804234Smckusick 	acg.cg_cgx = c;
3814234Smckusick 	acg.cg_ncyl = sblock.fs_cpg;
3824234Smckusick 	acg.cg_niblk = sblock.fs_ipg;
3834234Smckusick 	acg.cg_ndblk = dmax - cbase;
3844788Smckusic 	acg.cg_cs.cs_ndir = 0;
3854788Smckusic 	acg.cg_cs.cs_nffree = 0;
3864788Smckusic 	acg.cg_cs.cs_nbfree = 0;
3874788Smckusic 	acg.cg_cs.cs_nifree = 0;
3884465Smckusic 	acg.cg_rotor = dmin;
3894465Smckusic 	acg.cg_frotor = dmin;
3904257Smckusic 	acg.cg_irotor = 0;
391*5324Smckusic 	for (i = 0; i < sblock.fs_frag; i++) {
3924465Smckusic 		acg.cg_frsum[i] = 0;
3934465Smckusic 	}
3944465Smckusic 	for (i = 0; i < sblock.fs_ipg; ) {
395*5324Smckusic 		for (j = INOPB(&sblock); j > 0; j--) {
3964234Smckusick 			clrbit(acg.cg_iused, i);
3974234Smckusick 			i++;
3984234Smckusick 		}
399*5324Smckusic 		acg.cg_cs.cs_nifree += INOPB(&sblock);
4004234Smckusick 	}
4014234Smckusick 	while (i < MAXIPG) {
4024234Smckusick 		clrbit(acg.cg_iused, i);
4034234Smckusick 		i++;
4044234Smckusick 	}
405*5324Smckusic 	lseek(fso, fsbtodb(&sblock, cgimin(c,&sblock)) * DEV_BSIZE, 0);
4064234Smckusick 	if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) !=
4074234Smckusick 	    sblock.fs_ipg * sizeof (struct dinode))
408*5324Smckusic 		printf("write error %D\n", tell(fso) / sblock.fs_bsize);
4094234Smckusick 	for (i = 0; i < MAXCPG; i++)
4104234Smckusick 		for (j = 0; j < NRPOS; j++)
4114234Smckusick 			acg.cg_b[i][j] = 0;
4124234Smckusick 	if (c == 0) {
413*5324Smckusic 		dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) *
414*5324Smckusic 			sblock.fs_frag;
4154234Smckusick 	}
416*5324Smckusic 	for (d = 0; d < dmin; d += sblock.fs_frag)
417*5324Smckusic 		clrblock(&sblock, acg.cg_free, d/sblock.fs_frag);
418*5324Smckusic 	while ((d+sblock.fs_frag) <= dmax - cbase) {
419*5324Smckusic 		setblock(&sblock, acg.cg_free, d/sblock.fs_frag);
4204788Smckusic 		acg.cg_cs.cs_nbfree++;
421*5324Smckusic 		s = d * NSPF(&sblock);
422*5324Smckusic 		acg.cg_b[s / sblock.fs_spc]
423*5324Smckusic 		    [s % sblock.fs_nsect * NRPOS / sblock.fs_nsect]++;
424*5324Smckusic 		d += sblock.fs_frag;
4254234Smckusick 	}
4264234Smckusick 	if (d < dmax - cbase)
4274251Smckusic 		for (; d < dmax - cbase; d++) {
4284251Smckusic 			setbit(acg.cg_free, d);
4294788Smckusic 			acg.cg_cs.cs_nffree++;
4304251Smckusic 		}
431*5324Smckusic 	for (; d < MAXBPG(&sblock); d++)
4324234Smckusick 		clrbit(acg.cg_free, d);
4334788Smckusic 	sblock.fs_dsize += acg.cg_ndblk - dmin;
4344788Smckusic 	sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
4354788Smckusic 	sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
4364788Smckusic 	sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
4374788Smckusic 	sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
4384788Smckusic 	*cs = acg.cg_cs;
439*5324Smckusic 	wtfs(fsbtodb(&sblock, cgtod(c, &sblock)),
440*5324Smckusic 		sblock.fs_bsize, (char *)&acg);
4414234Smckusick }
4424234Smckusick 
4434234Smckusick cfile(par)
444*5324Smckusic 	struct inode *par;
4454234Smckusick {
4464234Smckusick 	struct inode in;
4474234Smckusick 	int dbc, ibc;
448*5324Smckusic 	char db[MAXBSIZE];
449*5324Smckusic 	daddr_t ib[MAXBSIZE / sizeof(daddr_t)];
4504234Smckusick 	int i, f, c;
4514234Smckusick 
4524234Smckusick 	/*
4534234Smckusick 	 * get mode, uid and gid
4544234Smckusick 	 */
4554234Smckusick 
4564234Smckusick 	getstr();
4574234Smckusick 	in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
4584234Smckusick 	in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0);
4594234Smckusick 	in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0);
4604234Smckusick 	for(i=3; i<6; i++) {
4614234Smckusick 		c = string[i];
4624234Smckusick 		if(c<'0' || c>'7') {
4634234Smckusick 			printf("%c/%s: bad octal mode digit\n", c, string);
4644234Smckusick 			error = 1;
4654234Smckusick 			c = 0;
4664234Smckusick 		}
4674234Smckusick 		in.i_mode |= (c-'0')<<(15-3*i);
4684234Smckusick 	}
4694234Smckusick 	in.i_uid = getnum();
4704234Smckusick 	in.i_gid = getnum();
4714251Smckusic 	in.i_atime = utime;
4724251Smckusic 	in.i_mtime = utime;
4734251Smckusic 	in.i_ctime = utime;
4744234Smckusick 
4754234Smckusick 	/*
4764234Smckusick 	 * general initialization prior to
4774234Smckusick 	 * switching on format
4784234Smckusick 	 */
4794234Smckusick 
4804234Smckusick 	ino++;
4814234Smckusick 	in.i_number = ino;
482*5324Smckusic 	for(i=0; i<sblock.fs_bsize; i++)
4834234Smckusick 		db[i] = 0;
484*5324Smckusic 	for(i=0; i<NINDIR(&sblock); i++)
4854234Smckusick 		ib[i] = (daddr_t)0;
4864234Smckusick 	in.i_nlink = 1;
4874234Smckusick 	in.i_size = 0;
4884234Smckusick 	for(i=0; i<NDADDR; i++)
4894251Smckusic 		in.i_db[i] = (daddr_t)0;
4904234Smckusick 	for(i=0; i<NIADDR; i++)
4914251Smckusic 		in.i_ib[i] = (daddr_t)0;
4924234Smckusick 	if(par == (struct inode *)0) {
4934234Smckusick 		par = &in;
4944234Smckusick 		in.i_nlink--;
4954234Smckusick 	}
4964234Smckusick 	dbc = 0;
4974234Smckusick 	ibc = 0;
4984234Smckusick 	switch(in.i_mode&IFMT) {
4994234Smckusick 
5004234Smckusick 	case IFREG:
5014234Smckusick 		/*
5024234Smckusick 		 * regular file
5034234Smckusick 		 * contents is a file name
5044234Smckusick 		 */
5054234Smckusick 
5064234Smckusick 		getstr();
5074234Smckusick 		f = open(string, 0);
5084234Smckusick 		if(f < 0) {
5094234Smckusick 			printf("%s: cannot open\n", string);
5104234Smckusick 			error = 1;
5114234Smckusick 			break;
5124234Smckusick 		}
513*5324Smckusic 		while((i = read(f, db, sblock.fs_bsize)) > 0) {
5144234Smckusick 			in.i_size += i;
515*5324Smckusic 			newblk(&dbc, db, &ibc, ib,
516*5324Smckusic 				ibc < NDADDR ? i : sblock.fs_bsize, 0);
5174234Smckusick 		}
5184234Smckusick 		close(f);
5194234Smckusick 		break;
5204234Smckusick 
5214234Smckusick 	case IFBLK:
5224234Smckusick 	case IFCHR:
5234234Smckusick 		/*
5244234Smckusick 		 * special file
5254234Smckusick 		 * content is maj/min types
5264234Smckusick 		 */
5274234Smckusick 
5284234Smckusick 		i = getnum() & 0377;
5294234Smckusick 		f = getnum() & 0377;
5304251Smckusic 		in.i_rdev = makedev(i, f);
5314234Smckusick 		break;
5324234Smckusick 
5334234Smckusick 	case IFDIR:
5344234Smckusick 		/*
5354234Smckusick 		 * directory
5364234Smckusick 		 * put in extra links
5374234Smckusick 		 * call recursively until
5384234Smckusick 		 * name of "$" found
5394234Smckusick 		 */
5404234Smckusick 
5414234Smckusick 		par->i_nlink++;
5424234Smckusick 		in.i_nlink++;
5434234Smckusick 		entry(in.i_number, ".", &dbc, db, &ibc, ib);
5444234Smckusick 		entry(par->i_number, "..", &dbc, db, &ibc, ib);
5454234Smckusick 		in.i_size = 2*sizeof(struct direct);
5464234Smckusick 		for(;;) {
5474234Smckusick 			getstr();
5484234Smckusick 			if(string[0]=='$' && string[1]=='\0')
5494234Smckusick 				break;
550*5324Smckusic 			if (in.i_size >= sblock.fs_bsize * NDADDR) {
5514234Smckusick 				printf("can't handle direct of > %d entries\n",
552*5324Smckusic 				    NDIRECT(&sblock) * NDADDR);
5534234Smckusick 				exit(1);
5544234Smckusick 			}
5554234Smckusick 			entry(ino+1, string, &dbc, db, &ibc, ib);
5564234Smckusick 			in.i_size += sizeof(struct direct);
5574234Smckusick 			cfile(&in);
5584234Smckusick 		}
559*5324Smckusic 		newblk(&dbc, db, &ibc, ib, roundup(dbc, sblock.fs_fsize),
560*5324Smckusic 			IFDIR);
5614234Smckusick 		break;
5624234Smckusick 	}
5634234Smckusick 	iput(&in, &ibc, ib);
5644234Smckusick }
5654234Smckusick 
5664234Smckusick gmode(c, s, m0, m1, m2, m3)
567*5324Smckusic 	char c, *s;
568*5324Smckusic 	int m0, m1, m2, m3;
5694234Smckusick {
5704234Smckusick 	int i;
5714234Smckusick 
5724234Smckusick 	for(i=0; s[i]; i++)
5734234Smckusick 		if(c == s[i])
5744234Smckusick 			return((&m0)[i]);
5754234Smckusick 	printf("%c/%s: bad mode\n", c, string);
5764234Smckusick 	error = 1;
5774234Smckusick 	return(0);
5784234Smckusick }
5794234Smckusick 
5804234Smckusick long
5814234Smckusick getnum()
5824234Smckusick {
5834234Smckusick 	int i, c;
5844234Smckusick 	long n;
5854234Smckusick 
5864234Smckusick 	getstr();
5874234Smckusick 	n = 0;
5884234Smckusick 	i = 0;
5894234Smckusick 	for(i=0; c=string[i]; i++) {
5904234Smckusick 		if(c<'0' || c>'9') {
5914234Smckusick 			printf("%s: bad number\n", string);
5924234Smckusick 			error = 1;
5934234Smckusick 			return((long)0);
5944234Smckusick 		}
5954234Smckusick 		n = n*10 + (c-'0');
5964234Smckusick 	}
5974234Smckusick 	return(n);
5984234Smckusick }
5994234Smckusick 
6004234Smckusick getstr()
6014234Smckusick {
6024234Smckusick 	int i, c;
6034234Smckusick 
6044234Smckusick loop:
6054234Smckusick 	switch(c=getch()) {
6064234Smckusick 
6074234Smckusick 	case ' ':
6084234Smckusick 	case '\t':
6094234Smckusick 	case '\n':
6104234Smckusick 		goto loop;
6114234Smckusick 
6124234Smckusick 	case '\0':
6134234Smckusick 		printf("EOF\n");
6144234Smckusick 		exit(1);
6154234Smckusick 
6164234Smckusick 	case ':':
6174234Smckusick 		while(getch() != '\n');
6184234Smckusick 		goto loop;
6194234Smckusick 
6204234Smckusick 	}
6214234Smckusick 	i = 0;
6224234Smckusick 
6234234Smckusick 	do {
6244234Smckusick 		string[i++] = c;
6254234Smckusick 		c = getch();
6264234Smckusick 	} while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0');
6274234Smckusick 	string[i] = '\0';
6284234Smckusick }
6294234Smckusick 
6304234Smckusick rdfs(bno, size, bf)
631*5324Smckusic 	daddr_t bno;
632*5324Smckusic 	int size;
633*5324Smckusic 	char *bf;
6344234Smckusick {
6354234Smckusick 	int n;
6364234Smckusick 
637*5324Smckusic 	lseek(fsi, bno * DEV_BSIZE, 0);
6384234Smckusick 	n = read(fsi, bf, size);
6394234Smckusick 	if(n != size) {
6404234Smckusick 		printf("read error: %ld\n", bno);
6414234Smckusick 		exit(1);
6424234Smckusick 	}
6434234Smckusick }
6444234Smckusick 
6454234Smckusick wtfs(bno, size, bf)
646*5324Smckusic 	daddr_t bno;
647*5324Smckusic 	int size;
648*5324Smckusic 	char *bf;
6494234Smckusick {
6504234Smckusick 	int n;
6514234Smckusick 
652*5324Smckusic 	lseek(fso, bno * DEV_BSIZE, 0);
6534234Smckusick 	n = write(fso, bf, size);
6544234Smckusick 	if(n != size) {
6554234Smckusick 		printf("write error: %D\n", bno);
6564234Smckusick 		exit(1);
6574234Smckusick 	}
6584234Smckusick }
6594234Smckusick 
6604234Smckusick daddr_t
6614427Smckusic alloc(size, mode)
6624427Smckusic 	int size;
6634427Smckusic 	int mode;
6644234Smckusick {
6654234Smckusick 	int c, i, s, frag;
6664234Smckusick 	daddr_t d;
6674234Smckusick 
6684234Smckusick 	c = 0;
669*5324Smckusic 	rdfs(fsbtodb(&sblock, cgtod(0,&sblock)),
670*5324Smckusic 		sblock.fs_cgsize, (char *)&acg);
6714788Smckusic 	if (acg.cg_cs.cs_nbfree == 0) {
6724234Smckusick 		printf("first cylinder group ran out of space\n");
6734234Smckusick 		return (0);
6744234Smckusick 	}
675*5324Smckusic 	for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
676*5324Smckusic 		if (isblock(&sblock, acg.cg_free, d / sblock.fs_frag))
6774234Smckusick 			goto goth;
6784234Smckusick 	printf("internal error: can't find block in cyl 0\n");
6794234Smckusick 	return (0);
6804234Smckusick goth:
681*5324Smckusic 	clrblock(&sblock, acg.cg_free, d / sblock.fs_frag);
6824788Smckusic 	acg.cg_cs.cs_nbfree--;
6834788Smckusic 	sblock.fs_cstotal.cs_nbfree--;
6844234Smckusick 	fscs[0].cs_nbfree--;
6854427Smckusic 	if (mode & IFDIR) {
6864788Smckusic 		acg.cg_cs.cs_ndir++;
6874788Smckusic 		sblock.fs_cstotal.cs_ndir++;
6884427Smckusic 		fscs[0].cs_ndir++;
6894427Smckusic 	}
690*5324Smckusic 	s = d * NSPF(&sblock);
691*5324Smckusic 	acg.cg_b[s / sblock.fs_spc]
692*5324Smckusic 		[s % sblock.fs_nsect * NRPOS / sblock.fs_nsect]--;
693*5324Smckusic 	if (size != sblock.fs_bsize) {
694*5324Smckusic 		frag = howmany(size, sblock.fs_fsize);
695*5324Smckusic 		fscs[0].cs_nffree += sblock.fs_frag - frag;
696*5324Smckusic 		sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
697*5324Smckusic 		acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
698*5324Smckusic 		acg.cg_frsum[sblock.fs_frag - frag]++;
699*5324Smckusic 		for (i = frag; i < sblock.fs_frag; i++)
7004234Smckusick 			setbit(acg.cg_free, d+i);
7014234Smckusick 	}
702*5324Smckusic 	wtfs(fsbtodb(&sblock, cgtod(0,&sblock)),
703*5324Smckusic 		roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg);
7044234Smckusick 	return (d);
7054234Smckusick }
7064234Smckusick 
7074234Smckusick entry(inum, str, adbc, db, aibc, ib)
708*5324Smckusic 	ino_t inum;
709*5324Smckusic 	char *str;
710*5324Smckusic 	int *adbc, *aibc;
711*5324Smckusic 	char *db;
712*5324Smckusic 	daddr_t *ib;
7134234Smckusick {
7144234Smckusick 	struct direct *dp;
7154234Smckusick 	int i;
7164234Smckusick 
717*5324Smckusic 	if (*adbc == NDIRECT(&sblock))
718*5324Smckusic 		newblk(adbc, db, aibc, ib, sblock.fs_bsize, 0);
7194234Smckusick 	dp = (struct direct *)db;
7204234Smckusick 	dp += *adbc;
7214234Smckusick 	(*adbc)++;
7224234Smckusick 	dp->d_ino = inum;
723*5324Smckusic 	for(i=0; i < DIRSIZ; i++)
7244234Smckusick 		dp->d_name[i] = 0;
725*5324Smckusic 	for(i=0; i < DIRSIZ; i++)
7264234Smckusick 		if((dp->d_name[i] = str[i]) == 0)
7274234Smckusick 			break;
7284234Smckusick }
7294234Smckusick 
7304427Smckusic newblk(adbc, db, aibc, ib, size, mode)
7314427Smckusic 	int *adbc, *aibc;
7324427Smckusic 	char *db;
7334427Smckusic 	daddr_t *ib;
7344427Smckusic 	int size;
7354427Smckusic 	int mode;
7364234Smckusick {
7374234Smckusick 	int i;
7384234Smckusick 	daddr_t bno;
7394234Smckusick 
7404427Smckusic 	bno = alloc(size, mode);
741*5324Smckusic 	wtfs(fsbtodb(&sblock, bno), size, db);
742*5324Smckusic 	for(i = 0; i < size; i++)
7434234Smckusick 		db[i] = 0;
7444234Smckusick 	*adbc = 0;
7454234Smckusick 	ib[*aibc] = bno;
7464234Smckusick 	(*aibc)++;
747*5324Smckusic 	if(*aibc >= NINDIR(&sblock)) {
7484234Smckusick 		printf("indirect block full\n");
7494234Smckusick 		error = 1;
7504234Smckusick 		*aibc = 0;
7514234Smckusick 	}
7524234Smckusick }
7534234Smckusick 
7544234Smckusick getch()
7554234Smckusick {
7564234Smckusick 
7574234Smckusick #ifndef STANDALONE
7584234Smckusick 	if(charp)
7594234Smckusick #endif
7604234Smckusick 		return(*charp++);
7614234Smckusick #ifndef STANDALONE
7624234Smckusick 	return(getc(fin));
7634234Smckusick #endif
7644234Smckusick }
7654234Smckusick 
7664234Smckusick iput(ip, aibc, ib)
767*5324Smckusic 	struct inode *ip;
768*5324Smckusic 	int *aibc;
769*5324Smckusic 	daddr_t *ib;
7704234Smckusick {
7714234Smckusick 	struct dinode *dp;
7724234Smckusick 	daddr_t d;
7734234Smckusick 	int i, c = ip->i_number / sblock.fs_ipg;
7744234Smckusick 
775*5324Smckusic 	rdfs(fsbtodb(&sblock, cgtod(c,&sblock)),
776*5324Smckusic 		sblock.fs_cgsize, (char *)&acg);
7774788Smckusic 	acg.cg_cs.cs_nifree--;
7784234Smckusick 	setbit(acg.cg_iused, ip->i_number);
779*5324Smckusic 	wtfs(fsbtodb(&sblock, cgtod(c,&sblock)),
780*5324Smckusic 		roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg);
7814788Smckusic 	sblock.fs_cstotal.cs_nifree--;
7824234Smckusick 	fscs[0].cs_nifree--;
7834234Smckusick 	if(ip->i_number >= sblock.fs_ipg) {
7844234Smckusick 		printf("mkfs: cant handle more than one cg of inodes (yet)\n");
7854234Smckusick 		exit(1);
7864234Smckusick 	}
7874234Smckusick 	if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
7884234Smckusick 		if(error == 0)
7894234Smckusick 			printf("ilist too small\n");
7904234Smckusick 		error = 1;
7914234Smckusick 		return;
7924234Smckusick 	}
7934234Smckusick 	d = itod(ip->i_number,&sblock);
794*5324Smckusic 	rdfs(fsbtodb(&sblock, d), sblock.fs_bsize, buf);
795*5324Smckusic 	for(i = 0; i < *aibc; i++) {
7964251Smckusic 		if(i >= NDADDR)
7974251Smckusic 			break;
7984251Smckusic 		ip->i_db[i] = ib[i];
7994251Smckusic 	}
8004251Smckusic 	if(*aibc >= NDADDR) {
801*5324Smckusic 		ip->i_ib[0] = alloc(sblock.fs_bsize, 0);
802*5324Smckusic 		for(i=0; i<NINDIR(&sblock)-NDADDR; i++) {
8034251Smckusic 			ib[i] = ib[i+NDADDR];
8044251Smckusic 			ib[i+NDADDR] = (daddr_t)0;
8054234Smckusick 		}
806*5324Smckusic 		wtfs(fsbtodb(&sblock, ip->i_ib[0]), sblock.fs_bsize,
807*5324Smckusic 			(char *)ib);
8084234Smckusick 	}
809*5324Smckusic 	((struct dinode *)buf + itoo(ip->i_number, &sblock))->di_ic = ip->i_ic;
810*5324Smckusic 	wtfs(fsbtodb(&sblock, d), sblock.fs_bsize, buf);
8114234Smckusick }
812*5324Smckusic 
813*5324Smckusic /*
814*5324Smckusic  * block operations
815*5324Smckusic  */
816*5324Smckusic 
817*5324Smckusic isblock(fs, cp, h)
818*5324Smckusic 	struct fs *fs;
819*5324Smckusic 	unsigned char *cp;
820*5324Smckusic 	int h;
821*5324Smckusic {
822*5324Smckusic 	unsigned char mask;
823*5324Smckusic 
824*5324Smckusic 	switch (fs->fs_frag) {
825*5324Smckusic 	case 8:
826*5324Smckusic 		return (cp[h] == 0xff);
827*5324Smckusic 	case 4:
828*5324Smckusic 		mask = 0x0f << ((h & 0x1) << 2);
829*5324Smckusic 		return ((cp[h >> 1] & mask) == mask);
830*5324Smckusic 	case 2:
831*5324Smckusic 		mask = 0x03 << ((h & 0x3) << 1);
832*5324Smckusic 		return ((cp[h >> 2] & mask) == mask);
833*5324Smckusic 	case 1:
834*5324Smckusic 		mask = 0x01 << (h & 0x7);
835*5324Smckusic 		return ((cp[h >> 3] & mask) == mask);
836*5324Smckusic 	default:
837*5324Smckusic 		fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
838*5324Smckusic 		return;
839*5324Smckusic 	}
840*5324Smckusic }
841*5324Smckusic 
842*5324Smckusic clrblock(fs, cp, h)
843*5324Smckusic 	struct fs *fs;
844*5324Smckusic 	unsigned char *cp;
845*5324Smckusic 	int h;
846*5324Smckusic {
847*5324Smckusic 	switch ((fs)->fs_frag) {
848*5324Smckusic 	case 8:
849*5324Smckusic 		cp[h] = 0;
850*5324Smckusic 		return;
851*5324Smckusic 	case 4:
852*5324Smckusic 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
853*5324Smckusic 		return;
854*5324Smckusic 	case 2:
855*5324Smckusic 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
856*5324Smckusic 		return;
857*5324Smckusic 	case 1:
858*5324Smckusic 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
859*5324Smckusic 		return;
860*5324Smckusic 	default:
861*5324Smckusic 		fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
862*5324Smckusic 		return;
863*5324Smckusic 	}
864*5324Smckusic }
865*5324Smckusic 
866*5324Smckusic setblock(fs, cp, h)
867*5324Smckusic 	struct fs *fs;
868*5324Smckusic 	unsigned char *cp;
869*5324Smckusic 	int h;
870*5324Smckusic {
871*5324Smckusic 	switch (fs->fs_frag) {
872*5324Smckusic 	case 8:
873*5324Smckusic 		cp[h] = 0xff;
874*5324Smckusic 		return;
875*5324Smckusic 	case 4:
876*5324Smckusic 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
877*5324Smckusic 		return;
878*5324Smckusic 	case 2:
879*5324Smckusic 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
880*5324Smckusic 		return;
881*5324Smckusic 	case 1:
882*5324Smckusic 		cp[h >> 3] |= (0x01 << (h & 0x7));
883*5324Smckusic 		return;
884*5324Smckusic 	default:
885*5324Smckusic 		fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
886*5324Smckusic 		return;
887*5324Smckusic 	}
888*5324Smckusic }
889