|
|
1.1 root 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: static char sccsid[] = "@(#)utilities.c 5.2 (Berkeley) 8/5/85";
9: #endif not lint
10:
11: #include "restore.h"
12:
13: /*
14: * Insure that all the components of a pathname exist.
15: */
16: pathcheck(name)
17: char *name;
18: {
19: register char *cp;
20: struct entry *ep;
21: char *start;
22:
23: start = index(name, '/');
24: if (start == 0)
25: return;
26: for (cp = start; *cp != '\0'; cp++) {
27: if (*cp != '/')
28: continue;
29: *cp = '\0';
30: ep = lookupname(name);
31: if (ep == NIL) {
32: ep = addentry(name, psearch(name), NODE);
33: newnode(ep);
34: }
35: ep->e_flags |= NEW|KEEP;
36: *cp = '/';
37: }
38: }
39:
40: /*
41: * Change a name to a unique temporary name.
42: */
43: mktempname(ep)
44: register struct entry *ep;
45: {
46: char oldname[MAXPATHLEN];
47:
48: if (ep->e_flags & TMPNAME)
49: badentry(ep, "mktempname: called with TMPNAME");
50: ep->e_flags |= TMPNAME;
51: (void) strcpy(oldname, myname(ep));
52: freename(ep->e_name);
53: ep->e_name = savename(gentempname(ep));
54: ep->e_namlen = strlen(ep->e_name);
55: renameit(oldname, myname(ep));
56: }
57:
58: /*
59: * Generate a temporary name for an entry.
60: */
61: char *
62: gentempname(ep)
63: struct entry *ep;
64: {
65: static char name[MAXPATHLEN];
66: struct entry *np;
67: long i = 0;
68:
69: for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links)
70: i++;
71: if (np == NIL)
72: badentry(ep, "not on ino list");
73: (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
74: return (name);
75: }
76:
77: /*
78: * Rename a file or directory.
79: */
80: renameit(from, to)
81: char *from, *to;
82: {
83: if (rename(from, to) < 0) {
84: fprintf(stderr, "Warning: cannot rename %s to %s", from, to);
85: (void) fflush(stderr);
86: perror("");
87: return;
88: }
89: vprintf(stdout, "rename %s to %s\n", from, to);
90: }
91:
92: /*
93: * Create a new node (directory).
94: */
95: newnode(np)
96: struct entry *np;
97: {
98: char *cp;
99:
100: if (np->e_type != NODE)
101: badentry(np, "newnode: not a node");
102: cp = myname(np);
103: if (mkdir(cp, 0777) < 0) {
104: np->e_flags |= EXISTED;
105: fprintf(stderr, "Warning: ");
106: (void) fflush(stderr);
107: perror(cp);
108: return;
109: }
110: vprintf(stdout, "Make node %s\n", cp);
111: }
112:
113: /*
114: * Remove an old node (directory).
115: */
116: removenode(ep)
117: register struct entry *ep;
118: {
119: char *cp;
120:
121: if (ep->e_type != NODE)
122: badentry(ep, "removenode: not a node");
123: if (ep->e_entries != NIL)
124: badentry(ep, "removenode: non-empty directory");
125: ep->e_flags |= REMOVED;
126: ep->e_flags &= ~TMPNAME;
127: cp = myname(ep);
128: if (rmdir(cp) < 0) {
129: fprintf(stderr, "Warning: ");
130: (void) fflush(stderr);
131: perror(cp);
132: return;
133: }
134: vprintf(stdout, "Remove node %s\n", cp);
135: }
136:
137: /*
138: * Remove a leaf.
139: */
140: removeleaf(ep)
141: register struct entry *ep;
142: {
143: char *cp;
144:
145: if (ep->e_type != LEAF)
146: badentry(ep, "removeleaf: not a leaf");
147: ep->e_flags |= REMOVED;
148: ep->e_flags &= ~TMPNAME;
149: cp = myname(ep);
150: if (unlink(cp) < 0) {
151: fprintf(stderr, "Warning: ");
152: (void) fflush(stderr);
153: perror(cp);
154: return;
155: }
156: vprintf(stdout, "Remove leaf %s\n", cp);
157: }
158:
159: /*
160: * Create a link.
161: */
162: linkit(existing, new, type)
163: char *existing, *new;
164: int type;
165: {
166:
167: if (type == SYMLINK) {
168: if (symlink(existing, new) < 0) {
169: fprintf(stderr,
170: "Warning: cannot create symbolic link %s->%s: ",
171: new, existing);
172: (void) fflush(stderr);
173: perror("");
174: return (FAIL);
175: }
176: } else if (type == HARDLINK) {
177: if (link(existing, new) < 0) {
178: fprintf(stderr,
179: "Warning: cannot create hard link %s->%s: ",
180: new, existing);
181: (void) fflush(stderr);
182: perror("");
183: return (FAIL);
184: }
185: } else {
186: panic("linkit: unknown type %d\n", type);
187: return (FAIL);
188: }
189: vprintf(stdout, "Create %s link %s->%s\n",
190: type == SYMLINK ? "symbolic" : "hard", new, existing);
191: return (GOOD);
192: }
193:
194: /*
195: * find lowest number file (above "start") that needs to be extracted
196: */
197: ino_t
198: lowerbnd(start)
199: ino_t start;
200: {
201: register struct entry *ep;
202:
203: for ( ; start < maxino; start++) {
204: ep = lookupino(start);
205: if (ep == NIL || ep->e_type == NODE)
206: continue;
207: if (ep->e_flags & (NEW|EXTRACT))
208: return (start);
209: }
210: return (start);
211: }
212:
213: /*
214: * find highest number file (below "start") that needs to be extracted
215: */
216: ino_t
217: upperbnd(start)
218: ino_t start;
219: {
220: register struct entry *ep;
221:
222: for ( ; start > ROOTINO; start--) {
223: ep = lookupino(start);
224: if (ep == NIL || ep->e_type == NODE)
225: continue;
226: if (ep->e_flags & (NEW|EXTRACT))
227: return (start);
228: }
229: return (start);
230: }
231:
232: /*
233: * report on a badly formed entry
234: */
235: badentry(ep, msg)
236: register struct entry *ep;
237: char *msg;
238: {
239:
240: fprintf(stderr, "bad entry: %s\n", msg);
241: fprintf(stderr, "name: %s\n", myname(ep));
242: fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
243: if (ep->e_sibling != NIL)
244: fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
245: if (ep->e_entries != NIL)
246: fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
247: if (ep->e_links != NIL)
248: fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
249: if (ep->e_next != NIL)
250: fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next));
251: fprintf(stderr, "entry type: %s\n",
252: ep->e_type == NODE ? "NODE" : "LEAF");
253: fprintf(stderr, "inode number: %ld\n", ep->e_ino);
254: panic("flags: %s\n", flagvalues(ep));
255: }
256:
257: /*
258: * Construct a string indicating the active flag bits of an entry.
259: */
260: char *
261: flagvalues(ep)
262: register struct entry *ep;
263: {
264: static char flagbuf[BUFSIZ];
265:
266: (void) strcpy(flagbuf, "|NIL");
267: flagbuf[0] = '\0';
268: if (ep->e_flags & REMOVED)
269: (void) strcat(flagbuf, "|REMOVED");
270: if (ep->e_flags & TMPNAME)
271: (void) strcat(flagbuf, "|TMPNAME");
272: if (ep->e_flags & EXTRACT)
273: (void) strcat(flagbuf, "|EXTRACT");
274: if (ep->e_flags & NEW)
275: (void) strcat(flagbuf, "|NEW");
276: if (ep->e_flags & KEEP)
277: (void) strcat(flagbuf, "|KEEP");
278: if (ep->e_flags & EXISTED)
279: (void) strcat(flagbuf, "|EXISTED");
280: return (&flagbuf[1]);
281: }
282:
283: /*
284: * Check to see if a name is on a dump tape.
285: */
286: ino_t
287: dirlookup(name)
288: char *name;
289: {
290: ino_t ino;
291:
292: ino = psearch(name);
293: if (ino == 0 || BIT(ino, dumpmap) == 0)
294: fprintf(stderr, "%s is not on tape\n", name);
295: return (ino);
296: }
297:
298: /*
299: * Elicit a reply.
300: */
301: reply(question)
302: char *question;
303: {
304: char c;
305:
306: do {
307: fprintf(stderr, "%s? [yn] ", question);
308: (void) fflush(stderr);
309: c = getc(terminal);
310: while (c != '\n' && getc(terminal) != '\n')
311: if (feof(terminal))
312: return (FAIL);
313: } while (c != 'y' && c != 'n');
314: if (c == 'y')
315: return (GOOD);
316: return (FAIL);
317: }
318:
319: /*
320: * handle unexpected inconsistencies
321: */
322: /* VARARGS1 */
323: panic(msg, d1, d2)
324: char *msg;
325: long d1, d2;
326: {
327:
328: fprintf(stderr, msg, d1, d2);
329: if (reply("abort") == GOOD) {
330: if (reply("dump core") == GOOD)
331: abort();
332: done(1);
333: }
334: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.