Commit | Line | Data |
---|---|---|
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 | |
9 | char 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 | 15 | static 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 | |
29 | union { | |
30 | struct fs fs; | |
31 | char fsx[SBSIZE]; | |
32 | } ufs; | |
33 | #define sblock ufs.fs | |
34 | union { | |
35 | struct cg cg; | |
36 | char cgx[MAXBSIZE]; | |
37 | } ucg; | |
38 | #define acg ucg.cg | |
39 | struct fs *fs; | |
40 | struct csum *fscs; | |
41 | int fso, fsi; | |
42 | FILE *proto; | |
43 | char token[BUFSIZ]; | |
44 | int errs; | |
a66ab591 | 45 | long dev_bsize = 1; |
86c6257f KM |
46 | int ino = 10; |
47 | long getnum(); | |
48 | char *strcpy(); | |
3fa588b9 | 49 | ino_t ialloc(); |
86c6257f KM |
50 | |
51 | main(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 |
88 | descend(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 = ∈ | |
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*/ | |
198 | gmode(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 | ||
211 | long | |
212 | getnum() | |
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 | ||
231 | getstr() | |
232 | { | |
233 | int i, c; | |
234 | ||
235 | loop: | |
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 | ||
261 | entry(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 | ||
301 | newblk(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 |
322 | iput(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 | ||
368 | daddr_t | |
369 | alloc(size) | |
370 | int size; | |
371 | { | |
372 | int i, frag; | |
373 | daddr_t d; | |
374 | static int cg = 0; | |
375 | ||
376 | again: | |
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); | |
397 | goth: | |
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 | 421 | ino_t |
86c6257f | 422 | ialloc(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 | */ | |
457 | rdfs(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 | */ | |
480 | wtfs(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 | */ | |
502 | isblock(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 | */ | |
531 | clrblock(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 |