diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2004-11-29 16:23:23 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2004-11-29 16:23:23 +0000 |
commit | 55df41b563d595673e105141cf8ac1ab1c382847 (patch) | |
tree | 65338a97c83cc2c47badadcdb40164542b859e09 /bin | |
parent | a86db4536b7a6efb18d910baba52cf31ec5e9fbd (diff) |
Build the table of created directories in-memory, instead of using
a tmp file. Makes it possible to unpack an archive without using
/tmp, while memory usage is still within every reasonable limit.
"love it" deraadt@ ok millert@ jaredy@
Diffstat (limited to 'bin')
-rw-r--r-- | bin/pax/extern.h | 4 | ||||
-rw-r--r-- | bin/pax/file_subs.c | 10 | ||||
-rw-r--r-- | bin/pax/tables.c | 114 | ||||
-rw-r--r-- | bin/pax/tables.h | 13 |
4 files changed, 58 insertions, 83 deletions
diff --git a/bin/pax/extern.h b/bin/pax/extern.h index a05050a9cf1..f4237debfbc 100644 --- a/bin/pax/extern.h +++ b/bin/pax/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.28 2004/03/30 16:14:22 millert Exp $ */ +/* $OpenBSD: extern.h,v 1.29 2004/11/29 16:23:22 otto Exp $ */ /* $NetBSD: extern.h,v 1.5 1996/03/26 23:54:16 mrg Exp $ */ /*- @@ -271,7 +271,7 @@ void atdir_end(void); void add_atdir(char *, dev_t, ino_t, time_t, time_t); int get_atdir(dev_t, ino_t, time_t *, time_t *); int dir_start(void); -void add_dir(char *, int, struct stat *, int); +void add_dir(char *, struct stat *, int); void proc_dir(void); u_int st_hash(char *, int, int); diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c index 2a4e063ba9f..cd05bd1c4f0 100644 --- a/bin/pax/file_subs.c +++ b/bin/pax/file_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file_subs.c,v 1.27 2004/04/16 22:50:23 deraadt Exp $ */ +/* $OpenBSD: file_subs.c,v 1.28 2004/11/29 16:23:22 otto Exp $ */ /* $NetBSD: file_subs.c,v 1.4 1995/03/21 09:07:18 cgd Exp $ */ /*- @@ -38,7 +38,7 @@ #if 0 static const char sccsid[] = "@(#)file_subs.c 8.1 (Berkeley) 5/31/93"; #else -static const char rcsid[] = "$OpenBSD: file_subs.c,v 1.27 2004/04/16 22:50:23 deraadt Exp $"; +static const char rcsid[] = "$OpenBSD: file_subs.c,v 1.28 2004/11/29 16:23:22 otto Exp $"; #endif #endif /* not lint */ @@ -508,9 +508,9 @@ badlink: * we have to force the mode to what was set here, * since we changed it from the default as created. */ - add_dir(nm, strlen(nm), &(arcn->sb), 1); + add_dir(nm, &(arcn->sb), 1); } else if (pmode || patime || pmtime) - add_dir(nm, strlen(nm), &(arcn->sb), 0); + add_dir(nm, &(arcn->sb), 0); } if (patime || pmtime) @@ -645,7 +645,7 @@ chk_path(char *name, uid_t st_uid, gid_t st_gid) if ((access(name, R_OK | W_OK | X_OK) < 0) && (lstat(name, &sb) == 0)) { set_pmode(name, ((sb.st_mode & FILEBITS) | S_IRWXU)); - add_dir(name, spt - name, &sb, 1); + add_dir(name, &sb, 1); } *(spt++) = '/'; continue; diff --git a/bin/pax/tables.c b/bin/pax/tables.c index b90e47ceb21..6fc1446e127 100644 --- a/bin/pax/tables.c +++ b/bin/pax/tables.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tables.c,v 1.21 2003/08/16 17:31:55 deraadt Exp $ */ +/* $OpenBSD: tables.c,v 1.22 2004/11/29 16:23:22 otto Exp $ */ /* $NetBSD: tables.c,v 1.4 1995/03/21 09:07:45 cgd Exp $ */ /*- @@ -38,7 +38,7 @@ #if 0 static const char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 5/31/93"; #else -static const char rcsid[] = "$OpenBSD: tables.c,v 1.21 2003/08/16 17:31:55 deraadt Exp $"; +static const char rcsid[] = "$OpenBSD: tables.c,v 1.22 2004/11/29 16:23:22 otto Exp $"; #endif #endif /* not lint */ @@ -76,8 +76,9 @@ static FTM **ftab = NULL; /* file time table for updating arch */ static NAMT **ntab = NULL; /* interactive rename storage table */ static DEVT **dtab = NULL; /* device/inode mapping tables */ static ATDIR **atab = NULL; /* file tree directory time reset table */ -static int dirfd = -1; /* storage for setting created dir time/mode */ -static u_long dircnt; /* entries in dir time/mode storage */ +static DIRDATA *dirp = NULL; /* storage for setting created dir time/mode */ +static size_t dirsize; /* size of dirp table */ +static long dircnt = 0; /* entries in dir time/mode storage */ static int ffd = -1; /* tmp file for file time table name storage */ static DEVT *chk_dev(dev_t, int); @@ -1092,21 +1093,15 @@ get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime) int dir_start(void) { - - if (dirfd != -1) + if (dirp != NULL) return(0); - /* - * unlink the file so it goes away at termination by itself - */ - memcpy(tempbase, _TFILE_BASE, sizeof(_TFILE_BASE)); - if ((dirfd = mkstemp(tempfile)) >= 0) { - (void)unlink(tempfile); - return(0); + dirsize = DIRP_SIZE; + if ((dirp = malloc(dirsize * sizeof(DIRDATA))) == NULL) { + paxwarn(1, "Unable to allocate memory for directory times"); + return(-1); } - paxwarn(1, "Unable to create temporary file for directory times: %s", - tempfile); - return(-1); + return(0); } /* @@ -1123,38 +1118,34 @@ dir_start(void) */ void -add_dir(char *name, int nlen, struct stat *psb, int frc_mode) +add_dir(char *name, struct stat *psb, int frc_mode) { - DIRDATA dblk; + DIRDATA *dblk; - if (dirfd < 0) + if (dirp == NULL) return; - /* - * get current position (where file name will start) so we can store it - * in the trailer - */ - if ((dblk.npos = lseek(dirfd, 0L, SEEK_CUR)) < 0) { - paxwarn(1,"Unable to store mode and times for directory: %s",name); - return; + if (dircnt == dirsize) { + dblk = realloc(dirp, 2 * dirsize * sizeof(DIRDATA)); + if (dblk == NULL) { + paxwarn(1, "Unable to store mode and times for created" + " directory: %s", name); + return; + } + dirp = dblk; + dirsize *= 2; } - - /* - * write the file name followed by the trailer - */ - dblk.nlen = nlen + 1; - dblk.mode = psb->st_mode & 0xffff; - dblk.mtime = psb->st_mtime; - dblk.atime = psb->st_atime; - dblk.frc_mode = frc_mode; - if ((write(dirfd, name, dblk.nlen) == dblk.nlen) && - (write(dirfd, (char *)&dblk, sizeof(dblk)) == sizeof(dblk))) { - ++dircnt; + dblk = &dirp[dircnt]; + if ((dblk->name = strdup(name)) == NULL) { + paxwarn(1, "Unable to store mode and times for created" + " directory: %s", name); return; } - - paxwarn(1,"Unable to store mode and times for created directory: %s",name); - return; + dblk->mode = psb->st_mode & 0xffff; + dblk->mtime = psb->st_mtime; + dblk->atime = psb->st_atime; + dblk->frc_mode = frc_mode; + ++dircnt; } /* @@ -1166,46 +1157,31 @@ add_dir(char *name, int nlen, struct stat *psb, int frc_mode) void proc_dir(void) { - char name[PAXPATHLEN+1]; - DIRDATA dblk; - u_long cnt; + DIRDATA *dblk; + long cnt; - if (dirfd < 0) + if (dirp == NULL) return; /* * read backwards through the file and process each directory */ - for (cnt = 0; cnt < dircnt; ++cnt) { - /* - * read the trailer, then the file name, if this fails - * just give up. - */ - if (lseek(dirfd, -((off_t)sizeof(dblk)), SEEK_CUR) < 0) - break; - if (read(dirfd,(char *)&dblk, sizeof(dblk)) != sizeof(dblk)) - break; - if (lseek(dirfd, dblk.npos, SEEK_SET) < 0) - break; - if (read(dirfd, name, dblk.nlen) != dblk.nlen) - break; - if (lseek(dirfd, dblk.npos, SEEK_SET) < 0) - break; - + cnt = dircnt; + while (--cnt >= 0) { /* * frc_mode set, make sure we set the file modes even if * the user didn't ask for it (see file_subs.c for more info) */ - if (pmode || dblk.frc_mode) - set_pmode(name, dblk.mode); + dblk = &dirp[cnt]; + if (pmode || dblk->frc_mode) + set_pmode(dblk->name, dblk->mode); if (patime || pmtime) - set_ftime(name, dblk.mtime, dblk.atime, 0); + set_ftime(dblk->name, dblk->mtime, dblk->atime, 0); + free(dblk->name); } - (void)close(dirfd); - dirfd = -1; - if (cnt != dircnt) - paxwarn(1,"Unable to set mode and times for created directories"); - return; + free(dirp); + dirp = NULL; + dircnt = 0; } /* diff --git a/bin/pax/tables.h b/bin/pax/tables.h index bcf2826e695..e065387e4fa 100644 --- a/bin/pax/tables.h +++ b/bin/pax/tables.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tables.h,v 1.6 2003/10/20 06:22:27 jmc Exp $ */ +/* $OpenBSD: tables.h,v 1.7 2004/11/29 16:23:22 otto Exp $ */ /* $NetBSD: tables.h,v 1.3 1995/03/21 09:07:47 cgd Exp $ */ /*- @@ -51,6 +51,7 @@ #define D_TAB_SZ 317 /* unique device mapping table */ #define A_TAB_SZ 317 /* ftree dir access time reset table */ #define MAXKEYLEN 64 /* max number of chars for hash */ +#define DIRP_SIZE 64 /* initial size of created dir table */ /* * file hard link structure (hashed by dev/ino and chained) used to find the @@ -157,15 +158,13 @@ typedef struct atdir { * times and/or modes). We must reset time in the reverse order of creation, * because entries are added from the top of the file tree to the bottom. * We MUST reset times from leaf to root (it will not work the other - * direction). Entries are recorded into a spool file to make reverse - * reading faster. + * direction). */ typedef struct dirdata { - int nlen; /* length of the directory name (includes \0) */ - off_t npos; /* position in file where this dir name starts */ - mode_t mode; /* file mode to restore */ + char *name; /* file name */ time_t mtime; /* mtime to set */ time_t atime; /* atime to set */ - int frc_mode; /* do we force mode settings? */ + u_int16_t mode; /* file mode to restore */ + u_int16_t frc_mode; /* do we force mode settings? */ } DIRDATA; |