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