xref: /csrg-svn/sbin/restore/utilities.c (revision 10315)
1*10315Smckusick /* Copyright (c) 1983 Regents of the University of California */
2*10315Smckusick 
3*10315Smckusick #ifndef lint
4*10315Smckusick static char sccsid[] = "@(#)utilities.c	3.5	(Berkeley)	83/01/16";
5*10315Smckusick #endif
6*10315Smckusick 
7*10315Smckusick #include "restore.h"
8*10315Smckusick 
9*10315Smckusick /*
10*10315Smckusick  * Insure that all the components of a pathname exist.
11*10315Smckusick  */
12*10315Smckusick pathcheck(name)
13*10315Smckusick 	char *name;
14*10315Smckusick {
15*10315Smckusick 	register char *cp;
16*10315Smckusick 	struct entry *ep;
17*10315Smckusick 	char *start;
18*10315Smckusick 
19*10315Smckusick 	start = index(name, '/');
20*10315Smckusick 	if (start == 0)
21*10315Smckusick 		return;
22*10315Smckusick 	for (cp = start; *cp != '\0'; cp++) {
23*10315Smckusick 		if (*cp != '/')
24*10315Smckusick 			continue;
25*10315Smckusick 		*cp = '\0';
26*10315Smckusick 		ep = lookupname(name);
27*10315Smckusick 		if (ep == NIL) {
28*10315Smckusick 			ep = addentry(name, ep->e_ino, NODE);
29*10315Smckusick 			ep->e_flags |= KEEP;
30*10315Smckusick 			newnode(ep);
31*10315Smckusick 		}
32*10315Smckusick 		*cp = '/';
33*10315Smckusick 	}
34*10315Smckusick }
35*10315Smckusick 
36*10315Smckusick /*
37*10315Smckusick  * Change a name to a unique temporary name.
38*10315Smckusick  */
39*10315Smckusick mktempname(ep)
40*10315Smckusick 	register struct entry *ep;
41*10315Smckusick {
42*10315Smckusick 	char oldname[BUFSIZ];
43*10315Smckusick 
44*10315Smckusick 	if (ep->e_flags & TMPNAME)
45*10315Smckusick 		badentry(ep, "mktempname: called with TMPNAME");
46*10315Smckusick 	ep->e_flags |= TMPNAME;
47*10315Smckusick 	strcpy(oldname, myname(ep));
48*10315Smckusick 	ep->e_name[ep->e_namlen++] = TMPCHAR;
49*10315Smckusick 	ep->e_name[ep->e_namlen] = '\0';
50*10315Smckusick 	renameit(oldname, myname(ep));
51*10315Smckusick }
52*10315Smckusick 
53*10315Smckusick /*
54*10315Smckusick  * Rename a file or directory.
55*10315Smckusick  */
56*10315Smckusick renameit(from, to)
57*10315Smckusick 	char *from, *to;
58*10315Smckusick {
59*10315Smckusick 	if (rename(from, to) < 0) {
60*10315Smckusick 		perror("renameit");
61*10315Smckusick 		panic("Cannot rename %s to %s\n", from, to);
62*10315Smckusick 	}
63*10315Smckusick 	vprintf(stdout, "rename %s to %s\n", from, to);
64*10315Smckusick }
65*10315Smckusick 
66*10315Smckusick /*
67*10315Smckusick  * Create a new node (directory).
68*10315Smckusick  */
69*10315Smckusick newnode(np)
70*10315Smckusick 	struct entry *np;
71*10315Smckusick {
72*10315Smckusick 	char *cp;
73*10315Smckusick 
74*10315Smckusick 	if (np->e_type != NODE)
75*10315Smckusick 		badentry(np, "newnode: not a node");
76*10315Smckusick 	cp = myname(np);
77*10315Smckusick 	if (mkdir(cp, 0777) < 0) {
78*10315Smckusick 		if (command == 'x') {
79*10315Smckusick 			perror(cp);
80*10315Smckusick 			return;
81*10315Smckusick 		}
82*10315Smckusick 		perror("newnode");
83*10315Smckusick 		panic("Cannot make node %s\n", cp);
84*10315Smckusick 	}
85*10315Smckusick 	vprintf(stdout, "Make node %s\n", cp);
86*10315Smckusick }
87*10315Smckusick 
88*10315Smckusick /*
89*10315Smckusick  * Remove an old node (directory).
90*10315Smckusick  */
91*10315Smckusick removenode(ep)
92*10315Smckusick 	register struct entry *ep;
93*10315Smckusick {
94*10315Smckusick 	char *cp;
95*10315Smckusick 
96*10315Smckusick 	if (ep->e_type != NODE)
97*10315Smckusick 		badentry(ep, "removenode: not a node");
98*10315Smckusick 	if (ep->e_entries != NIL)
99*10315Smckusick 		badentry(ep, "removenode: non-empty directory");
100*10315Smckusick 	cp = myname(ep);
101*10315Smckusick 	if (rmdir(cp) < 0) {
102*10315Smckusick 		perror("removenode");
103*10315Smckusick 		panic("Cannot remove node %s\n", cp);
104*10315Smckusick 	}
105*10315Smckusick 	ep->e_flags |= REMOVED;
106*10315Smckusick 	ep->e_flags &= ~TMPNAME;
107*10315Smckusick 	vprintf(stdout, "Remove node %s\n", cp);
108*10315Smckusick }
109*10315Smckusick 
110*10315Smckusick /*
111*10315Smckusick  * Remove a leaf.
112*10315Smckusick  */
113*10315Smckusick removeleaf(ep)
114*10315Smckusick 	register struct entry *ep;
115*10315Smckusick {
116*10315Smckusick 	char *cp;
117*10315Smckusick 
118*10315Smckusick 	if (ep->e_type != LEAF)
119*10315Smckusick 		badentry(ep, "removeleaf: not a leaf");
120*10315Smckusick 	cp = myname(ep);
121*10315Smckusick 	if (unlink(cp) < 0) {
122*10315Smckusick 		perror("removeleaf");
123*10315Smckusick 		panic("Cannot remove leaf %s\n", cp);
124*10315Smckusick 	}
125*10315Smckusick 	ep->e_flags |= REMOVED;
126*10315Smckusick 	ep->e_flags &= ~TMPNAME;
127*10315Smckusick 	vprintf(stdout, "Remove leaf %s\n", cp);
128*10315Smckusick }
129*10315Smckusick 
130*10315Smckusick /*
131*10315Smckusick  * Create a link.
132*10315Smckusick  */
133*10315Smckusick linkit(existing, new, type)
134*10315Smckusick 	char *existing, *new;
135*10315Smckusick 	int type;
136*10315Smckusick {
137*10315Smckusick 
138*10315Smckusick 	if (type == SYMLINK) {
139*10315Smckusick 		if (symlink(existing, new) < 0) {
140*10315Smckusick 			perror("linkit");
141*10315Smckusick 			panic("Cannot create symbolic link %s->%s\n",
142*10315Smckusick 				new, existing);
143*10315Smckusick 		}
144*10315Smckusick 	} else if (type == HARDLINK) {
145*10315Smckusick 		if (link(existing, new) < 0) {
146*10315Smckusick 			perror("linkit");
147*10315Smckusick 			panic("Cannot create hard link %s->%s\n",
148*10315Smckusick 				new, existing);
149*10315Smckusick 		}
150*10315Smckusick 	} else {
151*10315Smckusick 		panic("linkit: unknown type %d\n", type);
152*10315Smckusick 	}
153*10315Smckusick 	vprintf(stdout, "Create %s link %s->%s\n",
154*10315Smckusick 		type == SYMLINK ? "symbolic" : "hard", new, existing);
155*10315Smckusick }
156*10315Smckusick 
157*10315Smckusick /*
158*10315Smckusick  * find lowest number file (above "start") that needs to be extracted
159*10315Smckusick  */
160*10315Smckusick ino_t
161*10315Smckusick lowerbnd(start)
162*10315Smckusick 	ino_t start;
163*10315Smckusick {
164*10315Smckusick 	register struct entry *ep;
165*10315Smckusick 
166*10315Smckusick 	for ( ; start < maxino; start++) {
167*10315Smckusick 		ep = lookupino(start);
168*10315Smckusick 		if (ep == NIL)
169*10315Smckusick 			continue;
170*10315Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
171*10315Smckusick 			return (start);
172*10315Smckusick 	}
173*10315Smckusick 	return (start);
174*10315Smckusick }
175*10315Smckusick 
176*10315Smckusick /*
177*10315Smckusick  * find highest number file (below "start") that needs to be extracted
178*10315Smckusick  */
179*10315Smckusick ino_t
180*10315Smckusick upperbnd(start)
181*10315Smckusick 	ino_t start;
182*10315Smckusick {
183*10315Smckusick 	register struct entry *ep;
184*10315Smckusick 
185*10315Smckusick 	for ( ; start > ROOTINO; start--) {
186*10315Smckusick 		ep = lookupino(start);
187*10315Smckusick 		if (ep == NIL)
188*10315Smckusick 			continue;
189*10315Smckusick 		if (ep->e_flags & (NEW|EXTRACT))
190*10315Smckusick 			return (start);
191*10315Smckusick 	}
192*10315Smckusick 	return (start);
193*10315Smckusick }
194*10315Smckusick 
195*10315Smckusick /*
196*10315Smckusick  * report on a badly formed entry
197*10315Smckusick  */
198*10315Smckusick badentry(ep, msg)
199*10315Smckusick 	register struct entry *ep;
200*10315Smckusick 	char *msg;
201*10315Smckusick {
202*10315Smckusick 	char flagbuf[BUFSIZ];
203*10315Smckusick 
204*10315Smckusick 	fprintf(stderr, "bad entry: %s\n", msg);
205*10315Smckusick 	fprintf(stderr, "name: %s\n", myname(ep));
206*10315Smckusick 	fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
207*10315Smckusick 	if (ep->e_sibling != NIL)
208*10315Smckusick 		fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
209*10315Smckusick 	if (ep->e_entries != NIL)
210*10315Smckusick 		fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
211*10315Smckusick 	if (ep->e_links != NIL)
212*10315Smckusick 		fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
213*10315Smckusick 	if (ep->e_next != NIL)
214*10315Smckusick 		fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next));
215*10315Smckusick 	fprintf(stderr, "entry type: %s\n",
216*10315Smckusick 		ep->e_type == NODE ? "NODE" : "LEAF");
217*10315Smckusick 	fprintf(stderr, "inode number: %ld\n", ep->e_ino);
218*10315Smckusick 	strcpy(flagbuf, "|NIL");
219*10315Smckusick 	flagbuf[0] = '\0';
220*10315Smckusick 	if (ep->e_flags & REMOVED)
221*10315Smckusick 		strcat(flagbuf, "|REMOVED");
222*10315Smckusick 	if (ep->e_flags & TMPNAME)
223*10315Smckusick 		strcat(flagbuf, "|TMPNAME");
224*10315Smckusick 	if (ep->e_flags & EXTRACT)
225*10315Smckusick 		strcat(flagbuf, "|EXTRACT");
226*10315Smckusick 	if (ep->e_flags & NEW)
227*10315Smckusick 		strcat(flagbuf, "|NEW");
228*10315Smckusick 	if (ep->e_flags & KEEP)
229*10315Smckusick 		strcat(flagbuf, "|KEEP");
230*10315Smckusick 	panic("flags: %s\n", &flagbuf[1]);
231*10315Smckusick }
232*10315Smckusick 
233*10315Smckusick /*
234*10315Smckusick  * canonicalize file names to always start with ``./''
235*10315Smckusick  */
236*10315Smckusick canon(rawname, canonname)
237*10315Smckusick 	char *rawname, *canonname;
238*10315Smckusick {
239*10315Smckusick 	int len;
240*10315Smckusick 
241*10315Smckusick 	if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0)
242*10315Smckusick 		(void) strcpy(canonname, "");
243*10315Smckusick 	else if (rawname[0] == '/')
244*10315Smckusick 		(void) strcpy(canonname, ".");
245*10315Smckusick 	else
246*10315Smckusick 		(void) strcpy(canonname, "./");
247*10315Smckusick 	(void) strcat(canonname, rawname);
248*10315Smckusick 	len = strlen(canonname) - 1;
249*10315Smckusick 	if (canonname[len] == '/')
250*10315Smckusick 		canonname[len] = '\0';
251*10315Smckusick }
252*10315Smckusick 
253*10315Smckusick /*
254*10315Smckusick  * elicit a reply
255*10315Smckusick  */
256*10315Smckusick reply(question)
257*10315Smckusick 	char *question;
258*10315Smckusick {
259*10315Smckusick 	char c;
260*10315Smckusick 
261*10315Smckusick 	fprintf(stderr, "%s? ", question);
262*10315Smckusick 	do	{
263*10315Smckusick 		fprintf(stderr, "[yn] ");
264*10315Smckusick 		c = getchar();
265*10315Smckusick 		while (c != '\n' && getchar() != '\n')
266*10315Smckusick 			/* void */;
267*10315Smckusick 	} while (c != 'y' && c != 'n');
268*10315Smckusick 	if (c == 'y')
269*10315Smckusick 		return (GOOD);
270*10315Smckusick 	return (FAIL);
271*10315Smckusick }
272