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