Work around glibc's lchmod() issue a better way.
authorWayne Davison <wayne@opencoder.net>
Sun, 29 Nov 2020 17:33:54 +0000 (09:33 -0800)
committerWayne Davison <wayne@opencoder.net>
Sun, 29 Nov 2020 17:40:03 +0000 (09:40 -0800)
configure.ac
syscall.c

index 19d6ae520189e9c42b50730d0184135ace958458..0f8e38f3b23351680bf1dc3c0d0bd9b2d3c4190c 100644 (file)
@@ -901,14 +901,6 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd chown chmod lchmod mknod mkfifo \
     extattr_get_link sigaction sigprocmask setattrlist getgrouplist \
     initgroups utimensat posix_fallocate attropen setvbuf nanosleep usleep)
 
-case "$host_os" in
-*linux*) # Work around a glibc bug. TODO eventually remove this?
-    ac_cv_func_lchmod=no
-    grep -v HAVE_LCHMOD confdefs.h >confdefs.h.new
-    mv confdefs.h.new confdefs.h
-    ;;
-esac
-
 dnl cygwin iconv.h defines iconv_open as libiconv_open
 if test x"$ac_cv_func_iconv_open" != x"yes"; then
     AC_CHECK_FUNC(libiconv_open, [ac_cv_func_iconv_open=yes; AC_DEFINE(HAVE_ICONV_OPEN, 1)])
index b9c3b4efc49763694f49e071e20d9ae69ab884b6..11d10e4a6b7dd58b1a1cbc1f5eb632f8f702f041 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -227,27 +227,35 @@ int do_open(const char *pathname, int flags, mode_t mode)
 #ifdef HAVE_CHMOD
 int do_chmod(const char *path, mode_t mode)
 {
+       static int switch_step = 0;
        int code;
        if (dry_run) return 0;
        RETURN_ERROR_IF_RO_OR_LO;
+       switch (switch_step) {
 #ifdef HAVE_LCHMOD
-       code = lchmod(path, mode & CHMOD_BITS);
-#else
-       if (S_ISLNK(mode)) {
+#include "case_N.h"
+               if ((code = lchmod(path, mode & CHMOD_BITS)) == 0 || errno != ENOTSUP)
+                       break;
+               switch_step++;
+#endif
+
+#include "case_N.h"
+               if (S_ISLNK(mode)) {
 # if defined HAVE_SETATTRLIST
-               struct attrlist attrList;
-               uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
+                       struct attrlist attrList;
+                       uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
 
-               memset(&attrList, 0, sizeof attrList);
-               attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
-               attrList.commonattr = ATTR_CMN_ACCESSMASK;
-               code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
+                       memset(&attrList, 0, sizeof attrList);
+                       attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
+                       attrList.commonattr = ATTR_CMN_ACCESSMASK;
+                       code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
 # else
-               code = 1;
+                       code = 1;
 # endif
-       } else
-               code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
-#endif /* !HAVE_LCHMOD */
+               } else
+                       code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+               break;
+       }
        if (code != 0 && (preserve_perms || preserve_executability))
                return code;
        return 0;