declare getpwnam in recipient.c for earlier systems
[unix-history] / usr / src / usr.sbin / mkproto / mkproto.c
CommitLineData
524aa063
SL
1#ifndef lint
2static char sccsid[] = "@(#)mkproto.c 4.4 (Berkeley) %G%";
3#endif
86c6257f
KM
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
15union {
16 struct fs fs;
17 char fsx[SBSIZE];
18} ufs;
19#define sblock ufs.fs
20union {
21 struct cg cg;
22 char cgx[MAXBSIZE];
23} ucg;
24#define acg ucg.cg
25struct fs *fs;
26struct csum *fscs;
27int fso, fsi;
28FILE *proto;
29char token[BUFSIZ];
30int errs;
31int ino = 10;
32long getnum();
33char *strcpy();
34
35main(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
70descend(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;
11f47f73 144 in.i_rdev = (i << 8) | f;
86c6257f
KM
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*/
178gmode(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
191long
192getnum()
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
211getstr()
212{
213 int i, c;
214
215loop:
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
241entry(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;
e84afc49 248 int oldsize, newsize, spacefree;
86c6257f
KM
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;
e84afc49 259 spacefree = odp->d_reclen - oldsize;
86c6257f
KM
260 dp = (struct direct *)((int)odp + oldsize);
261 dp->d_ino = inum;
262 dp->d_namlen = strlen(str);
263 newsize = DIRSIZ(dp);
e84afc49 264 if (spacefree >= newsize) {
86c6257f 265 odp->d_reclen = oldsize;
e84afc49 266 dp->d_reclen = spacefree;
86c6257f
KM
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
281newblk(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
302iput(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
346daddr_t
347alloc(size)
348 int size;
349{
350 int i, frag;
351 daddr_t d;
352 static int cg = 0;
353
354again:
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);
374goth:
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 */
398ialloc(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 */
435rdfs(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 */
457wtfs(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 */
479isblock(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 */
508clrblock(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