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