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