Commit | Line | Data |
---|---|---|
8c5eec2f DF |
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 | */ | |
e0519353 | 6 | |
8c5eec2f | 7 | #ifndef lint |
4af95b6b | 8 | static char sccsid[] = "@(#)utilities.c 5.2 (Berkeley) %G%"; |
8c5eec2f | 9 | #endif not lint |
ebd1f727 | 10 | |
e0519353 KM |
11 | #include "restore.h" |
12 | ||
13 | /* | |
14 | * Insure that all the components of a pathname exist. | |
15 | */ | |
16e2b8d5 | 16 | pathcheck(name) |
e0519353 KM |
17 | char *name; |
18 | { | |
19 | register char *cp; | |
20 | struct entry *ep; | |
9f13f26d | 21 | char *start; |
e0519353 KM |
22 | |
23 | start = index(name, '/'); | |
9f13f26d | 24 | if (start == 0) |
16e2b8d5 | 25 | return; |
e0519353 KM |
26 | for (cp = start; *cp != '\0'; cp++) { |
27 | if (*cp != '/') | |
28 | continue; | |
29 | *cp = '\0'; | |
30 | ep = lookupname(name); | |
31 | if (ep == NIL) { | |
7432ff81 | 32 | ep = addentry(name, psearch(name), NODE); |
e0519353 KM |
33 | newnode(ep); |
34 | } | |
7fd6e445 | 35 | ep->e_flags |= NEW|KEEP; |
e0519353 KM |
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 | { | |
16e2b8d5 | 46 | char oldname[MAXPATHLEN]; |
e0519353 KM |
47 | |
48 | if (ep->e_flags & TMPNAME) | |
49 | badentry(ep, "mktempname: called with TMPNAME"); | |
50 | ep->e_flags |= TMPNAME; | |
7432ff81 | 51 | (void) strcpy(oldname, myname(ep)); |
16e2b8d5 KM |
52 | freename(ep->e_name); |
53 | ep->e_name = savename(gentempname(ep)); | |
54 | ep->e_namlen = strlen(ep->e_name); | |
e0519353 KM |
55 | renameit(oldname, myname(ep)); |
56 | } | |
57 | ||
16e2b8d5 KM |
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"); | |
e9a184e3 | 73 | (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); |
16e2b8d5 KM |
74 | return (name); |
75 | } | |
76 | ||
e0519353 KM |
77 | /* |
78 | * Rename a file or directory. | |
79 | */ | |
80 | renameit(from, to) | |
81 | char *from, *to; | |
82 | { | |
83 | if (rename(from, to) < 0) { | |
e9e7ecc4 KM |
84 | fprintf(stderr, "Warning: cannot rename %s to %s", from, to); |
85 | (void) fflush(stderr); | |
86 | perror(""); | |
d66e0e37 | 87 | return; |
e0519353 KM |
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); | |
9f13f26d | 103 | if (mkdir(cp, 0777) < 0) { |
a7d37956 | 104 | np->e_flags |= EXISTED; |
d4ca0635 | 105 | fprintf(stderr, "Warning: "); |
7432ff81 | 106 | (void) fflush(stderr); |
d4ca0635 KM |
107 | perror(cp); |
108 | return; | |
e0519353 KM |
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"); | |
d66e0e37 KM |
125 | ep->e_flags |= REMOVED; |
126 | ep->e_flags &= ~TMPNAME; | |
e0519353 KM |
127 | cp = myname(ep); |
128 | if (rmdir(cp) < 0) { | |
d66e0e37 | 129 | fprintf(stderr, "Warning: "); |
7432ff81 | 130 | (void) fflush(stderr); |
d66e0e37 KM |
131 | perror(cp); |
132 | return; | |
e0519353 | 133 | } |
e0519353 KM |
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"); | |
d66e0e37 KM |
147 | ep->e_flags |= REMOVED; |
148 | ep->e_flags &= ~TMPNAME; | |
e0519353 KM |
149 | cp = myname(ep); |
150 | if (unlink(cp) < 0) { | |
d66e0e37 | 151 | fprintf(stderr, "Warning: "); |
7432ff81 | 152 | (void) fflush(stderr); |
d66e0e37 KM |
153 | perror(cp); |
154 | return; | |
e0519353 | 155 | } |
e0519353 KM |
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) { | |
d66e0e37 | 169 | fprintf(stderr, |
2eba41cd | 170 | "Warning: cannot create symbolic link %s->%s: ", |
e0519353 | 171 | new, existing); |
e9e7ecc4 KM |
172 | (void) fflush(stderr); |
173 | perror(""); | |
2eba41cd | 174 | return (FAIL); |
e0519353 KM |
175 | } |
176 | } else if (type == HARDLINK) { | |
177 | if (link(existing, new) < 0) { | |
d66e0e37 | 178 | fprintf(stderr, |
2eba41cd | 179 | "Warning: cannot create hard link %s->%s: ", |
e0519353 | 180 | new, existing); |
e9e7ecc4 KM |
181 | (void) fflush(stderr); |
182 | perror(""); | |
2eba41cd | 183 | return (FAIL); |
e0519353 KM |
184 | } |
185 | } else { | |
186 | panic("linkit: unknown type %d\n", type); | |
2eba41cd | 187 | return (FAIL); |
e0519353 KM |
188 | } |
189 | vprintf(stdout, "Create %s link %s->%s\n", | |
190 | type == SYMLINK ? "symbolic" : "hard", new, existing); | |
2eba41cd | 191 | return (GOOD); |
e0519353 KM |
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); | |
7432ff81 | 205 | if (ep == NIL || ep->e_type == NODE) |
e0519353 | 206 | continue; |
16e2b8d5 | 207 | if (ep->e_flags & (NEW|EXTRACT)) |
e0519353 KM |
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); | |
7432ff81 | 224 | if (ep == NIL || ep->e_type == NODE) |
e0519353 | 225 | continue; |
16e2b8d5 | 226 | if (ep->e_flags & (NEW|EXTRACT)) |
e0519353 KM |
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 | { | |
e0519353 KM |
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)); | |
16e2b8d5 KM |
249 | if (ep->e_next != NIL) |
250 | fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next)); | |
e0519353 KM |
251 | fprintf(stderr, "entry type: %s\n", |
252 | ep->e_type == NODE ? "NODE" : "LEAF"); | |
253 | fprintf(stderr, "inode number: %ld\n", ep->e_ino); | |
55f85ba7 KM |
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"); | |
e0519353 KM |
267 | flagbuf[0] = '\0'; |
268 | if (ep->e_flags & REMOVED) | |
55f85ba7 | 269 | (void) strcat(flagbuf, "|REMOVED"); |
e0519353 | 270 | if (ep->e_flags & TMPNAME) |
55f85ba7 | 271 | (void) strcat(flagbuf, "|TMPNAME"); |
e0519353 | 272 | if (ep->e_flags & EXTRACT) |
55f85ba7 | 273 | (void) strcat(flagbuf, "|EXTRACT"); |
e0519353 | 274 | if (ep->e_flags & NEW) |
55f85ba7 | 275 | (void) strcat(flagbuf, "|NEW"); |
e0519353 | 276 | if (ep->e_flags & KEEP) |
55f85ba7 | 277 | (void) strcat(flagbuf, "|KEEP"); |
a7d37956 KM |
278 | if (ep->e_flags & EXISTED) |
279 | (void) strcat(flagbuf, "|EXISTED"); | |
55f85ba7 | 280 | return (&flagbuf[1]); |
e0519353 KM |
281 | } |
282 | ||
38bbfe41 | 283 | /* |
7432ff81 KM |
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 | ||
e0519353 | 298 | /* |
7432ff81 | 299 | * Elicit a reply. |
e0519353 KM |
300 | */ |
301 | reply(question) | |
302 | char *question; | |
303 | { | |
304 | char c; | |
305 | ||
e0519353 | 306 | do { |
4af95b6b | 307 | fprintf(stderr, "%s? [yn] ", question); |
e9e7ecc4 | 308 | (void) fflush(stderr); |
7432ff81 KM |
309 | c = getc(terminal); |
310 | while (c != '\n' && getc(terminal) != '\n') | |
b8eb5f1f | 311 | if (feof(terminal)) |
4af95b6b | 312 | return (FAIL); |
e0519353 KM |
313 | } while (c != 'y' && c != 'n'); |
314 | if (c == 'y') | |
315 | return (GOOD); | |
316 | return (FAIL); | |
317 | } | |
7432ff81 | 318 | |
7432ff81 KM |
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 | } |