Commit | Line | Data |
---|---|---|
0947395d | 1 | static char *sccsid = "@(#)mkfs.c 1.9 (Berkeley) %G%"; |
d746d022 KM |
2 | |
3 | /* | |
4 | * make file system for cylinder-group style file systems | |
5 | * | |
6 | * usage: mkfs fs proto | |
7 | * or: mkfs size [ nsect ntrak cpg ] | |
8 | */ | |
9 | ||
10 | #define NDIRECT (BSIZE/sizeof(struct direct)) | |
11 | #define MAXFN 500 | |
12 | ||
d746d022 KM |
13 | #ifndef STANDALONE |
14 | #include <stdio.h> | |
15 | #include <a.out.h> | |
16 | #endif | |
17 | ||
18 | #include "../h/param.h" | |
d746d022 KM |
19 | #include "../h/inode.h" |
20 | #include "../h/fs.h" | |
21 | #include "../h/dir.h" | |
22 | ||
23 | time_t utime; | |
24 | ||
25 | #ifndef STANDALONE | |
26 | FILE *fin; | |
27 | #else | |
28 | int fin; | |
29 | #endif | |
30 | ||
31 | int fsi; | |
32 | int fso; | |
33 | char *charp; | |
34 | char buf[BSIZE]; | |
35 | #ifndef STANDALONE | |
36 | struct exec head; | |
37 | #endif | |
38 | char string[50]; | |
39 | ||
40 | union { | |
41 | struct fs fs; | |
42 | char pad[BSIZE]; | |
43 | } fsun; | |
44 | #define sblock fsun.fs | |
45 | struct csum *fscs; | |
46 | ||
47 | union { | |
48 | struct cg cg; | |
49 | char pad[BSIZE]; | |
50 | } cgun; | |
51 | #define acg cgun.cg | |
52 | ||
53 | #define howmany(x, y) (((x)+((y)-1))/(y)) | |
54 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | |
55 | ||
56 | char *fsys; | |
57 | char *proto; | |
58 | int error; | |
59 | ino_t ino = ROOTINO - 1; | |
60 | long getnum(); | |
61 | daddr_t alloc(); | |
62 | ||
63 | struct dinode zino[MAXIPG]; | |
64 | ||
65 | main(argc, argv) | |
66 | char *argv[]; | |
67 | { | |
68 | int f, c; | |
69 | long i,n; | |
70 | ||
71 | argc--, argv++; | |
72 | #ifndef STANDALONE | |
73 | time(&utime); | |
74 | if(argc < 2) { | |
75 | printf("usage: mkfs sblock proto/size [ nsect ntrak cpg ]\n"); | |
76 | exit(1); | |
77 | } | |
78 | fsys = argv[0]; | |
79 | proto = argv[1]; | |
80 | #else | |
81 | { | |
82 | static char protos[60]; | |
83 | ||
84 | printf("file sys size: "); | |
85 | gets(protos); | |
86 | proto = protos; | |
87 | } | |
88 | #endif | |
89 | #ifdef STANDALONE | |
90 | { | |
91 | char fsbuf[100]; | |
92 | ||
93 | do { | |
94 | printf("file system: "); | |
95 | gets(fsbuf); | |
96 | fso = open(fsbuf, 1); | |
97 | fsi = open(fsbuf, 0); | |
98 | } while (fso < 0 || fsi < 0); | |
99 | } | |
100 | fin = NULL; | |
101 | argc = 0; | |
102 | #else | |
103 | fso = creat(fsys, 0666); | |
104 | if(fso < 0) { | |
105 | printf("%s: cannot create\n", fsys); | |
106 | exit(1); | |
107 | } | |
108 | fsi = open(fsys, 0); | |
109 | if(fsi < 0) { | |
110 | printf("%s: cannot open\n", fsys); | |
111 | exit(1); | |
112 | } | |
113 | fin = fopen(proto, "r"); | |
114 | #endif | |
115 | #ifndef STANDALONE | |
116 | if (fin != NULL) { | |
117 | getstr(); | |
118 | f = open(string, 0); | |
119 | if (f < 0) { | |
120 | printf("%s: cannot open init\n", string); | |
121 | goto noinit; | |
122 | } | |
123 | read(f, (char *)&head, sizeof head); | |
124 | c = head.a_text + head.a_data; | |
125 | if (c > BSIZE) | |
126 | printf("%s: too big\n", string); | |
127 | else { | |
128 | read(f, buf, c); | |
129 | wtfs(BBLOCK, BSIZE, buf); | |
130 | } | |
131 | close(f); | |
132 | noinit: | |
133 | n = sblock.fs_size = getnum(); | |
134 | sblock.fs_ntrak = getnum(); | |
135 | sblock.fs_nsect = getnum(); | |
136 | sblock.fs_cpg = getnum(); | |
137 | } else | |
138 | #endif | |
139 | { | |
140 | charp = "d--777 0 0 $ "; | |
141 | n = 0; | |
142 | for (f=0; c=proto[f]; f++) { | |
143 | if (c<'0' || c>'9') { | |
144 | printf("%s: cannot open\n", proto); | |
145 | exit(1); | |
146 | } | |
147 | n = n*10 + (c-'0'); | |
148 | } | |
149 | sblock.fs_size = n; | |
150 | if (argc > 2) | |
151 | sblock.fs_nsect = atoi(argv[2]); | |
152 | else | |
153 | sblock.fs_nsect = 32; | |
154 | if (argc > 3) | |
155 | sblock.fs_ntrak = atoi(argv[3]); | |
156 | else | |
157 | sblock.fs_ntrak = 19; | |
158 | } | |
159 | /* | |
160 | * Now have size for file system and nsect and ntrak. | |
161 | * (And, if coming from prototype, cpg). | |
162 | * Determine number of cylinders occupied by file system. | |
163 | */ | |
164 | if (sblock.fs_ntrak <= 0) | |
165 | printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); | |
166 | if (sblock.fs_nsect <= 0) | |
167 | printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); | |
168 | if (sblock.fs_size <= 0) | |
169 | printf("preposterous size %d\n", sblock.fs_size), exit(1); | |
170 | if (sblock.fs_ntrak * sblock.fs_nsect > MAXBPG * NSPB) { | |
171 | printf("cylinder too large (%d sectors)\n", | |
172 | sblock.fs_ntrak * sblock.fs_nsect); | |
173 | printf("maximum cylinder size: %d sectors\n", | |
174 | MAXBPG * NSPB); | |
175 | exit(1); | |
176 | } | |
177 | sblock.fs_ncyl = n * NSPF / (sblock.fs_nsect * sblock.fs_ntrak); | |
178 | if (n * NSPF > sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak) { | |
179 | printf("%d sector(s) in last cylinder unused\n", | |
180 | n * NSPF - sblock.fs_ncyl * sblock.fs_nsect * sblock.fs_ntrak); | |
181 | sblock.fs_ncyl++; | |
182 | } | |
183 | sblock.fs_magic = FS_MAGIC; | |
184 | /* | |
185 | * Validate specified/determined cpg. | |
186 | */ | |
187 | #define CGTOOBIG(fs) ((fs).fs_nsect*(fs).fs_ntrak*(fs).fs_cpg/NSPB > MAXBPG) | |
188 | if (argc > 4 || fin) { | |
189 | if (fin == NULL) | |
190 | sblock.fs_cpg = atoi(argv[4]); | |
191 | if (CGTOOBIG(sblock)) { | |
192 | printf("cylinder group too large (%d blocks); ", | |
193 | sblock.fs_cpg * sblock.fs_nsect * sblock.fs_ntrak / NSPB); | |
194 | printf("max: %d blocks\n", MAXBPG); | |
195 | exit(1); | |
196 | } | |
197 | if (sblock.fs_cpg > MAXCPG) { | |
198 | printf("cylinder groups are limited to %d cylinders\n", | |
199 | MAXCPG); | |
200 | exit(1); | |
201 | } | |
202 | } else { | |
203 | sblock.fs_cpg = DESCPG; | |
204 | while (CGTOOBIG(sblock)) | |
205 | --sblock.fs_cpg; | |
206 | } | |
207 | /* | |
208 | * Compute/validate number of cylinder groups. | |
209 | */ | |
210 | sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; | |
211 | if (sblock.fs_ncyl % sblock.fs_cpg) | |
212 | sblock.fs_ncg++; | |
213 | if ((sblock.fs_nsect*sblock.fs_ntrak*sblock.fs_cpg) % NSPF) { | |
214 | printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", | |
215 | sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); | |
216 | printf("as this would would have cyl groups whose size\n"); | |
217 | printf("is not a multiple of %d; choke!\n", FSIZE); | |
218 | exit(1); | |
219 | } | |
220 | fscs = (struct csum *) | |
221 | calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE)); | |
222 | /* | |
223 | * Compute number of inode blocks per cylinder group. | |
224 | * Start with one inode per NBPI bytes; adjust as necessary. | |
225 | */ | |
226 | n = ((n * BSIZE) / NBPI) / INOPB; | |
227 | if (n <= 0) | |
228 | n = 1; | |
229 | if (n > 65500/INOPB) | |
230 | n = 65500/INOPB; | |
231 | sblock.fs_ipg = ((n / sblock.fs_ncg) + 1) * INOPB; | |
232 | if (sblock.fs_ipg < INOPB) | |
233 | sblock.fs_ipg = INOPB; | |
234 | if (sblock.fs_ipg > MAXIPG) | |
235 | sblock.fs_ipg = MAXIPG; | |
236 | while (sblock.fs_ipg * sblock.fs_ncyl > 65500) | |
237 | sblock.fs_ipg -= INOPB; | |
238 | sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; | |
239 | sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / (FSIZE / 512); | |
240 | if (cgdmin(0,&sblock) >= sblock.fs_fpg) | |
241 | printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", | |
242 | cgdmin(0,&sblock)/FRAG, sblock.fs_fpg/FRAG), exit(1); | |
0947395d | 243 | sblock.fs_cstotal.cs_nifree = sblock.fs_ipg * sblock.fs_ncg; |
d746d022 KM |
244 | sblock.fs_cgsize = cgsize(&sblock); |
245 | sblock.fs_cssize = cssize(&sblock); | |
246 | sblock.fs_sblkno = SBLOCK; | |
247 | sblock.fs_fmod = 0; | |
248 | sblock.fs_ronly = 0; | |
249 | ||
250 | /* | |
251 | * Dump out information about file system. | |
252 | */ | |
253 | printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", | |
254 | fsys, sblock.fs_size*NSPF, sblock.fs_ncyl, sblock.fs_ntrak, sblock.fs_nsect); | |
255 | printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", | |
256 | (float)sblock.fs_size*FSIZE*1e-6, sblock.fs_ncg, sblock.fs_cpg, | |
257 | (float)sblock.fs_fpg*FSIZE*1e-6, sblock.fs_ipg); | |
258 | /* | |
259 | printf("%7d size (%d blocks)\n", sblock.fs_size, sblock.fs_size/FRAG); | |
260 | printf("%7d cylinder groups\n", sblock.fs_ncg); | |
261 | printf("%7d cylinder group block size\n", sblock.fs_cgsize); | |
262 | printf("%7d tracks\n", sblock.fs_ntrak); | |
263 | printf("%7d sectors\n", sblock.fs_nsect); | |
264 | printf("%7d sectors per cylinder\n", sblock.fs_spc); | |
265 | printf("%7d cylinders\n", sblock.fs_ncyl); | |
266 | printf("%7d cylinders per group\n", sblock.fs_cpg); | |
267 | printf("%7d blocks per group\n", sblock.fs_fpg/FRAG); | |
268 | printf("%7d inodes per group\n", sblock.fs_ipg); | |
269 | if (sblock.fs_ncyl % sblock.fs_cpg) { | |
270 | printf("%7d cylinders in last group\n", | |
271 | i = sblock.fs_ncyl % sblock.fs_cpg); | |
272 | printf("%7d blocks in last group\n", | |
273 | i * sblock.fs_spc / NSPB); | |
274 | } | |
275 | */ | |
276 | /* | |
277 | * Now build the cylinders group blocks and | |
278 | * then print out indices of cylinder groups forwarded | |
279 | * past bad blocks or other obstructions. | |
280 | */ | |
0947395d KM |
281 | sblock.fs_cstotal.cs_ndir = 0; |
282 | sblock.fs_cstotal.cs_nbfree = 0; | |
283 | sblock.fs_cstotal.cs_nifree = 0; | |
284 | sblock.fs_cstotal.cs_nffree = 0; | |
743f1ef7 KM |
285 | sblock.fs_cgrotor = 0; |
286 | for (i = 0; i < NRPOS; i++) | |
287 | sblock.fs_postbl[i] = -1; | |
288 | for (i = 0; i < sblock.fs_spc; i += (NSPF * FRAG)) | |
289 | /* void */; | |
290 | for (i -= (NSPF * FRAG); i >= 0; i -= (NSPF * FRAG)) { | |
291 | c = i % sblock.fs_nsect * NRPOS / sblock.fs_nsect; | |
292 | sblock.fs_rotbl[i / (NSPF * FRAG)] = sblock.fs_postbl[c]; | |
293 | sblock.fs_postbl[c] = i / (NSPF * FRAG); | |
294 | } | |
d746d022 KM |
295 | for (c = 0; c < sblock.fs_ncg; c++) |
296 | initcg(c); | |
297 | printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n", | |
298 | SBLOCK, sblock.fs_fpg, SBLOCK+sblock.fs_fpg, | |
299 | SBLOCK+(sblock.fs_ncg-1)*sblock.fs_fpg); | |
300 | /* | |
301 | * Now construct the initial file system, and | |
302 | * then write out the super-block. | |
303 | */ | |
304 | cfile((struct inode *)0); | |
305 | sblock.fs_time = utime; | |
306 | wtfs(SBLOCK, BSIZE, (char *)&sblock); | |
307 | for (i = 0; i < cssize(&sblock); i += BSIZE) | |
308 | wtfs(csaddr(&sblock) + i/BSIZE, BSIZE, ((char *)fscs)+i); | |
309 | for (c = 0; c < sblock.fs_ncg; c++) | |
310 | wtfs(cgsblock(c, &sblock), BSIZE, (char *)&sblock); | |
311 | #ifndef STANDALONE | |
312 | exit(error); | |
313 | #endif | |
314 | } | |
315 | ||
316 | /* | |
317 | * Initialize a cylinder group. | |
318 | */ | |
319 | initcg(c) | |
320 | int c; | |
321 | { | |
322 | daddr_t cbase, d, dmin, dmax; | |
323 | long i, j, s; | |
324 | register struct csum *cs; | |
325 | ||
326 | /* | |
327 | * Determine block bounds for cylinder group. | |
328 | * Allow space for super block summary information in first | |
329 | * cylinder group. | |
330 | */ | |
331 | cbase = cgbase(c,&sblock); | |
332 | dmax = cbase + sblock.fs_fpg; | |
333 | if (dmax > sblock.fs_size) | |
334 | dmax = sblock.fs_size; | |
f3c028b7 | 335 | dmin = cgdmin(c,&sblock) - cbase; |
d746d022 KM |
336 | d = cbase; |
337 | cs = fscs+c; | |
d746d022 KM |
338 | acg.cg_time = utime; |
339 | acg.cg_magic = CG_MAGIC; | |
340 | acg.cg_cgx = c; | |
341 | acg.cg_ncyl = sblock.fs_cpg; | |
342 | acg.cg_niblk = sblock.fs_ipg; | |
343 | acg.cg_ndblk = dmax - cbase; | |
0947395d KM |
344 | acg.cg_cs.cs_ndir = 0; |
345 | acg.cg_cs.cs_nffree = 0; | |
346 | acg.cg_cs.cs_nbfree = 0; | |
347 | acg.cg_cs.cs_nifree = 0; | |
f3c028b7 KM |
348 | acg.cg_rotor = dmin; |
349 | acg.cg_frotor = dmin; | |
92ea6158 | 350 | acg.cg_irotor = 0; |
f3c028b7 KM |
351 | for (i = 0; i < FRAG; i++) { |
352 | acg.cg_frsum[i] = 0; | |
353 | } | |
354 | for (i = 0; i < sblock.fs_ipg; ) { | |
d746d022 KM |
355 | for (j = INOPB; j > 0; j--) { |
356 | clrbit(acg.cg_iused, i); | |
357 | i++; | |
358 | } | |
0947395d | 359 | acg.cg_cs.cs_nifree += INOPB; |
d746d022 KM |
360 | } |
361 | while (i < MAXIPG) { | |
362 | clrbit(acg.cg_iused, i); | |
363 | i++; | |
364 | } | |
365 | lseek(fso, cgimin(c,&sblock)*FSIZE, 0); | |
366 | if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) != | |
367 | sblock.fs_ipg * sizeof (struct dinode)) | |
368 | printf("write error %D\n", tell(fso) / BSIZE); | |
369 | for (i = 0; i < MAXCPG; i++) | |
370 | for (j = 0; j < NRPOS; j++) | |
371 | acg.cg_b[i][j] = 0; | |
d746d022 KM |
372 | if (c == 0) { |
373 | dmin += howmany(cssize(&sblock), BSIZE) * FRAG; | |
374 | } | |
375 | for (d = 0; d < dmin; d += FRAG) | |
376 | clrblock(acg.cg_free, d/FRAG); | |
377 | while ((d+FRAG) <= dmax - cbase) { | |
56d45dcd | 378 | setblock(acg.cg_free, d/FRAG); |
0947395d | 379 | acg.cg_cs.cs_nbfree++; |
56d45dcd KM |
380 | s = d * NSPF; |
381 | acg.cg_b[s/sblock.fs_spc] | |
382 | [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; | |
d746d022 KM |
383 | d += FRAG; |
384 | } | |
385 | if (d < dmax - cbase) | |
56d45dcd KM |
386 | for (; d < dmax - cbase; d++) { |
387 | setbit(acg.cg_free, d); | |
0947395d | 388 | acg.cg_cs.cs_nffree++; |
56d45dcd | 389 | } |
d746d022 KM |
390 | for (; d < MAXBPG; d++) |
391 | clrbit(acg.cg_free, d); | |
0947395d KM |
392 | sblock.fs_dsize += acg.cg_ndblk - dmin; |
393 | sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; | |
394 | sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; | |
395 | sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; | |
396 | sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; | |
397 | *cs = acg.cg_cs; | |
d746d022 KM |
398 | wtfs(cgtod(c, &sblock), BSIZE, (char *)&acg); |
399 | } | |
400 | ||
401 | cfile(par) | |
402 | struct inode *par; | |
403 | { | |
404 | struct inode in; | |
405 | int dbc, ibc; | |
406 | char db[BSIZE]; | |
407 | daddr_t ib[NINDIR]; | |
408 | int i, f, c; | |
409 | ||
410 | /* | |
411 | * get mode, uid and gid | |
412 | */ | |
413 | ||
414 | getstr(); | |
415 | in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR); | |
416 | in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0); | |
417 | in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0); | |
418 | for(i=3; i<6; i++) { | |
419 | c = string[i]; | |
420 | if(c<'0' || c>'7') { | |
421 | printf("%c/%s: bad octal mode digit\n", c, string); | |
422 | error = 1; | |
423 | c = 0; | |
424 | } | |
425 | in.i_mode |= (c-'0')<<(15-3*i); | |
426 | } | |
427 | in.i_uid = getnum(); | |
428 | in.i_gid = getnum(); | |
56d45dcd KM |
429 | in.i_atime = utime; |
430 | in.i_mtime = utime; | |
431 | in.i_ctime = utime; | |
d746d022 KM |
432 | |
433 | /* | |
434 | * general initialization prior to | |
435 | * switching on format | |
436 | */ | |
437 | ||
438 | ino++; | |
439 | in.i_number = ino; | |
440 | for(i=0; i<BSIZE; i++) | |
441 | db[i] = 0; | |
442 | for(i=0; i<NINDIR; i++) | |
443 | ib[i] = (daddr_t)0; | |
444 | in.i_nlink = 1; | |
445 | in.i_size = 0; | |
446 | for(i=0; i<NDADDR; i++) | |
56d45dcd | 447 | in.i_db[i] = (daddr_t)0; |
d746d022 | 448 | for(i=0; i<NIADDR; i++) |
56d45dcd | 449 | in.i_ib[i] = (daddr_t)0; |
d746d022 KM |
450 | if(par == (struct inode *)0) { |
451 | par = ∈ | |
452 | in.i_nlink--; | |
453 | } | |
454 | dbc = 0; | |
455 | ibc = 0; | |
456 | switch(in.i_mode&IFMT) { | |
457 | ||
458 | case IFREG: | |
459 | /* | |
460 | * regular file | |
461 | * contents is a file name | |
462 | */ | |
463 | ||
464 | getstr(); | |
465 | f = open(string, 0); | |
466 | if(f < 0) { | |
467 | printf("%s: cannot open\n", string); | |
468 | error = 1; | |
469 | break; | |
470 | } | |
471 | while((i=read(f, db, BSIZE)) > 0) { | |
472 | in.i_size += i; | |
07670f7d | 473 | newblk(&dbc, db, &ibc, ib, ibc < NDADDR ? i : BSIZE, 0); |
d746d022 KM |
474 | } |
475 | close(f); | |
476 | break; | |
477 | ||
478 | case IFBLK: | |
479 | case IFCHR: | |
480 | /* | |
481 | * special file | |
482 | * content is maj/min types | |
483 | */ | |
484 | ||
485 | i = getnum() & 0377; | |
486 | f = getnum() & 0377; | |
56d45dcd | 487 | in.i_rdev = makedev(i, f); |
d746d022 KM |
488 | break; |
489 | ||
490 | case IFDIR: | |
491 | /* | |
492 | * directory | |
493 | * put in extra links | |
494 | * call recursively until | |
495 | * name of "$" found | |
496 | */ | |
497 | ||
498 | par->i_nlink++; | |
499 | in.i_nlink++; | |
500 | entry(in.i_number, ".", &dbc, db, &ibc, ib); | |
501 | entry(par->i_number, "..", &dbc, db, &ibc, ib); | |
502 | in.i_size = 2*sizeof(struct direct); | |
503 | for(;;) { | |
504 | getstr(); | |
505 | if(string[0]=='$' && string[1]=='\0') | |
506 | break; | |
07670f7d | 507 | if (in.i_size >= BSIZE * NDADDR) { |
d746d022 | 508 | printf("can't handle direct of > %d entries\n", |
07670f7d | 509 | NDIRECT * NDADDR); |
d746d022 KM |
510 | exit(1); |
511 | } | |
512 | entry(ino+1, string, &dbc, db, &ibc, ib); | |
513 | in.i_size += sizeof(struct direct); | |
514 | cfile(&in); | |
515 | } | |
07670f7d | 516 | newblk(&dbc, db, &ibc, ib, roundup(dbc, FSIZE), IFDIR); |
d746d022 KM |
517 | break; |
518 | } | |
d746d022 KM |
519 | iput(&in, &ibc, ib); |
520 | } | |
521 | ||
522 | gmode(c, s, m0, m1, m2, m3) | |
523 | char c, *s; | |
524 | { | |
525 | int i; | |
526 | ||
527 | for(i=0; s[i]; i++) | |
528 | if(c == s[i]) | |
529 | return((&m0)[i]); | |
530 | printf("%c/%s: bad mode\n", c, string); | |
531 | error = 1; | |
532 | return(0); | |
533 | } | |
534 | ||
535 | long | |
536 | getnum() | |
537 | { | |
538 | int i, c; | |
539 | long n; | |
540 | ||
541 | getstr(); | |
542 | n = 0; | |
543 | i = 0; | |
544 | for(i=0; c=string[i]; i++) { | |
545 | if(c<'0' || c>'9') { | |
546 | printf("%s: bad number\n", string); | |
547 | error = 1; | |
548 | return((long)0); | |
549 | } | |
550 | n = n*10 + (c-'0'); | |
551 | } | |
552 | return(n); | |
553 | } | |
554 | ||
555 | getstr() | |
556 | { | |
557 | int i, c; | |
558 | ||
559 | loop: | |
560 | switch(c=getch()) { | |
561 | ||
562 | case ' ': | |
563 | case '\t': | |
564 | case '\n': | |
565 | goto loop; | |
566 | ||
567 | case '\0': | |
568 | printf("EOF\n"); | |
569 | exit(1); | |
570 | ||
571 | case ':': | |
572 | while(getch() != '\n'); | |
573 | goto loop; | |
574 | ||
575 | } | |
576 | i = 0; | |
577 | ||
578 | do { | |
579 | string[i++] = c; | |
580 | c = getch(); | |
581 | } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); | |
582 | string[i] = '\0'; | |
583 | } | |
584 | ||
585 | rdfs(bno, size, bf) | |
586 | daddr_t bno; | |
587 | int size; | |
588 | char *bf; | |
589 | { | |
590 | int n; | |
591 | ||
592 | lseek(fsi, bno*FSIZE, 0); | |
593 | n = read(fsi, bf, size); | |
594 | if(n != size) { | |
595 | printf("read error: %ld\n", bno); | |
596 | exit(1); | |
597 | } | |
598 | } | |
599 | ||
600 | wtfs(bno, size, bf) | |
601 | daddr_t bno; | |
602 | int size; | |
603 | char *bf; | |
604 | { | |
605 | int n; | |
606 | ||
607 | lseek(fso, bno*FSIZE, 0); | |
608 | n = write(fso, bf, size); | |
609 | if(n != size) { | |
610 | printf("write error: %D\n", bno); | |
611 | exit(1); | |
612 | } | |
613 | } | |
614 | ||
615 | daddr_t | |
07670f7d KM |
616 | alloc(size, mode) |
617 | int size; | |
618 | int mode; | |
d746d022 KM |
619 | { |
620 | int c, i, s, frag; | |
621 | daddr_t d; | |
622 | ||
623 | c = 0; | |
624 | rdfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); | |
0947395d | 625 | if (acg.cg_cs.cs_nbfree == 0) { |
d746d022 KM |
626 | printf("first cylinder group ran out of space\n"); |
627 | return (0); | |
628 | } | |
629 | for (d = 0; d < acg.cg_ndblk; d += FRAG) | |
630 | if (isblock(acg.cg_free, d/FRAG)) | |
631 | goto goth; | |
632 | printf("internal error: can't find block in cyl 0\n"); | |
633 | return (0); | |
634 | goth: | |
635 | clrblock(acg.cg_free, d/FRAG); | |
0947395d KM |
636 | acg.cg_cs.cs_nbfree--; |
637 | sblock.fs_cstotal.cs_nbfree--; | |
d746d022 | 638 | fscs[0].cs_nbfree--; |
07670f7d | 639 | if (mode & IFDIR) { |
0947395d KM |
640 | acg.cg_cs.cs_ndir++; |
641 | sblock.fs_cstotal.cs_ndir++; | |
07670f7d KM |
642 | fscs[0].cs_ndir++; |
643 | } | |
d746d022 KM |
644 | s = d * NSPF; |
645 | acg.cg_b[s/sblock.fs_spc][s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]--; | |
646 | if (size != BSIZE) { | |
647 | frag = howmany(size, FSIZE); | |
0947395d KM |
648 | fscs[0].cs_nffree += FRAG - frag; |
649 | sblock.fs_cstotal.cs_nffree += FRAG - frag; | |
650 | acg.cg_cs.cs_nffree += FRAG - frag; | |
f3c028b7 | 651 | acg.cg_frsum[FRAG - frag]++; |
d746d022 KM |
652 | for (i = frag; i < FRAG; i++) |
653 | setbit(acg.cg_free, d+i); | |
654 | } | |
655 | wtfs(cgtod(0,&sblock), sblock.fs_cgsize, (char *)&acg); | |
656 | return (d); | |
657 | } | |
658 | ||
659 | entry(inum, str, adbc, db, aibc, ib) | |
660 | ino_t inum; | |
661 | char *str; | |
662 | int *adbc, *aibc; | |
663 | char *db; | |
664 | daddr_t *ib; | |
665 | { | |
666 | struct direct *dp; | |
667 | int i; | |
668 | ||
07670f7d KM |
669 | if (*adbc == NDIRECT) |
670 | newblk(adbc, db, aibc, ib, BSIZE, 0); | |
d746d022 KM |
671 | dp = (struct direct *)db; |
672 | dp += *adbc; | |
673 | (*adbc)++; | |
674 | dp->d_ino = inum; | |
675 | for(i=0; i<DIRSIZ; i++) | |
676 | dp->d_name[i] = 0; | |
677 | for(i=0; i<DIRSIZ; i++) | |
678 | if((dp->d_name[i] = str[i]) == 0) | |
679 | break; | |
d746d022 KM |
680 | } |
681 | ||
07670f7d KM |
682 | newblk(adbc, db, aibc, ib, size, mode) |
683 | int *adbc, *aibc; | |
684 | char *db; | |
685 | daddr_t *ib; | |
686 | int size; | |
687 | int mode; | |
d746d022 KM |
688 | { |
689 | int i; | |
690 | daddr_t bno; | |
691 | ||
07670f7d | 692 | bno = alloc(size, mode); |
d746d022 KM |
693 | wtfs(bno, size, db); |
694 | for(i=0; i<size; i++) | |
695 | db[i] = 0; | |
696 | *adbc = 0; | |
697 | ib[*aibc] = bno; | |
698 | (*aibc)++; | |
699 | if(*aibc >= NINDIR) { | |
700 | printf("indirect block full\n"); | |
701 | error = 1; | |
702 | *aibc = 0; | |
703 | } | |
704 | } | |
705 | ||
706 | getch() | |
707 | { | |
708 | ||
709 | #ifndef STANDALONE | |
710 | if(charp) | |
711 | #endif | |
712 | return(*charp++); | |
713 | #ifndef STANDALONE | |
714 | return(getc(fin)); | |
715 | #endif | |
716 | } | |
717 | ||
718 | iput(ip, aibc, ib) | |
719 | struct inode *ip; | |
720 | int *aibc; | |
721 | daddr_t *ib; | |
722 | { | |
723 | struct dinode *dp; | |
724 | daddr_t d; | |
725 | int i, c = ip->i_number / sblock.fs_ipg; | |
726 | ||
727 | rdfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); | |
0947395d | 728 | acg.cg_cs.cs_nifree--; |
d746d022 KM |
729 | setbit(acg.cg_iused, ip->i_number); |
730 | wtfs(cgtod(c,&sblock), sblock.fs_cgsize, (char *)&acg); | |
0947395d | 731 | sblock.fs_cstotal.cs_nifree--; |
d746d022 KM |
732 | fscs[0].cs_nifree--; |
733 | if(ip->i_number >= sblock.fs_ipg) { | |
734 | printf("mkfs: cant handle more than one cg of inodes (yet)\n"); | |
735 | exit(1); | |
736 | } | |
737 | if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { | |
738 | if(error == 0) | |
739 | printf("ilist too small\n"); | |
740 | error = 1; | |
741 | return; | |
742 | } | |
743 | d = itod(ip->i_number,&sblock); | |
744 | rdfs(d, BSIZE, buf); | |
56d45dcd KM |
745 | for(i=0; i<*aibc; i++) { |
746 | if(i >= NDADDR) | |
747 | break; | |
748 | ip->i_db[i] = ib[i]; | |
749 | } | |
750 | if(*aibc >= NDADDR) { | |
07670f7d | 751 | ip->i_ib[0] = alloc(BSIZE, 0); |
56d45dcd KM |
752 | for(i=0; i<NINDIR-NDADDR; i++) { |
753 | ib[i] = ib[i+NDADDR]; | |
754 | ib[i+NDADDR] = (daddr_t)0; | |
d746d022 | 755 | } |
56d45dcd | 756 | wtfs(ip->i_ib[0], (char *)ib); |
d746d022 | 757 | } |
56d45dcd | 758 | ((struct dinode *)buf+itoo(ip->i_number))->di_ic = ip->i_ic; |
d746d022 KM |
759 | wtfs(d, BSIZE, buf); |
760 | } |