|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: static char sccsid[] = "@(#)utilities.c 5.6 (Berkeley) 6/1/90"; ! 22: #endif /* not lint */ ! 23: ! 24: #include "restore.h" ! 25: ! 26: /* ! 27: * Insure that all the components of a pathname exist. ! 28: */ ! 29: pathcheck(name) ! 30: char *name; ! 31: { ! 32: register char *cp; ! 33: struct entry *ep; ! 34: char *start; ! 35: ! 36: start = index(name, '/'); ! 37: if (start == 0) ! 38: return; ! 39: for (cp = start; *cp != '\0'; cp++) { ! 40: if (*cp != '/') ! 41: continue; ! 42: *cp = '\0'; ! 43: ep = lookupname(name); ! 44: if (ep == NIL) { ! 45: ep = addentry(name, psearch(name), NODE); ! 46: newnode(ep); ! 47: } ! 48: ep->e_flags |= NEW|KEEP; ! 49: *cp = '/'; ! 50: } ! 51: } ! 52: ! 53: /* ! 54: * Change a name to a unique temporary name. ! 55: */ ! 56: mktempname(ep) ! 57: register struct entry *ep; ! 58: { ! 59: char oldname[MAXPATHLEN]; ! 60: ! 61: if (ep->e_flags & TMPNAME) ! 62: badentry(ep, "mktempname: called with TMPNAME"); ! 63: ep->e_flags |= TMPNAME; ! 64: (void) strcpy(oldname, myname(ep)); ! 65: freename(ep->e_name); ! 66: ep->e_name = savename(gentempname(ep)); ! 67: ep->e_namlen = strlen(ep->e_name); ! 68: renameit(oldname, myname(ep)); ! 69: } ! 70: ! 71: /* ! 72: * Generate a temporary name for an entry. ! 73: */ ! 74: char * ! 75: gentempname(ep) ! 76: struct entry *ep; ! 77: { ! 78: static char name[MAXPATHLEN]; ! 79: struct entry *np; ! 80: long i = 0; ! 81: ! 82: for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links) ! 83: i++; ! 84: if (np == NIL) ! 85: badentry(ep, "not on ino list"); ! 86: (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); ! 87: return (name); ! 88: } ! 89: ! 90: /* ! 91: * Rename a file or directory. ! 92: */ ! 93: renameit(from, to) ! 94: char *from, *to; ! 95: { ! 96: if (!Nflag && rename(from, to) < 0) { ! 97: fprintf(stderr, "Warning: cannot rename %s to %s", from, to); ! 98: (void) fflush(stderr); ! 99: perror(""); ! 100: return; ! 101: } ! 102: vprintf(stdout, "rename %s to %s\n", from, to); ! 103: } ! 104: ! 105: /* ! 106: * Create a new node (directory). ! 107: */ ! 108: newnode(np) ! 109: struct entry *np; ! 110: { ! 111: char *cp; ! 112: ! 113: if (np->e_type != NODE) ! 114: badentry(np, "newnode: not a node"); ! 115: cp = myname(np); ! 116: if (!Nflag && mkdir(cp, 0777) < 0) { ! 117: np->e_flags |= EXISTED; ! 118: fprintf(stderr, "Warning: "); ! 119: (void) fflush(stderr); ! 120: perror(cp); ! 121: return; ! 122: } ! 123: vprintf(stdout, "Make node %s\n", cp); ! 124: } ! 125: ! 126: /* ! 127: * Remove an old node (directory). ! 128: */ ! 129: removenode(ep) ! 130: register struct entry *ep; ! 131: { ! 132: char *cp; ! 133: ! 134: if (ep->e_type != NODE) ! 135: badentry(ep, "removenode: not a node"); ! 136: if (ep->e_entries != NIL) ! 137: badentry(ep, "removenode: non-empty directory"); ! 138: ep->e_flags |= REMOVED; ! 139: ep->e_flags &= ~TMPNAME; ! 140: cp = myname(ep); ! 141: if (!Nflag && rmdir(cp) < 0) { ! 142: fprintf(stderr, "Warning: "); ! 143: (void) fflush(stderr); ! 144: perror(cp); ! 145: return; ! 146: } ! 147: vprintf(stdout, "Remove node %s\n", cp); ! 148: } ! 149: ! 150: /* ! 151: * Remove a leaf. ! 152: */ ! 153: removeleaf(ep) ! 154: register struct entry *ep; ! 155: { ! 156: char *cp; ! 157: ! 158: if (ep->e_type != LEAF) ! 159: badentry(ep, "removeleaf: not a leaf"); ! 160: ep->e_flags |= REMOVED; ! 161: ep->e_flags &= ~TMPNAME; ! 162: cp = myname(ep); ! 163: if (!Nflag && unlink(cp) < 0) { ! 164: fprintf(stderr, "Warning: "); ! 165: (void) fflush(stderr); ! 166: perror(cp); ! 167: return; ! 168: } ! 169: vprintf(stdout, "Remove leaf %s\n", cp); ! 170: } ! 171: ! 172: /* ! 173: * Create a link. ! 174: */ ! 175: linkit(existing, new, type) ! 176: char *existing, *new; ! 177: int type; ! 178: { ! 179: ! 180: if (type == SYMLINK) { ! 181: if (!Nflag && symlink(existing, new) < 0) { ! 182: fprintf(stderr, ! 183: "Warning: cannot create symbolic link %s->%s: ", ! 184: new, existing); ! 185: (void) fflush(stderr); ! 186: perror(""); ! 187: return (FAIL); ! 188: } ! 189: } else if (type == HARDLINK) { ! 190: if (!Nflag && link(existing, new) < 0) { ! 191: fprintf(stderr, ! 192: "Warning: cannot create hard link %s->%s: ", ! 193: new, existing); ! 194: (void) fflush(stderr); ! 195: perror(""); ! 196: return (FAIL); ! 197: } ! 198: } else { ! 199: panic("linkit: unknown type %d\n", type); ! 200: return (FAIL); ! 201: } ! 202: vprintf(stdout, "Create %s link %s->%s\n", ! 203: type == SYMLINK ? "symbolic" : "hard", new, existing); ! 204: return (GOOD); ! 205: } ! 206: ! 207: /* ! 208: * find lowest number file (above "start") that needs to be extracted ! 209: */ ! 210: ino_t ! 211: lowerbnd(start) ! 212: ino_t start; ! 213: { ! 214: register struct entry *ep; ! 215: ! 216: for ( ; start < maxino; start++) { ! 217: ep = lookupino(start); ! 218: if (ep == NIL || ep->e_type == NODE) ! 219: continue; ! 220: if (ep->e_flags & (NEW|EXTRACT)) ! 221: return (start); ! 222: } ! 223: return (start); ! 224: } ! 225: ! 226: /* ! 227: * find highest number file (below "start") that needs to be extracted ! 228: */ ! 229: ino_t ! 230: upperbnd(start) ! 231: ino_t start; ! 232: { ! 233: register struct entry *ep; ! 234: ! 235: for ( ; start > ROOTINO; start--) { ! 236: ep = lookupino(start); ! 237: if (ep == NIL || ep->e_type == NODE) ! 238: continue; ! 239: if (ep->e_flags & (NEW|EXTRACT)) ! 240: return (start); ! 241: } ! 242: return (start); ! 243: } ! 244: ! 245: /* ! 246: * report on a badly formed entry ! 247: */ ! 248: badentry(ep, msg) ! 249: register struct entry *ep; ! 250: char *msg; ! 251: { ! 252: ! 253: fprintf(stderr, "bad entry: %s\n", msg); ! 254: fprintf(stderr, "name: %s\n", myname(ep)); ! 255: fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); ! 256: if (ep->e_sibling != NIL) ! 257: fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); ! 258: if (ep->e_entries != NIL) ! 259: fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); ! 260: if (ep->e_links != NIL) ! 261: fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); ! 262: if (ep->e_next != NIL) ! 263: fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next)); ! 264: fprintf(stderr, "entry type: %s\n", ! 265: ep->e_type == NODE ? "NODE" : "LEAF"); ! 266: fprintf(stderr, "inode number: %ld\n", ep->e_ino); ! 267: panic("flags: %s\n", flagvalues(ep)); ! 268: } ! 269: ! 270: /* ! 271: * Construct a string indicating the active flag bits of an entry. ! 272: */ ! 273: char * ! 274: flagvalues(ep) ! 275: register struct entry *ep; ! 276: { ! 277: static char flagbuf[BUFSIZ]; ! 278: ! 279: (void) strcpy(flagbuf, "|NIL"); ! 280: flagbuf[0] = '\0'; ! 281: if (ep->e_flags & REMOVED) ! 282: (void) strcat(flagbuf, "|REMOVED"); ! 283: if (ep->e_flags & TMPNAME) ! 284: (void) strcat(flagbuf, "|TMPNAME"); ! 285: if (ep->e_flags & EXTRACT) ! 286: (void) strcat(flagbuf, "|EXTRACT"); ! 287: if (ep->e_flags & NEW) ! 288: (void) strcat(flagbuf, "|NEW"); ! 289: if (ep->e_flags & KEEP) ! 290: (void) strcat(flagbuf, "|KEEP"); ! 291: if (ep->e_flags & EXISTED) ! 292: (void) strcat(flagbuf, "|EXISTED"); ! 293: return (&flagbuf[1]); ! 294: } ! 295: ! 296: /* ! 297: * Check to see if a name is on a dump tape. ! 298: */ ! 299: ino_t ! 300: dirlookup(name) ! 301: char *name; ! 302: { ! 303: ino_t ino; ! 304: ! 305: ino = psearch(name); ! 306: if (ino == 0 || BIT(ino, dumpmap) == 0) ! 307: fprintf(stderr, "%s is not on tape\n", name); ! 308: return (ino); ! 309: } ! 310: ! 311: /* ! 312: * Elicit a reply. ! 313: */ ! 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: /* VARARGS1 */ ! 336: panic(msg, d1, d2) ! 337: char *msg; ! 338: long d1, d2; ! 339: { ! 340: ! 341: fprintf(stderr, msg, d1, d2); ! 342: if (yflag) ! 343: return; ! 344: if (reply("abort") == GOOD) { ! 345: if (reply("dump core") == GOOD) ! 346: abort(); ! 347: done(1); ! 348: } ! 349: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.