1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #ifndef lint 33 #endif /* not lint */ 34 35 /* 36 * These routines maintain the symbol table which tracks the state 37 * of the file system being restored. They provide lookup by either 38 * name or inode number. They also provide for creation, deletion, 39 * and renaming of entries. Because of the dynamic nature of pathnames, 40 * names should not be saved, but always constructed just before they 41 * are needed, by calling "myname". 42 */ 43 44 #include <sys/param.h> 45 #include <sys/stat.h> 46 47 #include <ufs/ufs/dinode.h> 48 49 #include <errno.h> 50 #include <fcntl.h> 51 #include <limits.h> 52 #include <stdint.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <unistd.h> 57 58 #include "restore.h" 59 #include "extern.h" 60 61 /* 62 * The following variables define the inode symbol table. 63 * The primary hash table is dynamically allocated based on 64 * the number of inodes in the file system (maxino), scaled by 65 * HASHFACTOR. The variable "entry" points to the hash table; 66 * the variable "entrytblsize" indicates its size (in entries). 67 */ 68 #define HASHFACTOR 5 69 static struct entry **entry; 70 static long entrytblsize; 71 72 static void addino(ino_t, struct entry *); 73 static struct entry *lookupparent(char *); 74 static void removeentry(struct entry *); 75 76 /* 77 * Look up an entry by inode number 78 */ 79 struct entry * 80 lookupino(ino_t inum) 81 { 82 struct entry *ep; 83 84 if (inum < UFS_WINO || inum >= maxino) 85 return (NULL); 86 for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next) 87 if (ep->e_ino == inum) 88 return (ep); 89 return (NULL); 90 } 91 92 /* 93 * Add an entry into the entry table 94 */ 95 static void 96 addino(ino_t inum, struct entry *np) 97 { 98 struct entry **epp; 99 100 if (inum < UFS_WINO || inum >= maxino) 101 panic("addino: out of range %ju\n", (uintmax_t)inum); 102 epp = &entry[inum % entrytblsize]; 103 np->e_ino = inum; 104 np->e_next = *epp; 105 *epp = np; 106 if (dflag) 107 for (np = np->e_next; np != NULL; np = np->e_next) 108 if (np->e_ino == inum) 109 badentry(np, "duplicate inum"); 110 } 111 112 /* 113 * Delete an entry from the entry table 114 */ 115 void 116 deleteino(ino_t inum) 117 { 118 struct entry *next; 119 struct entry **prev; 120 121 if (inum < UFS_WINO || inum >= maxino) 122 panic("deleteino: out of range %ju\n", (uintmax_t)inum); 123 prev = &entry[inum % entrytblsize]; 124 for (next = *prev; next != NULL; next = next->e_next) { 125 if (next->e_ino == inum) { 126 next->e_ino = 0; 127 *prev = next->e_next; 128 return; 129 } 130 prev = &next->e_next; 131 } 132 panic("deleteino: %ju not found\n", (uintmax_t)inum); 133 } 134 135 /* 136 * Look up an entry by name 137 */ 138 struct entry * 139 lookupname(char *name) 140 { 141 struct entry *ep; 142 char *np, *cp; 143 char buf[MAXPATHLEN]; 144 145 cp = name; 146 for (ep = lookupino(UFS_ROOTINO); ep != NULL; ep = ep->e_entries) { 147 for (np = buf; *cp != '/' && *cp != '\0' && 148 np < &buf[sizeof(buf)]; ) 149 *np++ = *cp++; 150 if (np == &buf[sizeof(buf)]) 151 break; 152 *np = '\0'; 153 for ( ; ep != NULL; ep = ep->e_sibling) 154 if (strcmp(ep->e_name, buf) == 0) 155 break; 156 if (ep == NULL) 157 break; 158 if (*cp++ == '\0') 159 return (ep); 160 } 161 return (NULL); 162 } 163 164 /* 165 * Look up the parent of a pathname 166 */ 167 static struct entry * 168 lookupparent(char *name) 169 { 170 struct entry *ep; 171 char *tailindex; 172 173 tailindex = strrchr(name, '/'); 174 if (tailindex == NULL) 175 return (NULL); 176 *tailindex = '\0'; 177 ep = lookupname(name); 178 *tailindex = '/'; 179 if (ep == NULL) 180 return (NULL); 181 if (ep->e_type != NODE) 182 panic("%s is not a directory\n", name); 183 return (ep); 184 } 185 186 /* 187 * Determine the current pathname of a node or leaf 188 */ 189 char * 190 myname(struct entry *ep) 191 { 192 char *cp; 193 static char namebuf[MAXPATHLEN]; 194 195 for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) { 196 cp -= ep->e_namlen; 197 memmove(cp, ep->e_name, (long)ep->e_namlen); 198 if (ep == lookupino(UFS_ROOTINO)) 199 return (cp); 200 *(--cp) = '/'; 201 ep = ep->e_parent; 202 } 203 panic("%s: pathname too long\n", cp); 204 return(cp); 205 } 206 207 /* 208 * Unused symbol table entries are linked together on a free list 209 * headed by the following pointer. 210 */ 211 static struct entry *freelist = NULL; 212 213 /* 214 * add an entry to the symbol table 215 */ 216 struct entry * 217 addentry(char *name, ino_t inum, int type) 218 { 219 struct entry *np, *ep; 220 221 if (freelist != NULL) { 222 np = freelist; 223 freelist = np->e_next; 224 memset(np, 0, (long)sizeof(struct entry)); 225 } else { 226 np = (struct entry *)calloc(1, sizeof(struct entry)); 227 if (np == NULL) 228 panic("no memory to extend symbol table\n"); 229 } 230 np->e_type = type & ~LINK; 231 ep = lookupparent(name); 232 if (ep == NULL) { 233 if (inum != UFS_ROOTINO || lookupino(UFS_ROOTINO) != NULL) 234 panic("bad name to addentry %s\n", name); 235 np->e_name = savename(name); 236 np->e_namlen = strlen(name); 237 np->e_parent = np; 238 addino(UFS_ROOTINO, np); 239 return (np); 240 } 241 np->e_name = savename(strrchr(name, '/') + 1); 242 np->e_namlen = strlen(np->e_name); 243 np->e_parent = ep; 244 np->e_sibling = ep->e_entries; 245 ep->e_entries = np; 246 if (type & LINK) { 247 ep = lookupino(inum); 248 if (ep == NULL) 249 panic("link to non-existent name\n"); 250 np->e_ino = inum; 251 np->e_links = ep->e_links; 252 ep->e_links = np; 253 } else if (inum != 0) { 254 if (lookupino(inum) != NULL) 255 panic("duplicate entry\n"); 256 addino(inum, np); 257 } 258 return (np); 259 } 260 261 /* 262 * delete an entry from the symbol table 263 */ 264 void 265 freeentry(struct entry *ep) 266 { 267 struct entry *np; 268 ino_t inum; 269 270 if (ep->e_flags != REMOVED) 271 badentry(ep, "not marked REMOVED"); 272 if (ep->e_type == NODE) { 273 if (ep->e_links != NULL) 274 badentry(ep, "freeing referenced directory"); 275 if (ep->e_entries != NULL) 276 badentry(ep, "freeing non-empty directory"); 277 } 278 if (ep->e_ino != 0) { 279 np = lookupino(ep->e_ino); 280 if (np == NULL) 281 badentry(ep, "lookupino failed"); 282 if (np == ep) { 283 inum = ep->e_ino; 284 deleteino(inum); 285 if (ep->e_links != NULL) 286 addino(inum, ep->e_links); 287 } else { 288 for (; np != NULL; np = np->e_links) { 289 if (np->e_links == ep) { 290 np->e_links = ep->e_links; 291 break; 292 } 293 } 294 if (np == NULL) 295 badentry(ep, "link not found"); 296 } 297 } 298 removeentry(ep); 299 freename(ep->e_name); 300 ep->e_next = freelist; 301 freelist = ep; 302 } 303 304 /* 305 * Relocate an entry in the tree structure 306 */ 307 void 308 moveentry(struct entry *ep, char *newname) 309 { 310 struct entry *np; 311 char *cp; 312 313 np = lookupparent(newname); 314 if (np == NULL) 315 badentry(ep, "cannot move ROOT"); 316 if (np != ep->e_parent) { 317 removeentry(ep); 318 ep->e_parent = np; 319 ep->e_sibling = np->e_entries; 320 np->e_entries = ep; 321 } 322 cp = strrchr(newname, '/') + 1; 323 freename(ep->e_name); 324 ep->e_name = savename(cp); 325 ep->e_namlen = strlen(cp); 326 if (strcmp(gentempname(ep), ep->e_name) == 0) 327 ep->e_flags |= TMPNAME; 328 else 329 ep->e_flags &= ~TMPNAME; 330 } 331 332 /* 333 * Remove an entry in the tree structure 334 */ 335 static void 336 removeentry(struct entry *ep) 337 { 338 struct entry *np; 339 340 np = ep->e_parent; 341 if (np->e_entries == ep) { 342 np->e_entries = ep->e_sibling; 343 } else { 344 for (np = np->e_entries; np != NULL; np = np->e_sibling) { 345 if (np->e_sibling == ep) { 346 np->e_sibling = ep->e_sibling; 347 break; 348 } 349 } 350 if (np == NULL) 351 badentry(ep, "cannot find entry in parent list"); 352 } 353 } 354 355 /* 356 * Table of unused string entries, sorted by length. 357 * 358 * Entries are allocated in STRTBLINCR sized pieces so that names 359 * of similar lengths can use the same entry. The value of STRTBLINCR 360 * is chosen so that every entry has at least enough space to hold 361 * a "struct strtbl" header. Thus every entry can be linked onto an 362 * appropriate free list. 363 * 364 * NB. The macro "allocsize" below assumes that "struct strhdr" 365 * has a size that is a power of two. 366 */ 367 struct strhdr { 368 struct strhdr *next; 369 }; 370 371 #define STRTBLINCR (sizeof(struct strhdr)) 372 #define allocsize(size) roundup2((size) + 1, STRTBLINCR) 373 374 static struct strhdr strtblhdr[allocsize(NAME_MAX) / STRTBLINCR]; 375 376 /* 377 * Allocate space for a name. It first looks to see if it already 378 * has an appropriate sized entry, and if not allocates a new one. 379 */ 380 char * 381 savename(char *name) 382 { 383 struct strhdr *np; 384 size_t len; 385 char *cp; 386 387 if (name == NULL) 388 panic("bad name\n"); 389 len = strlen(name); 390 np = strtblhdr[len / STRTBLINCR].next; 391 if (np != NULL) { 392 strtblhdr[len / STRTBLINCR].next = np->next; 393 cp = (char *)np; 394 } else { 395 cp = malloc(allocsize(len)); 396 if (cp == NULL) 397 panic("no space for string table\n"); 398 } 399 (void) strcpy(cp, name); 400 return (cp); 401 } 402 403 /* 404 * Free space for a name. The resulting entry is linked onto the 405 * appropriate free list. 406 */ 407 void 408 freename(char *name) 409 { 410 struct strhdr *tp, *np; 411 412 tp = &strtblhdr[strlen(name) / STRTBLINCR]; 413 np = (struct strhdr *)name; 414 np->next = tp->next; 415 tp->next = np; 416 } 417 418 /* 419 * Useful quantities placed at the end of a dumped symbol table. 420 */ 421 struct symtableheader { 422 int32_t volno; 423 int32_t stringsize; 424 int32_t entrytblsize; 425 time_t dumptime; 426 time_t dumpdate; 427 ino_t maxino; 428 int32_t ntrec; 429 }; 430 431 /* 432 * dump a snapshot of the symbol table 433 */ 434 void 435 dumpsymtable(char *filename, long checkpt) 436 { 437 struct entry *ep, *tep; 438 ino_t i; 439 struct entry temp, *tentry; 440 long mynum = 1, stroff = 0; 441 FILE *fd; 442 struct symtableheader hdr; 443 444 vprintf(stdout, "Checkpointing the restore\n"); 445 if (Nflag) 446 return; 447 if ((fd = fopen(filename, "w")) == NULL) { 448 fprintf(stderr, "fopen: %s\n", strerror(errno)); 449 panic("cannot create save file %s for symbol table\n", 450 filename); 451 done(1); 452 } 453 clearerr(fd); 454 /* 455 * Assign indices to each entry 456 * Write out the string entries 457 */ 458 for (i = UFS_WINO; i <= maxino; i++) { 459 for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { 460 ep->e_index = mynum++; 461 (void) fwrite(ep->e_name, sizeof(char), 462 (int)allocsize(ep->e_namlen), fd); 463 } 464 } 465 /* 466 * Convert pointers to indexes, and output 467 */ 468 tep = &temp; 469 stroff = 0; 470 for (i = UFS_WINO; i <= maxino; i++) { 471 for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { 472 memmove(tep, ep, (long)sizeof(struct entry)); 473 tep->e_name = (char *)stroff; 474 stroff += allocsize(ep->e_namlen); 475 tep->e_parent = (struct entry *)ep->e_parent->e_index; 476 if (ep->e_links != NULL) 477 tep->e_links = 478 (struct entry *)ep->e_links->e_index; 479 if (ep->e_sibling != NULL) 480 tep->e_sibling = 481 (struct entry *)ep->e_sibling->e_index; 482 if (ep->e_entries != NULL) 483 tep->e_entries = 484 (struct entry *)ep->e_entries->e_index; 485 if (ep->e_next != NULL) 486 tep->e_next = 487 (struct entry *)ep->e_next->e_index; 488 (void) fwrite((char *)tep, sizeof(struct entry), 1, fd); 489 } 490 } 491 /* 492 * Convert entry pointers to indexes, and output 493 */ 494 for (i = 0; i < entrytblsize; i++) { 495 if (entry[i] == NULL) 496 tentry = NULL; 497 else 498 tentry = (struct entry *)entry[i]->e_index; 499 (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd); 500 } 501 hdr.volno = checkpt; 502 hdr.maxino = maxino; 503 hdr.entrytblsize = entrytblsize; 504 hdr.stringsize = stroff; 505 hdr.dumptime = dumptime; 506 hdr.dumpdate = dumpdate; 507 hdr.ntrec = ntrec; 508 (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd); 509 if (ferror(fd)) { 510 fprintf(stderr, "fwrite: %s\n", strerror(errno)); 511 panic("output error to file %s writing symbol table\n", 512 filename); 513 } 514 (void) fclose(fd); 515 } 516 517 /* 518 * Initialize a symbol table from a file 519 */ 520 void 521 initsymtable(char *filename) 522 { 523 char *base; 524 long tblsize; 525 struct entry *ep; 526 struct entry *baseep, *lep; 527 struct symtableheader hdr; 528 struct stat stbuf; 529 long i; 530 int fd; 531 532 vprintf(stdout, "Initialize symbol table.\n"); 533 if (filename == NULL) { 534 entrytblsize = maxino / HASHFACTOR; 535 entry = calloc((unsigned)entrytblsize, sizeof(struct entry *)); 536 if (entry == NULL) 537 panic("no memory for entry table\n"); 538 ep = addentry(".", UFS_ROOTINO, NODE); 539 ep->e_flags |= NEW; 540 return; 541 } 542 if ((fd = open(filename, O_RDONLY, 0)) < 0) { 543 fprintf(stderr, "open: %s\n", strerror(errno)); 544 panic("cannot open symbol table file %s\n", filename); 545 } 546 if (fstat(fd, &stbuf) < 0) { 547 fprintf(stderr, "stat: %s\n", strerror(errno)); 548 panic("cannot stat symbol table file %s\n", filename); 549 } 550 tblsize = stbuf.st_size - sizeof(struct symtableheader); 551 base = calloc(sizeof(char), (unsigned)tblsize); 552 if (base == NULL) 553 panic("cannot allocate space for symbol table\n"); 554 if (read(fd, base, (int)tblsize) < 0 || 555 read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) { 556 fprintf(stderr, "read: %s\n", strerror(errno)); 557 panic("cannot read symbol table file %s\n", filename); 558 } 559 (void)close(fd); 560 switch (command) { 561 case 'r': 562 /* 563 * For normal continuation, insure that we are using 564 * the next incremental tape 565 */ 566 if (hdr.dumpdate != dumptime) { 567 if (hdr.dumpdate < dumptime) 568 fprintf(stderr, "Incremental tape too low\n"); 569 else 570 fprintf(stderr, "Incremental tape too high\n"); 571 done(1); 572 } 573 break; 574 case 'R': 575 /* 576 * For restart, insure that we are using the same tape 577 */ 578 curfile.action = SKIP; 579 dumptime = hdr.dumptime; 580 dumpdate = hdr.dumpdate; 581 if (!bflag) 582 newtapebuf(hdr.ntrec); 583 getvol(hdr.volno); 584 break; 585 default: 586 panic("initsymtable called from command %c\n", command); 587 break; 588 } 589 maxino = hdr.maxino; 590 entrytblsize = hdr.entrytblsize; 591 entry = (struct entry **) 592 (base + tblsize - (entrytblsize * sizeof(struct entry *))); 593 baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry)); 594 lep = (struct entry *)entry; 595 for (i = 0; i < entrytblsize; i++) { 596 if (entry[i] == NULL) 597 continue; 598 entry[i] = &baseep[(long)entry[i]]; 599 } 600 for (ep = &baseep[1]; ep < lep; ep++) { 601 ep->e_name = base + (long)ep->e_name; 602 ep->e_parent = &baseep[(long)ep->e_parent]; 603 if (ep->e_sibling != NULL) 604 ep->e_sibling = &baseep[(long)ep->e_sibling]; 605 if (ep->e_links != NULL) 606 ep->e_links = &baseep[(long)ep->e_links]; 607 if (ep->e_entries != NULL) 608 ep->e_entries = &baseep[(long)ep->e_entries]; 609 if (ep->e_next != NULL) 610 ep->e_next = &baseep[(long)ep->e_next]; 611 } 612 } 613