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