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