diff --git a/configure.ac b/configure.ac index 2d1dafdee..8e92d1599 100644 --- a/configure.ac +++ b/configure.ac @@ -1719,7 +1719,9 @@ AC_CHECK_FUNCS([ \ errx \ explicit_bzero \ fchmod \ + fchmodat \ fchown \ + fchownat \ flock \ freeaddrinfo \ freezero \ 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 */