summaryrefslogtreecommitdiff
path: root/openbsd-compat/bsd-misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsd-compat/bsd-misc.c')
-rw-r--r--openbsd-compat/bsd-misc.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c
index 5d7540a70f4b6..aa1c7d7a3dd6a 100644
--- a/openbsd-compat/bsd-misc.c
+++ b/openbsd-compat/bsd-misc.c
@@ -25,6 +25,7 @@
# include <sys/time.h>
#endif
+#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
@@ -117,6 +118,106 @@ int utimes(char *filename, struct timeval *tvp)
}
#endif
+#ifndef HAVE_UTIMENSAT
+/*
+ * A limited implementation of utimensat() that only implements the
+ * functionality used by OpenSSH, currently only AT_FDCWD and
+ * AT_SYMLINK_NOFOLLOW.
+ */
+int
+utimensat(int fd, const char *path, const struct timespec times[2],
+ int flag)
+{
+ struct timeval tv[2];
+ int ret, oflags = O_WRONLY;
+
+ tv[0].tv_sec = times[0].tv_sec;
+ tv[0].tv_usec = times[0].tv_nsec / 1000;
+ tv[1].tv_sec = times[1].tv_sec;
+ tv[1].tv_usec = times[1].tv_nsec / 1000;
+
+ if (fd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+# ifndef HAVE_FUTIMES
+ return utimes(path, tv);
+# else
+# ifdef O_NOFOLLOW
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+# endif /* O_NOFOLLOW */
+ if ((fd = open(path, oflags)) == -1)
+ return -1;
+ ret = futimes(fd, tv);
+ close(fd);
+ return ret;
+# endif
+}
+#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
+# ifdef O_NOFOLLOW
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+# endif /* 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
+# ifdef O_NOFOLLOW
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+# endif /* 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)
{