The recent homedir creation patches broke compilation on RHEL5.

SSSD 1.10 is no longer supported on RHEL5, but 1.9.x is and I know of
several users, who actually run 1.9.x in production.

The attached patch provides compatible implementations for several
functions that are not available, fixing the RHEL5 build.
>From 880fbe7dcdf95d61345357f78b6b4024fcafdfa3 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <[email protected]>
Date: Fri, 25 Jan 2013 10:57:54 -0500
Subject: [PATCH] TOOLS: Compile on old platforms such as RHEL5

Provides compatible declarations for modern file management functions
such as futimens or opening with the O_CLOEXEC flag
---
 configure.ac      |   4 ++
 src/tools/files.c | 177 ++++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 144 insertions(+), 37 deletions(-)

diff --git a/configure.ac b/configure.ac
index 
471c7ac6826d4a895e058dba4c1f62f3e552fea3..af976151ad3c90bfcb056dd7d8d24bbc8b884ca5
 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,10 @@ AC_CHECK_FUNCS([ pthread_mutexattr_setrobust \
                  pthread_mutex_consistent_np ])
 LIBS=$SAVE_LIBS
 
+# Check for presence of modern functions for setting file timestamps
+AC_CHECK_FUNCS([ utimensat \
+                 futimens ])
+
 #Check for PAM headers
 AC_CHECK_HEADERS([security/pam_appl.h security/pam_misc.h 
security/pam_modules.h],
     [AC_CHECK_LIB(pam, pam_get_item, [ PAM_LIBS="-lpam" ], [AC_MSG_ERROR([PAM 
must support pam_get_item])])],
diff --git a/src/tools/files.c b/src/tools/files.c
index 
4a6625eae56af87ef3f1b0c42323026c2bd4cac5..62fd00368c4e62715802d3c6c353985897569e3d
 100644
--- a/src/tools/files.c
+++ b/src/tools/files.c
@@ -54,6 +54,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "config.h"
+
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/time.h>
@@ -62,7 +64,6 @@
 #include <errno.h>
 #include <talloc.h>
 
-#include "config.h"
 #include "util/util.h"
 #include "tools/tools_util.h"
 
@@ -74,6 +75,125 @@ struct copy_ctx {
     gid_t       gid;
 };
 
+static int open_cloexec(const char *pathname, int flags, int *ret)
+{
+    int fd;
+    int oflags;
+
+    oflags = flags;
+#ifdef O_CLOEXEC
+    oflags |= O_CLOEXEC;
+#endif
+
+    errno = 0;
+    fd = open(pathname, oflags);
+    if (fd == -1) {
+        if (ret) {
+            *ret = errno;
+        }
+        return -1;
+    }
+
+#ifndef O_CLOEXEC
+    int v;
+
+    v = fcntl(fd, F_GETFD, 0);
+    /* we ignore an error, it's not fatal and there is nothing we
+     * can do about it anyways */
+    (void)fcntl(fd, F_SETFD, v | FD_CLOEXEC);
+#endif
+
+    return fd;
+}
+
+static int openat_cloexec(int dir_fd, const char *pathname, int flags, int 
*ret)
+{
+    int fd;
+    int oflags;
+
+    oflags = flags;
+#ifdef O_CLOEXEC
+    oflags |= O_CLOEXEC;
+#endif
+
+    errno = 0;
+    fd = openat(dir_fd, pathname, oflags);
+    if (fd == -1) {
+        if (ret) {
+            *ret = errno;
+        }
+        return -1;
+    }
+
+#ifndef O_CLOEXEC
+    int v;
+
+    v = fcntl(fd, F_GETFD, 0);
+    /* we ignore an error, it's not fatal and there is nothing we
+     * can do about it anyways */
+    (void)fcntl(fd, F_SETFD, v | FD_CLOEXEC);
+#endif
+
+    return fd;
+}
+
+static int sss_timeat_set(int dir_fd, const char *path,
+                          const struct stat *statp,
+                          int flags)
+{
+    int ret;
+
+#ifdef HAVE_UTIMENSAT
+    struct timespec timebuf[2];
+
+    timebuf[0] = statp->st_atim;
+    timebuf[1] = statp->st_mtim;
+
+    ret = utimensat(dir_fd, path, timebuf, flags);
+#else
+    struct timeval tv[2];
+
+    tv[0].tv_sec  = statp->st_atime;
+    tv[0].tv_usec = 0;
+    tv[1].tv_sec = statp->st_mtime;
+    tv[1].tv_usec = 0;
+
+    ret = futimesat(dir_fd, path, tv);
+#endif
+    if (ret == -1) {
+        return errno;
+    }
+
+    return EOK;
+}
+
+static int sss_futime_set(int fd, const struct stat *statp)
+{
+    int ret;
+
+#ifdef HAVE_FUTIMENS
+    struct timespec timebuf[2];
+
+    timebuf[0] = statp->st_atim;
+    timebuf[1] = statp->st_mtim;
+    ret = futimens(fd, timebuf);
+#else
+    struct timeval tv[2];
+
+    tv[0].tv_sec  = statp->st_atime;
+    tv[0].tv_usec = 0;
+    tv[1].tv_sec = statp->st_mtime;
+    tv[1].tv_usec = 0;
+
+    ret = futimes(fd, tv);
+#endif
+    if (ret == -1) {
+        return errno;
+    }
+
+    return EOK;
+}
+
 /* wrapper in order not to create a temporary context in
  * every iteration */
 static int remove_tree_with_ctx(TALLOC_CTX *mem_ctx,
@@ -112,8 +232,8 @@ static int remove_tree_with_ctx(TALLOC_CTX *mem_ctx,
     int ret, err;
     int dir_fd;
 
-    dir_fd = openat(parent_fd, dir_name,
-                    O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW);
+    dir_fd = openat_cloexec(parent_fd, dir_name,
+                            O_RDONLY | O_DIRECTORY | O_NOFOLLOW, &ret);
     if (dir_fd == -1) {
         ret = errno;
         DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot open %s: [%d]: %s\n",
@@ -246,7 +366,6 @@ copy_symlink(int src_dir_fd,
 {
     char *buf;
     errno_t ret;
-    struct timespec timebuf[2];
 
     buf = talloc_readlinkat(NULL, src_dir_fd, file_name);
     if (!buf) {
@@ -283,12 +402,9 @@ copy_symlink(int src_dir_fd,
         return ret;
     }
 
-    timebuf[0] = statp->st_atim;
-    timebuf[1] = statp->st_mtim;
-    ret = utimensat(dst_dir_fd, file_name, timebuf,
-                    AT_SYMLINK_NOFOLLOW);
-    if (ret == -1) {
-        ret = errno;
+    ret = sss_timeat_set(dst_dir_fd, file_name, statp,
+                         AT_SYMLINK_NOFOLLOW);
+    if (ret != EOK) {
         DEBUG(SSSDBG_MINOR_FAILURE, ("utimensat failed [%d]: %s\n",
               ret, strerror(ret)));
         /* Do not fail */
@@ -309,7 +425,6 @@ static int copy_special(int dst_dir_fd,
                         uid_t uid, gid_t gid)
 {
     int ret;
-    struct timespec timebuf[2];
 
     ret = selinux_file_context(full_path);
     if (ret != 0) {
@@ -346,9 +461,7 @@ static int copy_special(int dst_dir_fd,
         return ret;
     }
 
-    timebuf[0] = statp->st_atim;
-    timebuf[1] = statp->st_mtim;
-    ret = utimensat(dst_dir_fd, file_name, timebuf, 0);
+    ret = sss_timeat_set(dst_dir_fd, file_name, statp, 0);
     if (ret == -1) {
         ret = errno;
         DEBUG(SSSDBG_MINOR_FAILURE,
@@ -376,7 +489,6 @@ copy_file(int ifd,
     errno_t ret;
     char buf[1024];
     ssize_t cnt, written;
-    struct timespec timebuf[2];
 
     ret = selinux_file_context(full_path);
     if (ret != 0) {
@@ -443,12 +555,9 @@ copy_file(int ifd,
               goto done;
     }
 
-    timebuf[0] = statp->st_atim;
-    timebuf[1] = statp->st_mtim;
-    ret = futimens(ofd, timebuf);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_MINOR_FAILURE, ("futimens failed [%d]: %s\n",
+    ret = sss_futime_set(ofd, statp);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE, ("sss_futime_set failed [%d]: %s\n",
               ret, strerror(ret)));
         /* Do not fail */
     }
@@ -498,15 +607,14 @@ copy_entry(struct copy_ctx *cctx,
      * us against FIFOs and perhaps side-effects of the open() of a
      * device file if there ever was one here, and doesn't matter
      * for regular files or directories. */
-    ifd = openat(src_dir_fd, ent_name,
-                 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK);
-    if (ifd == -1 && errno != ELOOP) {
+    ifd = openat_cloexec(src_dir_fd, ent_name,
+                         O_RDONLY | O_NOFOLLOW | O_NONBLOCK, &ret);
+    if (ifd == -1 && ret != ELOOP) {
         /* openat error */
-        ret = errno;
         DEBUG(SSSDBG_CRIT_FAILURE, ("openat failed on '%s': %s\n",
               src_ent_path, strerror(ret)));
         goto done;
-    } else if (ifd == -1 && errno == ELOOP) {
+    } else if (ifd == -1 && ret == ELOOP) {
         /* Should be a symlink.. */
         ret = fstatat(src_dir_fd, ent_name, &st, AT_SYMLINK_NOFOLLOW);
         if (ret == -1) {
@@ -586,7 +694,6 @@ copy_dir(struct copy_ctx *cctx,
     int dest_dir_fd = -1;
     DIR *dir = NULL;
     struct dirent *ent;
-    struct timespec timebuf[2];
 
     if (!dest_dir_path) {
         return EINVAL;
@@ -613,8 +720,8 @@ copy_dir(struct copy_ctx *cctx,
         goto done;
     }
 
-    dest_dir_fd = openat(dest_parent_fd, dest_dir_name,
-                         O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW);
+    dest_dir_fd = openat_cloexec(dest_parent_fd, dest_dir_name,
+                                 O_RDONLY | O_DIRECTORY | O_NOFOLLOW, &ret);
     if (dest_dir_fd == -1) {
         ret = errno;
         DEBUG(SSSDBG_CRIT_FAILURE,
@@ -663,12 +770,9 @@ copy_dir(struct copy_ctx *cctx,
         goto done;
     }
 
-    timebuf[0] = src_dir_stat->st_atim;
-    timebuf[1] = src_dir_stat->st_mtim;
-    futimens(dest_dir_fd, timebuf);
-    if (ret == -1) {
-        ret = errno;
-        DEBUG(SSSDBG_MINOR_FAILURE, ("futimens failed [%d]: %s\n",
+    sss_futime_set(dest_dir_fd, src_dir_stat);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE, ("sss_futime_set failed [%d]: %s\n",
               ret, strerror(ret)));
         /* Do not fail */
     }
@@ -695,9 +799,8 @@ int copy_tree(const char *src_root, const char *dst_root,
     int fd = -1;
     struct stat s_src;
 
-    fd = open(src_root, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
+    fd = open_cloexec(src_root, O_RDONLY | O_DIRECTORY, &ret);
     if (fd == -1) {
-        ret = errno;
         goto fail;
     }
 
-- 
1.8.1

_______________________________________________
sssd-devel mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to