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