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