summaryrefslogtreecommitdiffstats
path: root/openbsd-compat
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
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')
-rw-r--r--openbsd-compat/bsd-misc.c58
-rw-r--r--openbsd-compat/bsd-misc.h12
2 files changed, 70 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)
{
diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h
index 584c2b5ef..cb158cd5c 100644
--- a/openbsd-compat/bsd-misc.h
+++ b/openbsd-compat/bsd-misc.h
@@ -72,6 +72,18 @@ int utimes(char *, struct timeval *);
int utimensat(int, const char *, const struct timespec[2], int);
#endif
+#ifndef AT_FDCWD
+# define AT_FDCWD (-2)
+#endif
+
+#ifndef HAVE_FCHMODAT
+int fchmodat(int, const char *, mode_t, int);
+#endif
+
+#ifndef HAVE_FCHOWNAT
+int fchownat(int, const char *, uid_t, gid_t, int);
+#endif
+
#ifndef HAVE_TRUNCATE
int truncate (const char *, off_t);
#endif /* HAVE_TRUNCATE */