try to make sure that path-addrs always have <angle brackets>
[unix-history] / usr / src / sbin / restore / utilities.c
CommitLineData
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 9static 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 30void
16e2b8d5 31pathcheck(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 58void
e0519353
KM
59mktempname(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 */
77char *
78gentempname(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 97void
e0519353
KM
98renameit(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 112void
e0519353
KM
113newnode(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 132void
e0519353
KM
133removenode(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 155void
e0519353
KM
156removeleaf(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 176int
e0519353
KM
177linkit(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 */
208ino_t
209lowerbnd(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 */
227ino_t
228upperbnd(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 246void
e0519353
KM
247badentry(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 */
273char *
274flagvalues(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 */
299ino_t
300dirlookup(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 314int
e0519353
KM
315reply(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
342void
343#if __STDC__
344panic(const char *fmt, ...)
345#else
346panic(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}