diff options
Diffstat (limited to 'bin/pax/file_subs.c')
-rw-r--r-- | bin/pax/file_subs.c | 74 |
1 files changed, 66 insertions, 8 deletions
diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c index cd05bd1c4f0..b0e0e9c6256 100644 --- a/bin/pax/file_subs.c +++ b/bin/pax/file_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file_subs.c,v 1.28 2004/11/29 16:23:22 otto Exp $ */ +/* $OpenBSD: file_subs.c,v 1.29 2005/04/25 19:39:52 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.28 2004/11/29 16:23:22 otto Exp $"; +static const char rcsid[] = "$OpenBSD: file_subs.c,v 1.29 2005/04/25 19:39:52 otto Exp $"; #endif #endif /* not lint */ @@ -140,9 +140,6 @@ file_close(ARCHD *arcn, int fd) if (fd < 0) return; - if (close(fd) < 0) - syswarn(0, errno, "Unable to close file descriptor on %s", - arcn->name); /* * set owner/groups first as this may strip off mode bits we want @@ -150,7 +147,8 @@ file_close(ARCHD *arcn, int fd) * modification times. */ if (pids) - res = set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid); + res = fset_ids(arcn->name, fd, arcn->sb.st_uid, + arcn->sb.st_gid); /* * IMPORTANT SECURITY NOTE: @@ -160,9 +158,13 @@ file_close(ARCHD *arcn, int fd) if (!pmode || res) arcn->sb.st_mode &= ~(SETBITS); if (pmode) - set_pmode(arcn->name, arcn->sb.st_mode); + fset_pmode(arcn->name, fd, arcn->sb.st_mode); if (patime || pmtime) - set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0); + fset_ftime(arcn->name, fd, arcn->sb.st_mtime, + arcn->sb.st_atime, 0); + if (close(fd) < 0) + syswarn(0, errno, "Unable to close file descriptor on %s", + arcn->name); } /* @@ -696,6 +698,36 @@ set_ftime(char *fnm, time_t mtime, time_t atime, int frc) return; } +void +fset_ftime(char *fnm, int fd, time_t mtime, time_t atime, int frc) +{ + static struct timeval tv[2] = {{0L, 0L}, {0L, 0L}}; + struct stat sb; + + tv[0].tv_sec = (long)atime; + tv[1].tv_sec = (long)mtime; + if (!frc && (!patime || !pmtime)) { + /* + * if we are not forcing, only set those times the user wants + * set. We get the current values of the times if we need them. + */ + if (fstat(fd, &sb) == 0) { + if (!patime) + tv[0].tv_sec = (long)sb.st_atime; + if (!pmtime) + tv[1].tv_sec = (long)sb.st_mtime; + } else + syswarn(0,errno,"Unable to obtain file stats %s", fnm); + } + /* + * set the times + */ + if (futimes(fd, tv) < 0) + syswarn(1, errno, "Access/modification time set failed on: %s", + fnm); + return; +} + /* * set_ids() * set the uid and gid of a file system node @@ -720,6 +752,23 @@ set_ids(char *fnm, uid_t uid, gid_t gid) return(0); } +int +fset_ids(char *fnm, int fd, uid_t uid, gid_t gid) +{ + if (fchown(fd, uid, gid) < 0) { + /* + * ignore EPERM unless in verbose mode or being run by root. + * if running as pax, POSIX requires a warning. + */ + if (strcmp(NM_PAX, argv0) == 0 || errno != EPERM || vflag || + geteuid() == 0) + syswarn(1, errno, "Unable to set file uid/gid of %s", + fnm); + return(-1); + } + return(0); +} + /* * set_lids() * set the uid and gid of a file system node @@ -758,6 +807,15 @@ set_pmode(char *fnm, mode_t mode) return; } +void +fset_pmode(char *fnm, int fd, mode_t mode) +{ + mode &= ABITS; + if (fchmod(fd, mode) < 0) + syswarn(1, errno, "Could not set permissions on %s", fnm); + return; +} + /* * file_write() * Write/copy a file (during copy or archive extract). This routine knows |