|
|
1.1 root 1: /*
2: * $Header: /usr.src/local/unmkfs.c,v 1.4 90/07/06 11:43:38 root Exp $
3: * $Log: /usr.src/local/unmkfs.c,v $
4: * Revision 1.4 90/07/06 11:43:38 root
5: * steve 7/6/90
6: * Changed usage to
7: * /etc/unmkfs [ -prefix ] directory nblocks [ file ]
8: * Corrected bug with 14-character filenames, which caused garbage in
9: * some lines (because of missing NUL terminator). Changed error messages.
10: * Added forward declarations of all functions.
11: * This corresponds to V3.0.1 object.
12: * ,.
13: *
14: * Revision 1.3 89/02/24 12:44:05 bin
15: * Defined realloc to remove integer pointer pun message.
16: *
17: * Revision 1.2 89/02/24 12:40:52 bin
18: * Change to generate file names for multiple prototypes based on
19: * a command-line supplied prefix.
20: *
21: * Revision 1.1 89/02/24 12:32:32 wgl
22: * Initial revision
23: *
24: */
25: static char *revision = "$Revision 1.1 $";
26: static char *header =
27: "$Header: /usr.src/local/unmkfs.c,v 1.4 90/07/06 11:43:38 root Exp $";
28:
29: /*
30: * Given a directory tree root and a filesystem size,
31: * write the fewest mkfs proto files necessary to
32: * copy the directory tree onto floppies.
33: * Preserve the ownerships, modes, dates, links, and order of links
34: * within a directory.
35: * Make each fragment root based so that a series of
36: * mount /dev/fd0 /f0; cpdir /f0 destination; umount /dev/fd0
37: * can be used to reinstall the original directory.
38: *
39: * The algorithm for partitioning is empirical and may not work very
40: * well for directories other than the pc coherent distribution.
41: * Some degree of interaction is probably desirable for getting
42: * reasonable partitioning of arbitrary directory trees.
43: *
44: * Overview:
45: * After minimal checks for necessary conditions,
46: * Read the source directory tree into a memory
47: * resident pseudo file system in which MINODE inumbers
48: * identify unique files and replace dp->d_ino in the
49: * directories.
50: * While the original root directory is not flagged I_DONE,
51: * copy those parts of the tree that are not flagged I_DONE.
52: * While the copy is too big for the floppy partition
53: * prune the copy.
54: * For each pruned copy produced, write the mkfs proto.
55: *
56: * -- rec 26.VI.84 -- invent cpfrag.
57: * -- rec 12.IX.84 -- reconstruct cpfrag -> unmkfs.
58: * -- norm 04.I.85 -- fix misc. bugs for z8000
59: */
60: #include <stdio.h>
61: #include <sys/dir.h>
62: #include <assert.h>
63: #include <sys/const.h>
64: #include <sys/types.h>
65: #include <sys/stat.h>
66: #include <sys/filsys.h>
67: #include <sys/ino.h>
68:
69: extern char *realloc();
70: extern char edata[];
71:
72: #define USAGE "Usage: /etc/unmkfs [ -prefix ] directory nblocks [ file ]\n"
73: #define IHASH 128
74: #define MAXFNAME 512
75: #define NDISK 32
76:
77: typedef struct MINODE {
78: struct MINODE *i_link1; /* dev x ino hash linkage */
79: struct MINODE *i_link2; /* my inumbering hash linkage */
80: char *i_linkname; /* Name of first instance of file in copy */
81: int i_mino; /* My inumber */
82: int i_flag; /* Miscellaneous flags */
83: int i_blks; /* Cumulative block size, includes indirects */
84: int i_inos; /* Cumulative inodes used */
85: int i_size; /* Total data, indir, and inode blocks */
86: int i_isdir; /* Simplify many tests */
87: dev_t i_dev; /* Some fields from stat() */
88: ino_t i_ino;
89: int i_mode;
90: int i_nlink;
91: int i_uid;
92: int i_gid;
93: int i_rdev;
94: time_t i_mtime;
95: int i_nent; /* Number of directory entries */
96: struct direct i_elem[]; /* Directory entries */
97: } MINODE;
98:
99: #define I_DONE 1 /* Inode is done */
100: #define I_COUNT 2 /* Inode is counted */
101: #define I_PUT 8 /* Inode size reported */
102: #define I_DONE1 16 /* Inode has been done once, for directories */
103: #define I_PURGE 32 /* Inode should be purged */
104: #define I_KEEP 64 /* Keep entire subdirectory */
105: #define I_CANFIT 128 /* Subdirectory could fit on disk */
106: #define I_ISMADE 256 /* Inode is made, do link */
107:
108: MINODE *disks[NDISK];
109: int dsize;
110: int dused;
111: int vflag = 1;
112: int outf = 0; /* Use file outpre.outsuf instead of stdout */
113: int excess;
114: int ndisk;
115: int myuid;
116: int mygid;
117:
118: char outpre[64]; /* Settable output file prefix */
119: char outsuf[] = ".p??"; /* Suffix for output file name */
120:
121: FILE *ofp;
122:
123: /* Forward. */
124: MINODE *makeroot();
125: void makedir();
126: void printroot();
127: void printdir();
128: void splat();
129: void makedisk();
130: void mkfs();
131: void insdir();
132: void indent();
133: void uflagroot();
134: void uflagdir();
135: void flagroot();
136: void flagdir();
137: void sizeroot();
138: void sizedir();
139: MINODE *cpyroot();
140: MINODE *cpydir();
141: void keepers();
142: MINODE *select();
143: void purge();
144: void donedir();
145: void markdir();
146: int entermi();
147: int duplmi();
148: MINODE *fetchmi();
149: void freemi();
150: long blkuse();
151: char *string();
152: char *myalloc();
153: void usage();
154: void fatal();
155:
156: char fname[MAXFNAME]; /* Filename buffer */
157: char fname1[MAXFNAME]; /* Second file name buffer */
158: char cmdbuf[128];
159: struct stat sbuf; /* Stat buffer */
160: struct stat tbuf; /* Time buffer, leave zero for all times */
161: char *argv0; /* For error recovery */
162:
163: main(argc, argv) int argc; char *argv[];
164: {
165: int i;
166: MINODE *rip, *tip, *sip;
167:
168: argv0 = argv[0];
169: if (argc > 1 && argv[1][0] == '-') {
170: strcpy(outpre, &argv[1][1]);
171: outf = 1;
172: ++argv;
173: --argc;
174: }
175: if (argc < 3 || argc > 4)
176: usage();
177: if ((dsize = atoi(argv[2])) <= 0)
178: fatal("illegal size \"%s\"", argv[2]);
179: if (argc == 4) {
180: if (stat(argv[3], &tbuf) < 0)
181: fatal("cannot stat \"%s\"", argv[3]);
182: } else
183: tbuf.st_mtime = 0; /* make time == 0 to get all files */
184: rip = makeroot(argv[1]);
185: while ((rip->i_flag & I_DONE) == 0) {
186: tip = cpyroot(rip);
187: dused = 4;
188: keepers(tip);
189: excess = tip->i_size + 2 - dsize;
190: while (excess > 0) {
191: while ((sip = select(tip)) == NULL) {
192: excess += 1;
193: }
194: flagroot(sip, I_PURGE);
195: purge(tip);
196: sizeroot(tip);
197: excess = tip->i_size + 2 - dsize;
198: }
199: donedir(tip);
200: markdir(rip);
201: disks[ndisk] = tip;
202: ndisk += 1;
203: }
204: for (i = 0; i < ndisk; i += 1)
205: makedisk(i, argv[1]);
206: }
207:
208: /*
209: ** Get the MINODE * corresponding to fname, and call
210: ** makedir() to build the in-memory tree. Call sizeroot()
211: ** return the MINODE corresponding to the root.
212: */
213: MINODE *
214: makeroot(cp) char *cp;
215: {
216: MINODE *rip;
217:
218: if (strlen(cp) >= MAXFNAME)
219: fatal("directory path name too long");
220: strcpy(fname, cp);
221: if (stat(fname, &sbuf) < 0)
222: fatal("cannot stat \"%s\"", fname);
223: if ((sbuf.st_mode&S_IFMT) != S_IFDIR)
224: fatal("\"%s\" is not a directory");
225: rip = fetchmi(entermi());
226: if (cp[0] == '/' && cp[1] == '\0')
227: fname[0] = 0;
228: makedir(rip);
229: sizeroot(rip);
230: return (rip);
231: }
232:
233: /*
234: ** Recursively build a tree of MINODE pointers
235: ** for the directory ip.
236: */
237: void
238: makedir(ip) MINODE *ip;
239: {
240: int fd;
241: int i;
242: struct direct *dp1, *dp2;
243: MINODE *tip;
244: char *cp;
245:
246: cp = fname + strlen(fname);
247: if (cp + DIRSIZ + 2 >= fname + MAXFNAME)
248: fatal("directory tree too deep");
249: if ((fd = open(fname, 0)) < 0)
250: fatal("cannot open \"%s\"", fname);
251: i = ip->i_nent * sizeof(struct direct);
252: if (read(fd, ip->i_elem, i) != i)
253: fatal("%s: read error", fname);
254: close(fd);
255: *cp = '/';
256: dp1 = dp2 = ip->i_elem;
257: for (i = 0; i < ip->i_nent; i += 1) {
258: if (dp2->d_name[0] == '.') {
259: if (dp2->d_name[1] == 0
260: || (dp2->d_name[1] == '.' && dp2->d_name[2] == 0))
261: dp2->d_ino = 0;
262: }
263: if (dp2->d_ino != 0) {
264: strncpy(cp+1, dp2->d_name, DIRSIZ);
265: if (stat(fname, &sbuf) < 0)
266: fatal("cannot stat \"%s\"", fname);
267: dp2->d_ino = entermi();
268: }
269: if (dp2->d_ino != 0) {
270: if (dp1 != dp2)
271: *dp1 = *dp2;
272: dp1 += 1;
273: }
274: dp2 += 1;
275: }
276: ip->i_nent = dp1 - ip->i_elem;
277: i = sizeof(MINODE) + ip->i_nent * sizeof(struct direct);
278: if (realloc(ip, i) != ip)
279: fatal("realloc moved block");
280: dp1 = ip->i_elem;
281: for (i = 0; i < ip->i_nent; i += 1) {
282: tip = fetchmi(dp1->d_ino);
283: if (tip->i_isdir) {
284: strncpy(cp+1, dp1->d_name, DIRSIZ);
285: makedir(tip);
286: }
287: dp1 += 1;
288: }
289: *cp = 0;
290: }
291:
292: void
293: printroot(cp, rip) char *cp; MINODE *rip;
294: {
295: uflagroot(rip, I_PUT);
296: strcpy(fname, cp);
297: splat(rip);
298: if (cp[0] == '/' && cp[1] == 0)
299: fname[0] = 0;
300: printdir(rip);
301: }
302:
303: void
304: printdir(ip) MINODE *ip;
305: {
306: int i;
307: MINODE *tip;
308: struct direct *dp;
309: char *cp;
310:
311: dp = ip->i_elem;
312: cp = fname + strlen(fname);
313: *cp = '/';
314: for (i = 0; i < ip->i_nent; i += 1) {
315: tip = fetchmi(dp->d_ino);
316: strncpy(cp+1, dp->d_name, DIRSIZ);
317: splat(tip);
318: if (tip->i_isdir)
319: printdir(tip);
320: dp += 1;
321: }
322: *cp = 0;
323: }
324:
325: void
326: splat(ip) MINODE *ip;
327: {
328: printf("(%2d,%2d,%4d) ",
329: major(ip->i_dev), minor(ip->i_dev), ip->i_ino);
330: if ((ip->i_flag & I_PUT) != 0)
331: printf("%6d %4d %6d ", 0, 0, 0);
332: else
333: printf("%6d %4d %6d ", ip->i_size, ip->i_inos, ip->i_blks);
334: printf("%s\n", fname);
335: ip->i_flag |= I_PUT;
336: }
337:
338: void
339: makedisk(n, cp) char *cp;
340: {
341: MINODE *ip;
342: char outfile[72];
343:
344: ip = disks[n];
345: fprintf(stderr, "Disk %d: %d inodes, %d data blocks\n",
346: n+1, ip->i_inos, ip->i_blks);
347: if (outf == 1) {
348: outsuf[2] = (n+1)/10 + '0';
349: outsuf[3] = (n+1)%10 + '0';
350: outsuf[4] = '\0';
351: strcpy(outfile, outpre);
352: strcat(outfile, outsuf);
353: if ((ofp = fopen(outfile, "w")) == NULL)
354: fatal("cannot open output file \"%s\"", outfile);
355: } else
356: ofp = stdout;
357: mkfs(ip->i_inos);
358: if (cp[0] == '/' && cp[1] == 0)
359: fname[0] = 0;
360: else
361: strcpy(fname, cp);
362: fprintf(ofp, "d--%03o %3d %3d\n", ip->i_mode&0777, ip->i_uid,
363: ip->i_gid);
364: indent(1);
365: insdir(ip);
366: indent(-1);
367: fprintf(ofp, "$\n");
368: }
369:
370: void
371: mkfs(nino)
372: {
373: fprintf(ofp, "/dev/null xxxxx xxxxx\n");
374: fprintf(ofp, "%d %d 1 1\n", dsize, nino);
375: }
376:
377: void
378: insdir(ip) MINODE *ip;
379: {
380: int i;
381: MINODE *tip;
382: struct direct *dp;
383: char *cp, *cp1, buf[DIRSIZ+1];
384: char dtype;
385:
386: cp = fname + strlen(fname);
387: cp1 = fname1 + strlen(fname1);
388: *cp = '/';
389: *cp1 = '/';
390: dp = ip->i_elem;
391: for (i = 0; i < ip->i_nent; i += 1) {
392: tip = fetchmi(dp->d_ino);
393: strncpy(buf, dp->d_name, DIRSIZ);
394: buf[DIRSIZ] = '\0';
395: strcpy(cp+1, buf);
396: strcpy(cp1+1, buf);
397: indent(0);
398: fprintf(ofp, "%-14s", buf);
399: if (tip->i_flag & I_ISMADE) {
400: fprintf(ofp, " l----- 0 0 %s\n", tip->i_linkname);
401: dp += 1;
402: continue;
403: }
404: switch (tip->i_mode & S_IFMT) {
405: case S_IFDIR:
406: dtype = 'd';
407: break;
408: case S_IFCHR:
409: dtype = 'c';
410: break;
411: case S_IFBLK:
412: dtype = 'b';
413: break;
414: case S_IFREG:
415: dtype = '-';
416: break;
417: default:
418: fatal("%s: bad file type %d", fname, tip->i_mode&S_IFMT);
419: }
420:
421: fprintf(ofp, " %c%c%c%03o %3d %3d",
422: dtype,
423: (tip->i_mode&ISUID) ? 'u' : '-',
424: (tip->i_mode&ISGID) ? 'g' : '-',
425: tip->i_mode&0777,
426: tip->i_uid, tip->i_gid);
427: switch (tip->i_mode & S_IFMT) {
428: case S_IFDIR:
429: fputc('\n', ofp);
430: indent(1);
431: insdir(tip);
432: indent(-1);
433: indent(0);
434: fprintf(ofp, "$\n");
435: break;
436: case S_IFCHR:
437: case S_IFBLK:
438: fprintf(ofp, "%3d %3d\n", major(tip->i_rdev),
439: minor(tip->i_rdev));
440: break;
441: case S_IFREG:
442: fprintf(ofp, " %s\n", fname);
443: break;
444: }
445: if (tip->i_nlink > 1)
446: tip->i_linkname = string(fname1);
447: tip->i_flag |= I_ISMADE;
448: dp += 1;
449: }
450: *cp = 0;
451: *cp1 = 0;
452: }
453:
454: void
455: indent(n) int n;
456: {
457: static int indent;
458:
459: if (n < 0)
460: indent -= 1;
461: else if (n > 0)
462: indent += 1;
463: else for (n = indent; --n >= 0; fprintf(ofp, " "));
464: }
465:
466: void
467: uflagroot(rip, flag) MINODE *rip;
468: {
469: uflagdir(rip, flag);
470: rip->i_flag &= ~flag;
471: }
472:
473: /*
474: ** Recursively turn off flag in ip and
475: ** all directories below ip.
476: */
477: void
478: uflagdir(ip, flag) MINODE *ip;
479: {
480: int i;
481: MINODE *tip;
482: struct direct *dp;
483:
484: dp = ip->i_elem;
485: for (i = 0; i < ip->i_nent; i += 1) {
486: tip = fetchmi(dp->d_ino);
487: tip->i_flag &= ~flag;
488: if (tip->i_isdir)
489: uflagdir(tip, flag);
490: dp += 1;
491: }
492: }
493:
494: void
495: flagroot(ip, flag) MINODE *ip; int flag;
496: {
497: if (ip->i_isdir)
498: flagdir(ip, flag);
499: ip->i_flag |= flag;
500: }
501:
502: void
503: flagdir(ip, flag) MINODE *ip; int flag;
504: {
505: int i;
506: MINODE *tip;
507: struct direct *dp;
508:
509: dp = ip->i_elem;
510: for (i = 0; i < ip->i_nent; i += 1) {
511: tip = fetchmi(dp->d_ino);
512: if (tip->i_isdir)
513: flagdir(tip, flag);
514: tip->i_flag |= flag;
515: dp += 1;
516: }
517: }
518:
519: void
520: sizeroot(rip) MINODE *rip;
521: {
522: uflagroot(rip, I_COUNT);
523: sizedir(rip);
524: /* Add in bad block inode */
525: rip->i_size = rip->i_blks + (++rip->i_inos+INOPB-1) / INOPB;
526: }
527:
528: /*
529: ** For subdirectories not flagged I_COUNT,
530: ** add the isize and blksize to that of ip.
531: */
532: void
533: sizedir(ip) MINODE *ip;
534: {
535: int i;
536: MINODE *tip;
537: struct direct *dp;
538:
539: ip->i_blks = 0;
540: ip->i_inos = 0;
541: dp = ip->i_elem;
542: for (i = 0; i < ip->i_nent; i += 1) {
543: tip = fetchmi(dp->d_ino);
544: if (tip->i_isdir)
545: sizedir(tip);
546: if ((tip->i_flag&I_COUNT) == 0) {
547: ip->i_inos += tip->i_inos;
548: ip->i_blks += tip->i_blks;
549: tip->i_flag |= I_COUNT;
550: }
551: dp += 1;
552: }
553: ip->i_inos += 1; /* For me */
554: ip->i_blks += blkuse((long)(ip->i_nent+2)*sizeof(struct direct));
555: ip->i_size = ip->i_blks + (ip->i_inos+INOPB-1) / INOPB;
556: }
557:
558: MINODE *
559: cpyroot(rip) MINODE *rip;
560: {
561: uflagdir(rip, I_PURGE|I_KEEP);
562: rip = cpydir(rip);
563: sizeroot(rip);
564: return (rip);
565: }
566:
567: MINODE *
568: cpydir(ip) MINODE *ip;
569: {
570: int i;
571: MINODE *nip, *tip;
572: struct direct *dp1, *dp2;
573:
574: nip = fetchmi(duplmi(ip));
575: nip->i_nent = 0;
576: dp1 = ip->i_elem;
577: dp2 = nip->i_elem;
578: for (i = 0; i < ip->i_nent; i += 1) {
579: tip = fetchmi(dp1->d_ino);
580: if ((tip->i_flag&I_DONE) != 0)
581: tip = NULL;
582: else if (tip->i_isdir)
583: tip = cpydir(tip);
584: if (tip != NULL) {
585: dp2->d_ino = tip->i_mino;
586: strncpy(dp2->d_name, dp1->d_name, DIRSIZ);
587: nip->i_nent += 1;
588: dp2 += 1;
589: }
590: dp1 += 1;
591: }
592: if (nip->i_nent < ip->i_nent) {
593: i = sizeof(MINODE) + nip->i_nent * sizeof(struct direct);
594: if (realloc(nip, i) != nip)
595: fatal("realloc moved block");
596: }
597: return (nip);
598: }
599:
600: void
601: keepers(ip) MINODE *ip;
602: {
603: int i;
604: MINODE *tip;
605: struct direct *dp;
606:
607: dp = ip->i_elem;
608: for (i = 0; i < ip->i_nent; i += 1) {
609: tip = fetchmi(dp->d_ino);
610: if (tip->i_isdir == 0) {
611: dp += 1;
612: continue;
613: }
614: if (tip->i_size < dsize - 4)
615: tip->i_flag |= I_CANFIT;
616: if (dused + tip->i_size < dsize) {
617: tip->i_flag |= I_KEEP;
618: dused += tip->i_size;
619: }
620: dp += 1;
621: }
622: dp = ip->i_elem;
623: for (i = 0; i < ip->i_nent; i += 1) {
624: tip = fetchmi(dp->d_ino);
625: if (tip->i_isdir != 0
626: && (tip->i_flag & (I_CANFIT|I_KEEP)) == 0)
627: keepers(tip);
628: dp += 1;
629: }
630: }
631:
632: MINODE *
633: select(ip) MINODE *ip;
634: {
635: int i;
636: MINODE *uip, *lip, *tip;
637: struct direct *dp;
638:
639: uip = lip = NULL;
640: dp = ip->i_elem;
641: for (i = 0; i < ip->i_nent; i += 1) {
642: tip = fetchmi(dp->d_ino);
643: if (tip->i_flag & I_KEEP) {
644: dp += 1;
645: continue;
646: }
647: if (tip->i_flag & I_CANFIT)
648: return (tip);
649: if (tip->i_size == excess)
650: return (tip);
651: else if (tip->i_size > excess) {
652: if (uip == NULL || uip->i_size > tip->i_size)
653: uip = tip;
654: } else {
655: if (lip == NULL || lip->i_size < tip->i_size)
656: lip = tip;
657: }
658: dp += 1;
659: }
660: if (lip != NULL)
661: return (lip);
662: if (uip->i_isdir)
663: return (select(uip));
664: return (uip);
665: }
666:
667: void
668: purge(rip) MINODE *rip;
669: {
670: int i;
671: MINODE *tip;
672: struct direct *dp1, *dp2;
673:
674: assert(rip->i_isdir);
675: #if I8086
676: assert((char *)&dp2 > edata + 16);
677: #endif
678: dp1 = dp2 = rip->i_elem;
679: for (i = 0; i < rip->i_nent; i += 1) {
680: tip = fetchmi(dp1->d_ino);
681: if (tip->i_isdir) {
682: purge(tip);
683: if ((tip->i_flag & I_PURGE) && tip->i_nent == 0) {
684: dp1->d_ino = 0;
685: freemi(tip->i_mino);
686: }
687: } else if (tip->i_flag & I_PURGE)
688: dp1->d_ino = 0;
689: if (dp1->d_ino != 0) {
690: if (dp1 != dp2)
691: *dp2 = *dp1;
692: dp2 += 1;
693: }
694: dp1 += 1;
695: }
696: rip->i_nent = dp2 - rip->i_elem;
697: }
698:
699: void
700: donedir(ip)
701: MINODE *ip;
702: {
703: int i;
704: MINODE *tip;
705: struct direct *dp;
706:
707: ip->i_link1->i_flag |= I_DONE1;
708: dp = ip->i_elem;
709: for (i = 0; i < ip->i_nent; i += 1) {
710: tip = fetchmi(dp->d_ino);
711: if (tip->i_isdir)
712: donedir(tip);
713: else
714: tip->i_flag |= I_DONE|I_DONE1;
715: dp += 1;
716: }
717: }
718:
719: void
720: markdir(ip) MINODE *ip;
721: {
722: int i;
723: MINODE *tip;
724: struct direct *dp;
725: int flag;
726:
727: if (ip->i_flag & I_DONE)
728: return;
729: dp = ip->i_elem;
730: flag = I_DONE;
731: for (i = 0; i < ip->i_nent; i += 1) {
732: tip = fetchmi(dp->d_ino);
733: if (tip->i_isdir)
734: markdir(tip);
735: flag &= tip->i_flag;
736: dp += 1;
737: }
738: if ((flag & I_DONE) != 0 && (ip->i_flag & I_DONE1) != 0)
739: ip->i_flag |= I_DONE;
740: }
741:
742: MINODE *ihash1[IHASH]; /* dev x ino hash */
743: MINODE *ihash2[IHASH]; /* mino hash */
744: int minumber = 1;
745:
746: /*
747: ** Return the mino in the hash table ihash1 corresponding to
748: ** the statbuf. If not found, enter it and return the resulting
749: ** entry.
750: */
751: int
752: entermi()
753: {
754: MINODE *ip, **ipp;
755: int nent;
756:
757: ipp = &ihash1[sbuf.st_ino % IHASH];
758: while ((ip = *ipp) != NULL) {
759: if (ip->i_ino == sbuf.st_ino
760: && ip->i_dev == sbuf.st_dev)
761: return (ip->i_mino);
762: ipp = &ip->i_link1;
763: }
764: nent = 0;
765: if ((sbuf.st_mode&S_IFMT) == S_IFDIR)
766: nent = sbuf.st_size / sizeof(struct direct);
767: else if (sbuf.st_mtime < tbuf.st_mtime)
768: return 0;
769: else if (blkuse(sbuf.st_size) > dsize-5) {
770: fprintf(stderr, "unmkfs: file %s too large - omitted\n", fname);
771: return 0;
772: }
773: *ipp = ip = myalloc(sizeof(MINODE) + nent * sizeof(struct direct));
774: ip->i_dev = sbuf.st_dev;
775: ip->i_ino = sbuf.st_ino;
776: ip->i_mode = sbuf.st_mode;
777: ip->i_nlink = sbuf.st_nlink;
778: ip->i_uid = sbuf.st_uid;
779: ip->i_gid = sbuf.st_gid;
780: ip->i_rdev = sbuf.st_rdev;
781: ip->i_mtime = sbuf.st_mtime;
782: ip->i_blks = blkuse(sbuf.st_size);
783: ip->i_inos = 1;
784: ip->i_size = ip->i_blks;
785: ip->i_nent = nent;
786: ip->i_mino = minumber++;
787: ip->i_isdir = (nent != 0);
788: ipp = &ihash2[ip->i_mino % IHASH];
789: ip->i_link2 = *ipp;
790: *ipp = ip;
791: return (ip->i_mino);
792: }
793:
794: int
795: duplmi(ip) MINODE *ip;
796: {
797: MINODE *nip, **ipp;
798:
799: nip = myalloc(sizeof(MINODE) + ip->i_nent * sizeof(struct direct));
800: nip->i_dev = ip->i_dev;
801: nip->i_ino = ip->i_ino;
802: nip->i_mode = ip->i_mode;
803: nip->i_nlink = ip->i_nlink;
804: nip->i_uid = ip->i_uid;
805: nip->i_gid = ip->i_gid;
806: nip->i_rdev = ip->i_rdev;
807: nip->i_blks = ip->i_blks;
808: nip->i_inos = ip->i_inos;
809: nip->i_size = ip->i_size;
810: nip->i_nent = ip->i_nent;
811: nip->i_mino = minumber++;
812: nip->i_isdir = ip->i_isdir;
813: ipp = &ihash2[nip->i_mino % IHASH];
814: nip->i_link2 = *ipp;
815: *ipp = nip;
816: nip->i_link1 = ip;
817: return (nip->i_mino);
818: }
819:
820: /*
821: ** Find the entry i ihash2 corresponding to mino.
822: ** Die with message if not there.
823: */
824: MINODE *
825: fetchmi(mino) int mino;
826: {
827: MINODE *ip, **ipp;
828:
829: ipp = &ihash2[mino % IHASH];
830: while ((ip = *ipp) != NULL)
831: if (ip->i_mino == mino)
832: return (ip);
833: else
834: ipp = &ip->i_link2;
835: fatal("nonexistent internal inumber %d", mino);
836: }
837:
838: void
839: freemi(mino) int mino;
840: {
841: MINODE *ip, **ipp;
842:
843: ipp = &ihash2[mino % IHASH];
844: while ((ip = *ipp) != NULL)
845: if (ip->i_mino == mino) {
846: *ipp = ip->i_link2;
847: free(ip);
848: return;
849: } else
850: ipp = &ip->i_link2;
851: fatal("nonexistent internal inumber %d", mino);
852: }
853:
854: /*
855: * A corrected disk usage computation
856: * for retrofit into /usr/src/cmd/du.c, /usr/src/cmd/ls.c/prsize(),
857: * and /usr/src/cmd/quot.c since they are all wrong.
858: *
859: * And this is not quite right either since it doesn't deal with sparse
860: * blocks.
861: */
862: long
863: blkuse(nb) long nb;
864: {
865: #undef NBN
866: #define NBN 128L
867: #define nindir(x) (((x)+NBN-1)/NBN)
868: #define nblock(x) (((x)+BSIZE-1)/BSIZE)
869: #define min(x, y) ((x)<(y) ? (x) : (y))
870: long bu, ndir, nidir, niidir;
871:
872: nb = nblock(nb);
873: ndir = min(nb, ND);
874: nb -= ndir;
875: bu = ndir;
876: if (nb) {
877: nidir = min(nb, NBN);
878: nb -= nidir;
879: bu += nidir + 1;
880: if (nb) {
881: niidir = min(nb, NBN*NBN);
882: nb -= niidir;
883: bu += niidir + 1 + nindir(niidir);
884: if (nb)
885: bu += nb + 1 + nindir(nindir(nb)) + nindir(nb);
886: }
887: }
888: return (bu);
889: }
890:
891: char *
892: string(cp) char *cp;
893: {
894: char *sp;
895:
896: sp = myalloc(strlen(cp)+1);
897: strcpy(sp, cp);
898: return (sp);
899: }
900:
901: char *
902: myalloc(nb) int nb;
903: {
904: char *p;
905:
906: if ((p = malloc(nb)) == NULL)
907: fatal("out of space");
908: while (--nb >= 0)
909: p[nb] = 0;
910: return (p);
911: }
912:
913: void
914: usage()
915: {
916: fprintf(stderr, USAGE);
917: exit(1);
918: }
919:
920: void
921: fatal(args) char *args;
922: {
923: fprintf(stderr, "%s: %r\n", argv0, &args);
924: exit(1);
925: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.