1*8a16b7a1SPedro F. Giffuni /*-
2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
3*8a16b7a1SPedro F. Giffuni *
48fae3551SRodney W. Grimes * Copyright (c) 1983, 1993
58fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved.
68fae3551SRodney W. Grimes *
78fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without
88fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions
98fae3551SRodney W. Grimes * are met:
108fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer.
128fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
138fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
148fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution.
15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
168fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software
178fae3551SRodney W. Grimes * without specific prior written permission.
188fae3551SRodney W. Grimes *
198fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
208fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
218fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
228fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
238fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
248fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
258fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
268fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
278fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
288fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
298fae3551SRodney W. Grimes * SUCH DAMAGE.
308fae3551SRodney W. Grimes */
318fae3551SRodney W. Grimes
328fae3551SRodney W. Grimes #include <sys/types.h>
338fae3551SRodney W. Grimes
3489fdc4e1SMike Barcroft #include <limits.h>
35e25a029eSMatthew D Fleming #include <stdint.h>
368fae3551SRodney W. Grimes #include <stdio.h>
378fae3551SRodney W. Grimes #include <string.h>
388fae3551SRodney W. Grimes
391c85e6a3SKirk McKusick #include <ufs/ufs/dinode.h>
401c85e6a3SKirk McKusick
418fae3551SRodney W. Grimes #include "restore.h"
428fae3551SRodney W. Grimes #include "extern.h"
438fae3551SRodney W. Grimes
442db673abSWarner Losh static char *keyval(int);
458fae3551SRodney W. Grimes
468fae3551SRodney W. Grimes /*
478fae3551SRodney W. Grimes * This implements the 't' option.
488fae3551SRodney W. Grimes * List entries on the tape.
498fae3551SRodney W. Grimes */
508fae3551SRodney W. Grimes long
listfile(char * name,ino_t ino,int type)512db673abSWarner Losh listfile(char *name, ino_t ino, int type)
528fae3551SRodney W. Grimes {
538fae3551SRodney W. Grimes long descend = hflag ? GOOD : FAIL;
548fae3551SRodney W. Grimes
558fae3551SRodney W. Grimes if (TSTINO(ino, dumpmap) == 0)
568fae3551SRodney W. Grimes return (descend);
578fae3551SRodney W. Grimes vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
58e25a029eSMatthew D Fleming fprintf(stdout, "%10ju\t%s\n", (uintmax_t)ino, name);
598fae3551SRodney W. Grimes return (descend);
608fae3551SRodney W. Grimes }
618fae3551SRodney W. Grimes
628fae3551SRodney W. Grimes /*
638fae3551SRodney W. Grimes * This implements the 'x' option.
648fae3551SRodney W. Grimes * Request that new entries be extracted.
658fae3551SRodney W. Grimes */
668fae3551SRodney W. Grimes long
addfile(char * name,ino_t ino,int type)672db673abSWarner Losh addfile(char *name, ino_t ino, int type)
688fae3551SRodney W. Grimes {
693d438ad6SDavid E. O'Brien struct entry *ep;
708fae3551SRodney W. Grimes long descend = hflag ? GOOD : FAIL;
718fae3551SRodney W. Grimes char buf[100];
728fae3551SRodney W. Grimes
738fae3551SRodney W. Grimes if (TSTINO(ino, dumpmap) == 0) {
748fae3551SRodney W. Grimes dprintf(stdout, "%s: not on the tape\n", name);
758fae3551SRodney W. Grimes return (descend);
768fae3551SRodney W. Grimes }
771dc349abSEd Maste if (ino == UFS_WINO && command == 'i' && !vflag)
78d87d79aeSPeter Wemm return (descend);
798fae3551SRodney W. Grimes if (!mflag) {
80e25a029eSMatthew D Fleming (void) sprintf(buf, "./%ju", (uintmax_t)ino);
818fae3551SRodney W. Grimes name = buf;
828fae3551SRodney W. Grimes if (type == NODE) {
838fae3551SRodney W. Grimes (void) genliteraldir(name, ino);
848fae3551SRodney W. Grimes return (descend);
858fae3551SRodney W. Grimes }
868fae3551SRodney W. Grimes }
878fae3551SRodney W. Grimes ep = lookupino(ino);
888fae3551SRodney W. Grimes if (ep != NULL) {
898fae3551SRodney W. Grimes if (strcmp(name, myname(ep)) == 0) {
908fae3551SRodney W. Grimes ep->e_flags |= NEW;
918fae3551SRodney W. Grimes return (descend);
928fae3551SRodney W. Grimes }
938fae3551SRodney W. Grimes type |= LINK;
948fae3551SRodney W. Grimes }
958fae3551SRodney W. Grimes ep = addentry(name, ino, type);
968fae3551SRodney W. Grimes if (type == NODE)
978fae3551SRodney W. Grimes newnode(ep);
988fae3551SRodney W. Grimes ep->e_flags |= NEW;
998fae3551SRodney W. Grimes return (descend);
1008fae3551SRodney W. Grimes }
1018fae3551SRodney W. Grimes
1028fae3551SRodney W. Grimes /*
1038fae3551SRodney W. Grimes * This is used by the 'i' option to undo previous requests made by addfile.
1048fae3551SRodney W. Grimes * Delete entries from the request queue.
1058fae3551SRodney W. Grimes */
1068fae3551SRodney W. Grimes /* ARGSUSED */
1078fae3551SRodney W. Grimes long
deletefile(char * name,ino_t ino,int type)1082db673abSWarner Losh deletefile(char *name, ino_t ino, int type)
1098fae3551SRodney W. Grimes {
1108fae3551SRodney W. Grimes long descend = hflag ? GOOD : FAIL;
1118fae3551SRodney W. Grimes struct entry *ep;
1128fae3551SRodney W. Grimes
1138fae3551SRodney W. Grimes if (TSTINO(ino, dumpmap) == 0)
1148fae3551SRodney W. Grimes return (descend);
115d87d79aeSPeter Wemm ep = lookupname(name);
116d87d79aeSPeter Wemm if (ep != NULL) {
1178fae3551SRodney W. Grimes ep->e_flags &= ~NEW;
118d87d79aeSPeter Wemm ep->e_flags |= REMOVED;
119d87d79aeSPeter Wemm if (ep->e_type != NODE)
120d87d79aeSPeter Wemm freeentry(ep);
121d87d79aeSPeter Wemm }
1228fae3551SRodney W. Grimes return (descend);
1238fae3551SRodney W. Grimes }
1248fae3551SRodney W. Grimes
1258fae3551SRodney W. Grimes /*
1268fae3551SRodney W. Grimes * The following four routines implement the incremental
1278fae3551SRodney W. Grimes * restore algorithm. The first removes old entries, the second
1288fae3551SRodney W. Grimes * does renames and calculates the extraction list, the third
1298fae3551SRodney W. Grimes * cleans up link names missed by the first two, and the final
1308fae3551SRodney W. Grimes * one deletes old directories.
1318fae3551SRodney W. Grimes *
1328fae3551SRodney W. Grimes * Directories cannot be immediately deleted, as they may have
1338fae3551SRodney W. Grimes * other files in them which need to be moved out first. As
1348fae3551SRodney W. Grimes * directories to be deleted are found, they are put on the
1358fae3551SRodney W. Grimes * following deletion list. After all deletions and renames
1368fae3551SRodney W. Grimes * are done, this list is actually deleted.
1378fae3551SRodney W. Grimes */
1388fae3551SRodney W. Grimes static struct entry *removelist;
1398fae3551SRodney W. Grimes
1408fae3551SRodney W. Grimes /*
141d87d79aeSPeter Wemm * Remove invalid whiteouts from the old tree.
1428fae3551SRodney W. Grimes * Remove unneeded leaves from the old tree.
1438fae3551SRodney W. Grimes * Remove directories from the lookup chains.
1448fae3551SRodney W. Grimes */
1458fae3551SRodney W. Grimes void
removeoldleaves(void)1462db673abSWarner Losh removeoldleaves(void)
1478fae3551SRodney W. Grimes {
1483d438ad6SDavid E. O'Brien struct entry *ep, *nextep;
1493d438ad6SDavid E. O'Brien ino_t i, mydirino;
1508fae3551SRodney W. Grimes
1518fae3551SRodney W. Grimes vprintf(stdout, "Mark entries to be removed.\n");
1521dc349abSEd Maste if ((ep = lookupino(UFS_WINO))) {
153d87d79aeSPeter Wemm vprintf(stdout, "Delete whiteouts\n");
154d87d79aeSPeter Wemm for ( ; ep != NULL; ep = nextep) {
155d87d79aeSPeter Wemm nextep = ep->e_links;
156d87d79aeSPeter Wemm mydirino = ep->e_parent->e_ino;
157d87d79aeSPeter Wemm /*
158d87d79aeSPeter Wemm * We remove all whiteouts that are in directories
159d87d79aeSPeter Wemm * that have been removed or that have been dumped.
160d87d79aeSPeter Wemm */
161d87d79aeSPeter Wemm if (TSTINO(mydirino, usedinomap) &&
162d87d79aeSPeter Wemm !TSTINO(mydirino, dumpmap))
163d87d79aeSPeter Wemm continue;
164d87d79aeSPeter Wemm delwhiteout(ep);
165d87d79aeSPeter Wemm freeentry(ep);
166d87d79aeSPeter Wemm }
167d87d79aeSPeter Wemm }
1681dc349abSEd Maste for (i = UFS_ROOTINO + 1; i < maxino; i++) {
1698fae3551SRodney W. Grimes ep = lookupino(i);
1708fae3551SRodney W. Grimes if (ep == NULL)
1718fae3551SRodney W. Grimes continue;
172d87d79aeSPeter Wemm if (TSTINO(i, usedinomap))
1738fae3551SRodney W. Grimes continue;
1748fae3551SRodney W. Grimes for ( ; ep != NULL; ep = ep->e_links) {
1758fae3551SRodney W. Grimes dprintf(stdout, "%s: REMOVE\n", myname(ep));
1768fae3551SRodney W. Grimes if (ep->e_type == LEAF) {
1778fae3551SRodney W. Grimes removeleaf(ep);
1788fae3551SRodney W. Grimes freeentry(ep);
1798fae3551SRodney W. Grimes } else {
1808fae3551SRodney W. Grimes mktempname(ep);
1818fae3551SRodney W. Grimes deleteino(ep->e_ino);
1828fae3551SRodney W. Grimes ep->e_next = removelist;
1838fae3551SRodney W. Grimes removelist = ep;
1848fae3551SRodney W. Grimes }
1858fae3551SRodney W. Grimes }
1868fae3551SRodney W. Grimes }
1878fae3551SRodney W. Grimes }
1888fae3551SRodney W. Grimes
1898fae3551SRodney W. Grimes /*
1908fae3551SRodney W. Grimes * For each directory entry on the incremental tape, determine which
1918fae3551SRodney W. Grimes * category it falls into as follows:
1928fae3551SRodney W. Grimes * KEEP - entries that are to be left alone.
1938fae3551SRodney W. Grimes * NEW - new entries to be added.
1948fae3551SRodney W. Grimes * EXTRACT - files that must be updated with new contents.
1958fae3551SRodney W. Grimes * LINK - new links to be added.
1968fae3551SRodney W. Grimes * Renames are done at the same time.
1978fae3551SRodney W. Grimes */
1988fae3551SRodney W. Grimes long
nodeupdates(char * name,ino_t ino,int type)1992db673abSWarner Losh nodeupdates(char *name, ino_t ino, int type)
2008fae3551SRodney W. Grimes {
2013d438ad6SDavid E. O'Brien struct entry *ep, *np, *ip;
2028fae3551SRodney W. Grimes long descend = GOOD;
2038fae3551SRodney W. Grimes int lookuptype = 0;
2048fae3551SRodney W. Grimes int key = 0;
2058fae3551SRodney W. Grimes /* key values */
2068fae3551SRodney W. Grimes # define ONTAPE 0x1 /* inode is on the tape */
2078fae3551SRodney W. Grimes # define INOFND 0x2 /* inode already exists */
2088fae3551SRodney W. Grimes # define NAMEFND 0x4 /* name already exists */
2098fae3551SRodney W. Grimes # define MODECHG 0x8 /* mode of inode changed */
2108fae3551SRodney W. Grimes
2118fae3551SRodney W. Grimes /*
2128fae3551SRodney W. Grimes * This routine is called once for each element in the
2138fae3551SRodney W. Grimes * directory hierarchy, with a full path name.
2148fae3551SRodney W. Grimes * The "type" value is incorrectly specified as LEAF for
2158fae3551SRodney W. Grimes * directories that are not on the dump tape.
2168fae3551SRodney W. Grimes *
2178fae3551SRodney W. Grimes * Check to see if the file is on the tape.
2188fae3551SRodney W. Grimes */
2198fae3551SRodney W. Grimes if (TSTINO(ino, dumpmap))
2208fae3551SRodney W. Grimes key |= ONTAPE;
2218fae3551SRodney W. Grimes /*
2228fae3551SRodney W. Grimes * Check to see if the name exists, and if the name is a link.
2238fae3551SRodney W. Grimes */
2248fae3551SRodney W. Grimes np = lookupname(name);
2258fae3551SRodney W. Grimes if (np != NULL) {
2268fae3551SRodney W. Grimes key |= NAMEFND;
2278fae3551SRodney W. Grimes ip = lookupino(np->e_ino);
2288fae3551SRodney W. Grimes if (ip == NULL)
2298fae3551SRodney W. Grimes panic("corrupted symbol table\n");
2308fae3551SRodney W. Grimes if (ip != np)
2318fae3551SRodney W. Grimes lookuptype = LINK;
2328fae3551SRodney W. Grimes }
2338fae3551SRodney W. Grimes /*
2348fae3551SRodney W. Grimes * Check to see if the inode exists, and if one of its links
2358fae3551SRodney W. Grimes * corresponds to the name (if one was found).
2368fae3551SRodney W. Grimes */
2378fae3551SRodney W. Grimes ip = lookupino(ino);
2388fae3551SRodney W. Grimes if (ip != NULL) {
2398fae3551SRodney W. Grimes key |= INOFND;
2408fae3551SRodney W. Grimes for (ep = ip->e_links; ep != NULL; ep = ep->e_links) {
2418fae3551SRodney W. Grimes if (ep == np) {
2428fae3551SRodney W. Grimes ip = ep;
2438fae3551SRodney W. Grimes break;
2448fae3551SRodney W. Grimes }
2458fae3551SRodney W. Grimes }
2468fae3551SRodney W. Grimes }
2478fae3551SRodney W. Grimes /*
2488fae3551SRodney W. Grimes * If both a name and an inode are found, but they do not
2498fae3551SRodney W. Grimes * correspond to the same file, then both the inode that has
2508fae3551SRodney W. Grimes * been found and the inode corresponding to the name that
2518fae3551SRodney W. Grimes * has been found need to be renamed. The current pathname
2528fae3551SRodney W. Grimes * is the new name for the inode that has been found. Since
2538fae3551SRodney W. Grimes * all files to be deleted have already been removed, the
2548fae3551SRodney W. Grimes * named file is either a now unneeded link, or it must live
2558fae3551SRodney W. Grimes * under a new name in this dump level. If it is a link, it
2568fae3551SRodney W. Grimes * can be removed. If it is not a link, it is given a
2578fae3551SRodney W. Grimes * temporary name in anticipation that it will be renamed
2588fae3551SRodney W. Grimes * when it is later found by inode number.
2598fae3551SRodney W. Grimes */
2608fae3551SRodney W. Grimes if (((key & (INOFND|NAMEFND)) == (INOFND|NAMEFND)) && ip != np) {
2618fae3551SRodney W. Grimes if (lookuptype == LINK) {
2628fae3551SRodney W. Grimes removeleaf(np);
2638fae3551SRodney W. Grimes freeentry(np);
2648fae3551SRodney W. Grimes } else {
2658fae3551SRodney W. Grimes dprintf(stdout, "name/inode conflict, mktempname %s\n",
2668fae3551SRodney W. Grimes myname(np));
2678fae3551SRodney W. Grimes mktempname(np);
2688fae3551SRodney W. Grimes }
2698fae3551SRodney W. Grimes np = NULL;
2708fae3551SRodney W. Grimes key &= ~NAMEFND;
2718fae3551SRodney W. Grimes }
2728fae3551SRodney W. Grimes if ((key & ONTAPE) &&
2738fae3551SRodney W. Grimes (((key & INOFND) && ip->e_type != type) ||
2748fae3551SRodney W. Grimes ((key & NAMEFND) && np->e_type != type)))
2758fae3551SRodney W. Grimes key |= MODECHG;
2768fae3551SRodney W. Grimes
2778fae3551SRodney W. Grimes /*
2788fae3551SRodney W. Grimes * Decide on the disposition of the file based on its flags.
2798fae3551SRodney W. Grimes * Note that we have already handled the case in which
2808fae3551SRodney W. Grimes * a name and inode are found that correspond to different files.
2818fae3551SRodney W. Grimes * Thus if both NAMEFND and INOFND are set then ip == np.
2828fae3551SRodney W. Grimes */
2838fae3551SRodney W. Grimes switch (key) {
2848fae3551SRodney W. Grimes
2858fae3551SRodney W. Grimes /*
2868fae3551SRodney W. Grimes * A previously existing file has been found.
2878fae3551SRodney W. Grimes * Mark it as KEEP so that other links to the inode can be
2888fae3551SRodney W. Grimes * detected, and so that it will not be reclaimed by the search
2898fae3551SRodney W. Grimes * for unreferenced names.
2908fae3551SRodney W. Grimes */
2918fae3551SRodney W. Grimes case INOFND|NAMEFND:
2928fae3551SRodney W. Grimes ip->e_flags |= KEEP;
2938fae3551SRodney W. Grimes dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
2948fae3551SRodney W. Grimes flagvalues(ip));
2958fae3551SRodney W. Grimes break;
2968fae3551SRodney W. Grimes
2978fae3551SRodney W. Grimes /*
2988fae3551SRodney W. Grimes * A file on the tape has a name which is the same as a name
2998fae3551SRodney W. Grimes * corresponding to a different file in the previous dump.
3008fae3551SRodney W. Grimes * Since all files to be deleted have already been removed,
3018fae3551SRodney W. Grimes * this file is either a now unneeded link, or it must live
3028fae3551SRodney W. Grimes * under a new name in this dump level. If it is a link, it
3038fae3551SRodney W. Grimes * can simply be removed. If it is not a link, it is given a
3048fae3551SRodney W. Grimes * temporary name in anticipation that it will be renamed
3058fae3551SRodney W. Grimes * when it is later found by inode number (see INOFND case
3068fae3551SRodney W. Grimes * below). The entry is then treated as a new file.
3078fae3551SRodney W. Grimes */
3088fae3551SRodney W. Grimes case ONTAPE|NAMEFND:
3098fae3551SRodney W. Grimes case ONTAPE|NAMEFND|MODECHG:
3108fae3551SRodney W. Grimes if (lookuptype == LINK) {
3118fae3551SRodney W. Grimes removeleaf(np);
3128fae3551SRodney W. Grimes freeentry(np);
3138fae3551SRodney W. Grimes } else {
3148fae3551SRodney W. Grimes mktempname(np);
3158fae3551SRodney W. Grimes }
3167fed38d0SPhilippe Charnier /* FALLTHROUGH */
3178fae3551SRodney W. Grimes
3188fae3551SRodney W. Grimes /*
3198fae3551SRodney W. Grimes * A previously non-existent file.
3208fae3551SRodney W. Grimes * Add it to the file system, and request its extraction.
3218fae3551SRodney W. Grimes * If it is a directory, create it immediately.
3228fae3551SRodney W. Grimes * (Since the name is unused there can be no conflict)
3238fae3551SRodney W. Grimes */
3248fae3551SRodney W. Grimes case ONTAPE:
3258fae3551SRodney W. Grimes ep = addentry(name, ino, type);
3268fae3551SRodney W. Grimes if (type == NODE)
3278fae3551SRodney W. Grimes newnode(ep);
3288fae3551SRodney W. Grimes ep->e_flags |= NEW|KEEP;
3298fae3551SRodney W. Grimes dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
3308fae3551SRodney W. Grimes flagvalues(ep));
3318fae3551SRodney W. Grimes break;
3328fae3551SRodney W. Grimes
3338fae3551SRodney W. Grimes /*
3348fae3551SRodney W. Grimes * A file with the same inode number, but a different
3358fae3551SRodney W. Grimes * name has been found. If the other name has not already
3368fae3551SRodney W. Grimes * been found (indicated by the KEEP flag, see above) then
3378fae3551SRodney W. Grimes * this must be a new name for the file, and it is renamed.
3388fae3551SRodney W. Grimes * If the other name has been found then this must be a
3398fae3551SRodney W. Grimes * link to the file. Hard links to directories are not
3408fae3551SRodney W. Grimes * permitted, and are either deleted or converted to
3418fae3551SRodney W. Grimes * symbolic links. Finally, if the file is on the tape,
3428fae3551SRodney W. Grimes * a request is made to extract it.
3438fae3551SRodney W. Grimes */
3448fae3551SRodney W. Grimes case ONTAPE|INOFND:
3458fae3551SRodney W. Grimes if (type == LEAF && (ip->e_flags & KEEP) == 0)
3468fae3551SRodney W. Grimes ip->e_flags |= EXTRACT;
3477fed38d0SPhilippe Charnier /* FALLTHROUGH */
3488fae3551SRodney W. Grimes case INOFND:
3498fae3551SRodney W. Grimes if ((ip->e_flags & KEEP) == 0) {
3508fae3551SRodney W. Grimes renameit(myname(ip), name);
3518fae3551SRodney W. Grimes moveentry(ip, name);
3528fae3551SRodney W. Grimes ip->e_flags |= KEEP;
3538fae3551SRodney W. Grimes dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
3548fae3551SRodney W. Grimes flagvalues(ip));
3558fae3551SRodney W. Grimes break;
3568fae3551SRodney W. Grimes }
3578fae3551SRodney W. Grimes if (ip->e_type == NODE) {
3588fae3551SRodney W. Grimes descend = FAIL;
3598fae3551SRodney W. Grimes fprintf(stderr,
3608fae3551SRodney W. Grimes "deleted hard link %s to directory %s\n",
3618fae3551SRodney W. Grimes name, myname(ip));
3628fae3551SRodney W. Grimes break;
3638fae3551SRodney W. Grimes }
3648fae3551SRodney W. Grimes ep = addentry(name, ino, type|LINK);
3658fae3551SRodney W. Grimes ep->e_flags |= NEW;
3668fae3551SRodney W. Grimes dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
3678fae3551SRodney W. Grimes flagvalues(ep));
3688fae3551SRodney W. Grimes break;
3698fae3551SRodney W. Grimes
3708fae3551SRodney W. Grimes /*
3718fae3551SRodney W. Grimes * A previously known file which is to be updated. If it is a link,
3728fae3551SRodney W. Grimes * then all names referring to the previous file must be removed
3738fae3551SRodney W. Grimes * so that the subset of them that remain can be recreated.
3748fae3551SRodney W. Grimes */
3758fae3551SRodney W. Grimes case ONTAPE|INOFND|NAMEFND:
3768fae3551SRodney W. Grimes if (lookuptype == LINK) {
3778fae3551SRodney W. Grimes removeleaf(np);
3788fae3551SRodney W. Grimes freeentry(np);
3798fae3551SRodney W. Grimes ep = addentry(name, ino, type|LINK);
3808fae3551SRodney W. Grimes if (type == NODE)
3818fae3551SRodney W. Grimes newnode(ep);
3828fae3551SRodney W. Grimes ep->e_flags |= NEW|KEEP;
3838fae3551SRodney W. Grimes dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
3848fae3551SRodney W. Grimes flagvalues(ep));
3858fae3551SRodney W. Grimes break;
3868fae3551SRodney W. Grimes }
3878fae3551SRodney W. Grimes if (type == LEAF && lookuptype != LINK)
3888fae3551SRodney W. Grimes np->e_flags |= EXTRACT;
3898fae3551SRodney W. Grimes np->e_flags |= KEEP;
3908fae3551SRodney W. Grimes dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
3918fae3551SRodney W. Grimes flagvalues(np));
3928fae3551SRodney W. Grimes break;
3938fae3551SRodney W. Grimes
3948fae3551SRodney W. Grimes /*
3958fae3551SRodney W. Grimes * An inode is being reused in a completely different way.
3968fae3551SRodney W. Grimes * Normally an extract can simply do an "unlink" followed
3978fae3551SRodney W. Grimes * by a "creat". Here we must do effectively the same
3988fae3551SRodney W. Grimes * thing. The complications arise because we cannot really
3998fae3551SRodney W. Grimes * delete a directory since it may still contain files
4008fae3551SRodney W. Grimes * that we need to rename, so we delete it from the symbol
4018fae3551SRodney W. Grimes * table, and put it on the list to be deleted eventually.
4028fae3551SRodney W. Grimes * Conversely if a directory is to be created, it must be
4038fae3551SRodney W. Grimes * done immediately, rather than waiting until the
4048fae3551SRodney W. Grimes * extraction phase.
4058fae3551SRodney W. Grimes */
4068fae3551SRodney W. Grimes case ONTAPE|INOFND|MODECHG:
4078fae3551SRodney W. Grimes case ONTAPE|INOFND|NAMEFND|MODECHG:
4088fae3551SRodney W. Grimes if (ip->e_flags & KEEP) {
4098fae3551SRodney W. Grimes badentry(ip, "cannot KEEP and change modes");
4108fae3551SRodney W. Grimes break;
4118fae3551SRodney W. Grimes }
4128fae3551SRodney W. Grimes if (ip->e_type == LEAF) {
4138fae3551SRodney W. Grimes /* changing from leaf to node */
414edb398d7SJoerg Wunsch for (ip = lookupino(ino); ip != NULL; ip = ip->e_links) {
415edb398d7SJoerg Wunsch if (ip->e_type != LEAF)
416edb398d7SJoerg Wunsch badentry(ip, "NODE and LEAF links to same inode");
4178fae3551SRodney W. Grimes removeleaf(ip);
4188fae3551SRodney W. Grimes freeentry(ip);
419edb398d7SJoerg Wunsch }
4208fae3551SRodney W. Grimes ip = addentry(name, ino, type);
4218fae3551SRodney W. Grimes newnode(ip);
4228fae3551SRodney W. Grimes } else {
4238fae3551SRodney W. Grimes /* changing from node to leaf */
4248fae3551SRodney W. Grimes if ((ip->e_flags & TMPNAME) == 0)
4258fae3551SRodney W. Grimes mktempname(ip);
4268fae3551SRodney W. Grimes deleteino(ip->e_ino);
4278fae3551SRodney W. Grimes ip->e_next = removelist;
4288fae3551SRodney W. Grimes removelist = ip;
4298fae3551SRodney W. Grimes ip = addentry(name, ino, type);
4308fae3551SRodney W. Grimes }
4318fae3551SRodney W. Grimes ip->e_flags |= NEW|KEEP;
4328fae3551SRodney W. Grimes dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
4338fae3551SRodney W. Grimes flagvalues(ip));
4348fae3551SRodney W. Grimes break;
4358fae3551SRodney W. Grimes
4368fae3551SRodney W. Grimes /*
43791ac32e4SPhilippe Charnier * A hard link to a directory that has been removed.
4388fae3551SRodney W. Grimes * Ignore it.
4398fae3551SRodney W. Grimes */
4408fae3551SRodney W. Grimes case NAMEFND:
4418fae3551SRodney W. Grimes dprintf(stdout, "[%s] %s: Extraneous name\n", keyval(key),
4428fae3551SRodney W. Grimes name);
4438fae3551SRodney W. Grimes descend = FAIL;
4448fae3551SRodney W. Grimes break;
4458fae3551SRodney W. Grimes
4468fae3551SRodney W. Grimes /*
4478fae3551SRodney W. Grimes * If we find a directory entry for a file that is not on
4488fae3551SRodney W. Grimes * the tape, then we must have found a file that was created
4498fae3551SRodney W. Grimes * while the dump was in progress. Since we have no contents
4508fae3551SRodney W. Grimes * for it, we discard the name knowing that it will be on the
4518fae3551SRodney W. Grimes * next incremental tape.
4528fae3551SRodney W. Grimes */
4530b0fe61dSWarner Losh case 0:
454e25a029eSMatthew D Fleming fprintf(stderr, "%s: (inode %ju) not found on tape\n",
455e25a029eSMatthew D Fleming name, (uintmax_t)ino);
4568fae3551SRodney W. Grimes break;
4578fae3551SRodney W. Grimes
4588fae3551SRodney W. Grimes /*
4598fae3551SRodney W. Grimes * If any of these arise, something is grievously wrong with
4608fae3551SRodney W. Grimes * the current state of the symbol table.
4618fae3551SRodney W. Grimes */
4628fae3551SRodney W. Grimes case INOFND|NAMEFND|MODECHG:
4638fae3551SRodney W. Grimes case NAMEFND|MODECHG:
4648fae3551SRodney W. Grimes case INOFND|MODECHG:
4658fae3551SRodney W. Grimes fprintf(stderr, "[%s] %s: inconsistent state\n", keyval(key),
4668fae3551SRodney W. Grimes name);
4678fae3551SRodney W. Grimes break;
4688fae3551SRodney W. Grimes
4698fae3551SRodney W. Grimes /*
4708fae3551SRodney W. Grimes * These states "cannot" arise for any state of the symbol table.
4718fae3551SRodney W. Grimes */
4728fae3551SRodney W. Grimes case ONTAPE|MODECHG:
4738fae3551SRodney W. Grimes case MODECHG:
4748fae3551SRodney W. Grimes default:
4758fae3551SRodney W. Grimes panic("[%s] %s: impossible state\n", keyval(key), name);
4768fae3551SRodney W. Grimes break;
4778fae3551SRodney W. Grimes }
4788fae3551SRodney W. Grimes return (descend);
4798fae3551SRodney W. Grimes }
4808fae3551SRodney W. Grimes
4818fae3551SRodney W. Grimes /*
4828fae3551SRodney W. Grimes * Calculate the active flags in a key.
4838fae3551SRodney W. Grimes */
4848fae3551SRodney W. Grimes static char *
keyval(int key)4852db673abSWarner Losh keyval(int key)
4868fae3551SRodney W. Grimes {
4878fae3551SRodney W. Grimes static char keybuf[32];
4888fae3551SRodney W. Grimes
4898fae3551SRodney W. Grimes (void) strcpy(keybuf, "|NIL");
4908fae3551SRodney W. Grimes keybuf[0] = '\0';
4918fae3551SRodney W. Grimes if (key & ONTAPE)
4928fae3551SRodney W. Grimes (void) strcat(keybuf, "|ONTAPE");
4938fae3551SRodney W. Grimes if (key & INOFND)
4948fae3551SRodney W. Grimes (void) strcat(keybuf, "|INOFND");
4958fae3551SRodney W. Grimes if (key & NAMEFND)
4968fae3551SRodney W. Grimes (void) strcat(keybuf, "|NAMEFND");
4978fae3551SRodney W. Grimes if (key & MODECHG)
4988fae3551SRodney W. Grimes (void) strcat(keybuf, "|MODECHG");
4998fae3551SRodney W. Grimes return (&keybuf[1]);
5008fae3551SRodney W. Grimes }
5018fae3551SRodney W. Grimes
5028fae3551SRodney W. Grimes /*
5038fae3551SRodney W. Grimes * Find unreferenced link names.
5048fae3551SRodney W. Grimes */
5058fae3551SRodney W. Grimes void
findunreflinks(void)5062db673abSWarner Losh findunreflinks(void)
5078fae3551SRodney W. Grimes {
5083d438ad6SDavid E. O'Brien struct entry *ep, *np;
5093d438ad6SDavid E. O'Brien ino_t i;
5108fae3551SRodney W. Grimes
5118fae3551SRodney W. Grimes vprintf(stdout, "Find unreferenced names.\n");
5121dc349abSEd Maste for (i = UFS_ROOTINO; i < maxino; i++) {
5138fae3551SRodney W. Grimes ep = lookupino(i);
5148fae3551SRodney W. Grimes if (ep == NULL || ep->e_type == LEAF || TSTINO(i, dumpmap) == 0)
5158fae3551SRodney W. Grimes continue;
5168fae3551SRodney W. Grimes for (np = ep->e_entries; np != NULL; np = np->e_sibling) {
5178fae3551SRodney W. Grimes if (np->e_flags == 0) {
5188fae3551SRodney W. Grimes dprintf(stdout,
5198fae3551SRodney W. Grimes "%s: remove unreferenced name\n",
5208fae3551SRodney W. Grimes myname(np));
5218fae3551SRodney W. Grimes removeleaf(np);
5228fae3551SRodney W. Grimes freeentry(np);
5238fae3551SRodney W. Grimes }
5248fae3551SRodney W. Grimes }
5258fae3551SRodney W. Grimes }
5268fae3551SRodney W. Grimes /*
5278fae3551SRodney W. Grimes * Any leaves remaining in removed directories is unreferenced.
5288fae3551SRodney W. Grimes */
5298fae3551SRodney W. Grimes for (ep = removelist; ep != NULL; ep = ep->e_next) {
5308fae3551SRodney W. Grimes for (np = ep->e_entries; np != NULL; np = np->e_sibling) {
5318fae3551SRodney W. Grimes if (np->e_type == LEAF) {
5328fae3551SRodney W. Grimes if (np->e_flags != 0)
5338fae3551SRodney W. Grimes badentry(np, "unreferenced with flags");
5348fae3551SRodney W. Grimes dprintf(stdout,
5358fae3551SRodney W. Grimes "%s: remove unreferenced name\n",
5368fae3551SRodney W. Grimes myname(np));
5378fae3551SRodney W. Grimes removeleaf(np);
5388fae3551SRodney W. Grimes freeentry(np);
5398fae3551SRodney W. Grimes }
5408fae3551SRodney W. Grimes }
5418fae3551SRodney W. Grimes }
5428fae3551SRodney W. Grimes }
5438fae3551SRodney W. Grimes
5448fae3551SRodney W. Grimes /*
5458fae3551SRodney W. Grimes * Remove old nodes (directories).
5468fae3551SRodney W. Grimes * Note that this routine runs in O(N*D) where:
5478fae3551SRodney W. Grimes * N is the number of directory entries to be removed.
5488fae3551SRodney W. Grimes * D is the maximum depth of the tree.
5498fae3551SRodney W. Grimes * If N == D this can be quite slow. If the list were
5508fae3551SRodney W. Grimes * topologically sorted, the deletion could be done in
5518fae3551SRodney W. Grimes * time O(N).
5528fae3551SRodney W. Grimes */
5538fae3551SRodney W. Grimes void
removeoldnodes(void)5542db673abSWarner Losh removeoldnodes(void)
5558fae3551SRodney W. Grimes {
5563d438ad6SDavid E. O'Brien struct entry *ep, **prev;
5578fae3551SRodney W. Grimes long change;
5588fae3551SRodney W. Grimes
5598fae3551SRodney W. Grimes vprintf(stdout, "Remove old nodes (directories).\n");
5608fae3551SRodney W. Grimes do {
5618fae3551SRodney W. Grimes change = 0;
5628fae3551SRodney W. Grimes prev = &removelist;
5638fae3551SRodney W. Grimes for (ep = removelist; ep != NULL; ep = *prev) {
5648fae3551SRodney W. Grimes if (ep->e_entries != NULL) {
5658fae3551SRodney W. Grimes prev = &ep->e_next;
5668fae3551SRodney W. Grimes continue;
5678fae3551SRodney W. Grimes }
5688fae3551SRodney W. Grimes *prev = ep->e_next;
5698fae3551SRodney W. Grimes removenode(ep);
5708fae3551SRodney W. Grimes freeentry(ep);
5718fae3551SRodney W. Grimes change++;
5728fae3551SRodney W. Grimes }
5738fae3551SRodney W. Grimes } while (change);
5748fae3551SRodney W. Grimes for (ep = removelist; ep != NULL; ep = ep->e_next)
5758fae3551SRodney W. Grimes badentry(ep, "cannot remove, non-empty");
5768fae3551SRodney W. Grimes }
5778fae3551SRodney W. Grimes
5788fae3551SRodney W. Grimes /*
5798fae3551SRodney W. Grimes * This is the routine used to extract files for the 'r' command.
5808fae3551SRodney W. Grimes * Extract new leaves.
5818fae3551SRodney W. Grimes */
5828fae3551SRodney W. Grimes void
createleaves(char * symtabfile)5832db673abSWarner Losh createleaves(char *symtabfile)
5848fae3551SRodney W. Grimes {
5853d438ad6SDavid E. O'Brien struct entry *ep;
5868fae3551SRodney W. Grimes ino_t first;
5878fae3551SRodney W. Grimes long curvol;
5888fae3551SRodney W. Grimes
5898fae3551SRodney W. Grimes if (command == 'R') {
5908fae3551SRodney W. Grimes vprintf(stdout, "Continue extraction of new leaves\n");
5918fae3551SRodney W. Grimes } else {
5928fae3551SRodney W. Grimes vprintf(stdout, "Extract new leaves.\n");
5938fae3551SRodney W. Grimes dumpsymtable(symtabfile, volno);
5948fae3551SRodney W. Grimes }
5951dc349abSEd Maste first = lowerbnd(UFS_ROOTINO);
5968fae3551SRodney W. Grimes curvol = volno;
5978fae3551SRodney W. Grimes while (curfile.ino < maxino) {
5988fae3551SRodney W. Grimes first = lowerbnd(first);
5998fae3551SRodney W. Grimes /*
6008fae3551SRodney W. Grimes * If the next available file is not the one which we
6018fae3551SRodney W. Grimes * expect then we have missed one or more files. Since
6028fae3551SRodney W. Grimes * we do not request files that were not on the tape,
6038fae3551SRodney W. Grimes * the lost files must have been due to a tape read error,
6048fae3551SRodney W. Grimes * or a file that was removed while the dump was in progress.
6058fae3551SRodney W. Grimes */
6068fae3551SRodney W. Grimes while (first < curfile.ino) {
6078fae3551SRodney W. Grimes ep = lookupino(first);
6088fae3551SRodney W. Grimes if (ep == NULL)
609e25a029eSMatthew D Fleming panic("%ju: bad first\n", (uintmax_t)first);
6108fae3551SRodney W. Grimes fprintf(stderr, "%s: not found on tape\n", myname(ep));
6118fae3551SRodney W. Grimes ep->e_flags &= ~(NEW|EXTRACT);
6128fae3551SRodney W. Grimes first = lowerbnd(first);
6138fae3551SRodney W. Grimes }
6148fae3551SRodney W. Grimes /*
6158fae3551SRodney W. Grimes * If we find files on the tape that have no corresponding
6168fae3551SRodney W. Grimes * directory entries, then we must have found a file that
6178fae3551SRodney W. Grimes * was created while the dump was in progress. Since we have
6188fae3551SRodney W. Grimes * no name for it, we discard it knowing that it will be
6198fae3551SRodney W. Grimes * on the next incremental tape.
6208fae3551SRodney W. Grimes */
6218fae3551SRodney W. Grimes if (first != curfile.ino) {
622e25a029eSMatthew D Fleming fprintf(stderr, "expected next file %ju, got %ju\n",
623e25a029eSMatthew D Fleming (uintmax_t)first, (uintmax_t)curfile.ino);
6248fae3551SRodney W. Grimes skipfile();
6258fae3551SRodney W. Grimes goto next;
6268fae3551SRodney W. Grimes }
6278fae3551SRodney W. Grimes ep = lookupino(curfile.ino);
6288fae3551SRodney W. Grimes if (ep == NULL)
6298fae3551SRodney W. Grimes panic("unknown file on tape\n");
6308fae3551SRodney W. Grimes if ((ep->e_flags & (NEW|EXTRACT)) == 0)
6318fae3551SRodney W. Grimes badentry(ep, "unexpected file on tape");
6328fae3551SRodney W. Grimes /*
6338fae3551SRodney W. Grimes * If the file is to be extracted, then the old file must
6348fae3551SRodney W. Grimes * be removed since its type may change from one leaf type
63591ac32e4SPhilippe Charnier * to another (e.g. "file" to "character special").
6368fae3551SRodney W. Grimes */
6378fae3551SRodney W. Grimes if ((ep->e_flags & EXTRACT) != 0) {
6388fae3551SRodney W. Grimes removeleaf(ep);
6398fae3551SRodney W. Grimes ep->e_flags &= ~REMOVED;
6408fae3551SRodney W. Grimes }
6418fae3551SRodney W. Grimes (void) extractfile(myname(ep));
6428fae3551SRodney W. Grimes ep->e_flags &= ~(NEW|EXTRACT);
6438fae3551SRodney W. Grimes /*
6448fae3551SRodney W. Grimes * We checkpoint the restore after every tape reel, so
6458fae3551SRodney W. Grimes * as to simplify the amount of work required by the
6468fae3551SRodney W. Grimes * 'R' command.
6478fae3551SRodney W. Grimes */
6488fae3551SRodney W. Grimes next:
6498fae3551SRodney W. Grimes if (curvol != volno) {
6508fae3551SRodney W. Grimes dumpsymtable(symtabfile, volno);
6518fae3551SRodney W. Grimes skipmaps();
6528fae3551SRodney W. Grimes curvol = volno;
6538fae3551SRodney W. Grimes }
6548fae3551SRodney W. Grimes }
6558fae3551SRodney W. Grimes }
6568fae3551SRodney W. Grimes
6578fae3551SRodney W. Grimes /*
6588fae3551SRodney W. Grimes * This is the routine used to extract files for the 'x' and 'i' commands.
6598fae3551SRodney W. Grimes * Efficiently extract a subset of the files on a tape.
6608fae3551SRodney W. Grimes */
6618fae3551SRodney W. Grimes void
createfiles(void)6622db673abSWarner Losh createfiles(void)
6638fae3551SRodney W. Grimes {
6643d438ad6SDavid E. O'Brien ino_t first, next, last;
6653d438ad6SDavid E. O'Brien struct entry *ep;
6668fae3551SRodney W. Grimes long curvol;
6678fae3551SRodney W. Grimes
6688fae3551SRodney W. Grimes vprintf(stdout, "Extract requested files\n");
6698fae3551SRodney W. Grimes curfile.action = SKIP;
6708fae3551SRodney W. Grimes getvol((long)1);
6718fae3551SRodney W. Grimes skipmaps();
6728fae3551SRodney W. Grimes skipdirs();
6731dc349abSEd Maste first = lowerbnd(UFS_ROOTINO);
6748fae3551SRodney W. Grimes last = upperbnd(maxino - 1);
6758fae3551SRodney W. Grimes for (;;) {
676cfd8a009SIan Dowse curvol = volno;
6778fae3551SRodney W. Grimes first = lowerbnd(first);
6788fae3551SRodney W. Grimes last = upperbnd(last);
6798fae3551SRodney W. Grimes /*
6808fae3551SRodney W. Grimes * Check to see if any files remain to be extracted
6818fae3551SRodney W. Grimes */
6828fae3551SRodney W. Grimes if (first > last)
6838fae3551SRodney W. Grimes return;
684cbc8bb98SDavid Malone if (Dflag) {
685cbc8bb98SDavid Malone if (curfile.ino == maxino)
686cbc8bb98SDavid Malone return;
687cbc8bb98SDavid Malone if((ep = lookupino(curfile.ino)) != NULL &&
688cbc8bb98SDavid Malone (ep->e_flags & (NEW|EXTRACT))) {
689cbc8bb98SDavid Malone goto justgetit;
690cbc8bb98SDavid Malone } else {
691cbc8bb98SDavid Malone skipfile();
692cbc8bb98SDavid Malone continue;
693cbc8bb98SDavid Malone }
694cbc8bb98SDavid Malone }
6958fae3551SRodney W. Grimes /*
696cfd8a009SIan Dowse * Reject any volumes with inodes greater than the last
697cfd8a009SIan Dowse * one needed, so that we can quickly skip backwards to
698cfd8a009SIan Dowse * a volume containing useful inodes. We can't do this
699cfd8a009SIan Dowse * if there are no further volumes available (curfile.ino
700cfd8a009SIan Dowse * >= maxino) or if we are already at the first tape.
7018fae3551SRodney W. Grimes */
702cfd8a009SIan Dowse if (curfile.ino > last && curfile.ino < maxino && volno > 1) {
7038fae3551SRodney W. Grimes curfile.action = SKIP;
7048fae3551SRodney W. Grimes getvol((long)0);
7058fae3551SRodney W. Grimes skipmaps();
7068fae3551SRodney W. Grimes skipdirs();
707cfd8a009SIan Dowse continue;
7088fae3551SRodney W. Grimes }
7098fae3551SRodney W. Grimes /*
7108fae3551SRodney W. Grimes * Decide on the next inode needed.
7118fae3551SRodney W. Grimes * Skip across the inodes until it is found
712cfd8a009SIan Dowse * or a volume change is encountered
7138fae3551SRodney W. Grimes */
714cfd8a009SIan Dowse if (curfile.ino < maxino) {
7158fae3551SRodney W. Grimes next = lowerbnd(curfile.ino);
7168fae3551SRodney W. Grimes while (next > curfile.ino && volno == curvol)
7178fae3551SRodney W. Grimes skipfile();
718cfd8a009SIan Dowse if (volno != curvol) {
7198fae3551SRodney W. Grimes skipmaps();
7208fae3551SRodney W. Grimes skipdirs();
7218fae3551SRodney W. Grimes continue;
722cfd8a009SIan Dowse }
723cfd8a009SIan Dowse } else {
724cfd8a009SIan Dowse /*
725cfd8a009SIan Dowse * No further volumes or inodes available. Set
726cfd8a009SIan Dowse * `next' to the first inode, so that a warning
727cfd8a009SIan Dowse * is emitted below for each missing file.
728cfd8a009SIan Dowse */
729cfd8a009SIan Dowse next = first;
730cfd8a009SIan Dowse }
7318fae3551SRodney W. Grimes /*
7328fae3551SRodney W. Grimes * If the current inode is greater than the one we were
7338fae3551SRodney W. Grimes * looking for then we missed the one we were looking for.
7348fae3551SRodney W. Grimes * Since we only attempt to extract files listed in the
7358fae3551SRodney W. Grimes * dump map, the lost files must have been due to a tape
7368fae3551SRodney W. Grimes * read error, or a file that was removed while the dump
7378fae3551SRodney W. Grimes * was in progress. Thus we report all requested files
7388fae3551SRodney W. Grimes * between the one we were looking for, and the one we
7398fae3551SRodney W. Grimes * found as missing, and delete their request flags.
7408fae3551SRodney W. Grimes */
7418fae3551SRodney W. Grimes while (next < curfile.ino) {
7428fae3551SRodney W. Grimes ep = lookupino(next);
7438fae3551SRodney W. Grimes if (ep == NULL)
7448fae3551SRodney W. Grimes panic("corrupted symbol table\n");
7458fae3551SRodney W. Grimes fprintf(stderr, "%s: not found on tape\n", myname(ep));
7468fae3551SRodney W. Grimes ep->e_flags &= ~NEW;
7478fae3551SRodney W. Grimes next = lowerbnd(next);
7488fae3551SRodney W. Grimes }
7498fae3551SRodney W. Grimes /*
7508fae3551SRodney W. Grimes * The current inode is the one that we are looking for,
7518fae3551SRodney W. Grimes * so extract it per its requested name.
7528fae3551SRodney W. Grimes */
7538fae3551SRodney W. Grimes if (next == curfile.ino && next <= last) {
7548fae3551SRodney W. Grimes ep = lookupino(next);
7558fae3551SRodney W. Grimes if (ep == NULL)
7568fae3551SRodney W. Grimes panic("corrupted symbol table\n");
757cbc8bb98SDavid Malone justgetit:
7588fae3551SRodney W. Grimes (void) extractfile(myname(ep));
7598fae3551SRodney W. Grimes ep->e_flags &= ~NEW;
7608fae3551SRodney W. Grimes if (volno != curvol)
7618fae3551SRodney W. Grimes skipmaps();
7628fae3551SRodney W. Grimes }
7638fae3551SRodney W. Grimes }
7648fae3551SRodney W. Grimes }
7658fae3551SRodney W. Grimes
7668fae3551SRodney W. Grimes /*
7678fae3551SRodney W. Grimes * Add links.
7688fae3551SRodney W. Grimes */
7698fae3551SRodney W. Grimes void
createlinks(void)7702db673abSWarner Losh createlinks(void)
7718fae3551SRodney W. Grimes {
7723d438ad6SDavid E. O'Brien struct entry *np, *ep;
7733d438ad6SDavid E. O'Brien ino_t i;
7748fae3551SRodney W. Grimes char name[BUFSIZ];
7758fae3551SRodney W. Grimes
7761dc349abSEd Maste if ((ep = lookupino(UFS_WINO))) {
777d87d79aeSPeter Wemm vprintf(stdout, "Add whiteouts\n");
778d87d79aeSPeter Wemm for ( ; ep != NULL; ep = ep->e_links) {
779d87d79aeSPeter Wemm if ((ep->e_flags & NEW) == 0)
780d87d79aeSPeter Wemm continue;
781d87d79aeSPeter Wemm (void) addwhiteout(myname(ep));
782d87d79aeSPeter Wemm ep->e_flags &= ~NEW;
783d87d79aeSPeter Wemm }
784d87d79aeSPeter Wemm }
7858fae3551SRodney W. Grimes vprintf(stdout, "Add links\n");
7861dc349abSEd Maste for (i = UFS_ROOTINO; i < maxino; i++) {
7878fae3551SRodney W. Grimes ep = lookupino(i);
7888fae3551SRodney W. Grimes if (ep == NULL)
7898fae3551SRodney W. Grimes continue;
7908fae3551SRodney W. Grimes for (np = ep->e_links; np != NULL; np = np->e_links) {
7918fae3551SRodney W. Grimes if ((np->e_flags & NEW) == 0)
7928fae3551SRodney W. Grimes continue;
7938fae3551SRodney W. Grimes (void) strcpy(name, myname(ep));
7948fae3551SRodney W. Grimes if (ep->e_type == NODE) {
7958fae3551SRodney W. Grimes (void) linkit(name, myname(np), SYMLINK);
7968fae3551SRodney W. Grimes } else {
7978fae3551SRodney W. Grimes (void) linkit(name, myname(np), HARDLINK);
7988fae3551SRodney W. Grimes }
7998fae3551SRodney W. Grimes np->e_flags &= ~NEW;
8008fae3551SRodney W. Grimes }
8018fae3551SRodney W. Grimes }
8028fae3551SRodney W. Grimes }
8038fae3551SRodney W. Grimes
8048fae3551SRodney W. Grimes /*
8058fae3551SRodney W. Grimes * Check the symbol table.
8068fae3551SRodney W. Grimes * We do this to insure that all the requested work was done, and
8078fae3551SRodney W. Grimes * that no temporary names remain.
8088fae3551SRodney W. Grimes */
8098fae3551SRodney W. Grimes void
checkrestore(void)8102db673abSWarner Losh checkrestore(void)
8118fae3551SRodney W. Grimes {
8123d438ad6SDavid E. O'Brien struct entry *ep;
8133d438ad6SDavid E. O'Brien ino_t i;
8148fae3551SRodney W. Grimes
8158fae3551SRodney W. Grimes vprintf(stdout, "Check the symbol table.\n");
8161dc349abSEd Maste for (i = UFS_WINO; i < maxino; i++) {
8178fae3551SRodney W. Grimes for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
8188fae3551SRodney W. Grimes ep->e_flags &= ~KEEP;
8198fae3551SRodney W. Grimes if (ep->e_type == NODE)
8208fae3551SRodney W. Grimes ep->e_flags &= ~(NEW|EXISTED);
821d030d2d2SPoul-Henning Kamp if (ep->e_flags != 0)
8228fae3551SRodney W. Grimes badentry(ep, "incomplete operations");
8238fae3551SRodney W. Grimes }
8248fae3551SRodney W. Grimes }
8258fae3551SRodney W. Grimes }
8268fae3551SRodney W. Grimes
8278fae3551SRodney W. Grimes /*
8288fae3551SRodney W. Grimes * Compare with the directory structure on the tape
8298fae3551SRodney W. Grimes * A paranoid check that things are as they should be.
8308fae3551SRodney W. Grimes */
8318fae3551SRodney W. Grimes long
verifyfile(char * name,ino_t ino,int type)8322db673abSWarner Losh verifyfile(char *name, ino_t ino, int type)
8338fae3551SRodney W. Grimes {
8348fae3551SRodney W. Grimes struct entry *np, *ep;
8358fae3551SRodney W. Grimes long descend = GOOD;
8368fae3551SRodney W. Grimes
8378fae3551SRodney W. Grimes ep = lookupname(name);
8388fae3551SRodney W. Grimes if (ep == NULL) {
8398fae3551SRodney W. Grimes fprintf(stderr, "Warning: missing name %s\n", name);
8408fae3551SRodney W. Grimes return (FAIL);
8418fae3551SRodney W. Grimes }
8428fae3551SRodney W. Grimes np = lookupino(ino);
8438fae3551SRodney W. Grimes if (np != ep)
8448fae3551SRodney W. Grimes descend = FAIL;
8458fae3551SRodney W. Grimes for ( ; np != NULL; np = np->e_links)
8468fae3551SRodney W. Grimes if (np == ep)
8478fae3551SRodney W. Grimes break;
8488fae3551SRodney W. Grimes if (np == NULL)
849e25a029eSMatthew D Fleming panic("missing inumber %ju\n", (uintmax_t)ino);
8508fae3551SRodney W. Grimes if (ep->e_type == LEAF && type != LEAF)
8518fae3551SRodney W. Grimes badentry(ep, "type should be LEAF");
8528fae3551SRodney W. Grimes return (descend);
8538fae3551SRodney W. Grimes }
854