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