summaryrefslogtreecommitdiffstats
path: root/openbsd-compat/bsd-misc.c
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@dtucker.net>2019-01-18 01:09:01 +0100
committerDarren Tucker <dtucker@dtucker.net>2019-01-18 01:09:01 +0100
commita6258e5dc314c7d504ac9f0fbc3be96475581dbe (patch)
tree19047ce95b4608e7791ef419452c000055a6dac7 /openbsd-compat/bsd-misc.c
parentAdd a minimal implementation of utimensat(). (diff)
downloadopenssh-a6258e5dc314c7d504ac9f0fbc3be96475581dbe.tar.xz
openssh-a6258e5dc314c7d504ac9f0fbc3be96475581dbe.zip
Add minimal fchownat and fchmodat implementations.
Fixes builds on at least OS X Lion, NetBSD 6 and Solaris 10.
Diffstat (limited to 'openbsd-compat/bsd-misc.c')
-rw-r--r--openbsd-compat/bsd-misc.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c
index 4bae96548..d3a41df50 100644
--- a/openbsd-compat/bsd-misc.c
+++ b/openbsd-compat/bsd-misc.c
@@ -154,6 +154,64 @@ utimensat(int fd, const char *path, const struct timespec times[2],
}
#endif
+#ifndef HAVE_FCHOWNAT
+/*
+ * A limited implementation of fchownat() that only implements the
+ * functionality used by OpenSSH, currently only AT_FDCWD and
+ * AT_SYMLINK_NOFOLLOW.
+ */
+int
+fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag)
+{
+ int ret, oflags = O_WRONLY;
+
+ if (fd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+# ifndef HAVE_FCHOWN
+ return chown(pathname, owner, group);
+# else
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+ if ((fd = open(path, oflags)) == -1)
+ return -1;
+ ret = fchown(fd, owner, group);
+ close(fd);
+ return ret;
+# endif
+}
+#endif
+
+#ifndef HAVE_FCHMODAT
+/*
+ * A limited implementation of fchmodat() that only implements the
+ * functionality used by OpenSSH, currently only AT_FDCWD and
+ * AT_SYMLINK_NOFOLLOW.
+ */
+int
+fchmodat(int fd, const char *path, mode_t mode, int flag)
+{
+ int ret, oflags = O_WRONLY;
+
+ if (fd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+# ifndef HAVE_FCHMOD
+ return chown(pathname, owner, group);
+# else
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+ if ((fd = open(path, oflags)) == -1)
+ return -1;
+ ret = fchmod(fd, mode);
+ close(fd);
+ return ret;
+# endif
+}
+#endif
+
#ifndef HAVE_TRUNCATE
int truncate(const char *path, off_t length)
{