diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2022-07-05 23:57:32 -0500 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2022-07-06 00:00:18 -0500 |
commit | 27436451ecbf250db4d1704c586763cb40e6dfeb (patch) | |
tree | a0713c338993726cc8bf4a8d1cef7d0336fa5065 /lib | |
parent | 2be06b13dd9582d7216c479e9874f0df6d32746b (diff) | |
download | emacs-27436451ecbf250db4d1704c586763cb40e6dfeb.tar.gz |
Update from Gnulib by running admin/merge-gnulib
* admin/merge-gnulib (AVOIDED_MODULES): Add chmod.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fchmodat.c | 59 | ||||
-rw-r--r-- | lib/filevercmp.c | 18 | ||||
-rw-r--r-- | lib/filevercmp.h | 4 | ||||
-rw-r--r-- | lib/gnulib.mk.in | 6 | ||||
-rw-r--r-- | lib/lchmod.c | 84 | ||||
-rw-r--r-- | lib/mini-gmp.h | 2 | ||||
-rw-r--r-- | lib/str-two-way.h | 4 | ||||
-rw-r--r-- | lib/string.in.h | 16 | ||||
-rw-r--r-- | lib/sys_stat.in.h | 28 |
9 files changed, 116 insertions, 105 deletions
diff --git a/lib/fchmodat.c b/lib/fchmodat.c index dc535833660..164e2c4a95f 100644 --- a/lib/fchmodat.c +++ b/lib/fchmodat.c @@ -83,9 +83,10 @@ fchmodat (int dir, char const *file, mode_t mode, int flags) # if NEED_FCHMODAT_NONSYMLINK_FIX if (flags == AT_SYMLINK_NOFOLLOW) { - struct stat st; +# if HAVE_READLINKAT + char readlink_buf[1]; -# if defined O_PATH && defined AT_EMPTY_PATH +# ifdef O_PATH /* Open a file descriptor with O_NOFOLLOW, to make sure we don't follow symbolic links, if /proc is mounted. O_PATH is used to avoid a failure if the file is not readable. @@ -94,49 +95,29 @@ fchmodat (int dir, char const *file, mode_t mode, int flags) if (fd < 0) return fd; - /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the - chmod call below will change the permissions of the symbolic link - - which is undesired - and on many file systems (ext4, btrfs, jfs, - xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is - misleading. Therefore test for a symbolic link explicitly. - Use fstatat because fstat does not work on O_PATH descriptors - before Linux 3.6. */ - if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0) + int err; + if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) + err = EOPNOTSUPP; + else if (errno == EINVAL) { - int stat_errno = errno; - close (fd); - errno = stat_errno; - return -1; - } - if (S_ISLNK (st.st_mode)) - { - close (fd); - errno = EOPNOTSUPP; - return -1; + static char const fmt[] = "/proc/self/fd/%d"; + char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; + sprintf (buf, fmt, fd); + err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; } + else + err = errno == ENOENT ? -1 : errno; -# if defined __linux__ || defined __ANDROID__ || defined __CYGWIN__ - static char const fmt[] = "/proc/self/fd/%d"; - char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; - sprintf (buf, fmt, fd); - int chmod_result = chmod (buf, mode); - int chmod_errno = errno; close (fd); - if (chmod_result == 0) - return chmod_result; - if (chmod_errno != ENOENT) - { - errno = chmod_errno; - return chmod_result; - } + + errno = err; + if (0 <= err) + return err == 0 ? 0 : -1; # endif - /* /proc is not mounted or would not work as in GNU/Linux. */ -# else - int fstatat_result = fstatat (dir, file, &st, AT_SYMLINK_NOFOLLOW); - if (fstatat_result != 0) - return fstatat_result; - if (S_ISLNK (st.st_mode)) + /* O_PATH + /proc is not supported. */ + + if (0 <= readlinkat (dir, file, readlink_buf, sizeof readlink_buf)) { errno = EOPNOTSUPP; return -1; diff --git a/lib/filevercmp.c b/lib/filevercmp.c index d546e790548..7e54793e613 100644 --- a/lib/filevercmp.c +++ b/lib/filevercmp.c @@ -29,6 +29,8 @@ /* Return the length of a prefix of S that corresponds to the suffix defined by this extended regular expression in the C locale: (\.[A-Za-z~][A-Za-z0-9~]*)*$ + Use the longest suffix matching this regular expression, + except do not use all of S as a suffix if S is nonempty. If *LEN is -1, S is a string; set *LEN to S's length. Otherwise, *LEN should be nonnegative, S is a char array, and *LEN does not change. */ @@ -36,20 +38,22 @@ static idx_t file_prefixlen (char const *s, ptrdiff_t *len) { size_t n = *len; /* SIZE_MAX if N == -1. */ + idx_t prefixlen = 0; - for (idx_t i = 0; ; i++) + for (idx_t i = 0; ; ) { - idx_t prefixlen = i; - while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1]) - || s[i + 1] == '~')) - for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++) - continue; - if (*len < 0 ? !s[i] : i == n) { *len = i; return prefixlen; } + + i++; + prefixlen = i; + while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1]) + || s[i + 1] == '~')) + for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++) + continue; } } diff --git a/lib/filevercmp.h b/lib/filevercmp.h index 5a336776719..57949760b25 100644 --- a/lib/filevercmp.h +++ b/lib/filevercmp.h @@ -61,7 +61,9 @@ without them, using version sort without special priority; if they do not compare equal, this comparison result is used and the suffixes are effectively ignored. Otherwise, the entire - strings are compared using version sort. + strings are compared using version sort. When removing a suffix + from a nonempty string, remove the maximal-length suffix such that + the remaining string is nonempty. This function is intended to be a replacement for strverscmp. */ int filevercmp (char const *a, char const *b) _GL_ATTRIBUTE_PURE; diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index bf0df878a5b..2ffe89d4239 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -35,6 +35,7 @@ # --macro-prefix=gl \ # --no-vc-files \ # --avoid=btowc \ +# --avoid=chmod \ # --avoid=close \ # --avoid=crypto/af_alg \ # --avoid=dup \ @@ -327,6 +328,7 @@ GL_GNULIB_CALLOC_GNU = @GL_GNULIB_CALLOC_GNU@ GL_GNULIB_CALLOC_POSIX = @GL_GNULIB_CALLOC_POSIX@ GL_GNULIB_CANONICALIZE_FILE_NAME = @GL_GNULIB_CANONICALIZE_FILE_NAME@ GL_GNULIB_CHDIR = @GL_GNULIB_CHDIR@ +GL_GNULIB_CHMOD = @GL_GNULIB_CHMOD@ GL_GNULIB_CHOWN = @GL_GNULIB_CHOWN@ GL_GNULIB_CLOSE = @GL_GNULIB_CLOSE@ GL_GNULIB_CLOSEDIR = @GL_GNULIB_CLOSEDIR@ @@ -1029,6 +1031,7 @@ REPLACE_ALIGNED_ALLOC = @REPLACE_ALIGNED_ALLOC@ REPLACE_CALLOC_FOR_CALLOC_GNU = @REPLACE_CALLOC_FOR_CALLOC_GNU@ REPLACE_CALLOC_FOR_CALLOC_POSIX = @REPLACE_CALLOC_FOR_CALLOC_POSIX@ REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CHMOD = @REPLACE_CHMOD@ REPLACE_CHOWN = @REPLACE_CHOWN@ REPLACE_CLOSE = @REPLACE_CLOSE@ REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@ @@ -1196,6 +1199,7 @@ SETTINGS_LIBS = @SETTINGS_LIBS@ SHELL = @SHELL@ SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +SMALL_JA_DIC = @SMALL_JA_DIC@ SQLITE3_LIBS = @SQLITE3_LIBS@ STDALIGN_H = @STDALIGN_H@ STDDEF_H = @STDDEF_H@ @@ -3497,6 +3501,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \ -e 's|@''WINDOWS_STAT_TIMESPEC''@|$(WINDOWS_STAT_TIMESPEC)|g' \ + -e 's/@''GNULIB_CHMOD''@/$(GL_GNULIB_CHMOD)/g' \ -e 's/@''GNULIB_FCHMODAT''@/$(GL_GNULIB_FCHMODAT)/g' \ -e 's/@''GNULIB_FSTAT''@/$(GL_GNULIB_FSTAT)/g' \ -e 's/@''GNULIB_FSTATAT''@/$(GL_GNULIB_FSTATAT)/g' \ @@ -3528,6 +3533,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \ -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \ -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \ + -e 's|@''REPLACE_CHMOD''@|$(REPLACE_CHMOD)|g' \ -e 's|@''REPLACE_FCHMODAT''@|$(REPLACE_FCHMODAT)|g' \ -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \ -e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \ diff --git a/lib/lchmod.c b/lib/lchmod.c index 706dddff7bb..8410a2d835f 100644 --- a/lib/lchmod.c +++ b/lib/lchmod.c @@ -25,17 +25,9 @@ #include <errno.h> #include <fcntl.h> #include <stdio.h> +#include <string.h> #include <unistd.h> -#ifdef __osf__ -/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc - eliminates this include because of the preliminary #include <sys/stat.h> - above. */ -# include "sys/stat.h" -#else -# include <sys/stat.h> -#endif - #include <intprops.h> /* Work like chmod, except when FILE is a symbolic link. @@ -45,7 +37,9 @@ int lchmod (char const *file, mode_t mode) { -#if defined O_PATH && defined AT_EMPTY_PATH + char readlink_buf[1]; + +#ifdef O_PATH /* Open a file descriptor with O_NOFOLLOW, to make sure we don't follow symbolic links, if /proc is mounted. O_PATH is used to avoid a failure if the file is not readable. @@ -54,56 +48,46 @@ lchmod (char const *file, mode_t mode) if (fd < 0) return fd; - /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the - chmod call below will change the permissions of the symbolic link - - which is undesired - and on many file systems (ext4, btrfs, jfs, - xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is - misleading. Therefore test for a symbolic link explicitly. - Use fstatat because fstat does not work on O_PATH descriptors - before Linux 3.6. */ - struct stat st; - if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0) + int err; + if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) + err = EOPNOTSUPP; + else if (errno == EINVAL) { - int stat_errno = errno; - close (fd); - errno = stat_errno; - return -1; - } - if (S_ISLNK (st.st_mode)) - { - close (fd); - errno = EOPNOTSUPP; - return -1; + static char const fmt[] = "/proc/self/fd/%d"; + char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; + sprintf (buf, fmt, fd); + err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; } + else + err = errno == ENOENT ? -1 : errno; -# if defined __linux__ || defined __ANDROID__ || defined __CYGWIN__ - static char const fmt[] = "/proc/self/fd/%d"; - char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; - sprintf (buf, fmt, fd); - int chmod_result = chmod (buf, mode); - int chmod_errno = errno; close (fd); - if (chmod_result == 0) - return chmod_result; - if (chmod_errno != ENOENT) + + errno = err; + if (0 <= err) + return err == 0 ? 0 : -1; +#endif + + size_t len = strlen (file); + if (len && file[len - 1] == '/') { - errno = chmod_errno; - return chmod_result; + struct stat st; + if (lstat (file, &st) < 0) + return -1; + if (!S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return -1; + } } -# endif - /* /proc is not mounted or would not work as in GNU/Linux. */ - -#elif HAVE_LSTAT - struct stat st; - int lstat_result = lstat (file, &st); - if (lstat_result != 0) - return lstat_result; - if (S_ISLNK (st.st_mode)) + + /* O_PATH + /proc is not supported. */ + + if (0 <= readlink (file, readlink_buf, sizeof readlink_buf)) { errno = EOPNOTSUPP; return -1; } -#endif /* Fall back on chmod, despite a possible race. */ return chmod (file, mode); diff --git a/lib/mini-gmp.h b/lib/mini-gmp.h index 508712d235b..59c24cf5111 100644 --- a/lib/mini-gmp.h +++ b/lib/mini-gmp.h @@ -8,7 +8,7 @@ The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of either: * the GNU Lesser General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your + Software Foundation; either version 3 of the License, or (at your option) any later version. or diff --git a/lib/str-two-way.h b/lib/str-two-way.h index 7ee344aea14..b00017c0b4b 100644 --- a/lib/str-two-way.h +++ b/lib/str-two-way.h @@ -231,7 +231,7 @@ critical_factorization (const unsigned char *needle, size_t needle_len, most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */ -static RETURN_TYPE +static RETURN_TYPE _GL_ATTRIBUTE_PURE two_way_short_needle (const unsigned char *haystack, size_t haystack_len, const unsigned char *needle, size_t needle_len) { @@ -325,7 +325,7 @@ two_way_short_needle (const unsigned char *haystack, size_t haystack_len, If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and sublinear performance is not possible. */ -static RETURN_TYPE +static RETURN_TYPE _GL_ATTRIBUTE_PURE two_way_long_needle (const unsigned char *haystack, size_t haystack_len, const unsigned char *needle, size_t needle_len) { diff --git a/lib/string.in.h b/lib/string.in.h index 33160b25254..3996da9fcb5 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -122,8 +122,12 @@ _GL_EXTERN_C void rpl_free (void *); # undef _GL_ATTRIBUTE_DEALLOC_FREE # define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (rpl_free, 1) # else -# if defined _MSC_VER -_GL_EXTERN_C void __cdecl free (void *); +# if defined _MSC_VER && !defined free +_GL_EXTERN_C +# if defined _DLL + __declspec (dllimport) +# endif + void __cdecl free (void *); # else # if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) _GL_EXTERN_C void free (void *) throw (); @@ -133,8 +137,12 @@ _GL_EXTERN_C void free (void *); # endif # endif #else -# if defined _MSC_VER -_GL_EXTERN_C void __cdecl free (void *); +# if defined _MSC_VER && !defined free +_GL_EXTERN_C +# if defined _DLL + __declspec (dllimport) +# endif + void __cdecl free (void *); # else # if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) _GL_EXTERN_C void free (void *) throw (); diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h index 28ddd42f818..714c3cb189e 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -391,7 +391,33 @@ struct stat #endif -#if @GNULIB_MDA_CHMOD@ +#if @GNULIB_CHMOD@ +# if @REPLACE_CHMOD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chmod +# define chmod rpl_chmod +# endif +_GL_FUNCDECL_RPL (chmod, int, (const char *filename, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (chmod, int, (const char *filename, mode_t mode)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chmod +# define chmod _chmod +# endif +/* Need to cast, because in mingw the last argument is 'int mode'. */ +_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode)); +# else +_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode)); +# endif +_GL_CXXALIASWARN (chmod); +#elif defined GNULIB_POSIXCHECK +# undef chmod +# if HAVE_RAW_DECL_CHMOD +_GL_WARN_ON_USE (chmod, "chmod has portability problems - " + "use gnulib module chmod for portability"); +# endif +#elif @GNULIB_MDA_CHMOD@ /* On native Windows, map 'chmod' to '_chmod', so that -loldnames is not required. In C++ with GNULIB_NAMESPACE, avoid differences between platforms by defining GNULIB_NAMESPACE::chmod always. */ |