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