18a16b7a1SPedro F. Giffuni /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro 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 * (c) UNIX System Laboratories, Inc. 78fae3551SRodney W. Grimes * All or some portions of this file are derived from material licensed 88fae3551SRodney W. Grimes * to the University of California by American Telephone and Telegraph 98fae3551SRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 108fae3551SRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 118fae3551SRodney W. Grimes * 128fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 138fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 148fae3551SRodney W. Grimes * are met: 158fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 168fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 178fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 188fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 198fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 20fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 218fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 228fae3551SRodney W. Grimes * without specific prior written permission. 238fae3551SRodney W. Grimes * 248fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 258fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 268fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 278fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 288fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 298fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 308fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 318fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 328fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 338fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 348fae3551SRodney W. Grimes * SUCH DAMAGE. 358fae3551SRodney W. Grimes */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #ifndef lint 3891ac32e4SPhilippe Charnier #if 0 39d87d79aeSPeter Wemm static char sccsid[] = "@(#)dirs.c 8.7 (Berkeley) 5/1/95"; 4091ac32e4SPhilippe Charnier #endif 4191ac32e4SPhilippe Charnier static const char rcsid[] = 427f3dea24SPeter Wemm "$FreeBSD$"; 438fae3551SRodney W. Grimes #endif /* not lint */ 448fae3551SRodney W. Grimes 458fae3551SRodney W. Grimes #include <sys/param.h> 468fae3551SRodney W. Grimes #include <sys/file.h> 478fae3551SRodney W. Grimes #include <sys/stat.h> 48eb2fc780SGarrett Wollman #include <sys/time.h> 498fae3551SRodney W. Grimes 508fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h> 518fae3551SRodney W. Grimes #include <ufs/ufs/dir.h> 528fae3551SRodney W. Grimes #include <protocols/dumprestore.h> 538fae3551SRodney W. Grimes 5491ac32e4SPhilippe Charnier #include <err.h> 558fae3551SRodney W. Grimes #include <errno.h> 5689fdc4e1SMike Barcroft #include <limits.h> 578454c72cSDavid E. O'Brien #include <paths.h> 58cca1b3aaSJaakko Heinonen #include <stdint.h> 598fae3551SRodney W. Grimes #include <stdio.h> 608fae3551SRodney W. Grimes #include <stdlib.h> 618fae3551SRodney W. Grimes #include <string.h> 628fae3551SRodney W. Grimes #include <unistd.h> 63a7ab72edSPaul Traina 648fae3551SRodney W. Grimes #include "restore.h" 658fae3551SRodney W. Grimes #include "extern.h" 668fae3551SRodney W. Grimes 678fae3551SRodney W. Grimes /* 688fae3551SRodney W. Grimes * Symbol table of directories read from tape. 698fae3551SRodney W. Grimes */ 708fae3551SRodney W. Grimes #define HASHSIZE 1000 718fae3551SRodney W. Grimes #define INOHASH(val) (val % HASHSIZE) 728fae3551SRodney W. Grimes struct inotab { 738fae3551SRodney W. Grimes struct inotab *t_next; 748fae3551SRodney W. Grimes ino_t t_ino; 7597b465b1SDima Ruban int32_t t_seekpt; 7697b465b1SDima Ruban int32_t t_size; 778fae3551SRodney W. Grimes }; 788fae3551SRodney W. Grimes static struct inotab *inotab[HASHSIZE]; 798fae3551SRodney W. Grimes 808fae3551SRodney W. Grimes /* 818fae3551SRodney W. Grimes * Information retained about directories. 828fae3551SRodney W. Grimes */ 838fae3551SRodney W. Grimes struct modeinfo { 848fae3551SRodney W. Grimes ino_t ino; 8559966d51SJilles Tjoelker struct timespec ctimep[2]; 8659966d51SJilles Tjoelker struct timespec mtimep[2]; 87d87d79aeSPeter Wemm mode_t mode; 88d87d79aeSPeter Wemm uid_t uid; 89d87d79aeSPeter Wemm gid_t gid; 9071a53e69SPedro F. Giffuni u_int flags; 91772ad651SKirk McKusick int extsize; 928fae3551SRodney W. Grimes }; 938fae3551SRodney W. Grimes 948fae3551SRodney W. Grimes /* 958fae3551SRodney W. Grimes * Definitions for library routines operating on directories. 968fae3551SRodney W. Grimes */ 978fae3551SRodney W. Grimes #undef DIRBLKSIZ 988fae3551SRodney W. Grimes #define DIRBLKSIZ 1024 998fae3551SRodney W. Grimes struct rstdirdesc { 1008fae3551SRodney W. Grimes int dd_fd; 10197b465b1SDima Ruban int32_t dd_loc; 10297b465b1SDima Ruban int32_t dd_size; 1038fae3551SRodney W. Grimes char dd_buf[DIRBLKSIZ]; 1048fae3551SRodney W. Grimes }; 1058fae3551SRodney W. Grimes 1068fae3551SRodney W. Grimes /* 1078fae3551SRodney W. Grimes * Global variables for this file. 1088fae3551SRodney W. Grimes */ 1098fae3551SRodney W. Grimes static long seekpt; 1108fae3551SRodney W. Grimes static FILE *df, *mf; 1118fae3551SRodney W. Grimes static RST_DIR *dirp; 112335524b9SWarner Losh static char dirfile[MAXPATHLEN] = "#"; /* No file */ 113335524b9SWarner Losh static char modefile[MAXPATHLEN] = "#"; /* No file */ 1148fae3551SRodney W. Grimes static char dot[2] = "."; /* So it can be modified */ 1158fae3551SRodney W. Grimes 1161c85e6a3SKirk McKusick static struct inotab *allocinotab(struct context *, long); 1172db673abSWarner Losh static void flushent(void); 1182db673abSWarner Losh static struct inotab *inotablookup(ino_t); 1192db673abSWarner Losh static RST_DIR *opendirfile(const char *); 12071a53e69SPedro F. Giffuni static void putdir(char *, size_t); 12171a53e69SPedro F. Giffuni static void putdirattrs(char *, size_t); 1222db673abSWarner Losh static void putent(struct direct *); 1232db673abSWarner Losh static void rst_seekdir(RST_DIR *, long, long); 1242db673abSWarner Losh static long rst_telldir(RST_DIR *); 1252db673abSWarner Losh static struct direct *searchdir(ino_t, char *); 126aed3576dSKirk McKusick static void fail_dirtmp(char *); 1278fae3551SRodney W. Grimes 1288fae3551SRodney W. Grimes /* 1298fae3551SRodney W. Grimes * Extract directory contents, building up a directory structure 1308fae3551SRodney W. Grimes * on disk for extraction by name. 1318fae3551SRodney W. Grimes * If genmode is requested, save mode, owner, and times for all 1328fae3551SRodney W. Grimes * directories on the tape. 1338fae3551SRodney W. Grimes */ 1348fae3551SRodney W. Grimes void 1352db673abSWarner Losh extractdirs(int genmode) 1368fae3551SRodney W. Grimes { 1378fae3551SRodney W. Grimes struct inotab *itp; 1388fae3551SRodney W. Grimes struct direct nulldir; 1391c85e6a3SKirk McKusick int i, fd; 1404afde855SMaxim Sobolev const char *tmpdir; 1418fae3551SRodney W. Grimes 1428fae3551SRodney W. Grimes vprintf(stdout, "Extract directories from tape\n"); 1434afde855SMaxim Sobolev if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0') 1444afde855SMaxim Sobolev tmpdir = _PATH_TMP; 14563298eb1SConrad Meyer (void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%jd", tmpdir, 14663298eb1SConrad Meyer (intmax_t)dumpdate); 147335524b9SWarner Losh if (command != 'r' && command != 'R') { 148cca1b3aaSJaakko Heinonen (void) strcat(dirfile, "-XXXXXX"); 149335524b9SWarner Losh fd = mkstemp(dirfile); 150335524b9SWarner Losh } else 151335524b9SWarner Losh fd = open(dirfile, O_RDWR|O_CREAT|O_EXCL, 0666); 152335524b9SWarner Losh if (fd == -1 || (df = fdopen(fd, "w")) == NULL) { 153335524b9SWarner Losh if (fd != -1) 154335524b9SWarner Losh close(fd); 155aed3576dSKirk McKusick warn("%s: cannot create directory database", dirfile); 1568fae3551SRodney W. Grimes done(1); 1578fae3551SRodney W. Grimes } 1588fae3551SRodney W. Grimes if (genmode != 0) { 15963298eb1SConrad Meyer (void) snprintf(modefile, sizeof(modefile), "%s/rstmode%jd", 16063298eb1SConrad Meyer tmpdir, (intmax_t)dumpdate); 161335524b9SWarner Losh if (command != 'r' && command != 'R') { 162cca1b3aaSJaakko Heinonen (void) strcat(modefile, "-XXXXXX"); 163335524b9SWarner Losh fd = mkstemp(modefile); 164335524b9SWarner Losh } else 165335524b9SWarner Losh fd = open(modefile, O_RDWR|O_CREAT|O_EXCL, 0666); 166335524b9SWarner Losh if (fd == -1 || (mf = fdopen(fd, "w")) == NULL) { 167335524b9SWarner Losh if (fd != -1) 168335524b9SWarner Losh close(fd); 169aed3576dSKirk McKusick warn("%s: cannot create modefile", modefile); 1708fae3551SRodney W. Grimes done(1); 1718fae3551SRodney W. Grimes } 1728fae3551SRodney W. Grimes } 1738fae3551SRodney W. Grimes nulldir.d_ino = 0; 1748fae3551SRodney W. Grimes nulldir.d_type = DT_DIR; 1758fae3551SRodney W. Grimes nulldir.d_namlen = 1; 1768fae3551SRodney W. Grimes (void) strcpy(nulldir.d_name, "/"); 1778fae3551SRodney W. Grimes nulldir.d_reclen = DIRSIZ(0, &nulldir); 1788fae3551SRodney W. Grimes for (;;) { 1798fae3551SRodney W. Grimes curfile.name = "<directory file - name unknown>"; 1808fae3551SRodney W. Grimes curfile.action = USING; 181*d8ba45e2SEd Maste if (curfile.mode == 0 || (curfile.mode & IFMT) != IFDIR) 182aed3576dSKirk McKusick break; 1831c85e6a3SKirk McKusick itp = allocinotab(&curfile, seekpt); 184772ad651SKirk McKusick getfile(putdir, putdirattrs, xtrnull); 1858fae3551SRodney W. Grimes putent(&nulldir); 1868fae3551SRodney W. Grimes flushent(); 1878fae3551SRodney W. Grimes itp->t_size = seekpt - itp->t_seekpt; 1888fae3551SRodney W. Grimes } 189aed3576dSKirk McKusick if (fclose(df) != 0) 190aed3576dSKirk McKusick fail_dirtmp(dirfile); 191aed3576dSKirk McKusick dirp = opendirfile(dirfile); 192aed3576dSKirk McKusick if (dirp == NULL) 193aed3576dSKirk McKusick fprintf(stderr, "opendirfile: %s\n", strerror(errno)); 194aed3576dSKirk McKusick if (mf != NULL && fclose(mf) != 0) 195aed3576dSKirk McKusick fail_dirtmp(modefile); 196aed3576dSKirk McKusick i = dirlookup(dot); 197aed3576dSKirk McKusick if (i == 0) 198aed3576dSKirk McKusick panic("Root directory is not on tape\n"); 1998fae3551SRodney W. Grimes } 2008fae3551SRodney W. Grimes 2018fae3551SRodney W. Grimes /* 2028fae3551SRodney W. Grimes * skip over all the directories on the tape 2038fae3551SRodney W. Grimes */ 2048fae3551SRodney W. Grimes void 2052db673abSWarner Losh skipdirs(void) 2068fae3551SRodney W. Grimes { 2078fae3551SRodney W. Grimes 208*d8ba45e2SEd Maste while (curfile.ino && (curfile.mode & IFMT) == IFDIR) { 2098fae3551SRodney W. Grimes skipfile(); 2108fae3551SRodney W. Grimes } 2118fae3551SRodney W. Grimes } 2128fae3551SRodney W. Grimes 2138fae3551SRodney W. Grimes /* 2148fae3551SRodney W. Grimes * Recursively find names and inumbers of all files in subtree 2158fae3551SRodney W. Grimes * pname and pass them off to be processed. 2168fae3551SRodney W. Grimes */ 2178fae3551SRodney W. Grimes void 2182db673abSWarner Losh treescan(char *pname, ino_t ino, long (*todo)(char *, ino_t, int)) 2198fae3551SRodney W. Grimes { 2203d438ad6SDavid E. O'Brien struct inotab *itp; 2213d438ad6SDavid E. O'Brien struct direct *dp; 2228fae3551SRodney W. Grimes int namelen; 2238fae3551SRodney W. Grimes long bpt; 22452b370feSWarner Losh char locname[MAXPATHLEN]; 2258fae3551SRodney W. Grimes 2268fae3551SRodney W. Grimes itp = inotablookup(ino); 2278fae3551SRodney W. Grimes if (itp == NULL) { 2288fae3551SRodney W. Grimes /* 2298fae3551SRodney W. Grimes * Pname is name of a simple file or an unchanged directory. 2308fae3551SRodney W. Grimes */ 2318fae3551SRodney W. Grimes (void) (*todo)(pname, ino, LEAF); 2328fae3551SRodney W. Grimes return; 2338fae3551SRodney W. Grimes } 2348fae3551SRodney W. Grimes /* 2358fae3551SRodney W. Grimes * Pname is a dumped directory name. 2368fae3551SRodney W. Grimes */ 2378fae3551SRodney W. Grimes if ((*todo)(pname, ino, NODE) == FAIL) 2388fae3551SRodney W. Grimes return; 2398fae3551SRodney W. Grimes /* 2408fae3551SRodney W. Grimes * begin search through the directory 2418fae3551SRodney W. Grimes * skipping over "." and ".." 2428fae3551SRodney W. Grimes */ 24352b370feSWarner Losh (void) strlcpy(locname, pname, sizeof(locname)); 24452b370feSWarner Losh (void) strlcat(locname, "/", sizeof(locname)); 2458fae3551SRodney W. Grimes namelen = strlen(locname); 2468fae3551SRodney W. Grimes rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 2478fae3551SRodney W. Grimes dp = rst_readdir(dirp); /* "." */ 2488fae3551SRodney W. Grimes if (dp != NULL && strcmp(dp->d_name, ".") == 0) 2498fae3551SRodney W. Grimes dp = rst_readdir(dirp); /* ".." */ 2508fae3551SRodney W. Grimes else 2518fae3551SRodney W. Grimes fprintf(stderr, "Warning: `.' missing from directory %s\n", 2528fae3551SRodney W. Grimes pname); 2538fae3551SRodney W. Grimes if (dp != NULL && strcmp(dp->d_name, "..") == 0) 2548fae3551SRodney W. Grimes dp = rst_readdir(dirp); /* first real entry */ 2558fae3551SRodney W. Grimes else 2568fae3551SRodney W. Grimes fprintf(stderr, "Warning: `..' missing from directory %s\n", 2578fae3551SRodney W. Grimes pname); 2588fae3551SRodney W. Grimes bpt = rst_telldir(dirp); 2598fae3551SRodney W. Grimes /* 2608fae3551SRodney W. Grimes * a zero inode signals end of directory 2618fae3551SRodney W. Grimes */ 262d87d79aeSPeter Wemm while (dp != NULL) { 2638fae3551SRodney W. Grimes locname[namelen] = '\0'; 264335524b9SWarner Losh if (namelen + dp->d_namlen >= sizeof(locname)) { 265cca1b3aaSJaakko Heinonen fprintf(stderr, "%s%s: name exceeds %zu char\n", 266335524b9SWarner Losh locname, dp->d_name, sizeof(locname) - 1); 2678fae3551SRodney W. Grimes } else { 26852b370feSWarner Losh (void)strlcat(locname, dp->d_name, sizeof(locname)); 2698fae3551SRodney W. Grimes treescan(locname, dp->d_ino, todo); 2708fae3551SRodney W. Grimes rst_seekdir(dirp, bpt, itp->t_seekpt); 2718fae3551SRodney W. Grimes } 2728fae3551SRodney W. Grimes dp = rst_readdir(dirp); 2738fae3551SRodney W. Grimes bpt = rst_telldir(dirp); 2748fae3551SRodney W. Grimes } 2758fae3551SRodney W. Grimes } 2768fae3551SRodney W. Grimes 2778fae3551SRodney W. Grimes /* 2781dc349abSEd Maste * Lookup a pathname which is always assumed to start from the UFS_ROOTINO. 2798fae3551SRodney W. Grimes */ 2808fae3551SRodney W. Grimes struct direct * 2812db673abSWarner Losh pathsearch(const char *pathname) 2828fae3551SRodney W. Grimes { 2838fae3551SRodney W. Grimes ino_t ino; 2848fae3551SRodney W. Grimes struct direct *dp; 2858fae3551SRodney W. Grimes char *path, *name, buffer[MAXPATHLEN]; 2868fae3551SRodney W. Grimes 2878fae3551SRodney W. Grimes strcpy(buffer, pathname); 2888fae3551SRodney W. Grimes path = buffer; 2891dc349abSEd Maste ino = UFS_ROOTINO; 2908fae3551SRodney W. Grimes while (*path == '/') 2918fae3551SRodney W. Grimes path++; 2928fae3551SRodney W. Grimes dp = NULL; 293d030d2d2SPoul-Henning Kamp while ((name = strsep(&path, "/")) != NULL && *name != '\0') { 2948fae3551SRodney W. Grimes if ((dp = searchdir(ino, name)) == NULL) 2958fae3551SRodney W. Grimes return (NULL); 2968fae3551SRodney W. Grimes ino = dp->d_ino; 2978fae3551SRodney W. Grimes } 2988fae3551SRodney W. Grimes return (dp); 2998fae3551SRodney W. Grimes } 3008fae3551SRodney W. Grimes 3018fae3551SRodney W. Grimes /* 3028fae3551SRodney W. Grimes * Lookup the requested name in directory inum. 3038fae3551SRodney W. Grimes * Return its inode number if found, zero if it does not exist. 3048fae3551SRodney W. Grimes */ 3058fae3551SRodney W. Grimes static struct direct * 3062db673abSWarner Losh searchdir(ino_t inum, char *name) 3078fae3551SRodney W. Grimes { 3083d438ad6SDavid E. O'Brien struct direct *dp; 3093d438ad6SDavid E. O'Brien struct inotab *itp; 3108fae3551SRodney W. Grimes int len; 3118fae3551SRodney W. Grimes 3128fae3551SRodney W. Grimes itp = inotablookup(inum); 3138fae3551SRodney W. Grimes if (itp == NULL) 3148fae3551SRodney W. Grimes return (NULL); 3158fae3551SRodney W. Grimes rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 3168fae3551SRodney W. Grimes len = strlen(name); 3178fae3551SRodney W. Grimes do { 3188fae3551SRodney W. Grimes dp = rst_readdir(dirp); 319d87d79aeSPeter Wemm if (dp == NULL) 3208fae3551SRodney W. Grimes return (NULL); 3218fae3551SRodney W. Grimes } while (dp->d_namlen != len || strncmp(dp->d_name, name, len) != 0); 3228fae3551SRodney W. Grimes return (dp); 3238fae3551SRodney W. Grimes } 3248fae3551SRodney W. Grimes 3258fae3551SRodney W. Grimes /* 3268fae3551SRodney W. Grimes * Put the directory entries in the directory file 3278fae3551SRodney W. Grimes */ 3288fae3551SRodney W. Grimes static void 32971a53e69SPedro F. Giffuni putdir(char *buf, size_t size) 3308fae3551SRodney W. Grimes { 3313d438ad6SDavid E. O'Brien struct direct *dp; 33271a53e69SPedro F. Giffuni size_t loc, i; 3338fae3551SRodney W. Grimes 3348fae3551SRodney W. Grimes for (loc = 0; loc < size; ) { 3358fae3551SRodney W. Grimes dp = (struct direct *)(buf + loc); 336a7ab72edSPaul Traina if (Bcvt) 3378fae3551SRodney W. Grimes swabst((u_char *)"ls", (u_char *) dp); 33866b42171SWarner Losh if (oldinofmt && dp->d_ino != 0) { 33966b42171SWarner Losh #if BYTE_ORDER == BIG_ENDIAN 34066b42171SWarner Losh if (Bcvt) 34166b42171SWarner Losh dp->d_namlen = dp->d_type; 34266b42171SWarner Losh #else 34366b42171SWarner Losh if (!Bcvt && dp->d_namlen == 0) 34466b42171SWarner Losh dp->d_namlen = dp->d_type; 34566b42171SWarner Losh #endif 34666b42171SWarner Losh dp->d_type = DT_UNKNOWN; 34766b42171SWarner Losh } 3488fae3551SRodney W. Grimes i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 3498fae3551SRodney W. Grimes if ((dp->d_reclen & 0x3) != 0 || 3508fae3551SRodney W. Grimes dp->d_reclen > i || 35130d38f7bSPeter Wemm dp->d_reclen < DIRSIZ(0, dp) 35230d38f7bSPeter Wemm #if NAME_MAX < 255 35330d38f7bSPeter Wemm || dp->d_namlen > NAME_MAX 35430d38f7bSPeter Wemm #endif 35530d38f7bSPeter Wemm ) { 3568fae3551SRodney W. Grimes vprintf(stdout, "Mangled directory: "); 3578fae3551SRodney W. Grimes if ((dp->d_reclen & 0x3) != 0) 3588fae3551SRodney W. Grimes vprintf(stdout, 3598fae3551SRodney W. Grimes "reclen not multiple of 4 "); 3608fae3551SRodney W. Grimes if (dp->d_reclen < DIRSIZ(0, dp)) 3618fae3551SRodney W. Grimes vprintf(stdout, 36271a53e69SPedro F. Giffuni "reclen less than DIRSIZ (%u < %zu) ", 3638fae3551SRodney W. Grimes dp->d_reclen, DIRSIZ(0, dp)); 36430d38f7bSPeter Wemm #if NAME_MAX < 255 3658fae3551SRodney W. Grimes if (dp->d_namlen > NAME_MAX) 3668fae3551SRodney W. Grimes vprintf(stdout, 36771a53e69SPedro F. Giffuni "reclen name too big (%u > %u) ", 3688fae3551SRodney W. Grimes dp->d_namlen, NAME_MAX); 36930d38f7bSPeter Wemm #endif 3708fae3551SRodney W. Grimes vprintf(stdout, "\n"); 3718fae3551SRodney W. Grimes loc += i; 3728fae3551SRodney W. Grimes continue; 3738fae3551SRodney W. Grimes } 3748fae3551SRodney W. Grimes loc += dp->d_reclen; 3758fae3551SRodney W. Grimes if (dp->d_ino != 0) { 3768fae3551SRodney W. Grimes putent(dp); 3778fae3551SRodney W. Grimes } 3788fae3551SRodney W. Grimes } 3798fae3551SRodney W. Grimes } 3808fae3551SRodney W. Grimes 3818fae3551SRodney W. Grimes /* 3828fae3551SRodney W. Grimes * These variables are "local" to the following two functions. 3838fae3551SRodney W. Grimes */ 3848fae3551SRodney W. Grimes char dirbuf[DIRBLKSIZ]; 3858fae3551SRodney W. Grimes long dirloc = 0; 3868fae3551SRodney W. Grimes long prev = 0; 3878fae3551SRodney W. Grimes 3888fae3551SRodney W. Grimes /* 3898fae3551SRodney W. Grimes * add a new directory entry to a file. 3908fae3551SRodney W. Grimes */ 3918fae3551SRodney W. Grimes static void 3922db673abSWarner Losh putent(struct direct *dp) 3938fae3551SRodney W. Grimes { 3948fae3551SRodney W. Grimes dp->d_reclen = DIRSIZ(0, dp); 3958fae3551SRodney W. Grimes if (dirloc + dp->d_reclen > DIRBLKSIZ) { 3968fae3551SRodney W. Grimes ((struct direct *)(dirbuf + prev))->d_reclen = 3978fae3551SRodney W. Grimes DIRBLKSIZ - prev; 398aed3576dSKirk McKusick if (fwrite(dirbuf, DIRBLKSIZ, 1, df) != 1) 399aed3576dSKirk McKusick fail_dirtmp(dirfile); 4008fae3551SRodney W. Grimes dirloc = 0; 4018fae3551SRodney W. Grimes } 402d87d79aeSPeter Wemm memmove(dirbuf + dirloc, dp, (long)dp->d_reclen); 4038fae3551SRodney W. Grimes prev = dirloc; 4048fae3551SRodney W. Grimes dirloc += dp->d_reclen; 4058fae3551SRodney W. Grimes } 4068fae3551SRodney W. Grimes 4078fae3551SRodney W. Grimes /* 4088fae3551SRodney W. Grimes * flush out a directory that is finished. 4098fae3551SRodney W. Grimes */ 4108fae3551SRodney W. Grimes static void 4112db673abSWarner Losh flushent(void) 4128fae3551SRodney W. Grimes { 4138fae3551SRodney W. Grimes ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 414aed3576dSKirk McKusick if (fwrite(dirbuf, (int)dirloc, 1, df) != 1) 415aed3576dSKirk McKusick fail_dirtmp(dirfile); 4168fae3551SRodney W. Grimes seekpt = ftell(df); 4178fae3551SRodney W. Grimes dirloc = 0; 4188fae3551SRodney W. Grimes } 4198fae3551SRodney W. Grimes 4208fae3551SRodney W. Grimes /* 421772ad651SKirk McKusick * Save extended attributes for a directory entry to a file. 422772ad651SKirk McKusick */ 423772ad651SKirk McKusick static void 42471a53e69SPedro F. Giffuni putdirattrs(char *buf, size_t size) 425772ad651SKirk McKusick { 426772ad651SKirk McKusick 427aed3576dSKirk McKusick if (mf != NULL && fwrite(buf, size, 1, mf) != 1) 428aed3576dSKirk McKusick fail_dirtmp(modefile); 429772ad651SKirk McKusick } 430772ad651SKirk McKusick 431772ad651SKirk McKusick /* 4328fae3551SRodney W. Grimes * Seek to an entry in a directory. 4338fae3551SRodney W. Grimes * Only values returned by rst_telldir should be passed to rst_seekdir. 4348fae3551SRodney W. Grimes * This routine handles many directories in a single file. 4358fae3551SRodney W. Grimes * It takes the base of the directory in the file, plus 4368fae3551SRodney W. Grimes * the desired seek offset into it. 4378fae3551SRodney W. Grimes */ 4388fae3551SRodney W. Grimes static void 4392db673abSWarner Losh rst_seekdir(RST_DIR *dirp, long loc, long base) 4408fae3551SRodney W. Grimes { 4418fae3551SRodney W. Grimes 4428fae3551SRodney W. Grimes if (loc == rst_telldir(dirp)) 4438fae3551SRodney W. Grimes return; 4448fae3551SRodney W. Grimes loc -= base; 4458fae3551SRodney W. Grimes if (loc < 0) 4467fafc6f6SBruce Evans fprintf(stderr, "bad seek pointer to rst_seekdir %ld\n", loc); 44705cfc40aSPedro F. Giffuni (void) lseek(dirp->dd_fd, base + rounddown2(loc, DIRBLKSIZ), SEEK_SET); 4488fae3551SRodney W. Grimes dirp->dd_loc = loc & (DIRBLKSIZ - 1); 4498fae3551SRodney W. Grimes if (dirp->dd_loc != 0) 4508fae3551SRodney W. Grimes dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 4518fae3551SRodney W. Grimes } 4528fae3551SRodney W. Grimes 4538fae3551SRodney W. Grimes /* 4548fae3551SRodney W. Grimes * get next entry in a directory. 4558fae3551SRodney W. Grimes */ 4568fae3551SRodney W. Grimes struct direct * 4572db673abSWarner Losh rst_readdir(RST_DIR *dirp) 4588fae3551SRodney W. Grimes { 4593d438ad6SDavid E. O'Brien struct direct *dp; 4608fae3551SRodney W. Grimes 4618fae3551SRodney W. Grimes for (;;) { 4628fae3551SRodney W. Grimes if (dirp->dd_loc == 0) { 4638fae3551SRodney W. Grimes dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 4648fae3551SRodney W. Grimes DIRBLKSIZ); 4658fae3551SRodney W. Grimes if (dirp->dd_size <= 0) { 4668fae3551SRodney W. Grimes dprintf(stderr, "error reading directory\n"); 4678fae3551SRodney W. Grimes return (NULL); 4688fae3551SRodney W. Grimes } 4698fae3551SRodney W. Grimes } 4708fae3551SRodney W. Grimes if (dirp->dd_loc >= dirp->dd_size) { 4718fae3551SRodney W. Grimes dirp->dd_loc = 0; 4728fae3551SRodney W. Grimes continue; 4738fae3551SRodney W. Grimes } 4748fae3551SRodney W. Grimes dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 4758fae3551SRodney W. Grimes if (dp->d_reclen == 0 || 4768fae3551SRodney W. Grimes dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { 4778fae3551SRodney W. Grimes dprintf(stderr, "corrupted directory: bad reclen %d\n", 4788fae3551SRodney W. Grimes dp->d_reclen); 4798fae3551SRodney W. Grimes return (NULL); 4808fae3551SRodney W. Grimes } 4818fae3551SRodney W. Grimes dirp->dd_loc += dp->d_reclen; 482d87d79aeSPeter Wemm if (dp->d_ino == 0 && strcmp(dp->d_name, "/") == 0) 483d87d79aeSPeter Wemm return (NULL); 4848fae3551SRodney W. Grimes if (dp->d_ino >= maxino) { 4858fae3551SRodney W. Grimes dprintf(stderr, "corrupted directory: bad inum %d\n", 4868fae3551SRodney W. Grimes dp->d_ino); 4878fae3551SRodney W. Grimes continue; 4888fae3551SRodney W. Grimes } 4898fae3551SRodney W. Grimes return (dp); 4908fae3551SRodney W. Grimes } 4918fae3551SRodney W. Grimes } 4928fae3551SRodney W. Grimes 4938fae3551SRodney W. Grimes /* 4948fae3551SRodney W. Grimes * Simulate the opening of a directory 4958fae3551SRodney W. Grimes */ 4961916772eSStefan Farfeleder void * 4972db673abSWarner Losh rst_opendir(const char *name) 4988fae3551SRodney W. Grimes { 4998fae3551SRodney W. Grimes struct inotab *itp; 5008fae3551SRodney W. Grimes RST_DIR *dirp; 5018fae3551SRodney W. Grimes ino_t ino; 5028fae3551SRodney W. Grimes 5038fae3551SRodney W. Grimes if ((ino = dirlookup(name)) > 0 && 5048fae3551SRodney W. Grimes (itp = inotablookup(ino)) != NULL) { 5058fae3551SRodney W. Grimes dirp = opendirfile(dirfile); 5068fae3551SRodney W. Grimes rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 5078fae3551SRodney W. Grimes return (dirp); 5088fae3551SRodney W. Grimes } 5098fae3551SRodney W. Grimes return (NULL); 5108fae3551SRodney W. Grimes } 5118fae3551SRodney W. Grimes 5128fae3551SRodney W. Grimes /* 5138fae3551SRodney W. Grimes * In our case, there is nothing to do when closing a directory. 5148fae3551SRodney W. Grimes */ 5158fae3551SRodney W. Grimes void 5161916772eSStefan Farfeleder rst_closedir(void *arg) 5178fae3551SRodney W. Grimes { 5181916772eSStefan Farfeleder RST_DIR *dirp; 5198fae3551SRodney W. Grimes 5201916772eSStefan Farfeleder dirp = arg; 5218fae3551SRodney W. Grimes (void)close(dirp->dd_fd); 5228fae3551SRodney W. Grimes free(dirp); 5238fae3551SRodney W. Grimes return; 5248fae3551SRodney W. Grimes } 5258fae3551SRodney W. Grimes 5268fae3551SRodney W. Grimes /* 5278fae3551SRodney W. Grimes * Simulate finding the current offset in the directory. 5288fae3551SRodney W. Grimes */ 5298fae3551SRodney W. Grimes static long 5302db673abSWarner Losh rst_telldir(RST_DIR *dirp) 5318fae3551SRodney W. Grimes { 5328fae3551SRodney W. Grimes return ((long)lseek(dirp->dd_fd, 5338fae3551SRodney W. Grimes (off_t)0, SEEK_CUR) - dirp->dd_size + dirp->dd_loc); 5348fae3551SRodney W. Grimes } 5358fae3551SRodney W. Grimes 5368fae3551SRodney W. Grimes /* 5378fae3551SRodney W. Grimes * Open a directory file. 5388fae3551SRodney W. Grimes */ 5398fae3551SRodney W. Grimes static RST_DIR * 5402db673abSWarner Losh opendirfile(const char *name) 5418fae3551SRodney W. Grimes { 5423d438ad6SDavid E. O'Brien RST_DIR *dirp; 5433d438ad6SDavid E. O'Brien int fd; 5448fae3551SRodney W. Grimes 5458fae3551SRodney W. Grimes if ((fd = open(name, O_RDONLY)) == -1) 5468fae3551SRodney W. Grimes return (NULL); 5478fae3551SRodney W. Grimes if ((dirp = malloc(sizeof(RST_DIR))) == NULL) { 5488fae3551SRodney W. Grimes (void)close(fd); 5498fae3551SRodney W. Grimes return (NULL); 5508fae3551SRodney W. Grimes } 5518fae3551SRodney W. Grimes dirp->dd_fd = fd; 5528fae3551SRodney W. Grimes dirp->dd_loc = 0; 5538fae3551SRodney W. Grimes return (dirp); 5548fae3551SRodney W. Grimes } 5558fae3551SRodney W. Grimes 5568fae3551SRodney W. Grimes /* 5578fae3551SRodney W. Grimes * Set the mode, owner, and times for all new or changed directories 5588fae3551SRodney W. Grimes */ 5598fae3551SRodney W. Grimes void 5602db673abSWarner Losh setdirmodes(int flags) 5618fae3551SRodney W. Grimes { 5628fae3551SRodney W. Grimes FILE *mf; 5638fae3551SRodney W. Grimes struct modeinfo node; 5648fae3551SRodney W. Grimes struct entry *ep; 565772ad651SKirk McKusick char *cp, *buf; 5664afde855SMaxim Sobolev const char *tmpdir; 567772ad651SKirk McKusick int bufsize; 568c028393dSKirk McKusick uid_t myuid; 5698fae3551SRodney W. Grimes 5708fae3551SRodney W. Grimes vprintf(stdout, "Set directory mode, owner, and times.\n"); 5714afde855SMaxim Sobolev if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0') 5724afde855SMaxim Sobolev tmpdir = _PATH_TMP; 573335524b9SWarner Losh if (command == 'r' || command == 'R') 57463298eb1SConrad Meyer (void) snprintf(modefile, sizeof(modefile), "%s/rstmode%jd", 57563298eb1SConrad Meyer tmpdir, (intmax_t)dumpdate); 576335524b9SWarner Losh if (modefile[0] == '#') { 577335524b9SWarner Losh panic("modefile not defined\n"); 578335524b9SWarner Losh fprintf(stderr, "directory mode, owner, and times not set\n"); 579335524b9SWarner Losh return; 580335524b9SWarner Losh } 5818fae3551SRodney W. Grimes mf = fopen(modefile, "r"); 5828fae3551SRodney W. Grimes if (mf == NULL) { 5838fae3551SRodney W. Grimes fprintf(stderr, "fopen: %s\n", strerror(errno)); 5848fae3551SRodney W. Grimes fprintf(stderr, "cannot open mode file %s\n", modefile); 5858fae3551SRodney W. Grimes fprintf(stderr, "directory mode, owner, and times not set\n"); 5868fae3551SRodney W. Grimes return; 5878fae3551SRodney W. Grimes } 5888fae3551SRodney W. Grimes clearerr(mf); 589772ad651SKirk McKusick bufsize = 0; 590c028393dSKirk McKusick myuid = getuid(); 5918fae3551SRodney W. Grimes for (;;) { 5928fae3551SRodney W. Grimes (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); 593aed3576dSKirk McKusick if (ferror(mf)) { 594aed3576dSKirk McKusick warn("%s: cannot read modefile.", modefile); 595aed3576dSKirk McKusick fprintf(stderr, "Mode, owner, and times not set.\n"); 596aed3576dSKirk McKusick break; 597aed3576dSKirk McKusick } 5988fae3551SRodney W. Grimes if (feof(mf)) 5998fae3551SRodney W. Grimes break; 600772ad651SKirk McKusick if (node.extsize > 0) { 601772ad651SKirk McKusick if (bufsize < node.extsize) { 602772ad651SKirk McKusick if (bufsize > 0) 603772ad651SKirk McKusick free(buf); 604e63ce3deSMarcelo Araujo if ((buf = malloc(node.extsize)) != NULL) { 605772ad651SKirk McKusick bufsize = node.extsize; 606772ad651SKirk McKusick } else { 607772ad651SKirk McKusick bufsize = 0; 608772ad651SKirk McKusick } 609772ad651SKirk McKusick } 610772ad651SKirk McKusick if (bufsize >= node.extsize) { 611772ad651SKirk McKusick (void) fread(buf, 1, node.extsize, mf); 612aed3576dSKirk McKusick if (ferror(mf)) { 613aed3576dSKirk McKusick warn("%s: cannot read modefile.", 614aed3576dSKirk McKusick modefile); 615aed3576dSKirk McKusick fprintf(stderr, "Not all external "); 616aed3576dSKirk McKusick fprintf(stderr, "attributes set.\n"); 617aed3576dSKirk McKusick break; 618aed3576dSKirk McKusick } 619772ad651SKirk McKusick } else { 620772ad651SKirk McKusick (void) fseek(mf, node.extsize, SEEK_CUR); 621aed3576dSKirk McKusick if (ferror(mf)) { 622aed3576dSKirk McKusick warn("%s: cannot seek in modefile.", 623aed3576dSKirk McKusick modefile); 624aed3576dSKirk McKusick fprintf(stderr, "Not all directory "); 625aed3576dSKirk McKusick fprintf(stderr, "attributes set.\n"); 626aed3576dSKirk McKusick break; 627aed3576dSKirk McKusick } 628772ad651SKirk McKusick } 629772ad651SKirk McKusick } 6308fae3551SRodney W. Grimes ep = lookupino(node.ino); 6318fae3551SRodney W. Grimes if (command == 'i' || command == 'x') { 6328fae3551SRodney W. Grimes if (ep == NULL) 6338fae3551SRodney W. Grimes continue; 6348fae3551SRodney W. Grimes if ((flags & FORCE) == 0 && ep->e_flags & EXISTED) { 6358fae3551SRodney W. Grimes ep->e_flags &= ~NEW; 6368fae3551SRodney W. Grimes continue; 6378fae3551SRodney W. Grimes } 6381dc349abSEd Maste if (node.ino == UFS_ROOTINO && 6398fae3551SRodney W. Grimes reply("set owner/mode for '.'") == FAIL) 6408fae3551SRodney W. Grimes continue; 6418fae3551SRodney W. Grimes } 6428fae3551SRodney W. Grimes if (ep == NULL) { 643e25a029eSMatthew D Fleming panic("cannot find directory inode %ju\n", 644e25a029eSMatthew D Fleming (uintmax_t)node.ino); 645772ad651SKirk McKusick continue; 646772ad651SKirk McKusick } 6478fae3551SRodney W. Grimes cp = myname(ep); 648b9595aa5SDima Dorfman if (!Nflag) { 649772ad651SKirk McKusick if (node.extsize > 0) { 650772ad651SKirk McKusick if (bufsize >= node.extsize) { 651c9bf8148SConrad Meyer set_extattr(-1, cp, buf, node.extsize, SXA_FILE); 652772ad651SKirk McKusick } else { 653772ad651SKirk McKusick fprintf(stderr, "Cannot restore %s%s\n", 654772ad651SKirk McKusick "extended attributes for ", cp); 655772ad651SKirk McKusick } 656772ad651SKirk McKusick } 657c028393dSKirk McKusick if (myuid != 0) 658c028393dSKirk McKusick (void) chown(cp, myuid, node.gid); 659c028393dSKirk McKusick else 6608fae3551SRodney W. Grimes (void) chown(cp, node.uid, node.gid); 6618fae3551SRodney W. Grimes (void) chmod(cp, node.mode); 66259966d51SJilles Tjoelker utimensat(AT_FDCWD, cp, node.ctimep, 0); 66359966d51SJilles Tjoelker utimensat(AT_FDCWD, cp, node.mtimep, 0); 664fddde8b0SDavid Malone (void) chflags(cp, node.flags); 665b9595aa5SDima Dorfman } 6668fae3551SRodney W. Grimes ep->e_flags &= ~NEW; 6678fae3551SRodney W. Grimes } 668772ad651SKirk McKusick if (bufsize > 0) 669772ad651SKirk McKusick free(buf); 6708fae3551SRodney W. Grimes (void) fclose(mf); 6718fae3551SRodney W. Grimes } 6728fae3551SRodney W. Grimes 6738fae3551SRodney W. Grimes /* 6748fae3551SRodney W. Grimes * Generate a literal copy of a directory. 6758fae3551SRodney W. Grimes */ 6768fae3551SRodney W. Grimes int 6772db673abSWarner Losh genliteraldir(char *name, ino_t ino) 6788fae3551SRodney W. Grimes { 6793d438ad6SDavid E. O'Brien struct inotab *itp; 6808fae3551SRodney W. Grimes int ofile, dp, i, size; 6818fae3551SRodney W. Grimes char buf[BUFSIZ]; 6828fae3551SRodney W. Grimes 6838fae3551SRodney W. Grimes itp = inotablookup(ino); 6848fae3551SRodney W. Grimes if (itp == NULL) 685e25a029eSMatthew D Fleming panic("Cannot find directory inode %ju named %s\n", 686e25a029eSMatthew D Fleming (uintmax_t)ino, name); 687335524b9SWarner Losh if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { 6888fae3551SRodney W. Grimes fprintf(stderr, "%s: ", name); 6898fae3551SRodney W. Grimes (void) fflush(stderr); 6908fae3551SRodney W. Grimes fprintf(stderr, "cannot create file: %s\n", strerror(errno)); 6918fae3551SRodney W. Grimes return (FAIL); 6928fae3551SRodney W. Grimes } 6938fae3551SRodney W. Grimes rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 6948fae3551SRodney W. Grimes dp = dup(dirp->dd_fd); 6958fae3551SRodney W. Grimes for (i = itp->t_size; i > 0; i -= BUFSIZ) { 696f4b72a8dSMarcelo Araujo size = MIN(i, BUFSIZ); 6978fae3551SRodney W. Grimes if (read(dp, buf, (int) size) == -1) { 6988fae3551SRodney W. Grimes fprintf(stderr, 699e25a029eSMatthew D Fleming "write error extracting inode %ju, name %s\n", 700e25a029eSMatthew D Fleming (uintmax_t)curfile.ino, curfile.name); 7018fae3551SRodney W. Grimes fprintf(stderr, "read: %s\n", strerror(errno)); 7028fae3551SRodney W. Grimes done(1); 7038fae3551SRodney W. Grimes } 7048fae3551SRodney W. Grimes if (!Nflag && write(ofile, buf, (int) size) == -1) { 7058fae3551SRodney W. Grimes fprintf(stderr, 706e25a029eSMatthew D Fleming "write error extracting inode %ju, name %s\n", 707e25a029eSMatthew D Fleming (uintmax_t)curfile.ino, curfile.name); 7088fae3551SRodney W. Grimes fprintf(stderr, "write: %s\n", strerror(errno)); 7098fae3551SRodney W. Grimes done(1); 7108fae3551SRodney W. Grimes } 7118fae3551SRodney W. Grimes } 7128fae3551SRodney W. Grimes (void) close(dp); 7138fae3551SRodney W. Grimes (void) close(ofile); 7148fae3551SRodney W. Grimes return (GOOD); 7158fae3551SRodney W. Grimes } 7168fae3551SRodney W. Grimes 7178fae3551SRodney W. Grimes /* 7188fae3551SRodney W. Grimes * Determine the type of an inode 7198fae3551SRodney W. Grimes */ 7208fae3551SRodney W. Grimes int 7212db673abSWarner Losh inodetype(ino_t ino) 7228fae3551SRodney W. Grimes { 7238fae3551SRodney W. Grimes struct inotab *itp; 7248fae3551SRodney W. Grimes 7258fae3551SRodney W. Grimes itp = inotablookup(ino); 7268fae3551SRodney W. Grimes if (itp == NULL) 7278fae3551SRodney W. Grimes return (LEAF); 7288fae3551SRodney W. Grimes return (NODE); 7298fae3551SRodney W. Grimes } 7308fae3551SRodney W. Grimes 7318fae3551SRodney W. Grimes /* 7328fae3551SRodney W. Grimes * Allocate and initialize a directory inode entry. 7338fae3551SRodney W. Grimes * If requested, save its pertinent mode, owner, and time info. 7348fae3551SRodney W. Grimes */ 7358fae3551SRodney W. Grimes static struct inotab * 7361c85e6a3SKirk McKusick allocinotab(struct context *ctxp, long seekpt) 7378fae3551SRodney W. Grimes { 7383d438ad6SDavid E. O'Brien struct inotab *itp; 7398fae3551SRodney W. Grimes struct modeinfo node; 7408fae3551SRodney W. Grimes 7418fae3551SRodney W. Grimes itp = calloc(1, sizeof(struct inotab)); 7428fae3551SRodney W. Grimes if (itp == NULL) 743772ad651SKirk McKusick panic("no memory for directory table\n"); 7441c85e6a3SKirk McKusick itp->t_next = inotab[INOHASH(ctxp->ino)]; 7451c85e6a3SKirk McKusick inotab[INOHASH(ctxp->ino)] = itp; 7461c85e6a3SKirk McKusick itp->t_ino = ctxp->ino; 7478fae3551SRodney W. Grimes itp->t_seekpt = seekpt; 7488fae3551SRodney W. Grimes if (mf == NULL) 7498fae3551SRodney W. Grimes return (itp); 7501c85e6a3SKirk McKusick node.ino = ctxp->ino; 751fb36a3d8SKirk McKusick node.mtimep[0].tv_sec = ctxp->atime_sec; 75259966d51SJilles Tjoelker node.mtimep[0].tv_nsec = ctxp->atime_nsec; 753fb36a3d8SKirk McKusick node.mtimep[1].tv_sec = ctxp->mtime_sec; 75459966d51SJilles Tjoelker node.mtimep[1].tv_nsec = ctxp->mtime_nsec; 755fb36a3d8SKirk McKusick node.ctimep[0].tv_sec = ctxp->atime_sec; 75659966d51SJilles Tjoelker node.ctimep[0].tv_nsec = ctxp->atime_nsec; 757fb36a3d8SKirk McKusick node.ctimep[1].tv_sec = ctxp->birthtime_sec; 75859966d51SJilles Tjoelker node.ctimep[1].tv_nsec = ctxp->birthtime_nsec; 759772ad651SKirk McKusick node.extsize = ctxp->extsize; 7601c85e6a3SKirk McKusick node.mode = ctxp->mode; 7611c85e6a3SKirk McKusick node.flags = ctxp->file_flags; 7621c85e6a3SKirk McKusick node.uid = ctxp->uid; 7631c85e6a3SKirk McKusick node.gid = ctxp->gid; 764aed3576dSKirk McKusick if (fwrite((char *)&node, sizeof(struct modeinfo), 1, mf) != 1) 765aed3576dSKirk McKusick fail_dirtmp(modefile); 7668fae3551SRodney W. Grimes return (itp); 7678fae3551SRodney W. Grimes } 7688fae3551SRodney W. Grimes 7698fae3551SRodney W. Grimes /* 7708fae3551SRodney W. Grimes * Look up an inode in the table of directories 7718fae3551SRodney W. Grimes */ 7728fae3551SRodney W. Grimes static struct inotab * 7732db673abSWarner Losh inotablookup(ino_t ino) 7748fae3551SRodney W. Grimes { 7753d438ad6SDavid E. O'Brien struct inotab *itp; 7768fae3551SRodney W. Grimes 7778fae3551SRodney W. Grimes for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) 7788fae3551SRodney W. Grimes if (itp->t_ino == ino) 7798fae3551SRodney W. Grimes return (itp); 7808fae3551SRodney W. Grimes return (NULL); 7818fae3551SRodney W. Grimes } 7828fae3551SRodney W. Grimes 7838fae3551SRodney W. Grimes /* 7848fae3551SRodney W. Grimes * Clean up and exit 7858fae3551SRodney W. Grimes */ 786eaa86f9dSBruce Evans void 7872db673abSWarner Losh done(int exitcode) 7888fae3551SRodney W. Grimes { 7898fae3551SRodney W. Grimes 7908fae3551SRodney W. Grimes closemt(); 791aed3576dSKirk McKusick if (modefile[0] != '#') { 792aed3576dSKirk McKusick (void) truncate(modefile, 0); 7938fae3551SRodney W. Grimes (void) unlink(modefile); 794aed3576dSKirk McKusick } 795aed3576dSKirk McKusick if (dirfile[0] != '#') { 796aed3576dSKirk McKusick (void) truncate(dirfile, 0); 7978fae3551SRodney W. Grimes (void) unlink(dirfile); 798aed3576dSKirk McKusick } 7998fae3551SRodney W. Grimes exit(exitcode); 8008fae3551SRodney W. Grimes } 801aed3576dSKirk McKusick 802aed3576dSKirk McKusick /* 803aed3576dSKirk McKusick * Print out information about the failure to save directory, 804aed3576dSKirk McKusick * extended attribute, and mode information. 805aed3576dSKirk McKusick */ 806aed3576dSKirk McKusick static void 807aed3576dSKirk McKusick fail_dirtmp(char *filename) 808aed3576dSKirk McKusick { 809aed3576dSKirk McKusick const char *tmpdir; 810aed3576dSKirk McKusick 811aed3576dSKirk McKusick warn("%s: cannot write directory database", filename); 812aed3576dSKirk McKusick if (errno == ENOSPC) { 813aed3576dSKirk McKusick if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0') 814aed3576dSKirk McKusick tmpdir = _PATH_TMP; 815aed3576dSKirk McKusick fprintf(stderr, "Try making space in %s, %s\n%s\n", tmpdir, 816aed3576dSKirk McKusick "or set environment variable TMPDIR", 817aed3576dSKirk McKusick "to an alternate location with more disk space."); 818aed3576dSKirk McKusick } 819aed3576dSKirk McKusick done(1); 820aed3576dSKirk McKusick } 821