1/* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39#ifndef lint 40static char sccsid[] = "@(#)dirs.c 8.2 (Berkeley) 1/21/94"; 41#endif /* not lint */ 42 43#include <sys/param.h> 44#include <sys/file.h> 45#include <sys/stat.h> 46#include <sys/time.h> 47 48#include <ufs/ffs/fs.h> 49#include <ufs/ufs/dinode.h> 50#include <ufs/ufs/dir.h> 51#include <protocols/dumprestore.h> 52 53#include <errno.h> 54#include <stdio.h> 55#include <stdlib.h> 56#include <string.h> 57#include <unistd.h> 58 59#include <machine/endian.h> 60 61#include "pathnames.h" 62#include "restore.h" 63#include "extern.h" 64 65/* 66 * Symbol table of directories read from tape. 67 */ 68#define HASHSIZE 1000 69#define INOHASH(val) (val % HASHSIZE) 70struct inotab { 71 struct inotab *t_next; 72 ino_t t_ino; 73 long t_seekpt; 74 long t_size; 75}; 76static struct inotab *inotab[HASHSIZE]; 77 78/* 79 * Information retained about directories. 80 */ 81struct modeinfo { 82 ino_t ino; 83 struct timeval timep[2]; 84 short mode; 85 short uid; 86 short gid; 87}; 88 89/* 90 * Definitions for library routines operating on directories. 91 */ 92#undef DIRBLKSIZ 93#define DIRBLKSIZ 1024 94struct rstdirdesc { 95 int dd_fd; 96 long dd_loc; 97 long dd_size; 98 char dd_buf[DIRBLKSIZ]; 99}; 100 101/* 102 * Global variables for this file. 103 */ 104static long seekpt; 105static FILE *df, *mf; 106static RST_DIR *dirp;
| 1/* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39#ifndef lint 40static char sccsid[] = "@(#)dirs.c 8.2 (Berkeley) 1/21/94"; 41#endif /* not lint */ 42 43#include <sys/param.h> 44#include <sys/file.h> 45#include <sys/stat.h> 46#include <sys/time.h> 47 48#include <ufs/ffs/fs.h> 49#include <ufs/ufs/dinode.h> 50#include <ufs/ufs/dir.h> 51#include <protocols/dumprestore.h> 52 53#include <errno.h> 54#include <stdio.h> 55#include <stdlib.h> 56#include <string.h> 57#include <unistd.h> 58 59#include <machine/endian.h> 60 61#include "pathnames.h" 62#include "restore.h" 63#include "extern.h" 64 65/* 66 * Symbol table of directories read from tape. 67 */ 68#define HASHSIZE 1000 69#define INOHASH(val) (val % HASHSIZE) 70struct inotab { 71 struct inotab *t_next; 72 ino_t t_ino; 73 long t_seekpt; 74 long t_size; 75}; 76static struct inotab *inotab[HASHSIZE]; 77 78/* 79 * Information retained about directories. 80 */ 81struct modeinfo { 82 ino_t ino; 83 struct timeval timep[2]; 84 short mode; 85 short uid; 86 short gid; 87}; 88 89/* 90 * Definitions for library routines operating on directories. 91 */ 92#undef DIRBLKSIZ 93#define DIRBLKSIZ 1024 94struct rstdirdesc { 95 int dd_fd; 96 long dd_loc; 97 long dd_size; 98 char dd_buf[DIRBLKSIZ]; 99}; 100 101/* 102 * Global variables for this file. 103 */ 104static long seekpt; 105static FILE *df, *mf; 106static RST_DIR *dirp;
|
107static char dirfile[32] = "#"; /* No file */ 108static char modefile[32] = "#"; /* No file */ 109static char dot[2] = "."; /* So it can be modified */
| 107static char dirfile[MAXPATHLEN] = "#"; /* No file */ 108static char modefile[MAXPATHLEN] = "#"; /* No file */ 109static char dot[2] = "."; /* So it can be modified */
|
110 111/* 112 * Format of old style directories. 113 */ 114#define ODIRSIZ 14 115struct odirect { 116 u_short d_ino; 117 char d_name[ODIRSIZ]; 118}; 119 120static struct inotab *allocinotab __P((ino_t, struct dinode *, long)); 121static void dcvt __P((struct odirect *, struct direct *)); 122static void flushent __P((void)); 123static struct inotab *inotablookup __P((ino_t)); 124static RST_DIR *opendirfile __P((const char *)); 125static void putdir __P((char *, long)); 126static void putent __P((struct direct *)); 127static void rst_seekdir __P((RST_DIR *, long, long)); 128static long rst_telldir __P((RST_DIR *)); 129static struct direct *searchdir __P((ino_t, char *)); 130 131/* 132 * Extract directory contents, building up a directory structure 133 * on disk for extraction by name. 134 * If genmode is requested, save mode, owner, and times for all 135 * directories on the tape. 136 */ 137void 138extractdirs(genmode) 139 int genmode; 140{ 141 register int i; 142 register struct dinode *ip; 143 struct inotab *itp; 144 struct direct nulldir;
| 110 111/* 112 * Format of old style directories. 113 */ 114#define ODIRSIZ 14 115struct odirect { 116 u_short d_ino; 117 char d_name[ODIRSIZ]; 118}; 119 120static struct inotab *allocinotab __P((ino_t, struct dinode *, long)); 121static void dcvt __P((struct odirect *, struct direct *)); 122static void flushent __P((void)); 123static struct inotab *inotablookup __P((ino_t)); 124static RST_DIR *opendirfile __P((const char *)); 125static void putdir __P((char *, long)); 126static void putent __P((struct direct *)); 127static void rst_seekdir __P((RST_DIR *, long, long)); 128static long rst_telldir __P((RST_DIR *)); 129static struct direct *searchdir __P((ino_t, char *)); 130 131/* 132 * Extract directory contents, building up a directory structure 133 * on disk for extraction by name. 134 * If genmode is requested, save mode, owner, and times for all 135 * directories on the tape. 136 */ 137void 138extractdirs(genmode) 139 int genmode; 140{ 141 register int i; 142 register struct dinode *ip; 143 struct inotab *itp; 144 struct direct nulldir;
|
| 145 int fd;
|
145 146 vprintf(stdout, "Extract directories from tape\n");
| 146 147 vprintf(stdout, "Extract directories from tape\n");
|
147 (void) sprintf(dirfile, "%s/rstdir%d", _PATH_TMP, dumpdate); 148 df = fopen(dirfile, "w"); 149 if (df == NULL) {
| 148 (void) sprintf(dirfile, "%srstdir%d", _PATH_TMP, dumpdate); 149 if (command != 'r' && command != 'R') { 150 (void *) strcat(dirfile, "-XXXXXX"); 151 fd = mkstemp(dirfile); 152 } else 153 fd = open(dirfile, O_RDWR|O_CREAT|O_EXCL, 0666); 154 if (fd == -1 || (df = fdopen(fd, "w")) == NULL) { 155 if (fd != -1) 156 close(fd);
|
150 fprintf(stderr, 151 "restore: %s - cannot create directory temporary\n", 152 dirfile); 153 fprintf(stderr, "fopen: %s\n", strerror(errno)); 154 done(1); 155 } 156 if (genmode != 0) {
| 157 fprintf(stderr, 158 "restore: %s - cannot create directory temporary\n", 159 dirfile); 160 fprintf(stderr, "fopen: %s\n", strerror(errno)); 161 done(1); 162 } 163 if (genmode != 0) {
|
157 (void) sprintf(modefile, "%s/rstmode%d", _PATH_TMP, dumpdate); 158 mf = fopen(modefile, "w"); 159 if (mf == NULL) {
| 164 (void) sprintf(modefile, "%srstmode%d", _PATH_TMP, dumpdate); 165 if (command != 'r' && command != 'R') { 166 (void *) strcat(modefile, "-XXXXXX"); 167 fd = mkstemp(modefile); 168 } else 169 fd = open(modefile, O_RDWR|O_CREAT|O_EXCL, 0666); 170 if (fd == -1 || (mf = fdopen(fd, "w")) == NULL) { 171 if (fd != -1) 172 close(fd);
|
160 fprintf(stderr, 161 "restore: %s - cannot create modefile \n", 162 modefile); 163 fprintf(stderr, "fopen: %s\n", strerror(errno)); 164 done(1); 165 } 166 } 167 nulldir.d_ino = 0; 168 nulldir.d_type = DT_DIR; 169 nulldir.d_namlen = 1; 170 (void) strcpy(nulldir.d_name, "/"); 171 nulldir.d_reclen = DIRSIZ(0, &nulldir); 172 for (;;) { 173 curfile.name = "<directory file - name unknown>"; 174 curfile.action = USING; 175 ip = curfile.dip; 176 if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { 177 (void) fclose(df); 178 dirp = opendirfile(dirfile); 179 if (dirp == NULL) 180 fprintf(stderr, "opendirfile: %s\n", 181 strerror(errno)); 182 if (mf != NULL) 183 (void) fclose(mf); 184 i = dirlookup(dot); 185 if (i == 0) 186 panic("Root directory is not on tape\n"); 187 return; 188 } 189 itp = allocinotab(curfile.ino, ip, seekpt); 190 getfile(putdir, xtrnull); 191 putent(&nulldir); 192 flushent(); 193 itp->t_size = seekpt - itp->t_seekpt; 194 } 195} 196 197/* 198 * skip over all the directories on the tape 199 */ 200void 201skipdirs() 202{ 203 204 while (curfile.dip && (curfile.dip->di_mode & IFMT) == IFDIR) { 205 skipfile(); 206 } 207} 208 209/* 210 * Recursively find names and inumbers of all files in subtree 211 * pname and pass them off to be processed. 212 */ 213void 214treescan(pname, ino, todo) 215 char *pname; 216 ino_t ino; 217 long (*todo) __P((char *, ino_t, int)); 218{ 219 register struct inotab *itp; 220 register struct direct *dp; 221 int namelen; 222 long bpt; 223 char locname[MAXPATHLEN + 1]; 224 225 itp = inotablookup(ino); 226 if (itp == NULL) { 227 /* 228 * Pname is name of a simple file or an unchanged directory. 229 */ 230 (void) (*todo)(pname, ino, LEAF); 231 return; 232 } 233 /* 234 * Pname is a dumped directory name. 235 */ 236 if ((*todo)(pname, ino, NODE) == FAIL) 237 return; 238 /* 239 * begin search through the directory 240 * skipping over "." and ".." 241 */
| 173 fprintf(stderr, 174 "restore: %s - cannot create modefile \n", 175 modefile); 176 fprintf(stderr, "fopen: %s\n", strerror(errno)); 177 done(1); 178 } 179 } 180 nulldir.d_ino = 0; 181 nulldir.d_type = DT_DIR; 182 nulldir.d_namlen = 1; 183 (void) strcpy(nulldir.d_name, "/"); 184 nulldir.d_reclen = DIRSIZ(0, &nulldir); 185 for (;;) { 186 curfile.name = "<directory file - name unknown>"; 187 curfile.action = USING; 188 ip = curfile.dip; 189 if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { 190 (void) fclose(df); 191 dirp = opendirfile(dirfile); 192 if (dirp == NULL) 193 fprintf(stderr, "opendirfile: %s\n", 194 strerror(errno)); 195 if (mf != NULL) 196 (void) fclose(mf); 197 i = dirlookup(dot); 198 if (i == 0) 199 panic("Root directory is not on tape\n"); 200 return; 201 } 202 itp = allocinotab(curfile.ino, ip, seekpt); 203 getfile(putdir, xtrnull); 204 putent(&nulldir); 205 flushent(); 206 itp->t_size = seekpt - itp->t_seekpt; 207 } 208} 209 210/* 211 * skip over all the directories on the tape 212 */ 213void 214skipdirs() 215{ 216 217 while (curfile.dip && (curfile.dip->di_mode & IFMT) == IFDIR) { 218 skipfile(); 219 } 220} 221 222/* 223 * Recursively find names and inumbers of all files in subtree 224 * pname and pass them off to be processed. 225 */ 226void 227treescan(pname, ino, todo) 228 char *pname; 229 ino_t ino; 230 long (*todo) __P((char *, ino_t, int)); 231{ 232 register struct inotab *itp; 233 register struct direct *dp; 234 int namelen; 235 long bpt; 236 char locname[MAXPATHLEN + 1]; 237 238 itp = inotablookup(ino); 239 if (itp == NULL) { 240 /* 241 * Pname is name of a simple file or an unchanged directory. 242 */ 243 (void) (*todo)(pname, ino, LEAF); 244 return; 245 } 246 /* 247 * Pname is a dumped directory name. 248 */ 249 if ((*todo)(pname, ino, NODE) == FAIL) 250 return; 251 /* 252 * begin search through the directory 253 * skipping over "." and ".." 254 */
|
242 (void) strncpy(locname, pname, MAXPATHLEN); 243 (void) strncat(locname, "/", MAXPATHLEN);
| 255 (void) strncpy(locname, pname, sizeof(locname) - 1); 256 locname[sizeof(locname) - 1] = '\0'; 257 (void) strncat(locname, "/", sizeof(locname) - strlen(locname));
|
244 namelen = strlen(locname); 245 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 246 dp = rst_readdir(dirp); /* "." */ 247 if (dp != NULL && strcmp(dp->d_name, ".") == 0) 248 dp = rst_readdir(dirp); /* ".." */ 249 else 250 fprintf(stderr, "Warning: `.' missing from directory %s\n", 251 pname); 252 if (dp != NULL && strcmp(dp->d_name, "..") == 0) 253 dp = rst_readdir(dirp); /* first real entry */ 254 else 255 fprintf(stderr, "Warning: `..' missing from directory %s\n", 256 pname); 257 bpt = rst_telldir(dirp); 258 /* 259 * a zero inode signals end of directory 260 */ 261 while (dp != NULL && dp->d_ino != 0) { 262 locname[namelen] = '\0';
| 258 namelen = strlen(locname); 259 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 260 dp = rst_readdir(dirp); /* "." */ 261 if (dp != NULL && strcmp(dp->d_name, ".") == 0) 262 dp = rst_readdir(dirp); /* ".." */ 263 else 264 fprintf(stderr, "Warning: `.' missing from directory %s\n", 265 pname); 266 if (dp != NULL && strcmp(dp->d_name, "..") == 0) 267 dp = rst_readdir(dirp); /* first real entry */ 268 else 269 fprintf(stderr, "Warning: `..' missing from directory %s\n", 270 pname); 271 bpt = rst_telldir(dirp); 272 /* 273 * a zero inode signals end of directory 274 */ 275 while (dp != NULL && dp->d_ino != 0) { 276 locname[namelen] = '\0';
|
263 if (namelen + dp->d_namlen >= MAXPATHLEN) {
| 277 if (namelen + dp->d_namlen >= sizeof(locname)) {
|
264 fprintf(stderr, "%s%s: name exceeds %d char\n",
| 278 fprintf(stderr, "%s%s: name exceeds %d char\n",
|
265 locname, dp->d_name, MAXPATHLEN);
| 279 locname, dp->d_name, sizeof(locname) - 1);
|
266 } else { 267 (void) strncat(locname, dp->d_name, (int)dp->d_namlen); 268 treescan(locname, dp->d_ino, todo); 269 rst_seekdir(dirp, bpt, itp->t_seekpt); 270 } 271 dp = rst_readdir(dirp); 272 bpt = rst_telldir(dirp); 273 } 274 if (dp == NULL) 275 fprintf(stderr, "corrupted directory: %s.\n", locname); 276} 277 278/* 279 * Lookup a pathname which is always assumed to start from the ROOTINO. 280 */ 281struct direct * 282pathsearch(pathname) 283 const char *pathname; 284{ 285 ino_t ino; 286 struct direct *dp; 287 char *path, *name, buffer[MAXPATHLEN]; 288 289 strcpy(buffer, pathname); 290 path = buffer; 291 ino = ROOTINO; 292 while (*path == '/') 293 path++; 294 dp = NULL; 295 while ((name = strsep(&path, "/")) != NULL && *name != NULL) { 296 if ((dp = searchdir(ino, name)) == NULL) 297 return (NULL); 298 ino = dp->d_ino; 299 } 300 return (dp); 301} 302 303/* 304 * Lookup the requested name in directory inum. 305 * Return its inode number if found, zero if it does not exist. 306 */ 307static struct direct * 308searchdir(inum, name) 309 ino_t inum; 310 char *name; 311{ 312 register struct direct *dp; 313 register struct inotab *itp; 314 int len; 315 316 itp = inotablookup(inum); 317 if (itp == NULL) 318 return (NULL); 319 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 320 len = strlen(name); 321 do { 322 dp = rst_readdir(dirp); 323 if (dp == NULL || dp->d_ino == 0) 324 return (NULL); 325 } while (dp->d_namlen != len || strncmp(dp->d_name, name, len) != 0); 326 return (dp); 327} 328 329/* 330 * Put the directory entries in the directory file 331 */ 332static void 333putdir(buf, size) 334 char *buf; 335 long size; 336{ 337 struct direct cvtbuf; 338 register struct odirect *odp; 339 struct odirect *eodp; 340 register struct direct *dp; 341 long loc, i; 342 343 if (cvtflag) { 344 eodp = (struct odirect *)&buf[size]; 345 for (odp = (struct odirect *)buf; odp < eodp; odp++) 346 if (odp->d_ino != 0) { 347 dcvt(odp, &cvtbuf); 348 putent(&cvtbuf); 349 } 350 } else { 351 for (loc = 0; loc < size; ) { 352 dp = (struct direct *)(buf + loc); 353 if (Bcvt) 354 swabst((u_char *)"ls", (u_char *) dp); 355 if (oldinofmt && dp->d_ino != 0) { 356#if BYTE_ORDER == BIG_ENDIAN 357 if (Bcvt) 358#else 359 if (!Bcvt) 360#endif 361 dp->d_namlen = dp->d_type; 362 dp->d_type = DT_UNKNOWN; 363 } 364 i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 365 if ((dp->d_reclen & 0x3) != 0 || 366 dp->d_reclen > i || 367 dp->d_reclen < DIRSIZ(0, dp) || 368 dp->d_namlen > NAME_MAX) { 369 vprintf(stdout, "Mangled directory: "); 370 if ((dp->d_reclen & 0x3) != 0) 371 vprintf(stdout, 372 "reclen not multiple of 4 "); 373 if (dp->d_reclen < DIRSIZ(0, dp)) 374 vprintf(stdout, 375 "reclen less than DIRSIZ (%d < %d) ", 376 dp->d_reclen, DIRSIZ(0, dp)); 377 if (dp->d_namlen > NAME_MAX) 378 vprintf(stdout, 379 "reclen name too big (%d > %d) ", 380 dp->d_namlen, NAME_MAX); 381 vprintf(stdout, "\n"); 382 loc += i; 383 continue; 384 } 385 loc += dp->d_reclen; 386 if (dp->d_ino != 0) { 387 putent(dp); 388 } 389 } 390 } 391} 392 393/* 394 * These variables are "local" to the following two functions. 395 */ 396char dirbuf[DIRBLKSIZ]; 397long dirloc = 0; 398long prev = 0; 399 400/* 401 * add a new directory entry to a file. 402 */ 403static void 404putent(dp) 405 struct direct *dp; 406{ 407 dp->d_reclen = DIRSIZ(0, dp); 408 if (dirloc + dp->d_reclen > DIRBLKSIZ) { 409 ((struct direct *)(dirbuf + prev))->d_reclen = 410 DIRBLKSIZ - prev; 411 (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); 412 dirloc = 0; 413 } 414 bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 415 prev = dirloc; 416 dirloc += dp->d_reclen; 417} 418 419/* 420 * flush out a directory that is finished. 421 */ 422static void 423flushent() 424{ 425 ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 426 (void) fwrite(dirbuf, (int)dirloc, 1, df); 427 seekpt = ftell(df); 428 dirloc = 0; 429} 430 431static void 432dcvt(odp, ndp) 433 register struct odirect *odp; 434 register struct direct *ndp; 435{ 436 437 bzero((char *)ndp, (long)(sizeof *ndp)); 438 ndp->d_ino = odp->d_ino; 439 ndp->d_type = DT_UNKNOWN; 440 (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 441 ndp->d_namlen = strlen(ndp->d_name); 442 ndp->d_reclen = DIRSIZ(0, ndp); 443} 444 445/* 446 * Seek to an entry in a directory. 447 * Only values returned by rst_telldir should be passed to rst_seekdir. 448 * This routine handles many directories in a single file. 449 * It takes the base of the directory in the file, plus 450 * the desired seek offset into it. 451 */ 452static void 453rst_seekdir(dirp, loc, base) 454 register RST_DIR *dirp; 455 long loc, base; 456{ 457 458 if (loc == rst_telldir(dirp)) 459 return; 460 loc -= base; 461 if (loc < 0) 462 fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); 463 (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), SEEK_SET); 464 dirp->dd_loc = loc & (DIRBLKSIZ - 1); 465 if (dirp->dd_loc != 0) 466 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 467} 468 469/* 470 * get next entry in a directory. 471 */ 472struct direct * 473rst_readdir(dirp) 474 register RST_DIR *dirp; 475{ 476 register struct direct *dp; 477 478 for (;;) { 479 if (dirp->dd_loc == 0) { 480 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 481 DIRBLKSIZ); 482 if (dirp->dd_size <= 0) { 483 dprintf(stderr, "error reading directory\n"); 484 return (NULL); 485 } 486 } 487 if (dirp->dd_loc >= dirp->dd_size) { 488 dirp->dd_loc = 0; 489 continue; 490 } 491 dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 492 if (dp->d_reclen == 0 || 493 dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { 494 dprintf(stderr, "corrupted directory: bad reclen %d\n", 495 dp->d_reclen); 496 return (NULL); 497 } 498 dirp->dd_loc += dp->d_reclen; 499 if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) 500 continue; 501 if (dp->d_ino >= maxino) { 502 dprintf(stderr, "corrupted directory: bad inum %d\n", 503 dp->d_ino); 504 continue; 505 } 506 return (dp); 507 } 508} 509 510/* 511 * Simulate the opening of a directory 512 */ 513RST_DIR * 514rst_opendir(name) 515 const char *name; 516{ 517 struct inotab *itp; 518 RST_DIR *dirp; 519 ino_t ino; 520 521 if ((ino = dirlookup(name)) > 0 && 522 (itp = inotablookup(ino)) != NULL) { 523 dirp = opendirfile(dirfile); 524 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 525 return (dirp); 526 } 527 return (NULL); 528} 529 530/* 531 * In our case, there is nothing to do when closing a directory. 532 */ 533void 534rst_closedir(dirp) 535 RST_DIR *dirp; 536{ 537 538 (void)close(dirp->dd_fd); 539 free(dirp); 540 return; 541} 542 543/* 544 * Simulate finding the current offset in the directory. 545 */ 546static long 547rst_telldir(dirp) 548 RST_DIR *dirp; 549{ 550 return ((long)lseek(dirp->dd_fd, 551 (off_t)0, SEEK_CUR) - dirp->dd_size + dirp->dd_loc); 552} 553 554/* 555 * Open a directory file. 556 */ 557static RST_DIR * 558opendirfile(name) 559 const char *name; 560{ 561 register RST_DIR *dirp; 562 register int fd; 563 564 if ((fd = open(name, O_RDONLY)) == -1) 565 return (NULL); 566 if ((dirp = malloc(sizeof(RST_DIR))) == NULL) { 567 (void)close(fd); 568 return (NULL); 569 } 570 dirp->dd_fd = fd; 571 dirp->dd_loc = 0; 572 return (dirp); 573} 574 575/* 576 * Set the mode, owner, and times for all new or changed directories 577 */ 578void 579setdirmodes(flags) 580 int flags; 581{ 582 FILE *mf; 583 struct modeinfo node; 584 struct entry *ep; 585 char *cp; 586 587 vprintf(stdout, "Set directory mode, owner, and times.\n");
| 280 } else { 281 (void) strncat(locname, dp->d_name, (int)dp->d_namlen); 282 treescan(locname, dp->d_ino, todo); 283 rst_seekdir(dirp, bpt, itp->t_seekpt); 284 } 285 dp = rst_readdir(dirp); 286 bpt = rst_telldir(dirp); 287 } 288 if (dp == NULL) 289 fprintf(stderr, "corrupted directory: %s.\n", locname); 290} 291 292/* 293 * Lookup a pathname which is always assumed to start from the ROOTINO. 294 */ 295struct direct * 296pathsearch(pathname) 297 const char *pathname; 298{ 299 ino_t ino; 300 struct direct *dp; 301 char *path, *name, buffer[MAXPATHLEN]; 302 303 strcpy(buffer, pathname); 304 path = buffer; 305 ino = ROOTINO; 306 while (*path == '/') 307 path++; 308 dp = NULL; 309 while ((name = strsep(&path, "/")) != NULL && *name != NULL) { 310 if ((dp = searchdir(ino, name)) == NULL) 311 return (NULL); 312 ino = dp->d_ino; 313 } 314 return (dp); 315} 316 317/* 318 * Lookup the requested name in directory inum. 319 * Return its inode number if found, zero if it does not exist. 320 */ 321static struct direct * 322searchdir(inum, name) 323 ino_t inum; 324 char *name; 325{ 326 register struct direct *dp; 327 register struct inotab *itp; 328 int len; 329 330 itp = inotablookup(inum); 331 if (itp == NULL) 332 return (NULL); 333 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 334 len = strlen(name); 335 do { 336 dp = rst_readdir(dirp); 337 if (dp == NULL || dp->d_ino == 0) 338 return (NULL); 339 } while (dp->d_namlen != len || strncmp(dp->d_name, name, len) != 0); 340 return (dp); 341} 342 343/* 344 * Put the directory entries in the directory file 345 */ 346static void 347putdir(buf, size) 348 char *buf; 349 long size; 350{ 351 struct direct cvtbuf; 352 register struct odirect *odp; 353 struct odirect *eodp; 354 register struct direct *dp; 355 long loc, i; 356 357 if (cvtflag) { 358 eodp = (struct odirect *)&buf[size]; 359 for (odp = (struct odirect *)buf; odp < eodp; odp++) 360 if (odp->d_ino != 0) { 361 dcvt(odp, &cvtbuf); 362 putent(&cvtbuf); 363 } 364 } else { 365 for (loc = 0; loc < size; ) { 366 dp = (struct direct *)(buf + loc); 367 if (Bcvt) 368 swabst((u_char *)"ls", (u_char *) dp); 369 if (oldinofmt && dp->d_ino != 0) { 370#if BYTE_ORDER == BIG_ENDIAN 371 if (Bcvt) 372#else 373 if (!Bcvt) 374#endif 375 dp->d_namlen = dp->d_type; 376 dp->d_type = DT_UNKNOWN; 377 } 378 i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 379 if ((dp->d_reclen & 0x3) != 0 || 380 dp->d_reclen > i || 381 dp->d_reclen < DIRSIZ(0, dp) || 382 dp->d_namlen > NAME_MAX) { 383 vprintf(stdout, "Mangled directory: "); 384 if ((dp->d_reclen & 0x3) != 0) 385 vprintf(stdout, 386 "reclen not multiple of 4 "); 387 if (dp->d_reclen < DIRSIZ(0, dp)) 388 vprintf(stdout, 389 "reclen less than DIRSIZ (%d < %d) ", 390 dp->d_reclen, DIRSIZ(0, dp)); 391 if (dp->d_namlen > NAME_MAX) 392 vprintf(stdout, 393 "reclen name too big (%d > %d) ", 394 dp->d_namlen, NAME_MAX); 395 vprintf(stdout, "\n"); 396 loc += i; 397 continue; 398 } 399 loc += dp->d_reclen; 400 if (dp->d_ino != 0) { 401 putent(dp); 402 } 403 } 404 } 405} 406 407/* 408 * These variables are "local" to the following two functions. 409 */ 410char dirbuf[DIRBLKSIZ]; 411long dirloc = 0; 412long prev = 0; 413 414/* 415 * add a new directory entry to a file. 416 */ 417static void 418putent(dp) 419 struct direct *dp; 420{ 421 dp->d_reclen = DIRSIZ(0, dp); 422 if (dirloc + dp->d_reclen > DIRBLKSIZ) { 423 ((struct direct *)(dirbuf + prev))->d_reclen = 424 DIRBLKSIZ - prev; 425 (void) fwrite(dirbuf, 1, DIRBLKSIZ, df); 426 dirloc = 0; 427 } 428 bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 429 prev = dirloc; 430 dirloc += dp->d_reclen; 431} 432 433/* 434 * flush out a directory that is finished. 435 */ 436static void 437flushent() 438{ 439 ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 440 (void) fwrite(dirbuf, (int)dirloc, 1, df); 441 seekpt = ftell(df); 442 dirloc = 0; 443} 444 445static void 446dcvt(odp, ndp) 447 register struct odirect *odp; 448 register struct direct *ndp; 449{ 450 451 bzero((char *)ndp, (long)(sizeof *ndp)); 452 ndp->d_ino = odp->d_ino; 453 ndp->d_type = DT_UNKNOWN; 454 (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 455 ndp->d_namlen = strlen(ndp->d_name); 456 ndp->d_reclen = DIRSIZ(0, ndp); 457} 458 459/* 460 * Seek to an entry in a directory. 461 * Only values returned by rst_telldir should be passed to rst_seekdir. 462 * This routine handles many directories in a single file. 463 * It takes the base of the directory in the file, plus 464 * the desired seek offset into it. 465 */ 466static void 467rst_seekdir(dirp, loc, base) 468 register RST_DIR *dirp; 469 long loc, base; 470{ 471 472 if (loc == rst_telldir(dirp)) 473 return; 474 loc -= base; 475 if (loc < 0) 476 fprintf(stderr, "bad seek pointer to rst_seekdir %d\n", loc); 477 (void) lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), SEEK_SET); 478 dirp->dd_loc = loc & (DIRBLKSIZ - 1); 479 if (dirp->dd_loc != 0) 480 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 481} 482 483/* 484 * get next entry in a directory. 485 */ 486struct direct * 487rst_readdir(dirp) 488 register RST_DIR *dirp; 489{ 490 register struct direct *dp; 491 492 for (;;) { 493 if (dirp->dd_loc == 0) { 494 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 495 DIRBLKSIZ); 496 if (dirp->dd_size <= 0) { 497 dprintf(stderr, "error reading directory\n"); 498 return (NULL); 499 } 500 } 501 if (dirp->dd_loc >= dirp->dd_size) { 502 dirp->dd_loc = 0; 503 continue; 504 } 505 dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 506 if (dp->d_reclen == 0 || 507 dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { 508 dprintf(stderr, "corrupted directory: bad reclen %d\n", 509 dp->d_reclen); 510 return (NULL); 511 } 512 dirp->dd_loc += dp->d_reclen; 513 if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) 514 continue; 515 if (dp->d_ino >= maxino) { 516 dprintf(stderr, "corrupted directory: bad inum %d\n", 517 dp->d_ino); 518 continue; 519 } 520 return (dp); 521 } 522} 523 524/* 525 * Simulate the opening of a directory 526 */ 527RST_DIR * 528rst_opendir(name) 529 const char *name; 530{ 531 struct inotab *itp; 532 RST_DIR *dirp; 533 ino_t ino; 534 535 if ((ino = dirlookup(name)) > 0 && 536 (itp = inotablookup(ino)) != NULL) { 537 dirp = opendirfile(dirfile); 538 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 539 return (dirp); 540 } 541 return (NULL); 542} 543 544/* 545 * In our case, there is nothing to do when closing a directory. 546 */ 547void 548rst_closedir(dirp) 549 RST_DIR *dirp; 550{ 551 552 (void)close(dirp->dd_fd); 553 free(dirp); 554 return; 555} 556 557/* 558 * Simulate finding the current offset in the directory. 559 */ 560static long 561rst_telldir(dirp) 562 RST_DIR *dirp; 563{ 564 return ((long)lseek(dirp->dd_fd, 565 (off_t)0, SEEK_CUR) - dirp->dd_size + dirp->dd_loc); 566} 567 568/* 569 * Open a directory file. 570 */ 571static RST_DIR * 572opendirfile(name) 573 const char *name; 574{ 575 register RST_DIR *dirp; 576 register int fd; 577 578 if ((fd = open(name, O_RDONLY)) == -1) 579 return (NULL); 580 if ((dirp = malloc(sizeof(RST_DIR))) == NULL) { 581 (void)close(fd); 582 return (NULL); 583 } 584 dirp->dd_fd = fd; 585 dirp->dd_loc = 0; 586 return (dirp); 587} 588 589/* 590 * Set the mode, owner, and times for all new or changed directories 591 */ 592void 593setdirmodes(flags) 594 int flags; 595{ 596 FILE *mf; 597 struct modeinfo node; 598 struct entry *ep; 599 char *cp; 600 601 vprintf(stdout, "Set directory mode, owner, and times.\n");
|
588 (void) sprintf(modefile, "%s/rstmode%d", _PATH_TMP, dumpdate);
| 602 if (command == 'r' || command == 'R') 603 (void) sprintf(modefile, "%srstmode%d", _PATH_TMP, dumpdate); 604 if (modefile[0] == '#') { 605 panic("modefile not defined\n"); 606 fprintf(stderr, "directory mode, owner, and times not set\n"); 607 return; 608 }
|
589 mf = fopen(modefile, "r"); 590 if (mf == NULL) { 591 fprintf(stderr, "fopen: %s\n", strerror(errno)); 592 fprintf(stderr, "cannot open mode file %s\n", modefile); 593 fprintf(stderr, "directory mode, owner, and times not set\n"); 594 return; 595 } 596 clearerr(mf); 597 for (;;) { 598 (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); 599 if (feof(mf)) 600 break; 601 ep = lookupino(node.ino); 602 if (command == 'i' || command == 'x') { 603 if (ep == NULL) 604 continue; 605 if ((flags & FORCE) == 0 && ep->e_flags & EXISTED) { 606 ep->e_flags &= ~NEW; 607 continue; 608 } 609 if (node.ino == ROOTINO && 610 reply("set owner/mode for '.'") == FAIL) 611 continue; 612 } 613 if (ep == NULL) { 614 panic("cannot find directory inode %d\n", node.ino); 615 } else { 616 cp = myname(ep); 617 (void) chown(cp, node.uid, node.gid); 618 (void) chmod(cp, node.mode); 619 utimes(cp, node.timep); 620 ep->e_flags &= ~NEW; 621 } 622 } 623 if (ferror(mf)) 624 panic("error setting directory modes\n"); 625 (void) fclose(mf); 626} 627 628/* 629 * Generate a literal copy of a directory. 630 */ 631int 632genliteraldir(name, ino) 633 char *name; 634 ino_t ino; 635{ 636 register struct inotab *itp; 637 int ofile, dp, i, size; 638 char buf[BUFSIZ]; 639 640 itp = inotablookup(ino); 641 if (itp == NULL) 642 panic("Cannot find directory inode %d named %s\n", ino, name);
| 609 mf = fopen(modefile, "r"); 610 if (mf == NULL) { 611 fprintf(stderr, "fopen: %s\n", strerror(errno)); 612 fprintf(stderr, "cannot open mode file %s\n", modefile); 613 fprintf(stderr, "directory mode, owner, and times not set\n"); 614 return; 615 } 616 clearerr(mf); 617 for (;;) { 618 (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); 619 if (feof(mf)) 620 break; 621 ep = lookupino(node.ino); 622 if (command == 'i' || command == 'x') { 623 if (ep == NULL) 624 continue; 625 if ((flags & FORCE) == 0 && ep->e_flags & EXISTED) { 626 ep->e_flags &= ~NEW; 627 continue; 628 } 629 if (node.ino == ROOTINO && 630 reply("set owner/mode for '.'") == FAIL) 631 continue; 632 } 633 if (ep == NULL) { 634 panic("cannot find directory inode %d\n", node.ino); 635 } else { 636 cp = myname(ep); 637 (void) chown(cp, node.uid, node.gid); 638 (void) chmod(cp, node.mode); 639 utimes(cp, node.timep); 640 ep->e_flags &= ~NEW; 641 } 642 } 643 if (ferror(mf)) 644 panic("error setting directory modes\n"); 645 (void) fclose(mf); 646} 647 648/* 649 * Generate a literal copy of a directory. 650 */ 651int 652genliteraldir(name, ino) 653 char *name; 654 ino_t ino; 655{ 656 register struct inotab *itp; 657 int ofile, dp, i, size; 658 char buf[BUFSIZ]; 659 660 itp = inotablookup(ino); 661 if (itp == NULL) 662 panic("Cannot find directory inode %d named %s\n", ino, name);
|
643 if ((ofile = creat(name, 0666)) < 0) {
| 663 if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
|
644 fprintf(stderr, "%s: ", name); 645 (void) fflush(stderr); 646 fprintf(stderr, "cannot create file: %s\n", strerror(errno)); 647 return (FAIL); 648 } 649 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 650 dp = dup(dirp->dd_fd); 651 for (i = itp->t_size; i > 0; i -= BUFSIZ) { 652 size = i < BUFSIZ ? i : BUFSIZ; 653 if (read(dp, buf, (int) size) == -1) { 654 fprintf(stderr, 655 "write error extracting inode %d, name %s\n", 656 curfile.ino, curfile.name); 657 fprintf(stderr, "read: %s\n", strerror(errno)); 658 done(1); 659 } 660 if (!Nflag && write(ofile, buf, (int) size) == -1) { 661 fprintf(stderr, 662 "write error extracting inode %d, name %s\n", 663 curfile.ino, curfile.name); 664 fprintf(stderr, "write: %s\n", strerror(errno)); 665 done(1); 666 } 667 } 668 (void) close(dp); 669 (void) close(ofile); 670 return (GOOD); 671} 672 673/* 674 * Determine the type of an inode 675 */ 676int 677inodetype(ino) 678 ino_t ino; 679{ 680 struct inotab *itp; 681 682 itp = inotablookup(ino); 683 if (itp == NULL) 684 return (LEAF); 685 return (NODE); 686} 687 688/* 689 * Allocate and initialize a directory inode entry. 690 * If requested, save its pertinent mode, owner, and time info. 691 */ 692static struct inotab * 693allocinotab(ino, dip, seekpt) 694 ino_t ino; 695 struct dinode *dip; 696 long seekpt; 697{ 698 register struct inotab *itp; 699 struct modeinfo node; 700 701 itp = calloc(1, sizeof(struct inotab)); 702 if (itp == NULL) 703 panic("no memory directory table\n"); 704 itp->t_next = inotab[INOHASH(ino)]; 705 inotab[INOHASH(ino)] = itp; 706 itp->t_ino = ino; 707 itp->t_seekpt = seekpt; 708 if (mf == NULL) 709 return (itp); 710 node.ino = ino; 711 node.timep[0].tv_sec = dip->di_atime.tv_sec; 712 node.timep[0].tv_usec = dip->di_atime.tv_nsec / 1000; 713 node.timep[1].tv_sec = dip->di_mtime.tv_sec; 714 node.timep[1].tv_usec = dip->di_mtime.tv_nsec / 1000; 715 node.mode = dip->di_mode; 716 node.uid = dip->di_uid; 717 node.gid = dip->di_gid; 718 (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); 719 return (itp); 720} 721 722/* 723 * Look up an inode in the table of directories 724 */ 725static struct inotab * 726inotablookup(ino) 727 ino_t ino; 728{ 729 register struct inotab *itp; 730 731 for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) 732 if (itp->t_ino == ino) 733 return (itp); 734 return (NULL); 735} 736 737/* 738 * Clean up and exit 739 */ 740void 741done(exitcode) 742 int exitcode; 743{ 744 745 closemt(); 746 if (modefile[0] != '#') 747 (void) unlink(modefile); 748 if (dirfile[0] != '#') 749 (void) unlink(dirfile); 750 exit(exitcode); 751}
| 664 fprintf(stderr, "%s: ", name); 665 (void) fflush(stderr); 666 fprintf(stderr, "cannot create file: %s\n", strerror(errno)); 667 return (FAIL); 668 } 669 rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 670 dp = dup(dirp->dd_fd); 671 for (i = itp->t_size; i > 0; i -= BUFSIZ) { 672 size = i < BUFSIZ ? i : BUFSIZ; 673 if (read(dp, buf, (int) size) == -1) { 674 fprintf(stderr, 675 "write error extracting inode %d, name %s\n", 676 curfile.ino, curfile.name); 677 fprintf(stderr, "read: %s\n", strerror(errno)); 678 done(1); 679 } 680 if (!Nflag && write(ofile, buf, (int) size) == -1) { 681 fprintf(stderr, 682 "write error extracting inode %d, name %s\n", 683 curfile.ino, curfile.name); 684 fprintf(stderr, "write: %s\n", strerror(errno)); 685 done(1); 686 } 687 } 688 (void) close(dp); 689 (void) close(ofile); 690 return (GOOD); 691} 692 693/* 694 * Determine the type of an inode 695 */ 696int 697inodetype(ino) 698 ino_t ino; 699{ 700 struct inotab *itp; 701 702 itp = inotablookup(ino); 703 if (itp == NULL) 704 return (LEAF); 705 return (NODE); 706} 707 708/* 709 * Allocate and initialize a directory inode entry. 710 * If requested, save its pertinent mode, owner, and time info. 711 */ 712static struct inotab * 713allocinotab(ino, dip, seekpt) 714 ino_t ino; 715 struct dinode *dip; 716 long seekpt; 717{ 718 register struct inotab *itp; 719 struct modeinfo node; 720 721 itp = calloc(1, sizeof(struct inotab)); 722 if (itp == NULL) 723 panic("no memory directory table\n"); 724 itp->t_next = inotab[INOHASH(ino)]; 725 inotab[INOHASH(ino)] = itp; 726 itp->t_ino = ino; 727 itp->t_seekpt = seekpt; 728 if (mf == NULL) 729 return (itp); 730 node.ino = ino; 731 node.timep[0].tv_sec = dip->di_atime.tv_sec; 732 node.timep[0].tv_usec = dip->di_atime.tv_nsec / 1000; 733 node.timep[1].tv_sec = dip->di_mtime.tv_sec; 734 node.timep[1].tv_usec = dip->di_mtime.tv_nsec / 1000; 735 node.mode = dip->di_mode; 736 node.uid = dip->di_uid; 737 node.gid = dip->di_gid; 738 (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); 739 return (itp); 740} 741 742/* 743 * Look up an inode in the table of directories 744 */ 745static struct inotab * 746inotablookup(ino) 747 ino_t ino; 748{ 749 register struct inotab *itp; 750 751 for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) 752 if (itp->t_ino == ino) 753 return (itp); 754 return (NULL); 755} 756 757/* 758 * Clean up and exit 759 */ 760void 761done(exitcode) 762 int exitcode; 763{ 764 765 closemt(); 766 if (modefile[0] != '#') 767 (void) unlink(modefile); 768 if (dirfile[0] != '#') 769 (void) unlink(dirfile); 770 exit(exitcode); 771}
|