xref: /original-bsd/usr.sbin/mkproto/mkproto.c (revision 92d3de31)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)mkproto.c	4.3	(Berkeley)	05/03/83";
4 
5 /*
6  * Make a file system prototype.
7  * usage: mkproto filsys proto
8  */
9 #include <stdio.h>
10 #include <sys/param.h>
11 #include <sys/inode.h>
12 #include <sys/fs.h>
13 #include <sys/dir.h>
14 
15 union {
16 	struct	fs fs;
17 	char	fsx[SBSIZE];
18 } ufs;
19 #define sblock	ufs.fs
20 union {
21 	struct	cg cg;
22 	char	cgx[MAXBSIZE];
23 } ucg;
24 #define	acg	ucg.cg
25 struct	fs *fs;
26 struct	csum *fscs;
27 int	fso, fsi;
28 FILE	*proto;
29 char	token[BUFSIZ];
30 int	errs;
31 int	ino = 10;
32 long	getnum();
33 char	*strcpy();
34 
35 main(argc, argv)
36 	int argc;
37 	char *argv[];
38 {
39 	int i;
40 
41 	if (argc != 3) {
42 		fprintf(stderr, "usage: mkproto filsys proto\n");
43 		exit(1);
44 	}
45 	fso = open(argv[1], 1);
46 	fsi = open(argv[1], 0);
47 	if (fso < 0 || fsi < 0) {
48 		perror(argv[1]);
49 		exit(1);
50 	}
51 	fs = &sblock;
52 	rdfs(SBLOCK, SBSIZE, (char *)fs);
53 	fscs = (struct csum *)calloc(1, fs->fs_cssize);
54 	for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize)
55 		rdfs(fsbtodb(fs, fs->fs_csaddr + numfrags(fs, i)),
56 			(int)(fs->fs_cssize - i < fs->fs_bsize ?
57 			    fs->fs_cssize - i : fs->fs_bsize),
58 			((char *)fscs) + i);
59 	proto = fopen(argv[2], "r");
60 	descend((struct inode *)0);
61 	wtfs(SBLOCK, SBSIZE, (char *)fs);
62 	for (i = 0; i < fs->fs_cssize; i += fs->fs_bsize)
63 		wtfs(fsbtodb(&sblock, fs->fs_csaddr + numfrags(&sblock, i)),
64 			(int)(fs->fs_cssize - i < fs->fs_bsize ?
65 			    fs->fs_cssize - i : fs->fs_bsize),
66 			((char *)fscs) + i);
67 	exit(errs);
68 }
69 
70 descend(par)
71 	struct inode *par;
72 {
73 	struct inode in;
74 	int ibc = 0;
75 	int i, f, c;
76 	struct dinode *dip, inos[MAXBSIZE / sizeof (struct dinode)];
77 	daddr_t ib[MAXBSIZE / sizeof (daddr_t)];
78 	char buf[MAXBSIZE];
79 
80 	getstr();
81 	in.i_mode = gmode(token[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
82 	in.i_mode |= gmode(token[1], "-u", 0, ISUID, 0, 0);
83 	in.i_mode |= gmode(token[2], "-g", 0, ISGID, 0, 0);
84 	for (i = 3; i < 6; i++) {
85 		c = token[i];
86 		if (c < '0' || c > '7') {
87 			printf("%c/%s: bad octal mode digit\n", c, token);
88 			errs++;
89 			c = 0;
90 		}
91 		in.i_mode |= (c-'0')<<(15-3*i);
92 	}
93 	in.i_uid = getnum(); in.i_gid = getnum();
94 	for (i = 0; i < fs->fs_bsize; i++)
95 		buf[i] = 0;
96 	for (i = 0; i < NINDIR(fs); i++)
97 		ib[i] = (daddr_t)0;
98 	in.i_nlink = 1;
99 	in.i_size = 0;
100 	for (i = 0; i < NDADDR; i++)
101 		in.i_db[i] = (daddr_t)0;
102 	for (i = 0; i < NIADDR; i++)
103 		in.i_ib[i] = (daddr_t)0;
104 	if (par != (struct inode *)0) {
105 		ialloc(&in);
106 	} else {
107 		par = &in;
108 		i = itod(fs, ROOTINO);
109 		rdfs(fsbtodb(fs, i), fs->fs_bsize, (char *)inos);
110 		dip = &inos[ROOTINO % INOPB(fs)];
111 		in.i_number = ROOTINO;
112 		in.i_nlink = dip->di_nlink;
113 		in.i_size = dip->di_size;
114 		in.i_db[0] = dip->di_db[0];
115 		rdfs(fsbtodb(fs, in.i_db[0]), fs->fs_bsize, buf);
116 	}
117 
118 	switch (in.i_mode&IFMT) {
119 
120 	case IFREG:
121 		getstr();
122 		f = open(token, 0);
123 		if (f < 0) {
124 			printf("%s: cannot open\n", token);
125 			errs++;
126 			break;
127 		}
128 		while ((i = read(f, buf, (int)fs->fs_bsize)) > 0) {
129 			in.i_size += i;
130 			newblk(buf, &ibc, ib, (int)blksize(fs, &in, ibc));
131 		}
132 		close(f);
133 		break;
134 
135 	case IFBLK:
136 	case IFCHR:
137 		/*
138 		 * special file
139 		 * content is maj/min types
140 		 */
141 
142 		i = getnum() & 0377;
143 		f = getnum() & 0377;
144 		in.i_rdev = (i << 8) | f;
145 		break;
146 
147 	case IFDIR:
148 		/*
149 		 * directory
150 		 * put in extra links
151 		 * call recursively until
152 		 * name of "$" found
153 		 */
154 
155 		if (in.i_number != ROOTINO) {
156 			par->i_nlink++;
157 			in.i_nlink++;
158 			entry(&in, in.i_number, ".", buf);
159 			entry(&in, par->i_number, "..", buf);
160 		}
161 		for (;;) {
162 			getstr();
163 			if (token[0]=='$' && token[1]=='\0')
164 				break;
165 			entry(&in, (ino_t)(ino+1), token, buf);
166 			descend(&in);
167 		}
168 		if (in.i_number != ROOTINO)
169 			newblk(buf, &ibc, ib, (int)blksize(fs, &in, 0));
170 		else
171 			wtfs(fsbtodb(fs, in.i_db[0]), (int)fs->fs_bsize, buf);
172 		break;
173 	}
174 	iput(&in, &ibc, ib);
175 }
176 
177 /*ARGSUSED*/
178 gmode(c, s, m0, m1, m2, m3)
179 	char c, *s;
180 {
181 	int i;
182 
183 	for (i = 0; s[i]; i++)
184 		if (c == s[i])
185 			return((&m0)[i]);
186 	printf("%c/%s: bad mode\n", c, token);
187 	errs++;
188 	return(0);
189 }
190 
191 long
192 getnum()
193 {
194 	int i, c;
195 	long n;
196 
197 	getstr();
198 	n = 0;
199 	i = 0;
200 	for (i = 0; c=token[i]; i++) {
201 		if (c<'0' || c>'9') {
202 			printf("%s: bad number\n", token);
203 			errs++;
204 			return((long)0);
205 		}
206 		n = n*10 + (c-'0');
207 	}
208 	return(n);
209 }
210 
211 getstr()
212 {
213 	int i, c;
214 
215 loop:
216 	switch (c = getc(proto)) {
217 
218 	case ' ':
219 	case '\t':
220 	case '\n':
221 		goto loop;
222 
223 	case EOF:
224 		printf("Unexpected EOF\n");
225 		exit(1);
226 
227 	case ':':
228 		while (getc(proto) != '\n')
229 			;
230 		goto loop;
231 
232 	}
233 	i = 0;
234 	do {
235 		token[i++] = c;
236 		c = getc(proto);
237 	} while (c != ' ' && c != '\t' && c != '\n' && c != '\0');
238 	token[i] = 0;
239 }
240 
241 entry(ip, inum, str, buf)
242 	struct inode *ip;
243 	ino_t inum;
244 	char *str;
245 	char *buf;
246 {
247 	register struct direct *dp, *odp;
248 	int oldsize, newsize, spacefree;
249 
250 	odp = dp = (struct direct *)buf;
251 	while ((int)dp - (int)buf < ip->i_size) {
252 		odp = dp;
253 		dp = (struct direct *)((int)dp + dp->d_reclen);
254 	}
255 	if (odp != dp)
256 		oldsize = DIRSIZ(odp);
257 	else
258 		oldsize = 0;
259 	spacefree = odp->d_reclen - oldsize;
260 	dp = (struct direct *)((int)odp + oldsize);
261 	dp->d_ino = inum;
262 	dp->d_namlen = strlen(str);
263 	newsize = DIRSIZ(dp);
264 	if (spacefree >= newsize) {
265 		odp->d_reclen = oldsize;
266 		dp->d_reclen = spacefree;
267 	} else {
268 		dp = (struct direct *)((int)odp + odp->d_reclen);
269 		if ((int)dp - (int)buf >= fs->fs_bsize) {
270 			printf("directory too large\n");
271 			exit(1);
272 		}
273 		dp->d_ino = inum;
274 		dp->d_namlen = strlen(str);
275 		dp->d_reclen = DIRBLKSIZ;
276 	}
277 	strcpy(dp->d_name, str);
278 	ip->i_size = (int)dp - (int)buf + newsize;
279 }
280 
281 newblk(buf, aibc, ib, size)
282 	int *aibc;
283 	char *buf;
284 	daddr_t *ib;
285 	int size;
286 {
287 	int i;
288 	daddr_t bno;
289 
290 	bno = alloc(size);
291 	wtfs(fsbtodb(fs, bno), (int)fs->fs_bsize, buf);
292 	for (i = 0; i < fs->fs_bsize; i++)
293 		buf[i] = 0;
294 	ib[(*aibc)++] = bno;
295 	if (*aibc >= NINDIR(fs)) {
296 		printf("indirect block full\n");
297 		errs++;
298 		*aibc = 0;
299 	}
300 }
301 
302 iput(ip, aibc, ib)
303 	struct inode *ip;
304 	int *aibc;
305 	daddr_t *ib;
306 {
307 	daddr_t d;
308 	int i;
309 	struct dinode buf[MAXBSIZE / sizeof (struct dinode)];
310 
311 	ip->i_atime = ip->i_mtime = ip->i_ctime = time((long *)0);
312 	switch (ip->i_mode&IFMT) {
313 
314 	case IFDIR:
315 	case IFREG:
316 		for (i = 0; i < *aibc; i++) {
317 			if (i >= NDADDR)
318 				break;
319 			ip->i_db[i] = ib[i];
320 		}
321 		if (*aibc > NDADDR) {
322 			ip->i_ib[0] = alloc((int)fs->fs_bsize);
323 			for (i = 0; i < NINDIR(fs) - NDADDR; i++) {
324 				ib[i] = ib[i+NDADDR];
325 				ib[i+NDADDR] = (daddr_t)0;
326 			}
327 			wtfs(fsbtodb(fs, ip->i_ib[0]),
328 			    (int)fs->fs_bsize, (char *)ib);
329 		}
330 		break;
331 
332 	case IFBLK:
333 	case IFCHR:
334 		break;
335 
336 	default:
337 		printf("bad mode %o\n", ip->i_mode);
338 		exit(1);
339 	}
340 	d = fsbtodb(fs, itod(fs, ip->i_number));
341 	rdfs(d, (int)fs->fs_bsize, (char *)buf);
342 	buf[itoo(fs, ip->i_number)].di_ic = ip->i_ic;
343 	wtfs(d, (int)fs->fs_bsize, (char *)buf);
344 }
345 
346 daddr_t
347 alloc(size)
348 	int size;
349 {
350 	int i, frag;
351 	daddr_t d;
352 	static int cg = 0;
353 
354 again:
355 	rdfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize,
356 	    (char *)&acg);
357 	if (acg.cg_magic != CG_MAGIC) {
358 		printf("cg %d: bad magic number\n", cg);
359 		return (0);
360 	}
361 	if (acg.cg_cs.cs_nbfree == 0) {
362 		cg++;
363 		if (cg >= fs->fs_ncg) {
364 			printf("ran out of space\n");
365 			return (0);
366 		}
367 		goto again;
368 	}
369 	for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
370 		if (isblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag))
371 			goto goth;
372 	printf("internal error: can't find block in cyl %d\n", cg);
373 	return (0);
374 goth:
375 	clrblock(&sblock, (u_char *)acg.cg_free, d / sblock.fs_frag);
376 	acg.cg_cs.cs_nbfree--;
377 	sblock.fs_cstotal.cs_nbfree--;
378 	fscs[cg].cs_nbfree--;
379 	acg.cg_btot[cbtocylno(&sblock, d)]--;
380 	acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--;
381 	if (size != sblock.fs_bsize) {
382 		frag = howmany(size, sblock.fs_fsize);
383 		fscs[cg].cs_nffree += sblock.fs_frag - frag;
384 		sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
385 		acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
386 		acg.cg_frsum[sblock.fs_frag - frag]++;
387 		for (i = frag; i < sblock.fs_frag; i++)
388 			setbit(acg.cg_free, d + i);
389 	}
390 	wtfs(fsbtodb(&sblock, cgtod(&sblock, cg)), (int)sblock.fs_cgsize,
391 	    (char *)&acg);
392 	return (acg.cg_cgx * fs->fs_fpg + d);
393 }
394 
395 /*
396  * Allocate an inode on the disk
397  */
398 ialloc(ip)
399 	register struct inode *ip;
400 {
401 	struct dinode buf[MAXBSIZE / sizeof (struct dinode)];
402 	daddr_t d;
403 	int c;
404 
405 	ip->i_number = ++ino;
406 	c = itog(&sblock, ip->i_number);
407 	rdfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize,
408 	    (char *)&acg);
409 	if (acg.cg_magic != CG_MAGIC) {
410 		printf("cg %d: bad magic number\n", c);
411 		exit(1);
412 	}
413 	if (ip->i_mode & IFDIR) {
414 		acg.cg_cs.cs_ndir++;
415 		sblock.fs_cstotal.cs_ndir++;
416 		fscs[c].cs_ndir++;
417 	}
418 	acg.cg_cs.cs_nifree--;
419 	setbit(acg.cg_iused, ip->i_number);
420 	wtfs(fsbtodb(&sblock, cgtod(&sblock, c)), (int)sblock.fs_cgsize,
421 	    (char *)&acg);
422 	sblock.fs_cstotal.cs_nifree--;
423 	fscs[c].cs_nifree--;
424 	if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
425 		printf("fsinit: inode value out of range (%d).\n",
426 		    ip->i_number);
427 		exit(1);
428 	}
429 	return (ip->i_number);
430 }
431 
432 /*
433  * read a block from the file system
434  */
435 rdfs(bno, size, bf)
436 	int bno, size;
437 	char *bf;
438 {
439 	int n;
440 
441 	if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) {
442 		printf("seek error: %ld\n", bno);
443 		perror("rdfs");
444 		exit(1);
445 	}
446 	n = read(fsi, bf, size);
447 	if(n != size) {
448 		printf("read error: %ld\n", bno);
449 		perror("rdfs");
450 		exit(1);
451 	}
452 }
453 
454 /*
455  * write a block to the file system
456  */
457 wtfs(bno, size, bf)
458 	int bno, size;
459 	char *bf;
460 {
461 	int n;
462 
463 	lseek(fso, bno * DEV_BSIZE, 0);
464 	if (lseek(fso, bno * DEV_BSIZE, 0) < 0) {
465 		printf("seek error: %ld\n", bno);
466 		perror("wtfs");
467 		exit(1);
468 	}
469 	n = write(fso, bf, size);
470 	if(n != size) {
471 		printf("write error: %D\n", bno);
472 		perror("wtfs");
473 		exit(1);
474 	}
475 }
476 /*
477  * check if a block is available
478  */
479 isblock(fs, cp, h)
480 	struct fs *fs;
481 	unsigned char *cp;
482 	int h;
483 {
484 	unsigned char mask;
485 
486 	switch (fs->fs_frag) {
487 	case 8:
488 		return (cp[h] == 0xff);
489 	case 4:
490 		mask = 0x0f << ((h & 0x1) << 2);
491 		return ((cp[h >> 1] & mask) == mask);
492 	case 2:
493 		mask = 0x03 << ((h & 0x3) << 1);
494 		return ((cp[h >> 2] & mask) == mask);
495 	case 1:
496 		mask = 0x01 << (h & 0x7);
497 		return ((cp[h >> 3] & mask) == mask);
498 	default:
499 		fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
500 		return (0);
501 	}
502 	/*NOTREACHED*/
503 }
504 
505 /*
506  * take a block out of the map
507  */
508 clrblock(fs, cp, h)
509 	struct fs *fs;
510 	unsigned char *cp;
511 	int h;
512 {
513 	switch ((fs)->fs_frag) {
514 	case 8:
515 		cp[h] = 0;
516 		return;
517 	case 4:
518 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
519 		return;
520 	case 2:
521 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
522 		return;
523 	case 1:
524 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
525 		return;
526 	default:
527 		fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
528 		return;
529 	}
530 }
531 
532