summaryrefslogtreecommitdiff
path: root/bin/pax/file_subs.c
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2005-04-25 19:39:53 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2005-04-25 19:39:53 +0000
commite84358e720ae63930c0fdbe7a346422f7d346bf8 (patch)
treebe0b07b19cd9b6ea30435818e3e1980565bf28a2 /bin/pax/file_subs.c
parent82d0504cfbb8840ac58acf9708c557f60e4ffe83 (diff)
Use the various f* functions to set owner, mode and times, instead
of operating on the path name. Avoids some races. ok deraadt@ cloder@ millert@
Diffstat (limited to 'bin/pax/file_subs.c')
-rw-r--r--bin/pax/file_subs.c74
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