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 #include <sys/param.h>
388fae3551SRodney W. Grimes #include <sys/file.h>
398fae3551SRodney W. Grimes #include <sys/stat.h>
40eb2fc780SGarrett Wollman #include <sys/time.h>
418fae3551SRodney W. Grimes
428fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h>
438fae3551SRodney W. Grimes #include <ufs/ufs/dir.h>
448fae3551SRodney W. Grimes #include <protocols/dumprestore.h>
458fae3551SRodney W. Grimes
4691ac32e4SPhilippe Charnier #include <err.h>
478fae3551SRodney W. Grimes #include <errno.h>
4889fdc4e1SMike Barcroft #include <limits.h>
498454c72cSDavid E. O'Brien #include <paths.h>
50cca1b3aaSJaakko Heinonen #include <stdint.h>
518fae3551SRodney W. Grimes #include <stdio.h>
528fae3551SRodney W. Grimes #include <stdlib.h>
538fae3551SRodney W. Grimes #include <string.h>
548fae3551SRodney W. Grimes #include <unistd.h>
55a7ab72edSPaul Traina
568fae3551SRodney W. Grimes #include "restore.h"
578fae3551SRodney W. Grimes #include "extern.h"
588fae3551SRodney W. Grimes
598fae3551SRodney W. Grimes /*
608fae3551SRodney W. Grimes * Symbol table of directories read from tape.
618fae3551SRodney W. Grimes */
628fae3551SRodney W. Grimes #define HASHSIZE 1000
638fae3551SRodney W. Grimes #define INOHASH(val) (val % HASHSIZE)
648fae3551SRodney W. Grimes struct inotab {
658fae3551SRodney W. Grimes struct inotab *t_next;
668fae3551SRodney W. Grimes ino_t t_ino;
6797b465b1SDima Ruban int32_t t_seekpt;
6897b465b1SDima Ruban int32_t t_size;
698fae3551SRodney W. Grimes };
708fae3551SRodney W. Grimes static struct inotab *inotab[HASHSIZE];
718fae3551SRodney W. Grimes
728fae3551SRodney W. Grimes /*
738fae3551SRodney W. Grimes * Information retained about directories.
748fae3551SRodney W. Grimes */
758fae3551SRodney W. Grimes struct modeinfo {
768fae3551SRodney W. Grimes ino_t ino;
7759966d51SJilles Tjoelker struct timespec ctimep[2];
7859966d51SJilles Tjoelker struct timespec mtimep[2];
79d87d79aeSPeter Wemm mode_t mode;
80d87d79aeSPeter Wemm uid_t uid;
81d87d79aeSPeter Wemm gid_t gid;
8271a53e69SPedro F. Giffuni u_int flags;
83772ad651SKirk McKusick int extsize;
848fae3551SRodney W. Grimes };
858fae3551SRodney W. Grimes
868fae3551SRodney W. Grimes /*
878fae3551SRodney W. Grimes * Definitions for library routines operating on directories.
888fae3551SRodney W. Grimes */
898fae3551SRodney W. Grimes #undef DIRBLKSIZ
908fae3551SRodney W. Grimes #define DIRBLKSIZ 1024
918fae3551SRodney W. Grimes struct rstdirdesc {
928fae3551SRodney W. Grimes int dd_fd;
9397b465b1SDima Ruban int32_t dd_loc;
9497b465b1SDima Ruban int32_t dd_size;
958fae3551SRodney W. Grimes char dd_buf[DIRBLKSIZ];
968fae3551SRodney W. Grimes };
978fae3551SRodney W. Grimes
988fae3551SRodney W. Grimes /*
998fae3551SRodney W. Grimes * Global variables for this file.
1008fae3551SRodney W. Grimes */
1018fae3551SRodney W. Grimes static long seekpt;
1028fae3551SRodney W. Grimes static FILE *df, *mf;
1038fae3551SRodney W. Grimes static RST_DIR *dirp;
104335524b9SWarner Losh static char dirfile[MAXPATHLEN] = "#"; /* No file */
105335524b9SWarner Losh static char modefile[MAXPATHLEN] = "#"; /* No file */
1068fae3551SRodney W. Grimes static char dot[2] = "."; /* So it can be modified */
1078fae3551SRodney W. Grimes
1081c85e6a3SKirk McKusick static struct inotab *allocinotab(struct context *, long);
1092db673abSWarner Losh static void flushent(void);
1102db673abSWarner Losh static struct inotab *inotablookup(ino_t);
1112db673abSWarner Losh static RST_DIR *opendirfile(const char *);
11271a53e69SPedro F. Giffuni static void putdir(char *, size_t);
11371a53e69SPedro F. Giffuni static void putdirattrs(char *, size_t);
1142db673abSWarner Losh static void putent(struct direct *);
1152db673abSWarner Losh static void rst_seekdir(RST_DIR *, long, long);
1162db673abSWarner Losh static long rst_telldir(RST_DIR *);
1172db673abSWarner Losh static struct direct *searchdir(ino_t, char *);
118aed3576dSKirk McKusick static void fail_dirtmp(char *);
1198fae3551SRodney W. Grimes
1208fae3551SRodney W. Grimes /*
1218fae3551SRodney W. Grimes * Extract directory contents, building up a directory structure
1228fae3551SRodney W. Grimes * on disk for extraction by name.
1238fae3551SRodney W. Grimes * If genmode is requested, save mode, owner, and times for all
1248fae3551SRodney W. Grimes * directories on the tape.
1258fae3551SRodney W. Grimes */
1268fae3551SRodney W. Grimes void
extractdirs(int genmode)1272db673abSWarner Losh extractdirs(int genmode)
1288fae3551SRodney W. Grimes {
1298fae3551SRodney W. Grimes struct inotab *itp;
1308fae3551SRodney W. Grimes struct direct nulldir;
1311c85e6a3SKirk McKusick int i, fd;
1324afde855SMaxim Sobolev const char *tmpdir;
1338fae3551SRodney W. Grimes
1348fae3551SRodney W. Grimes vprintf(stdout, "Extract directories from tape\n");
1354afde855SMaxim Sobolev if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0')
1364afde855SMaxim Sobolev tmpdir = _PATH_TMP;
13763298eb1SConrad Meyer (void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%jd", tmpdir,
13863298eb1SConrad Meyer (intmax_t)dumpdate);
139335524b9SWarner Losh if (command != 'r' && command != 'R') {
140cca1b3aaSJaakko Heinonen (void) strcat(dirfile, "-XXXXXX");
141335524b9SWarner Losh fd = mkstemp(dirfile);
142335524b9SWarner Losh } else
143335524b9SWarner Losh fd = open(dirfile, O_RDWR|O_CREAT|O_EXCL, 0666);
144335524b9SWarner Losh if (fd == -1 || (df = fdopen(fd, "w")) == NULL) {
145335524b9SWarner Losh if (fd != -1)
146335524b9SWarner Losh close(fd);
147aed3576dSKirk McKusick warn("%s: cannot create directory database", dirfile);
1488fae3551SRodney W. Grimes done(1);
1498fae3551SRodney W. Grimes }
1508fae3551SRodney W. Grimes if (genmode != 0) {
15163298eb1SConrad Meyer (void) snprintf(modefile, sizeof(modefile), "%s/rstmode%jd",
15263298eb1SConrad Meyer tmpdir, (intmax_t)dumpdate);
153335524b9SWarner Losh if (command != 'r' && command != 'R') {
154cca1b3aaSJaakko Heinonen (void) strcat(modefile, "-XXXXXX");
155335524b9SWarner Losh fd = mkstemp(modefile);
156335524b9SWarner Losh } else
157335524b9SWarner Losh fd = open(modefile, O_RDWR|O_CREAT|O_EXCL, 0666);
158335524b9SWarner Losh if (fd == -1 || (mf = fdopen(fd, "w")) == NULL) {
159335524b9SWarner Losh if (fd != -1)
160335524b9SWarner Losh close(fd);
161aed3576dSKirk McKusick warn("%s: cannot create modefile", modefile);
1628fae3551SRodney W. Grimes done(1);
1638fae3551SRodney W. Grimes }
1648fae3551SRodney W. Grimes }
1658fae3551SRodney W. Grimes nulldir.d_ino = 0;
1668fae3551SRodney W. Grimes nulldir.d_type = DT_DIR;
1678fae3551SRodney W. Grimes nulldir.d_namlen = 1;
1688fae3551SRodney W. Grimes (void) strcpy(nulldir.d_name, "/");
1698fae3551SRodney W. Grimes nulldir.d_reclen = DIRSIZ(0, &nulldir);
1708fae3551SRodney W. Grimes for (;;) {
1718fae3551SRodney W. Grimes curfile.name = "<directory file - name unknown>";
1728fae3551SRodney W. Grimes curfile.action = USING;
173d8ba45e2SEd Maste if (curfile.mode == 0 || (curfile.mode & IFMT) != IFDIR)
174aed3576dSKirk McKusick break;
1751c85e6a3SKirk McKusick itp = allocinotab(&curfile, seekpt);
176772ad651SKirk McKusick getfile(putdir, putdirattrs, xtrnull);
1778fae3551SRodney W. Grimes putent(&nulldir);
1788fae3551SRodney W. Grimes flushent();
1798fae3551SRodney W. Grimes itp->t_size = seekpt - itp->t_seekpt;
1808fae3551SRodney W. Grimes }
181aed3576dSKirk McKusick if (fclose(df) != 0)
182aed3576dSKirk McKusick fail_dirtmp(dirfile);
183aed3576dSKirk McKusick dirp = opendirfile(dirfile);
184aed3576dSKirk McKusick if (dirp == NULL)
185aed3576dSKirk McKusick fprintf(stderr, "opendirfile: %s\n", strerror(errno));
186aed3576dSKirk McKusick if (mf != NULL && fclose(mf) != 0)
187aed3576dSKirk McKusick fail_dirtmp(modefile);
188aed3576dSKirk McKusick i = dirlookup(dot);
189aed3576dSKirk McKusick if (i == 0)
190aed3576dSKirk McKusick panic("Root directory is not on tape\n");
1918fae3551SRodney W. Grimes }
1928fae3551SRodney W. Grimes
1938fae3551SRodney W. Grimes /*
1948fae3551SRodney W. Grimes * skip over all the directories on the tape
1958fae3551SRodney W. Grimes */
1968fae3551SRodney W. Grimes void
skipdirs(void)1972db673abSWarner Losh skipdirs(void)
1988fae3551SRodney W. Grimes {
1998fae3551SRodney W. Grimes
200d8ba45e2SEd Maste while (curfile.ino && (curfile.mode & IFMT) == IFDIR) {
2018fae3551SRodney W. Grimes skipfile();
2028fae3551SRodney W. Grimes }
2038fae3551SRodney W. Grimes }
2048fae3551SRodney W. Grimes
2058fae3551SRodney W. Grimes /*
2068fae3551SRodney W. Grimes * Recursively find names and inumbers of all files in subtree
2078fae3551SRodney W. Grimes * pname and pass them off to be processed.
2088fae3551SRodney W. Grimes */
2098fae3551SRodney W. Grimes void
treescan(char * pname,ino_t ino,long (* todo)(char *,ino_t,int))2102db673abSWarner Losh treescan(char *pname, ino_t ino, long (*todo)(char *, ino_t, int))
2118fae3551SRodney W. Grimes {
2123d438ad6SDavid E. O'Brien struct inotab *itp;
2133d438ad6SDavid E. O'Brien struct direct *dp;
2148fae3551SRodney W. Grimes int namelen;
2158fae3551SRodney W. Grimes long bpt;
21652b370feSWarner Losh char locname[MAXPATHLEN];
2178fae3551SRodney W. Grimes
2188fae3551SRodney W. Grimes itp = inotablookup(ino);
2198fae3551SRodney W. Grimes if (itp == NULL) {
2208fae3551SRodney W. Grimes /*
2218fae3551SRodney W. Grimes * Pname is name of a simple file or an unchanged directory.
2228fae3551SRodney W. Grimes */
2238fae3551SRodney W. Grimes (void) (*todo)(pname, ino, LEAF);
2248fae3551SRodney W. Grimes return;
2258fae3551SRodney W. Grimes }
2268fae3551SRodney W. Grimes /*
2278fae3551SRodney W. Grimes * Pname is a dumped directory name.
2288fae3551SRodney W. Grimes */
2298fae3551SRodney W. Grimes if ((*todo)(pname, ino, NODE) == FAIL)
2308fae3551SRodney W. Grimes return;
2318fae3551SRodney W. Grimes /*
2328fae3551SRodney W. Grimes * begin search through the directory
2338fae3551SRodney W. Grimes * skipping over "." and ".."
2348fae3551SRodney W. Grimes */
23552b370feSWarner Losh (void) strlcpy(locname, pname, sizeof(locname));
23652b370feSWarner Losh (void) strlcat(locname, "/", sizeof(locname));
2378fae3551SRodney W. Grimes namelen = strlen(locname);
2388fae3551SRodney W. Grimes rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
2398fae3551SRodney W. Grimes dp = rst_readdir(dirp); /* "." */
2408fae3551SRodney W. Grimes if (dp != NULL && strcmp(dp->d_name, ".") == 0)
2418fae3551SRodney W. Grimes dp = rst_readdir(dirp); /* ".." */
2428fae3551SRodney W. Grimes else
2438fae3551SRodney W. Grimes fprintf(stderr, "Warning: `.' missing from directory %s\n",
2448fae3551SRodney W. Grimes pname);
2458fae3551SRodney W. Grimes if (dp != NULL && strcmp(dp->d_name, "..") == 0)
2468fae3551SRodney W. Grimes dp = rst_readdir(dirp); /* first real entry */
2478fae3551SRodney W. Grimes else
2488fae3551SRodney W. Grimes fprintf(stderr, "Warning: `..' missing from directory %s\n",
2498fae3551SRodney W. Grimes pname);
2508fae3551SRodney W. Grimes bpt = rst_telldir(dirp);
2518fae3551SRodney W. Grimes /*
2528fae3551SRodney W. Grimes * a zero inode signals end of directory
2538fae3551SRodney W. Grimes */
254d87d79aeSPeter Wemm while (dp != NULL) {
2558fae3551SRodney W. Grimes locname[namelen] = '\0';
256335524b9SWarner Losh if (namelen + dp->d_namlen >= sizeof(locname)) {
257cca1b3aaSJaakko Heinonen fprintf(stderr, "%s%s: name exceeds %zu char\n",
258335524b9SWarner Losh locname, dp->d_name, sizeof(locname) - 1);
2598fae3551SRodney W. Grimes } else {
26052b370feSWarner Losh (void)strlcat(locname, dp->d_name, sizeof(locname));
2618fae3551SRodney W. Grimes treescan(locname, dp->d_ino, todo);
2628fae3551SRodney W. Grimes rst_seekdir(dirp, bpt, itp->t_seekpt);
2638fae3551SRodney W. Grimes }
2648fae3551SRodney W. Grimes dp = rst_readdir(dirp);
2658fae3551SRodney W. Grimes bpt = rst_telldir(dirp);
2668fae3551SRodney W. Grimes }
2678fae3551SRodney W. Grimes }
2688fae3551SRodney W. Grimes
2698fae3551SRodney W. Grimes /*
2701dc349abSEd Maste * Lookup a pathname which is always assumed to start from the UFS_ROOTINO.
2718fae3551SRodney W. Grimes */
2728fae3551SRodney W. Grimes struct direct *
pathsearch(const char * pathname)2732db673abSWarner Losh pathsearch(const char *pathname)
2748fae3551SRodney W. Grimes {
2758fae3551SRodney W. Grimes ino_t ino;
2768fae3551SRodney W. Grimes struct direct *dp;
2778fae3551SRodney W. Grimes char *path, *name, buffer[MAXPATHLEN];
2788fae3551SRodney W. Grimes
2798fae3551SRodney W. Grimes strcpy(buffer, pathname);
2808fae3551SRodney W. Grimes path = buffer;
2811dc349abSEd Maste ino = UFS_ROOTINO;
2828fae3551SRodney W. Grimes while (*path == '/')
2838fae3551SRodney W. Grimes path++;
2848fae3551SRodney W. Grimes dp = NULL;
285d030d2d2SPoul-Henning Kamp while ((name = strsep(&path, "/")) != NULL && *name != '\0') {
2868fae3551SRodney W. Grimes if ((dp = searchdir(ino, name)) == NULL)
2878fae3551SRodney W. Grimes return (NULL);
2888fae3551SRodney W. Grimes ino = dp->d_ino;
2898fae3551SRodney W. Grimes }
2908fae3551SRodney W. Grimes return (dp);
2918fae3551SRodney W. Grimes }
2928fae3551SRodney W. Grimes
2938fae3551SRodney W. Grimes /*
2948fae3551SRodney W. Grimes * Lookup the requested name in directory inum.
2958fae3551SRodney W. Grimes * Return its inode number if found, zero if it does not exist.
2968fae3551SRodney W. Grimes */
2978fae3551SRodney W. Grimes static struct direct *
searchdir(ino_t inum,char * name)2982db673abSWarner Losh searchdir(ino_t inum, char *name)
2998fae3551SRodney W. Grimes {
3003d438ad6SDavid E. O'Brien struct direct *dp;
3013d438ad6SDavid E. O'Brien struct inotab *itp;
3028fae3551SRodney W. Grimes int len;
3038fae3551SRodney W. Grimes
3048fae3551SRodney W. Grimes itp = inotablookup(inum);
3058fae3551SRodney W. Grimes if (itp == NULL)
3068fae3551SRodney W. Grimes return (NULL);
3078fae3551SRodney W. Grimes rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
3088fae3551SRodney W. Grimes len = strlen(name);
3098fae3551SRodney W. Grimes do {
3108fae3551SRodney W. Grimes dp = rst_readdir(dirp);
311d87d79aeSPeter Wemm if (dp == NULL)
3128fae3551SRodney W. Grimes return (NULL);
3138fae3551SRodney W. Grimes } while (dp->d_namlen != len || strncmp(dp->d_name, name, len) != 0);
3148fae3551SRodney W. Grimes return (dp);
3158fae3551SRodney W. Grimes }
3168fae3551SRodney W. Grimes
3178fae3551SRodney W. Grimes /*
3188fae3551SRodney W. Grimes * Put the directory entries in the directory file
3198fae3551SRodney W. Grimes */
3208fae3551SRodney W. Grimes static void
putdir(char * buf,size_t size)32171a53e69SPedro F. Giffuni putdir(char *buf, size_t size)
3228fae3551SRodney W. Grimes {
3233d438ad6SDavid E. O'Brien struct direct *dp;
32471a53e69SPedro F. Giffuni size_t loc, i;
3258fae3551SRodney W. Grimes
3268fae3551SRodney W. Grimes for (loc = 0; loc < size; ) {
3278fae3551SRodney W. Grimes dp = (struct direct *)(buf + loc);
328a7ab72edSPaul Traina if (Bcvt)
3298fae3551SRodney W. Grimes swabst((u_char *)"ls", (u_char *) dp);
33066b42171SWarner Losh if (oldinofmt && dp->d_ino != 0) {
33166b42171SWarner Losh #if BYTE_ORDER == BIG_ENDIAN
33266b42171SWarner Losh if (Bcvt)
33366b42171SWarner Losh dp->d_namlen = dp->d_type;
33466b42171SWarner Losh #else
33566b42171SWarner Losh if (!Bcvt && dp->d_namlen == 0)
33666b42171SWarner Losh dp->d_namlen = dp->d_type;
33766b42171SWarner Losh #endif
33866b42171SWarner Losh dp->d_type = DT_UNKNOWN;
33966b42171SWarner Losh }
3408fae3551SRodney W. Grimes i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
3418fae3551SRodney W. Grimes if ((dp->d_reclen & 0x3) != 0 ||
3428fae3551SRodney W. Grimes dp->d_reclen > i ||
34330d38f7bSPeter Wemm dp->d_reclen < DIRSIZ(0, dp)
34430d38f7bSPeter Wemm #if NAME_MAX < 255
34530d38f7bSPeter Wemm || dp->d_namlen > NAME_MAX
34630d38f7bSPeter Wemm #endif
34730d38f7bSPeter Wemm ) {
3488fae3551SRodney W. Grimes vprintf(stdout, "Mangled directory: ");
3498fae3551SRodney W. Grimes if ((dp->d_reclen & 0x3) != 0)
3508fae3551SRodney W. Grimes vprintf(stdout,
3518fae3551SRodney W. Grimes "reclen not multiple of 4 ");
3528fae3551SRodney W. Grimes if (dp->d_reclen < DIRSIZ(0, dp))
3538fae3551SRodney W. Grimes vprintf(stdout,
35471a53e69SPedro F. Giffuni "reclen less than DIRSIZ (%u < %zu) ",
3558fae3551SRodney W. Grimes dp->d_reclen, DIRSIZ(0, dp));
35630d38f7bSPeter Wemm #if NAME_MAX < 255
3578fae3551SRodney W. Grimes if (dp->d_namlen > NAME_MAX)
3588fae3551SRodney W. Grimes vprintf(stdout,
35971a53e69SPedro F. Giffuni "reclen name too big (%u > %u) ",
3608fae3551SRodney W. Grimes dp->d_namlen, NAME_MAX);
36130d38f7bSPeter Wemm #endif
3628fae3551SRodney W. Grimes vprintf(stdout, "\n");
3638fae3551SRodney W. Grimes loc += i;
3648fae3551SRodney W. Grimes continue;
3658fae3551SRodney W. Grimes }
3668fae3551SRodney W. Grimes loc += dp->d_reclen;
3678fae3551SRodney W. Grimes if (dp->d_ino != 0) {
3688fae3551SRodney W. Grimes putent(dp);
3698fae3551SRodney W. Grimes }
3708fae3551SRodney W. Grimes }
3718fae3551SRodney W. Grimes }
3728fae3551SRodney W. Grimes
3738fae3551SRodney W. Grimes /*
3748fae3551SRodney W. Grimes * These variables are "local" to the following two functions.
3758fae3551SRodney W. Grimes */
3768fae3551SRodney W. Grimes char dirbuf[DIRBLKSIZ];
3778fae3551SRodney W. Grimes long dirloc = 0;
3788fae3551SRodney W. Grimes long prev = 0;
3798fae3551SRodney W. Grimes
3808fae3551SRodney W. Grimes /*
3818fae3551SRodney W. Grimes * add a new directory entry to a file.
3828fae3551SRodney W. Grimes */
3838fae3551SRodney W. Grimes static void
putent(struct direct * dp)3842db673abSWarner Losh putent(struct direct *dp)
3858fae3551SRodney W. Grimes {
3868fae3551SRodney W. Grimes dp->d_reclen = DIRSIZ(0, dp);
3878fae3551SRodney W. Grimes if (dirloc + dp->d_reclen > DIRBLKSIZ) {
3888fae3551SRodney W. Grimes ((struct direct *)(dirbuf + prev))->d_reclen =
3898fae3551SRodney W. Grimes DIRBLKSIZ - prev;
390aed3576dSKirk McKusick if (fwrite(dirbuf, DIRBLKSIZ, 1, df) != 1)
391aed3576dSKirk McKusick fail_dirtmp(dirfile);
3928fae3551SRodney W. Grimes dirloc = 0;
3938fae3551SRodney W. Grimes }
394d87d79aeSPeter Wemm memmove(dirbuf + dirloc, dp, (long)dp->d_reclen);
3958fae3551SRodney W. Grimes prev = dirloc;
3968fae3551SRodney W. Grimes dirloc += dp->d_reclen;
3978fae3551SRodney W. Grimes }
3988fae3551SRodney W. Grimes
3998fae3551SRodney W. Grimes /*
4008fae3551SRodney W. Grimes * flush out a directory that is finished.
4018fae3551SRodney W. Grimes */
4028fae3551SRodney W. Grimes static void
flushent(void)4032db673abSWarner Losh flushent(void)
4048fae3551SRodney W. Grimes {
4058fae3551SRodney W. Grimes ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
406aed3576dSKirk McKusick if (fwrite(dirbuf, (int)dirloc, 1, df) != 1)
407aed3576dSKirk McKusick fail_dirtmp(dirfile);
4088fae3551SRodney W. Grimes seekpt = ftell(df);
4098fae3551SRodney W. Grimes dirloc = 0;
4108fae3551SRodney W. Grimes }
4118fae3551SRodney W. Grimes
4128fae3551SRodney W. Grimes /*
413772ad651SKirk McKusick * Save extended attributes for a directory entry to a file.
414772ad651SKirk McKusick */
415772ad651SKirk McKusick static void
putdirattrs(char * buf,size_t size)41671a53e69SPedro F. Giffuni putdirattrs(char *buf, size_t size)
417772ad651SKirk McKusick {
418772ad651SKirk McKusick
419aed3576dSKirk McKusick if (mf != NULL && fwrite(buf, size, 1, mf) != 1)
420aed3576dSKirk McKusick fail_dirtmp(modefile);
421772ad651SKirk McKusick }
422772ad651SKirk McKusick
423772ad651SKirk McKusick /*
4248fae3551SRodney W. Grimes * Seek to an entry in a directory.
4258fae3551SRodney W. Grimes * Only values returned by rst_telldir should be passed to rst_seekdir.
4268fae3551SRodney W. Grimes * This routine handles many directories in a single file.
4278fae3551SRodney W. Grimes * It takes the base of the directory in the file, plus
4288fae3551SRodney W. Grimes * the desired seek offset into it.
4298fae3551SRodney W. Grimes */
4308fae3551SRodney W. Grimes static void
rst_seekdir(RST_DIR * dirp,long loc,long base)4312db673abSWarner Losh rst_seekdir(RST_DIR *dirp, long loc, long base)
4328fae3551SRodney W. Grimes {
4338fae3551SRodney W. Grimes
4348fae3551SRodney W. Grimes if (loc == rst_telldir(dirp))
4358fae3551SRodney W. Grimes return;
4368fae3551SRodney W. Grimes loc -= base;
4378fae3551SRodney W. Grimes if (loc < 0)
4387fafc6f6SBruce Evans fprintf(stderr, "bad seek pointer to rst_seekdir %ld\n", loc);
43905cfc40aSPedro F. Giffuni (void) lseek(dirp->dd_fd, base + rounddown2(loc, DIRBLKSIZ), SEEK_SET);
4408fae3551SRodney W. Grimes dirp->dd_loc = loc & (DIRBLKSIZ - 1);
4418fae3551SRodney W. Grimes if (dirp->dd_loc != 0)
4428fae3551SRodney W. Grimes dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
4438fae3551SRodney W. Grimes }
4448fae3551SRodney W. Grimes
4458fae3551SRodney W. Grimes /*
4468fae3551SRodney W. Grimes * get next entry in a directory.
4478fae3551SRodney W. Grimes */
4488fae3551SRodney W. Grimes struct direct *
rst_readdir(RST_DIR * dirp)4492db673abSWarner Losh rst_readdir(RST_DIR *dirp)
4508fae3551SRodney W. Grimes {
4513d438ad6SDavid E. O'Brien struct direct *dp;
4528fae3551SRodney W. Grimes
4538fae3551SRodney W. Grimes for (;;) {
4548fae3551SRodney W. Grimes if (dirp->dd_loc == 0) {
4558fae3551SRodney W. Grimes dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
4568fae3551SRodney W. Grimes DIRBLKSIZ);
4578fae3551SRodney W. Grimes if (dirp->dd_size <= 0) {
4588fae3551SRodney W. Grimes dprintf(stderr, "error reading directory\n");
4598fae3551SRodney W. Grimes return (NULL);
4608fae3551SRodney W. Grimes }
4618fae3551SRodney W. Grimes }
4628fae3551SRodney W. Grimes if (dirp->dd_loc >= dirp->dd_size) {
4638fae3551SRodney W. Grimes dirp->dd_loc = 0;
4648fae3551SRodney W. Grimes continue;
4658fae3551SRodney W. Grimes }
4668fae3551SRodney W. Grimes dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc);
4678fae3551SRodney W. Grimes if (dp->d_reclen == 0 ||
4688fae3551SRodney W. Grimes dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) {
4698fae3551SRodney W. Grimes dprintf(stderr, "corrupted directory: bad reclen %d\n",
4708fae3551SRodney W. Grimes dp->d_reclen);
4718fae3551SRodney W. Grimes return (NULL);
4728fae3551SRodney W. Grimes }
4738fae3551SRodney W. Grimes dirp->dd_loc += dp->d_reclen;
474d87d79aeSPeter Wemm if (dp->d_ino == 0 && strcmp(dp->d_name, "/") == 0)
475d87d79aeSPeter Wemm return (NULL);
4768fae3551SRodney W. Grimes if (dp->d_ino >= maxino) {
4778fae3551SRodney W. Grimes dprintf(stderr, "corrupted directory: bad inum %d\n",
4788fae3551SRodney W. Grimes dp->d_ino);
4798fae3551SRodney W. Grimes continue;
4808fae3551SRodney W. Grimes }
4818fae3551SRodney W. Grimes return (dp);
4828fae3551SRodney W. Grimes }
4838fae3551SRodney W. Grimes }
4848fae3551SRodney W. Grimes
4858fae3551SRodney W. Grimes /*
4868fae3551SRodney W. Grimes * Simulate the opening of a directory
4878fae3551SRodney W. Grimes */
4881916772eSStefan Farfeleder void *
rst_opendir(const char * name)4892db673abSWarner Losh rst_opendir(const char *name)
4908fae3551SRodney W. Grimes {
4918fae3551SRodney W. Grimes struct inotab *itp;
4928fae3551SRodney W. Grimes RST_DIR *dirp;
4938fae3551SRodney W. Grimes ino_t ino;
4948fae3551SRodney W. Grimes
4958fae3551SRodney W. Grimes if ((ino = dirlookup(name)) > 0 &&
4968fae3551SRodney W. Grimes (itp = inotablookup(ino)) != NULL) {
4978fae3551SRodney W. Grimes dirp = opendirfile(dirfile);
4988fae3551SRodney W. Grimes rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
4998fae3551SRodney W. Grimes return (dirp);
5008fae3551SRodney W. Grimes }
5018fae3551SRodney W. Grimes return (NULL);
5028fae3551SRodney W. Grimes }
5038fae3551SRodney W. Grimes
5048fae3551SRodney W. Grimes /*
5058fae3551SRodney W. Grimes * In our case, there is nothing to do when closing a directory.
5068fae3551SRodney W. Grimes */
5078fae3551SRodney W. Grimes void
rst_closedir(void * arg)5081916772eSStefan Farfeleder rst_closedir(void *arg)
5098fae3551SRodney W. Grimes {
5101916772eSStefan Farfeleder RST_DIR *dirp;
5118fae3551SRodney W. Grimes
5121916772eSStefan Farfeleder dirp = arg;
5138fae3551SRodney W. Grimes (void)close(dirp->dd_fd);
5148fae3551SRodney W. Grimes free(dirp);
5158fae3551SRodney W. Grimes return;
5168fae3551SRodney W. Grimes }
5178fae3551SRodney W. Grimes
5188fae3551SRodney W. Grimes /*
5198fae3551SRodney W. Grimes * Simulate finding the current offset in the directory.
5208fae3551SRodney W. Grimes */
5218fae3551SRodney W. Grimes static long
rst_telldir(RST_DIR * dirp)5222db673abSWarner Losh rst_telldir(RST_DIR *dirp)
5238fae3551SRodney W. Grimes {
5248fae3551SRodney W. Grimes return ((long)lseek(dirp->dd_fd,
5258fae3551SRodney W. Grimes (off_t)0, SEEK_CUR) - dirp->dd_size + dirp->dd_loc);
5268fae3551SRodney W. Grimes }
5278fae3551SRodney W. Grimes
5288fae3551SRodney W. Grimes /*
5298fae3551SRodney W. Grimes * Open a directory file.
5308fae3551SRodney W. Grimes */
5318fae3551SRodney W. Grimes static RST_DIR *
opendirfile(const char * name)5322db673abSWarner Losh opendirfile(const char *name)
5338fae3551SRodney W. Grimes {
5343d438ad6SDavid E. O'Brien RST_DIR *dirp;
5353d438ad6SDavid E. O'Brien int fd;
5368fae3551SRodney W. Grimes
5378fae3551SRodney W. Grimes if ((fd = open(name, O_RDONLY)) == -1)
5388fae3551SRodney W. Grimes return (NULL);
5398fae3551SRodney W. Grimes if ((dirp = malloc(sizeof(RST_DIR))) == NULL) {
5408fae3551SRodney W. Grimes (void)close(fd);
5418fae3551SRodney W. Grimes return (NULL);
5428fae3551SRodney W. Grimes }
5438fae3551SRodney W. Grimes dirp->dd_fd = fd;
5448fae3551SRodney W. Grimes dirp->dd_loc = 0;
5458fae3551SRodney W. Grimes return (dirp);
5468fae3551SRodney W. Grimes }
5478fae3551SRodney W. Grimes
5488fae3551SRodney W. Grimes /*
5498fae3551SRodney W. Grimes * Set the mode, owner, and times for all new or changed directories
5508fae3551SRodney W. Grimes */
5518fae3551SRodney W. Grimes void
setdirmodes(int flags)5522db673abSWarner Losh setdirmodes(int flags)
5538fae3551SRodney W. Grimes {
5548fae3551SRodney W. Grimes FILE *mf;
5558fae3551SRodney W. Grimes struct modeinfo node;
5568fae3551SRodney W. Grimes struct entry *ep;
557772ad651SKirk McKusick char *cp, *buf;
5584afde855SMaxim Sobolev const char *tmpdir;
559772ad651SKirk McKusick int bufsize;
560c028393dSKirk McKusick uid_t myuid;
5618fae3551SRodney W. Grimes
5628fae3551SRodney W. Grimes vprintf(stdout, "Set directory mode, owner, and times.\n");
5634afde855SMaxim Sobolev if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0')
5644afde855SMaxim Sobolev tmpdir = _PATH_TMP;
565335524b9SWarner Losh if (command == 'r' || command == 'R')
56663298eb1SConrad Meyer (void) snprintf(modefile, sizeof(modefile), "%s/rstmode%jd",
56763298eb1SConrad Meyer tmpdir, (intmax_t)dumpdate);
568335524b9SWarner Losh if (modefile[0] == '#') {
569335524b9SWarner Losh panic("modefile not defined\n");
570335524b9SWarner Losh fprintf(stderr, "directory mode, owner, and times not set\n");
571335524b9SWarner Losh return;
572335524b9SWarner Losh }
5738fae3551SRodney W. Grimes mf = fopen(modefile, "r");
5748fae3551SRodney W. Grimes if (mf == NULL) {
5758fae3551SRodney W. Grimes fprintf(stderr, "fopen: %s\n", strerror(errno));
5768fae3551SRodney W. Grimes fprintf(stderr, "cannot open mode file %s\n", modefile);
5778fae3551SRodney W. Grimes fprintf(stderr, "directory mode, owner, and times not set\n");
5788fae3551SRodney W. Grimes return;
5798fae3551SRodney W. Grimes }
5808fae3551SRodney W. Grimes clearerr(mf);
581772ad651SKirk McKusick bufsize = 0;
582c028393dSKirk McKusick myuid = getuid();
5838fae3551SRodney W. Grimes for (;;) {
5848fae3551SRodney W. Grimes (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf);
585aed3576dSKirk McKusick if (ferror(mf)) {
586aed3576dSKirk McKusick warn("%s: cannot read modefile.", modefile);
587aed3576dSKirk McKusick fprintf(stderr, "Mode, owner, and times not set.\n");
588aed3576dSKirk McKusick break;
589aed3576dSKirk McKusick }
5908fae3551SRodney W. Grimes if (feof(mf))
5918fae3551SRodney W. Grimes break;
592772ad651SKirk McKusick if (node.extsize > 0) {
593772ad651SKirk McKusick if (bufsize < node.extsize) {
594772ad651SKirk McKusick if (bufsize > 0)
595772ad651SKirk McKusick free(buf);
596e63ce3deSMarcelo Araujo if ((buf = malloc(node.extsize)) != NULL) {
597772ad651SKirk McKusick bufsize = node.extsize;
598772ad651SKirk McKusick } else {
599772ad651SKirk McKusick bufsize = 0;
600772ad651SKirk McKusick }
601772ad651SKirk McKusick }
602772ad651SKirk McKusick if (bufsize >= node.extsize) {
603772ad651SKirk McKusick (void) fread(buf, 1, node.extsize, mf);
604aed3576dSKirk McKusick if (ferror(mf)) {
605aed3576dSKirk McKusick warn("%s: cannot read modefile.",
606aed3576dSKirk McKusick modefile);
607aed3576dSKirk McKusick fprintf(stderr, "Not all external ");
608aed3576dSKirk McKusick fprintf(stderr, "attributes set.\n");
609aed3576dSKirk McKusick break;
610aed3576dSKirk McKusick }
611772ad651SKirk McKusick } else {
612772ad651SKirk McKusick (void) fseek(mf, node.extsize, SEEK_CUR);
613aed3576dSKirk McKusick if (ferror(mf)) {
614aed3576dSKirk McKusick warn("%s: cannot seek in modefile.",
615aed3576dSKirk McKusick modefile);
616aed3576dSKirk McKusick fprintf(stderr, "Not all directory ");
617aed3576dSKirk McKusick fprintf(stderr, "attributes set.\n");
618aed3576dSKirk McKusick break;
619aed3576dSKirk McKusick }
620772ad651SKirk McKusick }
621772ad651SKirk McKusick }
6228fae3551SRodney W. Grimes ep = lookupino(node.ino);
6238fae3551SRodney W. Grimes if (command == 'i' || command == 'x') {
6248fae3551SRodney W. Grimes if (ep == NULL)
6258fae3551SRodney W. Grimes continue;
6268fae3551SRodney W. Grimes if ((flags & FORCE) == 0 && ep->e_flags & EXISTED) {
6278fae3551SRodney W. Grimes ep->e_flags &= ~NEW;
6288fae3551SRodney W. Grimes continue;
6298fae3551SRodney W. Grimes }
6301dc349abSEd Maste if (node.ino == UFS_ROOTINO &&
6318fae3551SRodney W. Grimes reply("set owner/mode for '.'") == FAIL)
6328fae3551SRodney W. Grimes continue;
6338fae3551SRodney W. Grimes }
6348fae3551SRodney W. Grimes if (ep == NULL) {
635e25a029eSMatthew D Fleming panic("cannot find directory inode %ju\n",
636e25a029eSMatthew D Fleming (uintmax_t)node.ino);
637772ad651SKirk McKusick continue;
638772ad651SKirk McKusick }
6398fae3551SRodney W. Grimes cp = myname(ep);
640b9595aa5SDima Dorfman if (!Nflag) {
641*9dda00dfSChuck Silvers if (myuid != 0)
642*9dda00dfSChuck Silvers (void) chown(cp, myuid, node.gid);
643*9dda00dfSChuck Silvers else
644*9dda00dfSChuck Silvers (void) chown(cp, node.uid, node.gid);
645*9dda00dfSChuck Silvers (void) chmod(cp, node.mode);
646772ad651SKirk McKusick if (node.extsize > 0) {
647772ad651SKirk McKusick if (bufsize >= node.extsize) {
648c9bf8148SConrad Meyer set_extattr(-1, cp, buf, node.extsize, SXA_FILE);
649772ad651SKirk McKusick } else {
650772ad651SKirk McKusick fprintf(stderr, "Cannot restore %s%s\n",
651772ad651SKirk McKusick "extended attributes for ", cp);
652772ad651SKirk McKusick }
653772ad651SKirk McKusick }
65459966d51SJilles Tjoelker utimensat(AT_FDCWD, cp, node.ctimep, 0);
65559966d51SJilles Tjoelker utimensat(AT_FDCWD, cp, node.mtimep, 0);
656fddde8b0SDavid Malone (void) chflags(cp, node.flags);
657b9595aa5SDima Dorfman }
6588fae3551SRodney W. Grimes ep->e_flags &= ~NEW;
6598fae3551SRodney W. Grimes }
660772ad651SKirk McKusick if (bufsize > 0)
661772ad651SKirk McKusick free(buf);
6628fae3551SRodney W. Grimes (void) fclose(mf);
6638fae3551SRodney W. Grimes }
6648fae3551SRodney W. Grimes
6658fae3551SRodney W. Grimes /*
6668fae3551SRodney W. Grimes * Generate a literal copy of a directory.
6678fae3551SRodney W. Grimes */
6688fae3551SRodney W. Grimes int
genliteraldir(char * name,ino_t ino)6692db673abSWarner Losh genliteraldir(char *name, ino_t ino)
6708fae3551SRodney W. Grimes {
6713d438ad6SDavid E. O'Brien struct inotab *itp;
6728fae3551SRodney W. Grimes int ofile, dp, i, size;
6738fae3551SRodney W. Grimes char buf[BUFSIZ];
6748fae3551SRodney W. Grimes
6758fae3551SRodney W. Grimes itp = inotablookup(ino);
6768fae3551SRodney W. Grimes if (itp == NULL)
677e25a029eSMatthew D Fleming panic("Cannot find directory inode %ju named %s\n",
678e25a029eSMatthew D Fleming (uintmax_t)ino, name);
679335524b9SWarner Losh if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
6808fae3551SRodney W. Grimes fprintf(stderr, "%s: ", name);
6818fae3551SRodney W. Grimes (void) fflush(stderr);
6828fae3551SRodney W. Grimes fprintf(stderr, "cannot create file: %s\n", strerror(errno));
6838fae3551SRodney W. Grimes return (FAIL);
6848fae3551SRodney W. Grimes }
6858fae3551SRodney W. Grimes rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
6868fae3551SRodney W. Grimes dp = dup(dirp->dd_fd);
6878fae3551SRodney W. Grimes for (i = itp->t_size; i > 0; i -= BUFSIZ) {
688f4b72a8dSMarcelo Araujo size = MIN(i, BUFSIZ);
6898fae3551SRodney W. Grimes if (read(dp, buf, (int) size) == -1) {
6908fae3551SRodney W. Grimes fprintf(stderr,
691e25a029eSMatthew D Fleming "write error extracting inode %ju, name %s\n",
692e25a029eSMatthew D Fleming (uintmax_t)curfile.ino, curfile.name);
6938fae3551SRodney W. Grimes fprintf(stderr, "read: %s\n", strerror(errno));
6948fae3551SRodney W. Grimes done(1);
6958fae3551SRodney W. Grimes }
6968fae3551SRodney W. Grimes if (!Nflag && write(ofile, buf, (int) size) == -1) {
6978fae3551SRodney W. Grimes fprintf(stderr,
698e25a029eSMatthew D Fleming "write error extracting inode %ju, name %s\n",
699e25a029eSMatthew D Fleming (uintmax_t)curfile.ino, curfile.name);
7008fae3551SRodney W. Grimes fprintf(stderr, "write: %s\n", strerror(errno));
7018fae3551SRodney W. Grimes done(1);
7028fae3551SRodney W. Grimes }
7038fae3551SRodney W. Grimes }
7048fae3551SRodney W. Grimes (void) close(dp);
7058fae3551SRodney W. Grimes (void) close(ofile);
7068fae3551SRodney W. Grimes return (GOOD);
7078fae3551SRodney W. Grimes }
7088fae3551SRodney W. Grimes
7098fae3551SRodney W. Grimes /*
7108fae3551SRodney W. Grimes * Determine the type of an inode
7118fae3551SRodney W. Grimes */
7128fae3551SRodney W. Grimes int
inodetype(ino_t ino)7132db673abSWarner Losh inodetype(ino_t ino)
7148fae3551SRodney W. Grimes {
7158fae3551SRodney W. Grimes struct inotab *itp;
7168fae3551SRodney W. Grimes
7178fae3551SRodney W. Grimes itp = inotablookup(ino);
7188fae3551SRodney W. Grimes if (itp == NULL)
7198fae3551SRodney W. Grimes return (LEAF);
7208fae3551SRodney W. Grimes return (NODE);
7218fae3551SRodney W. Grimes }
7228fae3551SRodney W. Grimes
7238fae3551SRodney W. Grimes /*
7248fae3551SRodney W. Grimes * Allocate and initialize a directory inode entry.
7258fae3551SRodney W. Grimes * If requested, save its pertinent mode, owner, and time info.
7268fae3551SRodney W. Grimes */
7278fae3551SRodney W. Grimes static struct inotab *
allocinotab(struct context * ctxp,long seekpt)7281c85e6a3SKirk McKusick allocinotab(struct context *ctxp, long seekpt)
7298fae3551SRodney W. Grimes {
7303d438ad6SDavid E. O'Brien struct inotab *itp;
7318fae3551SRodney W. Grimes struct modeinfo node;
7328fae3551SRodney W. Grimes
7338fae3551SRodney W. Grimes itp = calloc(1, sizeof(struct inotab));
7348fae3551SRodney W. Grimes if (itp == NULL)
735772ad651SKirk McKusick panic("no memory for directory table\n");
7361c85e6a3SKirk McKusick itp->t_next = inotab[INOHASH(ctxp->ino)];
7371c85e6a3SKirk McKusick inotab[INOHASH(ctxp->ino)] = itp;
7381c85e6a3SKirk McKusick itp->t_ino = ctxp->ino;
7398fae3551SRodney W. Grimes itp->t_seekpt = seekpt;
7408fae3551SRodney W. Grimes if (mf == NULL)
7418fae3551SRodney W. Grimes return (itp);
7421c85e6a3SKirk McKusick node.ino = ctxp->ino;
743fb36a3d8SKirk McKusick node.mtimep[0].tv_sec = ctxp->atime_sec;
74459966d51SJilles Tjoelker node.mtimep[0].tv_nsec = ctxp->atime_nsec;
745fb36a3d8SKirk McKusick node.mtimep[1].tv_sec = ctxp->mtime_sec;
74659966d51SJilles Tjoelker node.mtimep[1].tv_nsec = ctxp->mtime_nsec;
747fb36a3d8SKirk McKusick node.ctimep[0].tv_sec = ctxp->atime_sec;
74859966d51SJilles Tjoelker node.ctimep[0].tv_nsec = ctxp->atime_nsec;
749fb36a3d8SKirk McKusick node.ctimep[1].tv_sec = ctxp->birthtime_sec;
75059966d51SJilles Tjoelker node.ctimep[1].tv_nsec = ctxp->birthtime_nsec;
751772ad651SKirk McKusick node.extsize = ctxp->extsize;
7521c85e6a3SKirk McKusick node.mode = ctxp->mode;
7531c85e6a3SKirk McKusick node.flags = ctxp->file_flags;
7541c85e6a3SKirk McKusick node.uid = ctxp->uid;
7551c85e6a3SKirk McKusick node.gid = ctxp->gid;
756aed3576dSKirk McKusick if (fwrite((char *)&node, sizeof(struct modeinfo), 1, mf) != 1)
757aed3576dSKirk McKusick fail_dirtmp(modefile);
7588fae3551SRodney W. Grimes return (itp);
7598fae3551SRodney W. Grimes }
7608fae3551SRodney W. Grimes
7618fae3551SRodney W. Grimes /*
7628fae3551SRodney W. Grimes * Look up an inode in the table of directories
7638fae3551SRodney W. Grimes */
7648fae3551SRodney W. Grimes static struct inotab *
inotablookup(ino_t ino)7652db673abSWarner Losh inotablookup(ino_t ino)
7668fae3551SRodney W. Grimes {
7673d438ad6SDavid E. O'Brien struct inotab *itp;
7688fae3551SRodney W. Grimes
7698fae3551SRodney W. Grimes for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next)
7708fae3551SRodney W. Grimes if (itp->t_ino == ino)
7718fae3551SRodney W. Grimes return (itp);
7728fae3551SRodney W. Grimes return (NULL);
7738fae3551SRodney W. Grimes }
7748fae3551SRodney W. Grimes
7758fae3551SRodney W. Grimes /*
7768fae3551SRodney W. Grimes * Clean up and exit
7778fae3551SRodney W. Grimes */
778eaa86f9dSBruce Evans void
done(int exitcode)7792db673abSWarner Losh done(int exitcode)
7808fae3551SRodney W. Grimes {
7818fae3551SRodney W. Grimes
7828fae3551SRodney W. Grimes closemt();
783aed3576dSKirk McKusick if (modefile[0] != '#') {
784aed3576dSKirk McKusick (void) truncate(modefile, 0);
7858fae3551SRodney W. Grimes (void) unlink(modefile);
786aed3576dSKirk McKusick }
787aed3576dSKirk McKusick if (dirfile[0] != '#') {
788aed3576dSKirk McKusick (void) truncate(dirfile, 0);
7898fae3551SRodney W. Grimes (void) unlink(dirfile);
790aed3576dSKirk McKusick }
7918fae3551SRodney W. Grimes exit(exitcode);
7928fae3551SRodney W. Grimes }
793aed3576dSKirk McKusick
794aed3576dSKirk McKusick /*
795aed3576dSKirk McKusick * Print out information about the failure to save directory,
796aed3576dSKirk McKusick * extended attribute, and mode information.
797aed3576dSKirk McKusick */
798aed3576dSKirk McKusick static void
fail_dirtmp(char * filename)799aed3576dSKirk McKusick fail_dirtmp(char *filename)
800aed3576dSKirk McKusick {
801aed3576dSKirk McKusick const char *tmpdir;
802aed3576dSKirk McKusick
803aed3576dSKirk McKusick warn("%s: cannot write directory database", filename);
804aed3576dSKirk McKusick if (errno == ENOSPC) {
805aed3576dSKirk McKusick if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0')
806aed3576dSKirk McKusick tmpdir = _PATH_TMP;
807aed3576dSKirk McKusick fprintf(stderr, "Try making space in %s, %s\n%s\n", tmpdir,
808aed3576dSKirk McKusick "or set environment variable TMPDIR",
809aed3576dSKirk McKusick "to an alternate location with more disk space.");
810aed3576dSKirk McKusick }
811aed3576dSKirk McKusick done(1);
812aed3576dSKirk McKusick }
813