xref: /csrg-svn/sbin/newfs/mkfs.c (revision 4234)
1*4234Smckusick static	char *sccsid = "@(#)mkfs.c	1.1 (Berkeley) 08/26/81";
2*4234Smckusick 
3*4234Smckusick /*
4*4234Smckusick  * make file system for cylinder-group style file systems
5*4234Smckusick  *
6*4234Smckusick  * usage: mkfs fs proto
7*4234Smckusick  * or: mkfs size [ nsect ntrak cpg ]
8*4234Smckusick  */
9*4234Smckusick 
10*4234Smckusick #define	NDIRECT	(BSIZE/sizeof(struct direct))
11*4234Smckusick #define	MAXFN	500
12*4234Smckusick 
13*4234Smckusick #define	setbit(a,i)	((a)[(i)/NBBY] |= 1<<((i)%NBBY))
14*4234Smckusick #define	clrbit(a,i)	((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
15*4234Smckusick #define	isset(a,i)	((a)[(i)/NBBY] & (1<<((i)%NBBY)))
16*4234Smckusick 
17*4234Smckusick #ifndef STANDALONE
18*4234Smckusick #include <stdio.h>
19*4234Smckusick #include <a.out.h>
20*4234Smckusick #endif
21*4234Smckusick 
22*4234Smckusick #include "../h/param.h"
23*4234Smckusick #include "../h/ino.h"
24*4234Smckusick #include "../h/inode.h"
25*4234Smckusick #include "../h/fs.h"
26*4234Smckusick #include "../h/dir.h"
27*4234Smckusick 
28*4234Smckusick time_t	utime;
29*4234Smckusick 
30*4234Smckusick #ifndef STANDALONE
31*4234Smckusick FILE 	*fin;
32*4234Smckusick #else
33*4234Smckusick int	fin;
34*4234Smckusick #endif
35*4234Smckusick 
36*4234Smckusick int	fsi;
37*4234Smckusick int	fso;
38*4234Smckusick char	*charp;
39*4234Smckusick char	buf[BSIZE];
40*4234Smckusick #ifndef STANDALONE
41*4234Smckusick struct exec head;
42*4234Smckusick #endif
43*4234Smckusick char	string[50];
44*4234Smckusick 
45*4234Smckusick union {
46*4234Smckusick 	struct fs fs;
47*4234Smckusick 	char pad[BSIZE];
48*4234Smckusick } fsun;
49*4234Smckusick #define	sblock	fsun.fs
50*4234Smckusick struct	csum *fscs;
51*4234Smckusick 
52*4234Smckusick union {
53*4234Smckusick 	struct cg cg;
54*4234Smckusick 	char pad[BSIZE];
55*4234Smckusick } cgun;
56*4234Smckusick #define	acg	cgun.cg
57*4234Smckusick 
58*4234Smckusick #define	howmany(x, y)	(((x)+((y)-1))/(y))
59*4234Smckusick #define	roundup(x, y)	((((x)+((y)-1))/(y))*(y))
60*4234Smckusick 
61*4234Smckusick char	*fsys;
62*4234Smckusick char	*proto;
63*4234Smckusick int	error;
64*4234Smckusick ino_t	ino = ROOTINO - 1;
65*4234Smckusick long	getnum();
66*4234Smckusick daddr_t	alloc();
67*4234Smckusick 
68*4234Smckusick struct	dinode zino[MAXIPG];
69*4234Smckusick 
70*4234Smckusick main(argc, argv)
71*4234Smckusick char *argv[];
72*4234Smckusick {
73*4234Smckusick 	int f, c;
74*4234Smckusick 	long i,n;
75*4234Smckusick 
76*4234Smckusick 	argc--, argv++;
77*4234Smckusick #ifndef STANDALONE
78*4234Smckusick 	time(&utime);
79*4234Smckusick 	if(argc < 2) {
80*4234Smckusick 		printf("usage: mkfs sblock proto/size [ nsect ntrak cpg ]\n");
81*4234Smckusick 		exit(1);
82*4234Smckusick 	}
83*4234Smckusick 	fsys = argv[0];
84*4234Smckusick 	proto = argv[1];
85*4234Smckusick #else
86*4234Smckusick 	{
87*4234Smckusick 		static char protos[60];
88*4234Smckusick 
89*4234Smckusick 		printf("file sys size: ");
90*4234Smckusick 		gets(protos);
91*4234Smckusick 		proto = protos;
92*4234Smckusick 	}
93*4234Smckusick #endif
94*4234Smckusick #ifdef STANDALONE
95*4234Smckusick 	{
96*4234Smckusick 		char fsbuf[100];
97*4234Smckusick 
98*4234Smckusick 		do {
99*4234Smckusick 			printf("file system: ");
100*4234Smckusick 			gets(fsbuf);
101*4234Smckusick 			fso = open(fsbuf, 1);
102*4234Smckusick 			fsi = open(fsbuf, 0);
103*4234Smckusick 		} while (fso < 0 || fsi < 0);
104*4234Smckusick 	}
105*4234Smckusick 	fin = NULL;
106*4234Smckusick 	argc = 0;
107*4234Smckusick #else
108*4234Smckusick 	fso = creat(fsys, 0666);
109*4234Smckusick 	if(fso < 0) {
110*4234Smckusick 		printf("%s: cannot create\n", fsys);
111*4234Smckusick 		exit(1);
112*4234Smckusick 	}
113*4234Smckusick 	fsi = open(fsys, 0);
114*4234Smckusick 	if(fsi < 0) {
115*4234Smckusick 		printf("%s: cannot open\n", fsys);
116*4234Smckusick 		exit(1);
117*4234Smckusick 	}
118*4234Smckusick 	fin = fopen(proto, "r");
119*4234Smckusick #endif
120*4234Smckusick #ifndef STANDALONE
121*4234Smckusick 	if (fin != NULL) {
122*4234Smckusick 		getstr();
123*4234Smckusick 		f = open(string, 0);
124*4234Smckusick 		if (f < 0) {
125*4234Smckusick 			printf("%s: cannot open init\n", string);
126*4234Smckusick 			goto noinit;
127*4234Smckusick 		}
128*4234Smckusick 		read(f, (char *)&head, sizeof head);
129*4234Smckusick 		c = head.a_text + head.a_data;
130*4234Smckusick 		if (c > BSIZE)
131*4234Smckusick 			printf("%s: too big\n", string);
132*4234Smckusick 		else {
133*4234Smckusick 			read(f, buf, c);
134*4234Smckusick 			wtfs(BBLOCK, BSIZE, buf);
135*4234Smckusick 		}
136*4234Smckusick 		close(f);
137*4234Smckusick noinit:
138*4234Smckusick 		n = sblock.fs_size = getnum();
139*4234Smckusick 		sblock.fs_ntrak = getnum();
140*4234Smckusick 		sblock.fs_nsect = getnum();
141*4234Smckusick 		sblock.fs_cpg = getnum();
142*4234Smckusick 	} else
143*4234Smckusick #endif
144*4234Smckusick 	{
145*4234Smckusick 		charp = "d--777 0 0 $ ";
146*4234Smckusick 		n = 0;
147*4234Smckusick 		for (f=0; c=proto[f]; f++) {
148*4234Smckusick 			if (c<'0' || c>'9') {
149*4234Smckusick 				printf("%s: cannot open\n", proto);
150*4234Smckusick 				exit(1);
151*4234Smckusick 			}
152*4234Smckusick 			n = n*10 + (c-'0');
153*4234Smckusick 		}
154*4234Smckusick 		sblock.fs_size = n;
155*4234Smckusick 		if (argc > 2)
156*4234Smckusick 			sblock.fs_nsect = atoi(argv[2]);
157*4234Smckusick 		else
158*4234Smckusick 			sblock.fs_nsect = 32;
159*4234Smckusick 		if (argc > 3)
160*4234Smckusick 			sblock.fs_ntrak = atoi(argv[3]);
161*4234Smckusick 		else
162*4234Smckusick 			sblock.fs_ntrak = 19;
163*4234Smckusick 	}
164*4234Smckusick 	/*
165*4234Smckusick 	 * Now have size for file system and nsect and ntrak.
166*4234Smckusick 	 * (And, if coming from prototype, cpg).
167*4234Smckusick 	 * Determine number of cylinders occupied by file system.
168*4234Smckusick 	 */
169*4234Smckusick 	if (sblock.fs_ntrak <= 0)
170*4234Smckusick 		printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1);
171*4234Smckusick 	if (sblock.fs_nsect <= 0)
172*4234Smckusick 		printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1);
173*4234Smckusick 	if (sblock.fs_size <= 0)
174*4234Smckusick 		printf("preposterous size %d\n", sblock.fs_size), exit(1);
175*4234Smckusick 	if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG * NSPB) {
176*4234Smckusick 		printf("cylinder too large (%d sectors)\n",
177*4234Smckusick 		    sblock.fs_ntrak * sblock.fs_nsect);
178*4234Smckusick 		printf("maximum cylinder size: %d sectors\n",
179*4234Smckusick 		    MAXBPG * NSPB);
180*4234Smckusick 		exit(1);
181*4234Smckusick 	}
182*4234Smckusick 	sblock.fs_ncyl = n * NSPF / (sblock.fs_nsect * sblock.fs_ntrak);
183*4234Smckusick 	if (n * NSPF > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) {
184*4234Smckusick 		printf("%d sector(s) in last cylinder unused\n",
185*4234Smckusick 		    n * NSPF - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak);
186*4234Smckusick 		sblock.fs_ncyl++;
187*4234Smckusick 	}
188*4234Smckusick 	sblock.fs_magic = FS_MAGIC;
189*4234Smckusick 	/*
190*4234Smckusick 	 * Validate specified/determined cpg.
191*4234Smckusick 	 */
192*4234Smckusick #define	CGTOOBIG(fs)	((fs).fs_nsect*(fs).fs_ntrak*(fs).fs_cpg/NSPB > MAXBPG)
193*4234Smckusick 	if (argc > 4 || fin) {
194*4234Smckusick 		if (fin == NULL)
195*4234Smckusick 			sblock.fs_cpg = atoi(argv[4]);
196*4234Smckusick 		if (CGTOOBIG(sblock)) {
197*4234Smckusick 			printf("cylinder group too large (%d blocks); ",
198*4234Smckusick 			    sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB);
199*4234Smckusick 			printf("max: %d blocks\n", MAXBPG);
200*4234Smckusick 			exit(1);
201*4234Smckusick 		}
202*4234Smckusick 		if (sblock.fs_cpg > MAXCPG) {
203*4234Smckusick 			printf("cylinder groups are limited to %d cylinders\n",
204*4234Smckusick 			    MAXCPG);
205*4234Smckusick 			exit(1);
206*4234Smckusick 		}
207*4234Smckusick 	} else {
208*4234Smckusick 		sblock.fs_cpg = DESCPG;
209*4234Smckusick 		while (CGTOOBIG(sblock))
210*4234Smckusick 			--sblock.fs_cpg;
211*4234Smckusick 	}
212*4234Smckusick 	/*
213*4234Smckusick 	 * Compute/validate number of cylinder groups.
214*4234Smckusick 	 */
215*4234Smckusick 	sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
216*4234Smckusick 	if (sblock.fs_ncyl % sblock.fs_cpg)
217*4234Smckusick 		sblock.fs_ncg++;
218*4234Smckusick 	if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF) {
219*4234Smckusick 		printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n",
220*4234Smckusick 		    sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg);
221*4234Smckusick 		printf("as this would would have cyl groups whose size\n");
222*4234Smckusick 		printf("is not a multiple of %d; choke!\n", FSIZE);
223*4234Smckusick 		exit(1);
224*4234Smckusick 	}
225*4234Smckusick 	fscs = (struct csum *)
226*4234Smckusick 	    calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE));
227*4234Smckusick 	/*
228*4234Smckusick 	 * Compute number of inode blocks per cylinder group.
229*4234Smckusick 	 * Start with one inode per NBPI bytes; adjust as necessary.
230*4234Smckusick 	 */
231*4234Smckusick 	n = ((n * BSIZE) / NBPI) / INOPB;
232*4234Smckusick 	if (n <= 0)
233*4234Smckusick 		n = 1;
234*4234Smckusick 	if (n > 65500/INOPB)
235*4234Smckusick 		n = 65500/INOPB;
236*4234Smckusick 	sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB;
237*4234Smckusick 	if (sblock.fs_ipg < INOPB)
238*4234Smckusick 		sblock.fs_ipg = INOPB;
239*4234Smckusick 	if (sblock.fs_ipg > MAXIPG)
240*4234Smckusick 		sblock.fs_ipg = MAXIPG;
241*4234Smckusick 	while (sblock.fs_ipg * sblock.fs_ncyl > 65500)
242*4234Smckusick 		sblock.fs_ipg -= INOPB;
243*4234Smckusick 	sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
244*4234Smckusick 	sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / (FSIZE / 512);
245*4234Smckusick 	if (cgdmin(0,&sblock) >= sblock.fs_fpg)
246*4234Smckusick 		printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
247*4234Smckusick 		    cgdmin(0,&sblock)/FRAG, sblock.fs_fpg/FRAG), exit(1);
248*4234Smckusick 	sblock.fs_nifree = sblock.fs_ipg * sblock.fs_ncg;
249*4234Smckusick 	sblock.fs_cgsize = cgsize(&sblock);
250*4234Smckusick 	sblock.fs_cssize = cssize(&sblock);
251*4234Smckusick 	sblock.fs_sblkno = SBLOCK;
252*4234Smckusick 	sblock.fs_fmod = 0;
253*4234Smckusick 	sblock.fs_ronly = 0;
254*4234Smckusick 
255*4234Smckusick 	/*
256*4234Smckusick 	 * Dump out information about file system.
257*4234Smckusick 	 */
258*4234Smckusick 	printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n",
259*4234Smckusick 	    fsys, sblock.fs_size*NSPF, sblock.fs_ncyl, sblock.fs_ntrak, sblock.fs_nsect);
260*4234Smckusick 	printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n",
261*4234Smckusick 	    (float)sblock.fs_size*FSIZE*1e-6, sblock.fs_ncg, sblock.fs_cpg,
262*4234Smckusick 	    (float)sblock.fs_fpg*FSIZE*1e-6, sblock.fs_ipg);
263*4234Smckusick /*
264*4234Smckusick 	printf("%7d size (%d blocks)\n", sblock.fs_size, sblock.fs_size/FRAG);
265*4234Smckusick 	printf("%7d cylinder groups\n", sblock.fs_ncg);
266*4234Smckusick 	printf("%7d cylinder group block size\n", sblock.fs_cgsize);
267*4234Smckusick 	printf("%7d tracks\n", sblock.fs_ntrak);
268*4234Smckusick 	printf("%7d sectors\n", sblock.fs_nsect);
269*4234Smckusick 	printf("%7d sectors per cylinder\n", sblock.fs_spc);
270*4234Smckusick 	printf("%7d cylinders\n", sblock.fs_ncyl);
271*4234Smckusick 	printf("%7d cylinders per group\n", sblock.fs_cpg);
272*4234Smckusick 	printf("%7d blocks per group\n", sblock.fs_fpg/FRAG);
273*4234Smckusick 	printf("%7d inodes per group\n", sblock.fs_ipg);
274*4234Smckusick 	if (sblock.fs_ncyl % sblock.fs_cpg) {
275*4234Smckusick 		printf("%7d cylinders in last group\n",
276*4234Smckusick 		    i = sblock.fs_ncyl % sblock.fs_cpg);
277*4234Smckusick 		printf("%7d blocks in last group\n",
278*4234Smckusick 		    i * sblock.fs_spc / NSPB);
279*4234Smckusick 	}
280*4234Smckusick */
281*4234Smckusick 	/*
282*4234Smckusick 	 * Now build the cylinders group blocks and
283*4234Smckusick 	 * then print out indices of cylinder groups forwarded
284*4234Smckusick 	 * past bad blocks or other obstructions.
285*4234Smckusick 	 */
286*4234Smckusick 	sblock.fs_nffree = 0;
287*4234Smckusick 	sblock.fs_nbfree = 0;
288*4234Smckusick 	for (c = 0; c < sblock.fs_ncg; c++)
289*4234Smckusick 		initcg(c);
290*4234Smckusick 	printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n",
291*4234Smckusick 	    SBLOCK, sblock.fs_fpg, SBLOCK+sblock.fs_fpg,
292*4234Smckusick 	    SBLOCK+(sblock.fs_ncg-1)*sblock.fs_fpg);
293*4234Smckusick 	/*
294*4234Smckusick 	 * Now construct the initial file system, and
295*4234Smckusick 	 * then write out the super-block.
296*4234Smckusick 	 */
297*4234Smckusick 	cfile((struct inode *)0);
298*4234Smckusick 	sblock.fs_time = utime;
299*4234Smckusick 	wtfs(SBLOCK, BSIZE, (char *)&sblock);
300*4234Smckusick 	for (i = 0; i < cssize(&sblock); i += BSIZE)
301*4234Smckusick 		wtfs(csaddr(&sblock) + i/BSIZE, BSIZE, ((char *)fscs)+i);
302*4234Smckusick 	for (c = 0; c < sblock.fs_ncg; c++)
303*4234Smckusick 		wtfs(cgsblock(c, &sblock), BSIZE, (char *)&sblock);
304*4234Smckusick #ifndef STANDALONE
305*4234Smckusick 	exit(error);
306*4234Smckusick #endif
307*4234Smckusick }
308*4234Smckusick 
309*4234Smckusick /*
310*4234Smckusick  * Initialize a cylinder group.
311*4234Smckusick  */
312*4234Smckusick initcg(c)
313*4234Smckusick 	int c;
314*4234Smckusick {
315*4234Smckusick 	daddr_t cbase, d, dmin, dmax;
316*4234Smckusick 	long i, j, s;
317*4234Smckusick 	register struct csum *cs;
318*4234Smckusick 
319*4234Smckusick 	/*
320*4234Smckusick 	 * Determine block bounds for cylinder group.
321*4234Smckusick 	 * Allow space for super block summary information in first
322*4234Smckusick 	 * cylinder group.
323*4234Smckusick 	 */
324*4234Smckusick 	cbase = cgbase(c,&sblock);
325*4234Smckusick 	dmax = cbase + sblock.fs_fpg;
326*4234Smckusick 	if (dmax > sblock.fs_size)
327*4234Smckusick 		dmax = sblock.fs_size;
328*4234Smckusick 	d = cbase;
329*4234Smckusick 	cs = fscs+c;
330*4234Smckusick tryagain:
331*4234Smckusick 	for (i = cgdmin(c,&sblock) - FRAG; i >= 0; i -= FRAG)
332*4234Smckusick 		if (badblk(d)) {
333*4234Smckusick 			d += i + FRAG;
334*4234Smckusick 			if (d + sblock.fs_ipg/INOPB >= dmax) {
335*4234Smckusick 				printf("bad blocks: cyl grp %d unusable\n", c);
336*4234Smckusick 				exit(1);
337*4234Smckusick 			}
338*4234Smckusick 			goto tryagain;
339*4234Smckusick 		}
340*4234Smckusick 	cs->cs_ndir = 0;
341*4234Smckusick 	acg.cg_time = utime;
342*4234Smckusick 	acg.cg_magic = CG_MAGIC;
343*4234Smckusick 	acg.cg_cgx = c;
344*4234Smckusick 	acg.cg_ncyl = sblock.fs_cpg;
345*4234Smckusick 	acg.cg_niblk = sblock.fs_ipg;
346*4234Smckusick 	acg.cg_ndblk = dmax - cbase;
347*4234Smckusick 	acg.cg_ndir = 0;
348*4234Smckusick 	acg.cg_nffree = 0;
349*4234Smckusick 	acg.cg_nbfree = 0;
350*4234Smckusick 	acg.cg_nifree = 0;
351*4234Smckusick 	acg.cg_rotor = 0;
352*4234Smckusick 	i = 0;
353*4234Smckusick 	d = cgimin(c,&sblock);
354*4234Smckusick 	while (i < sblock.fs_ipg) {
355*4234Smckusick 		for (j = INOPB; j > 0; j--) {
356*4234Smckusick 			clrbit(acg.cg_iused, i);
357*4234Smckusick 			i++;
358*4234Smckusick 		}
359*4234Smckusick 		acg.cg_nifree += INOPB;
360*4234Smckusick 		d++;
361*4234Smckusick 	}
362*4234Smckusick 	while (i < MAXIPG) {
363*4234Smckusick 		clrbit(acg.cg_iused, i);
364*4234Smckusick 		i++;
365*4234Smckusick 	}
366*4234Smckusick 	lseek(fso, cgimin(c,&sblock)*FSIZE, 0);
367*4234Smckusick 	if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) !=
368*4234Smckusick 	    sblock.fs_ipg * sizeof (struct dinode))
369*4234Smckusick 		printf("write error %D\n", tell(fso) / BSIZE);
370*4234Smckusick 	for (i = 0; i < MAXCPG; i++)
371*4234Smckusick 		for (j = 0; j < NRPOS; j++)
372*4234Smckusick 			acg.cg_b[i][j] = 0;
373*4234Smckusick 	dmin = cgdmin(c,&sblock) - cbase;
374*4234Smckusick 	if (c == 0) {
375*4234Smckusick 		dmin += howmany(cssize(&sblock), BSIZE) * FRAG;
376*4234Smckusick 	}
377*4234Smckusick 	for (d = 0; d < dmin; d += FRAG)
378*4234Smckusick 		clrblock(acg.cg_free, d/FRAG);
379*4234Smckusick 	while ((d+FRAG) <= dmax - cbase) {
380*4234Smckusick 		if (badblk(cbase+d))
381*4234Smckusick 			clrblock(acg.cg_free, d/FRAG);
382*4234Smckusick 		else {
383*4234Smckusick 			setblock(acg.cg_free, d/FRAG);
384*4234Smckusick 			acg.cg_nbfree++;
385*4234Smckusick 			s = d * NSPF;
386*4234Smckusick 			acg.cg_b[s/sblock.fs_spc]
387*4234Smckusick 			    [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++;
388*4234Smckusick 		}
389*4234Smckusick 		d += FRAG;
390*4234Smckusick 	}
391*4234Smckusick 	if (d < dmax - cbase)
392*4234Smckusick 		if (badblk(d))
393*4234Smckusick 			for (; d < dmax - cbase; d++)
394*4234Smckusick 				clrbit(acg.cg_free, d);
395*4234Smckusick 		else
396*4234Smckusick 			for (; d < dmax - cbase; d++) {
397*4234Smckusick 				setbit(acg.cg_free, d);
398*4234Smckusick 				acg.cg_nffree++;
399*4234Smckusick 			}
400*4234Smckusick 	for (; d < MAXBPG; d++)
401*4234Smckusick 		clrbit(acg.cg_free, d);
402*4234Smckusick 	sblock.fs_nffree += acg.cg_nffree;
403*4234Smckusick 	sblock.fs_nbfree += acg.cg_nbfree;
404*4234Smckusick 	cs->cs_nifree = acg.cg_nifree;
405*4234Smckusick 	cs->cs_nbfree = acg.cg_nbfree;
406*4234Smckusick 	wtfs(cgtod(c, &sblock), BSIZE, (char *)&acg);
407*4234Smckusick }
408*4234Smckusick 
409*4234Smckusick cfile(par)
410*4234Smckusick struct inode *par;
411*4234Smckusick {
412*4234Smckusick 	struct inode in;
413*4234Smckusick 	int dbc, ibc;
414*4234Smckusick 	char db[BSIZE];
415*4234Smckusick 	daddr_t ib[NINDIR];
416*4234Smckusick 	int i, f, c;
417*4234Smckusick 
418*4234Smckusick 	/*
419*4234Smckusick 	 * get mode, uid and gid
420*4234Smckusick 	 */
421*4234Smckusick 
422*4234Smckusick 	getstr();
423*4234Smckusick 	in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
424*4234Smckusick 	in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0);
425*4234Smckusick 	in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0);
426*4234Smckusick 	for(i=3; i<6; i++) {
427*4234Smckusick 		c = string[i];
428*4234Smckusick 		if(c<'0' || c>'7') {
429*4234Smckusick 			printf("%c/%s: bad octal mode digit\n", c, string);
430*4234Smckusick 			error = 1;
431*4234Smckusick 			c = 0;
432*4234Smckusick 		}
433*4234Smckusick 		in.i_mode |= (c-'0')<<(15-3*i);
434*4234Smckusick 	}
435*4234Smckusick 	in.i_uid = getnum();
436*4234Smckusick 	in.i_gid = getnum();
437*4234Smckusick 
438*4234Smckusick 	/*
439*4234Smckusick 	 * general initialization prior to
440*4234Smckusick 	 * switching on format
441*4234Smckusick 	 */
442*4234Smckusick 
443*4234Smckusick 	ino++;
444*4234Smckusick 	in.i_number = ino;
445*4234Smckusick 	for(i=0; i<BSIZE; i++)
446*4234Smckusick 		db[i] = 0;
447*4234Smckusick 	for(i=0; i<NINDIR; i++)
448*4234Smckusick 		ib[i] = (daddr_t)0;
449*4234Smckusick 	in.i_nlink = 1;
450*4234Smckusick 	in.i_size = 0;
451*4234Smckusick 	for(i=0; i<NDADDR; i++)
452*4234Smckusick 		in.i_un.i_f.i_db[i] = (daddr_t)0;
453*4234Smckusick 	for(i=0; i<NIADDR; i++)
454*4234Smckusick 		in.i_un.i_f.i_ib[i] = (daddr_t)0;
455*4234Smckusick 	if(par == (struct inode *)0) {
456*4234Smckusick 		par = &in;
457*4234Smckusick 		in.i_nlink--;
458*4234Smckusick 	}
459*4234Smckusick 	dbc = 0;
460*4234Smckusick 	ibc = 0;
461*4234Smckusick 	switch(in.i_mode&IFMT) {
462*4234Smckusick 
463*4234Smckusick 	case IFREG:
464*4234Smckusick 		/*
465*4234Smckusick 		 * regular file
466*4234Smckusick 		 * contents is a file name
467*4234Smckusick 		 */
468*4234Smckusick 
469*4234Smckusick 		getstr();
470*4234Smckusick 		f = open(string, 0);
471*4234Smckusick 		if(f < 0) {
472*4234Smckusick 			printf("%s: cannot open\n", string);
473*4234Smckusick 			error = 1;
474*4234Smckusick 			break;
475*4234Smckusick 		}
476*4234Smckusick 		while((i=read(f, db, BSIZE)) > 0) {
477*4234Smckusick 			in.i_size += i;
478*4234Smckusick 			newblk(&dbc, db, &ibc, ib, i);
479*4234Smckusick 		}
480*4234Smckusick 		close(f);
481*4234Smckusick 		break;
482*4234Smckusick 
483*4234Smckusick 	case IFBLK:
484*4234Smckusick 	case IFCHR:
485*4234Smckusick 		/*
486*4234Smckusick 		 * special file
487*4234Smckusick 		 * content is maj/min types
488*4234Smckusick 		 */
489*4234Smckusick 
490*4234Smckusick 		i = getnum() & 0377;
491*4234Smckusick 		f = getnum() & 0377;
492*4234Smckusick 		in.i_un.i_d.i_rdev = makedev(i, f);
493*4234Smckusick 		break;
494*4234Smckusick 
495*4234Smckusick 	case IFDIR:
496*4234Smckusick 		/*
497*4234Smckusick 		 * directory
498*4234Smckusick 		 * put in extra links
499*4234Smckusick 		 * call recursively until
500*4234Smckusick 		 * name of "$" found
501*4234Smckusick 		 */
502*4234Smckusick 
503*4234Smckusick 		par->i_nlink++;
504*4234Smckusick 		in.i_nlink++;
505*4234Smckusick 		entry(in.i_number, ".", &dbc, db, &ibc, ib);
506*4234Smckusick 		entry(par->i_number, "..", &dbc, db, &ibc, ib);
507*4234Smckusick 		in.i_size = 2*sizeof(struct direct);
508*4234Smckusick 		for(;;) {
509*4234Smckusick 			getstr();
510*4234Smckusick 			if(string[0]=='$' && string[1]=='\0')
511*4234Smckusick 				break;
512*4234Smckusick 			if (in.i_size >= FSIZE) {
513*4234Smckusick 				printf("can't handle direct of > %d entries\n",
514*4234Smckusick 				    NDIRECT/FRAG);
515*4234Smckusick 				exit(1);
516*4234Smckusick 			}
517*4234Smckusick 			entry(ino+1, string, &dbc, db, &ibc, ib);
518*4234Smckusick 			in.i_size += sizeof(struct direct);
519*4234Smckusick 			cfile(&in);
520*4234Smckusick 		}
521*4234Smckusick 		break;
522*4234Smckusick 	}
523*4234Smckusick 	if(dbc != 0)
524*4234Smckusick 		newblk(&dbc, db, &ibc, ib, roundup(dbc,FSIZE));
525*4234Smckusick 	iput(&in, &ibc, ib);
526*4234Smckusick }
527*4234Smckusick 
528*4234Smckusick gmode(c, s, m0, m1, m2, m3)
529*4234Smckusick char c, *s;
530*4234Smckusick {
531*4234Smckusick 	int i;
532*4234Smckusick 
533*4234Smckusick 	for(i=0; s[i]; i++)
534*4234Smckusick 		if(c == s[i])
535*4234Smckusick 			return((&m0)[i]);
536*4234Smckusick 	printf("%c/%s: bad mode\n", c, string);
537*4234Smckusick 	error = 1;
538*4234Smckusick 	return(0);
539*4234Smckusick }
540*4234Smckusick 
541*4234Smckusick long
542*4234Smckusick getnum()
543*4234Smckusick {
544*4234Smckusick 	int i, c;
545*4234Smckusick 	long n;
546*4234Smckusick 
547*4234Smckusick 	getstr();
548*4234Smckusick 	n = 0;
549*4234Smckusick 	i = 0;
550*4234Smckusick 	for(i=0; c=string[i]; i++) {
551*4234Smckusick 		if(c<'0' || c>'9') {
552*4234Smckusick 			printf("%s: bad number\n", string);
553*4234Smckusick 			error = 1;
554*4234Smckusick 			return((long)0);
555*4234Smckusick 		}
556*4234Smckusick 		n = n*10 + (c-'0');
557*4234Smckusick 	}
558*4234Smckusick 	return(n);
559*4234Smckusick }
560*4234Smckusick 
561*4234Smckusick getstr()
562*4234Smckusick {
563*4234Smckusick 	int i, c;
564*4234Smckusick 
565*4234Smckusick loop:
566*4234Smckusick 	switch(c=getch()) {
567*4234Smckusick 
568*4234Smckusick 	case ' ':
569*4234Smckusick 	case '\t':
570*4234Smckusick 	case '\n':
571*4234Smckusick 		goto loop;
572*4234Smckusick 
573*4234Smckusick 	case '\0':
574*4234Smckusick 		printf("EOF\n");
575*4234Smckusick 		exit(1);
576*4234Smckusick 
577*4234Smckusick 	case ':':
578*4234Smckusick 		while(getch() != '\n');
579*4234Smckusick 		goto loop;
580*4234Smckusick 
581*4234Smckusick 	}
582*4234Smckusick 	i = 0;
583*4234Smckusick 
584*4234Smckusick 	do {
585*4234Smckusick 		string[i++] = c;
586*4234Smckusick 		c = getch();
587*4234Smckusick 	} while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0');
588*4234Smckusick 	string[i] = '\0';
589*4234Smckusick }
590*4234Smckusick 
591*4234Smckusick rdfs(bno, size, bf)
592*4234Smckusick daddr_t bno;
593*4234Smckusick int size;
594*4234Smckusick char *bf;
595*4234Smckusick {
596*4234Smckusick 	int n;
597*4234Smckusick 
598*4234Smckusick 	lseek(fsi, bno*FSIZE, 0);
599*4234Smckusick 	n = read(fsi, bf, size);
600*4234Smckusick 	if(n != size) {
601*4234Smckusick 		printf("read error: %ld\n", bno);
602*4234Smckusick 		exit(1);
603*4234Smckusick 	}
604*4234Smckusick }
605*4234Smckusick 
606*4234Smckusick wtfs(bno, size, bf)
607*4234Smckusick daddr_t bno;
608*4234Smckusick int size;
609*4234Smckusick char *bf;
610*4234Smckusick {
611*4234Smckusick 	int n;
612*4234Smckusick 
613*4234Smckusick 	lseek(fso, bno*FSIZE, 0);
614*4234Smckusick 	n = write(fso, bf, size);
615*4234Smckusick 	if(n != size) {
616*4234Smckusick 		printf("write error: %D\n", bno);
617*4234Smckusick 		exit(1);
618*4234Smckusick 	}
619*4234Smckusick }
620*4234Smckusick 
621*4234Smckusick daddr_t
622*4234Smckusick alloc(size)
623*4234Smckusick int size;
624*4234Smckusick {
625*4234Smckusick 	int c, i, s, frag;
626*4234Smckusick 	daddr_t d;
627*4234Smckusick 
628*4234Smckusick 	c = 0;
629*4234Smckusick 	rdfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg);
630*4234Smckusick 	if (acg.cg_nbfree == 0) {
631*4234Smckusick 		printf("first cylinder group ran out of space\n");
632*4234Smckusick 		return (0);
633*4234Smckusick 	}
634*4234Smckusick 	for (d = 0; d < acg.cg_ndblk; d += FRAG)
635*4234Smckusick 		if (isblock(acg.cg_free, d/FRAG))
636*4234Smckusick 			goto goth;
637*4234Smckusick 	printf("internal error: can't find block in cyl 0\n");
638*4234Smckusick 	return (0);
639*4234Smckusick goth:
640*4234Smckusick 	clrblock(acg.cg_free, d/FRAG);
641*4234Smckusick 	acg.cg_nbfree--;
642*4234Smckusick 	sblock.fs_nbfree--;
643*4234Smckusick 	fscs[0].cs_nbfree--;
644*4234Smckusick 	s = d * NSPF;
645*4234Smckusick 	acg.cg_b[s/sblock.fs_spc][s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]--;
646*4234Smckusick 	if (size != BSIZE) {
647*4234Smckusick 		frag = howmany(size, FSIZE);
648*4234Smckusick 		acg.cg_nffree += FRAG - frag;
649*4234Smckusick 		sblock.fs_nffree += FRAG - frag;
650*4234Smckusick 		for (i = frag; i < FRAG; i++)
651*4234Smckusick 			setbit(acg.cg_free, d+i);
652*4234Smckusick 	}
653*4234Smckusick 	wtfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg);
654*4234Smckusick 	return (d);
655*4234Smckusick }
656*4234Smckusick 
657*4234Smckusick entry(inum, str, adbc, db, aibc, ib)
658*4234Smckusick ino_t inum;
659*4234Smckusick char *str;
660*4234Smckusick int *adbc, *aibc;
661*4234Smckusick char *db;
662*4234Smckusick daddr_t *ib;
663*4234Smckusick {
664*4234Smckusick 	struct direct *dp;
665*4234Smckusick 	int i;
666*4234Smckusick 
667*4234Smckusick 	dp = (struct direct *)db;
668*4234Smckusick 	dp += *adbc;
669*4234Smckusick 	(*adbc)++;
670*4234Smckusick 	dp->d_ino = inum;
671*4234Smckusick 	for(i=0; i<DIRSIZ; i++)
672*4234Smckusick 		dp->d_name[i] = 0;
673*4234Smckusick 	for(i=0; i<DIRSIZ; i++)
674*4234Smckusick 		if((dp->d_name[i] = str[i]) == 0)
675*4234Smckusick 			break;
676*4234Smckusick 	if(*adbc >= NDIRECT)
677*4234Smckusick 		newblk(adbc, db, aibc, ib, BSIZE);
678*4234Smckusick }
679*4234Smckusick 
680*4234Smckusick newblk(adbc, db, aibc, ib, size)
681*4234Smckusick int *adbc, *aibc;
682*4234Smckusick char *db;
683*4234Smckusick daddr_t *ib;
684*4234Smckusick int size;
685*4234Smckusick {
686*4234Smckusick 	int i;
687*4234Smckusick 	daddr_t bno;
688*4234Smckusick 
689*4234Smckusick 	bno = alloc(size);
690*4234Smckusick 	wtfs(bno, size, db);
691*4234Smckusick 	for(i=0; i<size; i++)
692*4234Smckusick 		db[i] = 0;
693*4234Smckusick 	*adbc = 0;
694*4234Smckusick 	ib[*aibc] = bno;
695*4234Smckusick 	(*aibc)++;
696*4234Smckusick 	if(*aibc >= NINDIR) {
697*4234Smckusick 		printf("indirect block full\n");
698*4234Smckusick 		error = 1;
699*4234Smckusick 		*aibc = 0;
700*4234Smckusick 	}
701*4234Smckusick }
702*4234Smckusick 
703*4234Smckusick getch()
704*4234Smckusick {
705*4234Smckusick 
706*4234Smckusick #ifndef STANDALONE
707*4234Smckusick 	if(charp)
708*4234Smckusick #endif
709*4234Smckusick 		return(*charp++);
710*4234Smckusick #ifndef STANDALONE
711*4234Smckusick 	return(getc(fin));
712*4234Smckusick #endif
713*4234Smckusick }
714*4234Smckusick 
715*4234Smckusick iput(ip, aibc, ib)
716*4234Smckusick struct inode *ip;
717*4234Smckusick int *aibc;
718*4234Smckusick daddr_t *ib;
719*4234Smckusick {
720*4234Smckusick 	struct dinode *dp;
721*4234Smckusick 	daddr_t d;
722*4234Smckusick 	int i, c = ip->i_number / sblock.fs_ipg;
723*4234Smckusick 
724*4234Smckusick 	rdfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg);
725*4234Smckusick 	acg.cg_nifree--;
726*4234Smckusick 	setbit(acg.cg_iused, ip->i_number);
727*4234Smckusick 	wtfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg);
728*4234Smckusick 	sblock.fs_nifree--;
729*4234Smckusick 	fscs[0].cs_nifree--;
730*4234Smckusick 	if(ip->i_number >= sblock.fs_ipg) {
731*4234Smckusick 		printf("mkfs: cant handle more than one cg of inodes (yet)\n");
732*4234Smckusick 		exit(1);
733*4234Smckusick 	}
734*4234Smckusick 	if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
735*4234Smckusick 		if(error == 0)
736*4234Smckusick 			printf("ilist too small\n");
737*4234Smckusick 		error = 1;
738*4234Smckusick 		return;
739*4234Smckusick 	}
740*4234Smckusick 	d = itod(ip->i_number,&sblock);
741*4234Smckusick 	rdfs(d, BSIZE, buf);
742*4234Smckusick 	dp = (struct dinode *)buf;
743*4234Smckusick 	dp += itoo(ip->i_number);
744*4234Smckusick 
745*4234Smckusick 	dp->di_mode = ip->i_mode;
746*4234Smckusick 	dp->di_nlink = ip->i_nlink;
747*4234Smckusick 	dp->di_uid = ip->i_uid;
748*4234Smckusick 	dp->di_gid = ip->i_gid;
749*4234Smckusick 	dp->di_size = ip->i_size;
750*4234Smckusick 	dp->di_atime = utime;
751*4234Smckusick 	dp->di_mtime = utime;
752*4234Smckusick 	dp->di_ctime = utime;
753*4234Smckusick 
754*4234Smckusick 	switch(ip->i_mode&IFMT) {
755*4234Smckusick 
756*4234Smckusick 	case IFDIR:
757*4234Smckusick 	case IFREG:
758*4234Smckusick 		for(i=0; i<*aibc; i++) {
759*4234Smckusick 			if(i >= NDADDR)
760*4234Smckusick 				break;
761*4234Smckusick 			ip->i_un.i_f.i_db[i] = ib[i];
762*4234Smckusick 		}
763*4234Smckusick 		if(*aibc >= NDADDR) {
764*4234Smckusick 			ip->i_un.i_f.i_ib[0] = alloc(BSIZE);
765*4234Smckusick 			for(i=0; i<NINDIR-NDADDR; i++) {
766*4234Smckusick 				ib[i] = ib[i+NDADDR];
767*4234Smckusick 				ib[i+NDADDR] = (daddr_t)0;
768*4234Smckusick 			}
769*4234Smckusick 			wtfs(ip->i_un.i_f.i_ib[0], (char *)ib);
770*4234Smckusick 		}
771*4234Smckusick 
772*4234Smckusick 	case IFBLK:
773*4234Smckusick 	case IFCHR:
774*4234Smckusick 		ltol3(dp->di_addr, ip->i_un.i_f.i_db, NDADDR+NIADDR);
775*4234Smckusick 		break;
776*4234Smckusick 
777*4234Smckusick 	default:
778*4234Smckusick 		printf("bad mode %o\n", ip->i_mode);
779*4234Smckusick 		exit(1);
780*4234Smckusick 	}
781*4234Smckusick 	wtfs(d, BSIZE, buf);
782*4234Smckusick }
783*4234Smckusick 
784*4234Smckusick badblk(bno)
785*4234Smckusick daddr_t bno;
786*4234Smckusick {
787*4234Smckusick 
788*4234Smckusick 	return(0);
789*4234Smckusick }
790