Commit | Line | Data |
---|---|---|
8c5eec2f | 1 | /* |
e7a042ee KB |
2 | * Copyright (c) 1983, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
b42768a6 | 4 | * |
70ab3c27 | 5 | * %sccs.include.redist.c% |
8c5eec2f | 6 | */ |
e0519353 | 7 | |
8c5eec2f | 8 | #ifndef lint |
e7a042ee | 9 | static char sccsid[] = "@(#)utilities.c 8.1 (Berkeley) %G%"; |
b42768a6 | 10 | #endif /* not lint */ |
ebd1f727 | 11 | |
451eb9a1 KB |
12 | #include <sys/param.h> |
13 | #include <sys/stat.h> | |
14 | ||
15 | #include <ufs/ufs/dinode.h> | |
5231a9f4 | 16 | #include <ufs/ufs/dir.h> |
451eb9a1 KB |
17 | |
18 | #include <errno.h> | |
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <unistd.h> | |
23 | ||
e0519353 | 24 | #include "restore.h" |
451eb9a1 | 25 | #include "extern.h" |
e0519353 KM |
26 | |
27 | /* | |
28 | * Insure that all the components of a pathname exist. | |
29 | */ | |
451eb9a1 | 30 | void |
16e2b8d5 | 31 | pathcheck(name) |
e0519353 KM |
32 | char *name; |
33 | { | |
34 | register char *cp; | |
35 | struct entry *ep; | |
9f13f26d | 36 | char *start; |
e0519353 KM |
37 | |
38 | start = index(name, '/'); | |
9f13f26d | 39 | if (start == 0) |
16e2b8d5 | 40 | return; |
e0519353 KM |
41 | for (cp = start; *cp != '\0'; cp++) { |
42 | if (*cp != '/') | |
43 | continue; | |
44 | *cp = '\0'; | |
45 | ep = lookupname(name); | |
451eb9a1 | 46 | if (ep == NULL) { |
5231a9f4 | 47 | ep = addentry(name, pathsearch(name)->d_ino, NODE); |
e0519353 KM |
48 | newnode(ep); |
49 | } | |
7fd6e445 | 50 | ep->e_flags |= NEW|KEEP; |
e0519353 KM |
51 | *cp = '/'; |
52 | } | |
53 | } | |
54 | ||
55 | /* | |
56 | * Change a name to a unique temporary name. | |
57 | */ | |
451eb9a1 | 58 | void |
e0519353 KM |
59 | mktempname(ep) |
60 | register struct entry *ep; | |
61 | { | |
16e2b8d5 | 62 | char oldname[MAXPATHLEN]; |
e0519353 KM |
63 | |
64 | if (ep->e_flags & TMPNAME) | |
65 | badentry(ep, "mktempname: called with TMPNAME"); | |
66 | ep->e_flags |= TMPNAME; | |
7432ff81 | 67 | (void) strcpy(oldname, myname(ep)); |
16e2b8d5 KM |
68 | freename(ep->e_name); |
69 | ep->e_name = savename(gentempname(ep)); | |
70 | ep->e_namlen = strlen(ep->e_name); | |
e0519353 KM |
71 | renameit(oldname, myname(ep)); |
72 | } | |
73 | ||
16e2b8d5 KM |
74 | /* |
75 | * Generate a temporary name for an entry. | |
76 | */ | |
77 | char * | |
78 | gentempname(ep) | |
79 | struct entry *ep; | |
80 | { | |
81 | static char name[MAXPATHLEN]; | |
82 | struct entry *np; | |
83 | long i = 0; | |
84 | ||
451eb9a1 KB |
85 | for (np = lookupino(ep->e_ino); |
86 | np != NULL && np != ep; np = np->e_links) | |
16e2b8d5 | 87 | i++; |
451eb9a1 | 88 | if (np == NULL) |
16e2b8d5 | 89 | badentry(ep, "not on ino list"); |
e9a184e3 | 90 | (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); |
16e2b8d5 KM |
91 | return (name); |
92 | } | |
93 | ||
e0519353 KM |
94 | /* |
95 | * Rename a file or directory. | |
96 | */ | |
451eb9a1 | 97 | void |
e0519353 KM |
98 | renameit(from, to) |
99 | char *from, *to; | |
100 | { | |
414c4f09 | 101 | if (!Nflag && rename(from, to) < 0) { |
451eb9a1 KB |
102 | fprintf(stderr, "warning: cannot rename %s to %s: %s\n", |
103 | from, to, strerror(errno)); | |
d66e0e37 | 104 | return; |
e0519353 KM |
105 | } |
106 | vprintf(stdout, "rename %s to %s\n", from, to); | |
107 | } | |
108 | ||
109 | /* | |
110 | * Create a new node (directory). | |
111 | */ | |
451eb9a1 | 112 | void |
e0519353 KM |
113 | newnode(np) |
114 | struct entry *np; | |
115 | { | |
116 | char *cp; | |
117 | ||
118 | if (np->e_type != NODE) | |
119 | badentry(np, "newnode: not a node"); | |
120 | cp = myname(np); | |
414c4f09 | 121 | if (!Nflag && mkdir(cp, 0777) < 0) { |
a7d37956 | 122 | np->e_flags |= EXISTED; |
451eb9a1 | 123 | fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); |
d4ca0635 | 124 | return; |
e0519353 KM |
125 | } |
126 | vprintf(stdout, "Make node %s\n", cp); | |
127 | } | |
128 | ||
129 | /* | |
130 | * Remove an old node (directory). | |
131 | */ | |
451eb9a1 | 132 | void |
e0519353 KM |
133 | removenode(ep) |
134 | register struct entry *ep; | |
135 | { | |
136 | char *cp; | |
137 | ||
138 | if (ep->e_type != NODE) | |
139 | badentry(ep, "removenode: not a node"); | |
451eb9a1 | 140 | if (ep->e_entries != NULL) |
e0519353 | 141 | badentry(ep, "removenode: non-empty directory"); |
d66e0e37 KM |
142 | ep->e_flags |= REMOVED; |
143 | ep->e_flags &= ~TMPNAME; | |
e0519353 | 144 | cp = myname(ep); |
414c4f09 | 145 | if (!Nflag && rmdir(cp) < 0) { |
451eb9a1 | 146 | fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); |
d66e0e37 | 147 | return; |
e0519353 | 148 | } |
e0519353 KM |
149 | vprintf(stdout, "Remove node %s\n", cp); |
150 | } | |
151 | ||
152 | /* | |
153 | * Remove a leaf. | |
154 | */ | |
451eb9a1 | 155 | void |
e0519353 KM |
156 | removeleaf(ep) |
157 | register struct entry *ep; | |
158 | { | |
159 | char *cp; | |
160 | ||
161 | if (ep->e_type != LEAF) | |
162 | badentry(ep, "removeleaf: not a leaf"); | |
d66e0e37 KM |
163 | ep->e_flags |= REMOVED; |
164 | ep->e_flags &= ~TMPNAME; | |
e0519353 | 165 | cp = myname(ep); |
414c4f09 | 166 | if (!Nflag && unlink(cp) < 0) { |
451eb9a1 | 167 | fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); |
d66e0e37 | 168 | return; |
e0519353 | 169 | } |
e0519353 KM |
170 | vprintf(stdout, "Remove leaf %s\n", cp); |
171 | } | |
172 | ||
173 | /* | |
174 | * Create a link. | |
175 | */ | |
451eb9a1 | 176 | int |
e0519353 KM |
177 | linkit(existing, new, type) |
178 | char *existing, *new; | |
179 | int type; | |
180 | { | |
181 | ||
182 | if (type == SYMLINK) { | |
414c4f09 | 183 | if (!Nflag && symlink(existing, new) < 0) { |
d66e0e37 | 184 | fprintf(stderr, |
451eb9a1 KB |
185 | "warning: cannot create symbolic link %s->%s: %s\n", |
186 | new, existing, strerror(errno)); | |
2eba41cd | 187 | return (FAIL); |
e0519353 KM |
188 | } |
189 | } else if (type == HARDLINK) { | |
414c4f09 | 190 | if (!Nflag && link(existing, new) < 0) { |
d66e0e37 | 191 | fprintf(stderr, |
451eb9a1 KB |
192 | "warning: cannot create hard link %s->%s: %s\n", |
193 | new, existing, strerror(errno)); | |
2eba41cd | 194 | return (FAIL); |
e0519353 KM |
195 | } |
196 | } else { | |
197 | panic("linkit: unknown type %d\n", type); | |
2eba41cd | 198 | return (FAIL); |
e0519353 KM |
199 | } |
200 | vprintf(stdout, "Create %s link %s->%s\n", | |
201 | type == SYMLINK ? "symbolic" : "hard", new, existing); | |
2eba41cd | 202 | return (GOOD); |
e0519353 KM |
203 | } |
204 | ||
205 | /* | |
206 | * find lowest number file (above "start") that needs to be extracted | |
207 | */ | |
208 | ino_t | |
209 | lowerbnd(start) | |
210 | ino_t start; | |
211 | { | |
212 | register struct entry *ep; | |
213 | ||
214 | for ( ; start < maxino; start++) { | |
215 | ep = lookupino(start); | |
451eb9a1 | 216 | if (ep == NULL || ep->e_type == NODE) |
e0519353 | 217 | continue; |
16e2b8d5 | 218 | if (ep->e_flags & (NEW|EXTRACT)) |
e0519353 KM |
219 | return (start); |
220 | } | |
221 | return (start); | |
222 | } | |
223 | ||
224 | /* | |
225 | * find highest number file (below "start") that needs to be extracted | |
226 | */ | |
227 | ino_t | |
228 | upperbnd(start) | |
229 | ino_t start; | |
230 | { | |
231 | register struct entry *ep; | |
232 | ||
233 | for ( ; start > ROOTINO; start--) { | |
234 | ep = lookupino(start); | |
451eb9a1 | 235 | if (ep == NULL || ep->e_type == NODE) |
e0519353 | 236 | continue; |
16e2b8d5 | 237 | if (ep->e_flags & (NEW|EXTRACT)) |
e0519353 KM |
238 | return (start); |
239 | } | |
240 | return (start); | |
241 | } | |
242 | ||
243 | /* | |
244 | * report on a badly formed entry | |
245 | */ | |
451eb9a1 | 246 | void |
e0519353 KM |
247 | badentry(ep, msg) |
248 | register struct entry *ep; | |
249 | char *msg; | |
250 | { | |
e0519353 KM |
251 | |
252 | fprintf(stderr, "bad entry: %s\n", msg); | |
253 | fprintf(stderr, "name: %s\n", myname(ep)); | |
254 | fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); | |
451eb9a1 | 255 | if (ep->e_sibling != NULL) |
e0519353 | 256 | fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); |
451eb9a1 | 257 | if (ep->e_entries != NULL) |
e0519353 | 258 | fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); |
451eb9a1 | 259 | if (ep->e_links != NULL) |
e0519353 | 260 | fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); |
451eb9a1 KB |
261 | if (ep->e_next != NULL) |
262 | fprintf(stderr, | |
263 | "next hashchain name: %s\n", myname(ep->e_next)); | |
e0519353 KM |
264 | fprintf(stderr, "entry type: %s\n", |
265 | ep->e_type == NODE ? "NODE" : "LEAF"); | |
266 | fprintf(stderr, "inode number: %ld\n", ep->e_ino); | |
55f85ba7 KM |
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"); | |
e0519353 KM |
280 | flagbuf[0] = '\0'; |
281 | if (ep->e_flags & REMOVED) | |
55f85ba7 | 282 | (void) strcat(flagbuf, "|REMOVED"); |
e0519353 | 283 | if (ep->e_flags & TMPNAME) |
55f85ba7 | 284 | (void) strcat(flagbuf, "|TMPNAME"); |
e0519353 | 285 | if (ep->e_flags & EXTRACT) |
55f85ba7 | 286 | (void) strcat(flagbuf, "|EXTRACT"); |
e0519353 | 287 | if (ep->e_flags & NEW) |
55f85ba7 | 288 | (void) strcat(flagbuf, "|NEW"); |
e0519353 | 289 | if (ep->e_flags & KEEP) |
55f85ba7 | 290 | (void) strcat(flagbuf, "|KEEP"); |
a7d37956 KM |
291 | if (ep->e_flags & EXISTED) |
292 | (void) strcat(flagbuf, "|EXISTED"); | |
55f85ba7 | 293 | return (&flagbuf[1]); |
e0519353 KM |
294 | } |
295 | ||
38bbfe41 | 296 | /* |
7432ff81 KM |
297 | * Check to see if a name is on a dump tape. |
298 | */ | |
299 | ino_t | |
300 | dirlookup(name) | |
2528da40 | 301 | const char *name; |
7432ff81 KM |
302 | { |
303 | ino_t ino; | |
304 | ||
5231a9f4 | 305 | ino = pathsearch(name)->d_ino; |
c1594b3f | 306 | if (ino == 0 || TSTINO(ino, dumpmap) == 0) |
7432ff81 KM |
307 | fprintf(stderr, "%s is not on tape\n", name); |
308 | return (ino); | |
309 | } | |
310 | ||
e0519353 | 311 | /* |
7432ff81 | 312 | * Elicit a reply. |
e0519353 | 313 | */ |
451eb9a1 | 314 | int |
e0519353 KM |
315 | reply(question) |
316 | char *question; | |
317 | { | |
318 | char c; | |
319 | ||
e0519353 | 320 | do { |
4af95b6b | 321 | fprintf(stderr, "%s? [yn] ", question); |
e9e7ecc4 | 322 | (void) fflush(stderr); |
7432ff81 KM |
323 | c = getc(terminal); |
324 | while (c != '\n' && getc(terminal) != '\n') | |
b8eb5f1f | 325 | if (feof(terminal)) |
4af95b6b | 326 | return (FAIL); |
e0519353 KM |
327 | } while (c != 'y' && c != 'n'); |
328 | if (c == 'y') | |
329 | return (GOOD); | |
330 | return (FAIL); | |
331 | } | |
7432ff81 | 332 | |
7432ff81 KM |
333 | /* |
334 | * handle unexpected inconsistencies | |
335 | */ | |
451eb9a1 KB |
336 | #if __STDC__ |
337 | #include <stdarg.h> | |
338 | #else | |
339 | #include <varargs.h> | |
340 | #endif | |
341 | ||
342 | void | |
343 | #if __STDC__ | |
344 | panic(const char *fmt, ...) | |
345 | #else | |
346 | panic(fmt, va_alist) | |
347 | char *fmt; | |
348 | va_dcl | |
349 | #endif | |
7432ff81 | 350 | { |
451eb9a1 KB |
351 | va_list ap; |
352 | #if __STDC__ | |
353 | va_start(ap, fmt); | |
354 | #else | |
355 | va_start(ap); | |
356 | #endif | |
7432ff81 | 357 | |
451eb9a1 | 358 | vfprintf(stderr, fmt, ap); |
4089a2c8 KM |
359 | if (yflag) |
360 | return; | |
7432ff81 KM |
361 | if (reply("abort") == GOOD) { |
362 | if (reply("dump core") == GOOD) | |
363 | abort(); | |
364 | done(1); | |
365 | } | |
366 | } |