Commit | Line | Data |
---|---|---|
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 | |
8 | char 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 | 14 | static 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 | ||
27 | union { | |
28 | struct fs fs; | |
29 | char fsx[SBSIZE]; | |
30 | } ufs; | |
31 | #define sblock ufs.fs | |
32 | union { | |
33 | struct cg cg; | |
34 | char cgx[MAXBSIZE]; | |
35 | } ucg; | |
36 | #define acg ucg.cg | |
37 | struct fs *fs; | |
38 | struct csum *fscs; | |
39 | int fso, fsi; | |
40 | FILE *proto; | |
41 | char token[BUFSIZ]; | |
42 | int errs; | |
a66ab591 | 43 | long dev_bsize = 1; |
86c6257f KM |
44 | int ino = 10; |
45 | long getnum(); | |
46 | char *strcpy(); | |
47 | ||
48 | main(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 | ||
84 | descend(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 = ∈ | |
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*/ | |
192 | gmode(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 | ||
205 | long | |
206 | getnum() | |
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 | ||
225 | getstr() | |
226 | { | |
227 | int i, c; | |
228 | ||
229 | loop: | |
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 | ||
255 | entry(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 | ||
295 | newblk(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 | ||
316 | iput(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 | ||
360 | daddr_t | |
361 | alloc(size) | |
362 | int size; | |
363 | { | |
364 | int i, frag; | |
365 | daddr_t d; | |
366 | static int cg = 0; | |
367 | ||
368 | again: | |
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); | |
388 | goth: | |
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 | */ | |
412 | ialloc(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 | */ | |
449 | rdfs(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 | */ | |
471 | wtfs(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 | */ | |
492 | isblock(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 | */ | |
521 | clrblock(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 |