aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPaul Eggert2025-06-27 22:32:33 -0700
committerPaul Eggert2025-06-27 23:06:40 -0700
commitdbdf761187d7cccfad20a2899bab3dc77f379c3a (patch)
treed4e160b187f6f56e27dad185dfdd4cb955c4ec80 /lib
parent68100ca656ad76e937622a1a74b6ca185bc82e07 (diff)
downloademacs-dbdf761187d7cccfad20a2899bab3dc77f379c3a.tar.gz
emacs-dbdf761187d7cccfad20a2899bab3dc77f379c3a.zip
Update from Gnulib by running admin/merge-gnulib
Diffstat (limited to 'lib')
-rw-r--r--lib/_Noreturn.h38
-rw-r--r--lib/acl.h2
-rw-r--r--lib/attribute.h5
-rw-r--r--lib/boot-time.h13
-rw-r--r--lib/fcntl.in.h6
-rw-r--r--lib/file-has-acl.c173
-rw-r--r--lib/gettext.h67
-rw-r--r--lib/gnulib.mk.in18
-rw-r--r--lib/open.c115
-rw-r--r--lib/qcopy-acl.c29
-rw-r--r--lib/regcomp.c53
-rw-r--r--lib/regexec.c2
-rw-r--r--lib/stat-time.h43
-rw-r--r--lib/stdckdint.in.h39
-rw-r--r--lib/stddef.in.h61
-rw-r--r--lib/string.in.h27
-rw-r--r--lib/sys_stat.in.h6
-rw-r--r--lib/unistd.in.h18
18 files changed, 503 insertions, 212 deletions
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index 0d452649fb2..8e63387914c 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -14,33 +14,25 @@
14 You should have received a copy of the GNU Lesser General Public License 14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
16 16
17/* The _Noreturn keyword of C11.
18 Do not use [[noreturn]], because with it the syntax
19 extern _Noreturn void func (...);
20 would not be valid; such a declaration would be valid only with 'extern'
21 and '_Noreturn' swapped, or without the 'extern' keyword. However, some
22 AIX system header files and several gnulib header files use precisely
23 this syntax with 'extern'. So even though C23 deprecates _Noreturn,
24 it is currently more portable to prefer it to [[noreturn]].
25
26 Also, do not try to work around LLVM bug 59792 (clang 15 or earlier).
27 This rare bug can be worked around by compiling with 'clang -D_Noreturn=',
28 though the workaround may generate many false-alarm warnings. */
17#ifndef _Noreturn 29#ifndef _Noreturn
18# if (defined __cplusplus \ 30# if 201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0)
19 && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
20 || (defined _MSC_VER && 1900 <= _MSC_VER)) \
21 && 0)
22 /* [[noreturn]] is not practically usable, because with it the syntax
23 extern _Noreturn void func (...);
24 would not be valid; such a declaration would only be valid with 'extern'
25 and '_Noreturn' swapped, or without the 'extern' keyword. However, some
26 AIX system header files and several gnulib header files use precisely
27 this syntax with 'extern'. */
28# define _Noreturn [[noreturn]]
29# elif (defined __clang__ && __clang_major__ < 16 \
30 && defined _GL_WORK_AROUND_LLVM_BUG_59792)
31 /* Compile with -D_GL_WORK_AROUND_LLVM_BUG_59792 to work around
32 that rare LLVM bug, though you may get many false-alarm warnings. */
33# define _Noreturn
34# elif ((!defined __cplusplus || defined __clang__) \
35 && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
36 || (!defined __STRICT_ANSI__ \
37 && (4 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __clang__ \
38 || (defined __apple_build_version__ \
39 ? 6000000 <= __apple_build_version__ \
40 : 3 < __clang_major__ + (5 <= __clang_minor__))))))
41 /* _Noreturn works as-is. */ 31 /* _Noreturn works as-is. */
42# elif (2 < __GNUC__ + (8 <= __GNUC_MINOR__) || defined __clang__ \ 32# elif (2 < __GNUC__ + (8 <= __GNUC_MINOR__) || defined __clang__ \
43 || 0x5110 <= __SUNPRO_C) 33 || 0x5110 <= __SUNPRO_C)
34 /* Prefer __attribute__ ((__noreturn__)) to plain _Noreturn even if the
35 latter works, as 'gcc -std=gnu99 -Wpedantic' warns about _Noreturn. */
44# define _Noreturn __attribute__ ((__noreturn__)) 36# define _Noreturn __attribute__ ((__noreturn__))
45# elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0) 37# elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0)
46# define _Noreturn __declspec (noreturn) 38# define _Noreturn __declspec (noreturn)
diff --git a/lib/acl.h b/lib/acl.h
index 90fd24e152d..e3c134fb41c 100644
--- a/lib/acl.h
+++ b/lib/acl.h
@@ -79,6 +79,8 @@ struct aclinfo
79bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST; 79bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST;
80int file_has_acl (char const *, struct stat const *); 80int file_has_acl (char const *, struct stat const *);
81int file_has_aclinfo (char const *restrict, struct aclinfo *restrict, int); 81int file_has_aclinfo (char const *restrict, struct aclinfo *restrict, int);
82int fdfile_has_aclinfo (int, char const *restrict,
83 struct aclinfo *restrict, int);
82 84
83#if HAVE_LINUX_XATTR_H && HAVE_LISTXATTR 85#if HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
84bool aclinfo_has_xattr (struct aclinfo const *, char const *) 86bool aclinfo_has_xattr (struct aclinfo const *, char const *)
diff --git a/lib/attribute.h b/lib/attribute.h
index ae7bbe8e2cb..c85412d90af 100644
--- a/lib/attribute.h
+++ b/lib/attribute.h
@@ -50,8 +50,9 @@
50 - In a function declaration/definition with a storage-class 50 - In a function declaration/definition with a storage-class
51 specifier: between the storage-class specifier and the return 51 specifier: between the storage-class specifier and the return
52 type. 52 type.
53 - Or after the parameter list, 53 - Or, in a function declaration:
54 ∙ but after ATTRIBUTE_NOTHROW if present. 54 after the parameter list,
55 ∙ but after ATTRIBUTE_NOTHROW if present.
55 56
56 In other declarations, such as variable declarations: 57 In other declarations, such as variable declarations:
57 58
diff --git a/lib/boot-time.h b/lib/boot-time.h
index 195839a2c53..7abfa12e444 100644
--- a/lib/boot-time.h
+++ b/lib/boot-time.h
@@ -29,11 +29,16 @@ extern "C" {
29/* Store the approximate time when the machine last booted in *P_BOOT_TIME, 29/* Store the approximate time when the machine last booted in *P_BOOT_TIME,
30 and return 0. If it cannot be determined, return -1. 30 and return 0. If it cannot be determined, return -1.
31 31
32 If the machine is a container inside another host machine,
33 return the boot time of the container, not the host.
34 The difference can matter in GNU/Linux, where times in /proc/stat
35 might be relative to boot time of the host, not the container.
36
32 This function is not multithread-safe, since on many platforms it 37 This function is not multithread-safe, since on many platforms it
33 invokes the functions setutxent, getutxent, endutxent. These 38 invokes the functions setutxent, getutxent, endutxent.
34 functions are needed because they may lock FILE (so that we don't 39 These functions may lock a file like /var/log/wtmp (so that we
35 read garbage when a concurrent process writes to FILE), but their 40 don't read garbage when a concurrent process writes to that file),
36 drawback is that they have a common global state. */ 41 but their drawback is that they have a common global state. */
37extern int get_boot_time (struct timespec *p_boot_time); 42extern int get_boot_time (struct timespec *p_boot_time);
38 43
39 44
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index d7f551b30f3..c5068ed48a0 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -209,7 +209,9 @@ _GL_WARN_ON_USE (open, "open is not always POSIX compliant - "
209# undef open 209# undef open
210# define open _open 210# define open _open
211# endif 211# endif
212_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...)); 212/* Need to cast, because in MSVC the parameter list of _open as a C++ function
213 is (const char *, int, int = 0). */
214_GL_CXXALIAS_MDA_CAST (open, int, (const char *filename, int flags, ...));
213# else 215# else
214_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); 216_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
215# endif 217# endif
@@ -313,7 +315,7 @@ _GL_WARN_ON_USE (openat, "openat is not portable - "
313#endif 315#endif
314 316
315#ifndef O_DIRECTORY 317#ifndef O_DIRECTORY
316# define O_DIRECTORY 0 318# define O_DIRECTORY 0x20000000 /* Try to not collide with system O_* flags. */
317#endif 319#endif
318 320
319#ifndef O_DSYNC 321#ifndef O_DSYNC
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index 66b920c1ab2..a9cfbf3a16e 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -85,6 +85,13 @@ smack_new_label_from_path (MAYBE_UNUSED const char *path,
85{ 85{
86 return -1; 86 return -1;
87} 87}
88static ssize_t
89smack_new_label_from_file (MAYBE_UNUSED int fd,
90 MAYBE_UNUSED const char *xattr,
91 MAYBE_UNUSED char **label)
92{
93 return -1;
94}
88# endif 95# endif
89static bool 96static bool
90is_smack_enabled (void) 97is_smack_enabled (void)
@@ -115,14 +122,16 @@ aclinfo_may_indicate_xattr (struct aclinfo const *ai)
115 122
116static bool 123static bool
117has_xattr (char const *xattr, struct aclinfo const *ai, 124has_xattr (char const *xattr, struct aclinfo const *ai,
118 MAYBE_UNUSED char const *restrict name, MAYBE_UNUSED int flags) 125 int fd, char const *restrict name, int flags)
119{ 126{
120 if (ai && aclinfo_has_xattr (ai, xattr)) 127 if (ai && aclinfo_has_xattr (ai, xattr))
121 return true; 128 return true;
122 else if (!ai || aclinfo_may_indicate_xattr (ai)) 129 else if (!ai || aclinfo_may_indicate_xattr (ai))
123 { 130 {
124 int ret = ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr) 131 int ret = (fd < 0
125 (name, xattr, NULL, 0)); 132 ? ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr)
133 (name, xattr, NULL, 0))
134 : fgetxattr (fd, xattr, NULL, 0));
126 if (0 <= ret || (errno == ERANGE || errno == E2BIG)) 135 if (0 <= ret || (errno == ERANGE || errno == E2BIG))
127 return true; 136 return true;
128 } 137 }
@@ -145,11 +154,12 @@ aclinfo_has_xattr (struct aclinfo const *ai, char const *xattr)
145 return false; 154 return false;
146} 155}
147 156
148/* Get attributes of the file NAME into AI, if USE_ACL. 157/* Get attributes of the file FD aka NAME into AI, if USE_ACL.
158 Ignore FD if it is negative.
149 If FLAGS & ACL_GET_SCONTEXT, also get security context. 159 If FLAGS & ACL_GET_SCONTEXT, also get security context.
150 If FLAGS & ACL_SYMLINK_FOLLOW, follow symbolic links. */ 160 If FLAGS & ACL_SYMLINK_FOLLOW, follow symbolic links. */
151static void 161static void
152get_aclinfo (char const *name, struct aclinfo *ai, int flags) 162get_aclinfo (int fd, char const *name, struct aclinfo *ai, int flags)
153{ 163{
154 int scontext_err = ENOTSUP; 164 int scontext_err = ENOTSUP;
155 ai->buf = ai->u.__gl_acl_ch; 165 ai->buf = ai->u.__gl_acl_ch;
@@ -163,7 +173,9 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags)
163 = (flags & ACL_SYMLINK_FOLLOW ? listxattr : llistxattr); 173 = (flags & ACL_SYMLINK_FOLLOW ? listxattr : llistxattr);
164 while (true) 174 while (true)
165 { 175 {
166 ai->size = lsxattr (name, ai->buf, acl_alloc); 176 ai->size = (fd < 0
177 ? lsxattr (name, ai->buf, acl_alloc)
178 : flistxattr (fd, ai->buf, acl_alloc));
167 if (0 < ai->size) 179 if (0 < ai->size)
168 break; 180 break;
169 ai->u.err = ai->size < 0 ? errno : 0; 181 ai->u.err = ai->size < 0 ? errno : 0;
@@ -171,7 +183,9 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags)
171 break; 183 break;
172 184
173 /* The buffer was too small. Find how large it should have been. */ 185 /* The buffer was too small. Find how large it should have been. */
174 ssize_t size = lsxattr (name, NULL, 0); 186 ssize_t size = (fd < 0
187 ? lsxattr (name, NULL, 0)
188 : flistxattr (fd, NULL, 0));
175 if (size <= 0) 189 if (size <= 0)
176 { 190 {
177 ai->size = size; 191 ai->size = size;
@@ -214,9 +228,13 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags)
214 { 228 {
215 if (ai->size < 0 || aclinfo_has_xattr (ai, XATTR_NAME_SMACK)) 229 if (ai->size < 0 || aclinfo_has_xattr (ai, XATTR_NAME_SMACK))
216 { 230 {
217 ssize_t r = smack_new_label_from_path (name, "security.SMACK64", 231 static char const SMACK64[] = "security.SMACK64";
218 flags & ACL_SYMLINK_FOLLOW, 232 ssize_t r =
219 &ai->scontext); 233 (fd < 0
234 ? smack_new_label_from_path (name, SMACK64,
235 flags & ACL_SYMLINK_FOLLOW,
236 &ai->scontext)
237 : smack_new_label_from_file (fd, SMACK64, &ai->scontext));
220 scontext_err = r < 0 ? errno : 0; 238 scontext_err = r < 0 ? errno : 0;
221 } 239 }
222 } 240 }
@@ -226,8 +244,10 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags)
226 if (ai->size < 0 || aclinfo_has_xattr (ai, XATTR_NAME_SELINUX)) 244 if (ai->size < 0 || aclinfo_has_xattr (ai, XATTR_NAME_SELINUX))
227 { 245 {
228 ssize_t r = 246 ssize_t r =
229 ((flags & ACL_SYMLINK_FOLLOW ? getfilecon : lgetfilecon) 247 (fd < 0
230 (name, &ai->scontext)); 248 ? ((flags & ACL_SYMLINK_FOLLOW ? getfilecon : lgetfilecon)
249 (name, &ai->scontext))
250 : fgetfilecon (fd, &ai->scontext));
231 scontext_err = r < 0 ? errno : 0; 251 scontext_err = r < 0 ? errno : 0;
232# ifndef SE_SELINUX_INLINE 252# ifndef SE_SELINUX_INLINE
233 /* Gnulib's selinux-h module is not in use, so getfilecon and 253 /* Gnulib's selinux-h module is not in use, so getfilecon and
@@ -362,11 +382,14 @@ acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes)
362} 382}
363#endif 383#endif
364 384
365#if (!USE_LINUX_XATTR && USE_ACL && HAVE_ACL_GET_FD \ 385#if (!USE_LINUX_XATTR && USE_ACL && HAVE_ACL_GET_FILE \
366 && !HAVE_ACL_EXTENDED_FILE && !HAVE_ACL_TYPE_EXTENDED \ 386 && !HAVE_ACL_EXTENDED_FILE && !HAVE_ACL_TYPE_EXTENDED)
367 && !HAVE_ACL_GET_LINK_NP) 387/* FreeBSD, NetBSD >= 10, IRIX, Tru64, Cygwin >= 2.5 */
368# include <fcntl.h> 388
369# ifdef O_PATH 389# if HAVE_ACL_GET_FD && !HAVE_ACL_GET_LINK_NP /* IRIX, Tru64, Cygwin >= 2.5 */
390# include <fcntl.h>
391# ifdef O_PATH
392# define acl_get_fd_np(fd, type) acl_get_fd (fd)
370 393
371/* Like acl_get_file, but do not follow symbolic links. */ 394/* Like acl_get_file, but do not follow symbolic links. */
372static acl_t 395static acl_t
@@ -381,8 +404,24 @@ acl_get_link_np (char const *name, acl_type_t type)
381 errno = err; 404 errno = err;
382 return r; 405 return r;
383} 406}
384# define HAVE_ACL_GET_LINK_NP 1 407# define HAVE_ACL_GET_LINK_NP 1
408# endif
385# endif 409# endif
410
411static acl_t
412acl_get_fdfile (int fd, char const *name, acl_type_t type, int flags)
413{
414 acl_t (*get) (char const *, acl_type_t) = acl_get_file;
415# if HAVE_ACL_GET_LINK_NP /* FreeBSD, NetBSD >= 10, Cygwin >= 2.5 */
416 if (0 <= fd)
417 return acl_get_fd_np (fd, type);
418 if (! (flags & ACL_SYMLINK_FOLLOW))
419 get = acl_get_link_np;
420# else
421 /* Ignore FD and FLAGS, unfortunately. */
422# endif
423 return get (name, type);
424}
386#endif 425#endif
387 426
388/* Return 1 if NAME has a nontrivial access control list, 427/* Return 1 if NAME has a nontrivial access control list,
@@ -398,14 +437,35 @@ acl_get_link_np (char const *name, acl_type_t type)
398 If the d_type value is not known, use DT_UNKNOWN though this may be less 437 If the d_type value is not known, use DT_UNKNOWN though this may be less
399 efficient. */ 438 efficient. */
400int 439int
401file_has_aclinfo (MAYBE_UNUSED char const *restrict name, 440file_has_aclinfo (char const *restrict name,
402 struct aclinfo *restrict ai, int flags) 441 struct aclinfo *restrict ai, int flags)
403{ 442{
443 return fdfile_has_aclinfo (-1, name, ai, flags);
444}
445
446/* Return 1 if FD aka NAME has a nontrivial access control list,
447 0 if ACLs are not supported, or if NAME has no or only a base ACL,
448 and -1 (setting errno) on error. Note callers can determine
449 if ACLs are not supported as errno is set in that case also.
450 Ignore FD if it is negative.
451 Set *AI to ACL info regardless of return value.
452 FLAGS should be a <dirent.h> d_type value, optionally ORed with
453 - _GL_DT_NOTDIR if it is known that NAME is not a directory,
454 - ACL_GET_SCONTEXT to retrieve security context and return 1 if present,
455 - ACL_SYMLINK_FOLLOW to follow the link if NAME is a symbolic link;
456 otherwise do not follow them if possible.
457 If the d_type value is not known, use DT_UNKNOWN though this may be less
458 efficient. */
459int
460fdfile_has_aclinfo (MAYBE_UNUSED int fd,
461 MAYBE_UNUSED char const *restrict name,
462 struct aclinfo *restrict ai, int flags)
463{
404 MAYBE_UNUSED unsigned char d_type = flags & UCHAR_MAX; 464 MAYBE_UNUSED unsigned char d_type = flags & UCHAR_MAX;
405 465
406#if USE_LINUX_XATTR 466#if USE_LINUX_XATTR
407 int initial_errno = errno; 467 int initial_errno = errno;
408 get_aclinfo (name, ai, flags); 468 get_aclinfo (fd, name, ai, flags);
409 469
410 if (!aclinfo_may_indicate_xattr (ai) && ai->size <= 0) 470 if (!aclinfo_may_indicate_xattr (ai) && ai->size <= 0)
411 { 471 {
@@ -418,11 +478,11 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
418 In earlier Fedora the two types of ACLs were mutually exclusive. 478 In earlier Fedora the two types of ACLs were mutually exclusive.
419 Attempt to work correctly on both kinds of systems. */ 479 Attempt to work correctly on both kinds of systems. */
420 480
421 if (!has_xattr (XATTR_NAME_NFSV4_ACL, ai, name, flags)) 481 if (!has_xattr (XATTR_NAME_NFSV4_ACL, ai, fd, name, flags))
422 return 482 return
423 (has_xattr (XATTR_NAME_POSIX_ACL_ACCESS, ai, name, flags) 483 (has_xattr (XATTR_NAME_POSIX_ACL_ACCESS, ai, fd, name, flags)
424 || ((d_type == DT_DIR || d_type == DT_UNKNOWN) 484 || ((d_type == DT_DIR || d_type == DT_UNKNOWN)
425 && has_xattr (XATTR_NAME_POSIX_ACL_DEFAULT, ai, name, flags))); 485 && has_xattr (XATTR_NAME_POSIX_ACL_DEFAULT, ai, fd, name, flags)));
426 486
427 /* A buffer large enough to hold any trivial NFSv4 ACL. 487 /* A buffer large enough to hold any trivial NFSv4 ACL.
428 The max length of a trivial NFSv4 ACL is 6 words for owner, 488 The max length of a trivial NFSv4 ACL is 6 words for owner,
@@ -432,8 +492,10 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
432 everyone is another word to hold "EVERYONE@". */ 492 everyone is another word to hold "EVERYONE@". */
433 uint32_t buf[2 * (6 + 6 + 7)]; 493 uint32_t buf[2 * (6 + 6 + 7)];
434 494
435 int ret = ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr) 495 int ret = (fd < 0
436 (name, XATTR_NAME_NFSV4_ACL, buf, sizeof buf)); 496 ? ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr)
497 (name, XATTR_NAME_NFSV4_ACL, buf, sizeof buf))
498 : fgetxattr (fd, XATTR_NAME_NFSV4_ACL, buf, sizeof buf));
437 if (ret < 0) 499 if (ret < 0)
438 switch (errno) 500 switch (errno)
439 { 501 {
@@ -467,20 +529,23 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
467 /* On Linux, acl_extended_file is an optimized function: It only 529 /* On Linux, acl_extended_file is an optimized function: It only
468 makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for 530 makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
469 ACL_TYPE_DEFAULT. */ 531 ACL_TYPE_DEFAULT. */
470 ret = ((flags & ACL_SYMLINK_FOLLOW 532 ret = (fd < 0
471 ? acl_extended_file 533 ? ((flags & ACL_SYMLINK_FOLLOW
472 : acl_extended_file_nofollow) 534 ? acl_extended_file
473 (name)); 535 : acl_extended_file_nofollow)
536 (name))
537 : acl_extended_fd (fd));
474# elif HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ 538# elif HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
475 /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) 539 /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS)
476 and acl_get_file (name, ACL_TYPE_DEFAULT) 540 and acl_get_file (name, ACL_TYPE_DEFAULT)
477 always return NULL / EINVAL. There is no point in making 541 always return NULL / EINVAL. There is no point in making
478 these two useless calls. The real ACL is retrieved through 542 these two useless calls. The real ACL is retrieved through
479 acl_get_file (name, ACL_TYPE_EXTENDED). */ 543 ACL_TYPE_EXTENDED. */
480 acl_t acl = ((flags & ACL_SYMLINK_FOLLOW 544 acl_t acl =
481 ? acl_get_file 545 (fd < 0
482 : acl_get_link_np) 546 ? ((flags & ACL_SYMLINK_FOLLOW ? acl_get_file : acl_get_link_np)
483 (name, ACL_TYPE_EXTENDED)); 547 (name, ACL_TYPE_EXTENDED))
548 : acl_get_fd_np (fd, ACL_TYPE_EXTENDED));
484 if (acl) 549 if (acl)
485 { 550 {
486 ret = acl_extended_nontrivial (acl); 551 ret = acl_extended_nontrivial (acl);
@@ -489,13 +554,8 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
489 else 554 else
490 ret = -1; 555 ret = -1;
491# else /* FreeBSD, NetBSD >= 10, IRIX, Tru64, Cygwin >= 2.5 */ 556# else /* FreeBSD, NetBSD >= 10, IRIX, Tru64, Cygwin >= 2.5 */
492 acl_t (*acl_get_file_or_link) (char const *, acl_type_t) = acl_get_file;
493# if HAVE_ACL_GET_LINK_NP /* FreeBSD, NetBSD >= 10, Cygwin >= 2.5 */
494 if (! (flags & ACL_SYMLINK_FOLLOW))
495 acl_get_file_or_link = acl_get_link_np;
496# endif
497 557
498 acl_t acl = acl_get_file_or_link (name, ACL_TYPE_ACCESS); 558 acl_t acl = acl_get_fdfile (fd, name, ACL_TYPE_ACCESS, flags);
499 if (acl) 559 if (acl)
500 { 560 {
501 ret = acl_access_nontrivial (acl); 561 ret = acl_access_nontrivial (acl);
@@ -517,7 +577,7 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
517 && (d_type == DT_DIR 577 && (d_type == DT_DIR
518 || (d_type == DT_UNKNOWN && !(flags & _GL_DT_NOTDIR)))) 578 || (d_type == DT_UNKNOWN && !(flags & _GL_DT_NOTDIR))))
519 { 579 {
520 acl = acl_get_file_or_link (name, ACL_TYPE_DEFAULT); 580 acl = acl_get_fdfile (fd, name, ACL_TYPE_DEFAULT, flags);
521 if (acl) 581 if (acl)
522 { 582 {
523# ifdef __CYGWIN__ /* Cygwin >= 2.5 */ 583# ifdef __CYGWIN__ /* Cygwin >= 2.5 */
@@ -562,7 +622,10 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
562 622
563 /* Solaris 10 (newer version), which has additional API declared in 623 /* Solaris 10 (newer version), which has additional API declared in
564 <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial, 624 <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
565 acl_fromtext, ...). */ 625 acl_fromtext, ...).
626
627 Ignore FD, unfortunately. That is better than mishandling
628 ZFS-style ACLs, as the general case code does. */
566 return acl_trivial (name); 629 return acl_trivial (name);
567 630
568# else /* Solaris, Cygwin, general case */ 631# else /* Solaris, Cygwin, general case */
@@ -586,7 +649,9 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
586 649
587 for (;;) 650 for (;;)
588 { 651 {
589 count = acl (name, GETACL, alloc, entries); 652 count = (fd < 0
653 ? acl (name, GETACL, alloc, entries)
654 : facl (fd, GETACL, alloc, entries));
590 if (count < 0 && errno == ENOSPC) 655 if (count < 0 && errno == ENOSPC)
591 { 656 {
592 /* Increase the size of the buffer. */ 657 /* Increase the size of the buffer. */
@@ -657,7 +722,9 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
657 722
658 for (;;) 723 for (;;)
659 { 724 {
660 count = acl (name, ACE_GETACL, alloc, entries); 725 count = (fd < 0
726 ? acl (name, ACE_GETACL, alloc, entries)
727 : facl (fd, ACE_GETACL, alloc, entries));
661 if (count < 0 && errno == ENOSPC) 728 if (count < 0 && errno == ENOSPC)
662 { 729 {
663 /* Increase the size of the buffer. */ 730 /* Increase the size of the buffer. */
@@ -722,7 +789,9 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
722 struct acl_entry entries[NACLENTRIES]; 789 struct acl_entry entries[NACLENTRIES];
723 int count; 790 int count;
724 791
725 count = getacl (name, NACLENTRIES, entries); 792 count = (fd < 0
793 ? getacl (name, NACLENTRIES, entries)
794 : fgetacl (fd, NACLENTRIES, entries));
726 795
727 if (count < 0) 796 if (count < 0)
728 { 797 {
@@ -751,7 +820,8 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
751 { 820 {
752 struct stat statbuf; 821 struct stat statbuf;
753 822
754 if (stat (name, &statbuf) == -1 && errno != EOVERFLOW) 823 if ((fd < 0 ? stat (name, &statbuf) : fstat (fd, &statbuf)) < 0
824 && errno != EOVERFLOW)
755 return -1; 825 return -1;
756 826
757 return acl_nontrivial (count, entries); 827 return acl_nontrivial (count, entries);
@@ -765,6 +835,7 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
765 struct acl entries[NACLVENTRIES]; 835 struct acl entries[NACLVENTRIES];
766 int count; 836 int count;
767 837
838 /* Ignore FD, unfortunately. */
768 count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries); 839 count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries);
769 840
770 if (count < 0) 841 if (count < 0)
@@ -809,7 +880,9 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
809 /* The docs say that type being 0 is equivalent to ACL_ANY, but it 880 /* The docs say that type being 0 is equivalent to ACL_ANY, but it
810 is not true, in AIX 5.3. */ 881 is not true, in AIX 5.3. */
811 type.u64 = ACL_ANY; 882 type.u64 = ACL_ANY;
812 if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0) 883 if (0 <= (fd < 0
884 ? aclx_get (name, 0, &type, aclbuf, &aclsize, &mode)
885 : aclx_fget (fd, 0, &type, aclbuf, &aclsize, &mode)))
813 break; 886 break;
814 if (errno == ENOSYS) 887 if (errno == ENOSYS)
815 return 0; 888 return 0;
@@ -855,7 +928,10 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
855 928
856 union { struct acl a; char room[4096]; } u; 929 union { struct acl a; char room[4096]; } u;
857 930
858 if (statacl ((char *) name, STX_NORMAL, &u.a, sizeof (u)) < 0) 931 if ((fd < 0
932 ? statacl ((char *) name, STX_NORMAL, &u.a, sizeof u)
933 : fstatacl (fd, STX_NORMAL, &u.a, sizeof u))
934 < 0)
859 return -1; 935 return -1;
860 936
861 return acl_nontrivial (&u.a); 937 return acl_nontrivial (&u.a);
@@ -866,6 +942,7 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
866 struct acl entries[NACLENTRIES]; 942 struct acl entries[NACLENTRIES];
867 int count; 943 int count;
868 944
945 /* Ignore FD, unfortunately. */
869 count = acl ((char *) name, ACL_GET, NACLENTRIES, entries); 946 count = acl ((char *) name, ACL_GET, NACLENTRIES, entries);
870 947
871 if (count < 0) 948 if (count < 0)
diff --git a/lib/gettext.h b/lib/gettext.h
index ea0c27e0002..fd6c62b7eb7 100644
--- a/lib/gettext.h
+++ b/lib/gettext.h
@@ -59,18 +59,61 @@
59# endif 59# endif
60# endif 60# endif
61 61
62/* Disabled NLS. 62/* Disabled NLS. */
63 The casts to 'const char *' serve the purpose of producing warnings 63# if defined __GNUC__ && !defined __clang__ && !defined __cplusplus
64 for invalid uses of the value returned from these functions. 64/* Use inline functions, to avoid warnings
65 On pre-ANSI systems without 'const', the config.h file is supposed to 65 warning: format not a string literal and no format arguments
66 contain "#define const". */ 66 that don't occur with enabled NLS. */
67# undef gettext 67/* The return type 'const char *' serves the purpose of producing warnings
68# define gettext(Msgid) ((const char *) (Msgid)) 68 for invalid uses of the value returned from these functions. */
69# undef dgettext 69# if __GNUC__ >= 9
70# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) 70# pragma GCC diagnostic push
71# undef dcgettext 71# pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
72# define dcgettext(Domainname, Msgid, Category) \ 72# endif
73 ((void) (Category), dgettext (Domainname, Msgid)) 73__attribute__ ((__always_inline__, __gnu_inline__)) extern inline
74# if !defined(__sun)
75const
76# endif
77char *
78gettext (const char *msgid)
79{
80 return msgid;
81}
82__attribute__ ((__always_inline__, __gnu_inline__)) extern inline
83# if !defined(__sun)
84const
85# endif
86char *
87dgettext (const char *domain, const char *msgid)
88{
89 (void) domain;
90 return msgid;
91}
92__attribute__ ((__always_inline__, __gnu_inline__)) extern inline
93# if !defined(__sun)
94const
95# endif
96char *
97dcgettext (const char *domain, const char *msgid, int category)
98{
99 (void) domain;
100 (void) category;
101 return msgid;
102}
103# if __GNUC__ >= 9
104# pragma GCC diagnostic pop
105# endif
106# else
107/* The casts to 'const char *' serve the purpose of producing warnings
108 for invalid uses of the value returned from these functions. */
109# undef gettext
110# define gettext(Msgid) ((const char *) (Msgid))
111# undef dgettext
112# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
113# undef dcgettext
114# define dcgettext(Domainname, Msgid, Category) \
115 ((void) (Category), dgettext (Domainname, Msgid))
116# endif
74# undef ngettext 117# undef ngettext
75# define ngettext(Msgid1, Msgid2, N) \ 118# define ngettext(Msgid1, Msgid2, N) \
76 ((N) == 1 \ 119 ((N) == 1 \
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index fb34cf2cc1d..bb147b69eed 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -739,6 +739,9 @@ HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@
739HAVE_CHOWN = @HAVE_CHOWN@ 739HAVE_CHOWN = @HAVE_CHOWN@
740HAVE_CLOSEDIR = @HAVE_CLOSEDIR@ 740HAVE_CLOSEDIR = @HAVE_CLOSEDIR@
741HAVE_COPY_FILE_RANGE = @HAVE_COPY_FILE_RANGE@ 741HAVE_COPY_FILE_RANGE = @HAVE_COPY_FILE_RANGE@
742HAVE_CXX_STDCKDINT_H = @HAVE_CXX_STDCKDINT_H@
743HAVE_C_STDCKDINT_H = @HAVE_C_STDCKDINT_H@
744HAVE_C_UNREACHABLE = @HAVE_C_UNREACHABLE@
742HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@ 745HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@
743HAVE_DECL_ECVT = @HAVE_DECL_ECVT@ 746HAVE_DECL_ECVT = @HAVE_DECL_ECVT@
744HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ 747HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
@@ -911,6 +914,7 @@ HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@
911HAVE_SIGSET_T = @HAVE_SIGSET_T@ 914HAVE_SIGSET_T = @HAVE_SIGSET_T@
912HAVE_SLEEP = @HAVE_SLEEP@ 915HAVE_SLEEP = @HAVE_SLEEP@
913HAVE_SPAWN_H = @HAVE_SPAWN_H@ 916HAVE_SPAWN_H = @HAVE_SPAWN_H@
917HAVE_STDCKDINT_H = @HAVE_STDCKDINT_H@
914HAVE_STDINT_H = @HAVE_STDINT_H@ 918HAVE_STDINT_H = @HAVE_STDINT_H@
915HAVE_STPCPY = @HAVE_STPCPY@ 919HAVE_STPCPY = @HAVE_STPCPY@
916HAVE_STPNCPY = @HAVE_STPNCPY@ 920HAVE_STPNCPY = @HAVE_STPNCPY@
@@ -960,6 +964,8 @@ HAVE_VASPRINTF = @HAVE_VASPRINTF@
960HAVE_VDPRINTF = @HAVE_VDPRINTF@ 964HAVE_VDPRINTF = @HAVE_VDPRINTF@
961HAVE_WCHAR_H = @HAVE_WCHAR_H@ 965HAVE_WCHAR_H = @HAVE_WCHAR_H@
962HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ 966HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@
967HAVE_WORKING_CXX_STDCKDINT_H = @HAVE_WORKING_CXX_STDCKDINT_H@
968HAVE_WORKING_C_STDCKDINT_H = @HAVE_WORKING_C_STDCKDINT_H@
963HAVE_XSERVER = @HAVE_XSERVER@ 969HAVE_XSERVER = @HAVE_XSERVER@
964HAVE__EXIT = @HAVE__EXIT@ 970HAVE__EXIT = @HAVE__EXIT@
965IEEE754_H = @IEEE754_H@ 971IEEE754_H = @IEEE754_H@
@@ -1087,6 +1093,7 @@ NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@
1087NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@ 1093NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@
1088NEXT_AS_FIRST_DIRECTIVE_LIMITS_H = @NEXT_AS_FIRST_DIRECTIVE_LIMITS_H@ 1094NEXT_AS_FIRST_DIRECTIVE_LIMITS_H = @NEXT_AS_FIRST_DIRECTIVE_LIMITS_H@
1089NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ 1095NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@
1096NEXT_AS_FIRST_DIRECTIVE_STDCKDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDCKDINT_H@
1090NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ 1097NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@
1091NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ 1098NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@
1092NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ 1099NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@
@@ -1107,6 +1114,7 @@ NEXT_GETOPT_H = @NEXT_GETOPT_H@
1107NEXT_INTTYPES_H = @NEXT_INTTYPES_H@ 1114NEXT_INTTYPES_H = @NEXT_INTTYPES_H@
1108NEXT_LIMITS_H = @NEXT_LIMITS_H@ 1115NEXT_LIMITS_H = @NEXT_LIMITS_H@
1109NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ 1116NEXT_SIGNAL_H = @NEXT_SIGNAL_H@
1117NEXT_STDCKDINT_H = @NEXT_STDCKDINT_H@
1110NEXT_STDDEF_H = @NEXT_STDDEF_H@ 1118NEXT_STDDEF_H = @NEXT_STDDEF_H@
1111NEXT_STDINT_H = @NEXT_STDINT_H@ 1119NEXT_STDINT_H = @NEXT_STDINT_H@
1112NEXT_STDIO_H = @NEXT_STDIO_H@ 1120NEXT_STDIO_H = @NEXT_STDIO_H@
@@ -3202,6 +3210,15 @@ BUILT_SOURCES += $(STDCKDINT_H)
3202ifneq (,$(GL_GENERATE_STDCKDINT_H_CONDITION)) 3210ifneq (,$(GL_GENERATE_STDCKDINT_H_CONDITION))
3203stdckdint.h: stdckdint.in.h $(top_builddir)/config.status 3211stdckdint.h: stdckdint.in.h $(top_builddir)/config.status
3204 $(gl_V_at)$(SED_HEADER_STDOUT) \ 3212 $(gl_V_at)$(SED_HEADER_STDOUT) \
3213 -e 's|@''GUARD_PREFIX''@|GL|g' \
3214 -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
3215 -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
3216 -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
3217 -e 's|@''NEXT_STDCKDINT_H''@|$(NEXT_STDCKDINT_H)|g' \
3218 -e 's|@''HAVE_C_STDCKDINT_H''@|$(HAVE_C_STDCKDINT_H)|g' \
3219 -e 's|@''HAVE_WORKING_C_STDCKDINT_H''@|$(HAVE_WORKING_C_STDCKDINT_H)|g' \
3220 -e 's|@''HAVE_CXX_STDCKDINT_H''@|$(HAVE_CXX_STDCKDINT_H)|g' \
3221 -e 's|@''HAVE_WORKING_CXX_STDCKDINT_H''@|$(HAVE_WORKING_CXX_STDCKDINT_H)|g' \
3205 $(srcdir)/stdckdint.in.h > $@-t 3222 $(srcdir)/stdckdint.in.h > $@-t
3206 $(AM_V_at)mv $@-t $@ 3223 $(AM_V_at)mv $@-t $@
3207else 3224else
@@ -3234,6 +3251,7 @@ stddef.h: stddef.in.h $(top_builddir)/config.status
3234 -e 's|@''STDDEF_NOT_IDEMPOTENT''@|$(STDDEF_NOT_IDEMPOTENT)|g' \ 3251 -e 's|@''STDDEF_NOT_IDEMPOTENT''@|$(STDDEF_NOT_IDEMPOTENT)|g' \
3235 -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \ 3252 -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \
3236 -e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \ 3253 -e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \
3254 -e 's|@''HAVE_C_UNREACHABLE''@|$(HAVE_C_UNREACHABLE)|g' \
3237 $(srcdir)/stddef.in.h > $@-t 3255 $(srcdir)/stddef.in.h > $@-t
3238 $(AM_V_at)mv $@-t $@ 3256 $(AM_V_at)mv $@-t $@
3239else 3257else
diff --git a/lib/open.c b/lib/open.c
index 7415b48f81c..8356c14f5b3 100644
--- a/lib/open.c
+++ b/lib/open.c
@@ -55,24 +55,25 @@ orig_open (const char *filename, int flags, mode_t mode)
55#include <sys/stat.h> 55#include <sys/stat.h>
56#include <unistd.h> 56#include <unistd.h>
57 57
58#ifndef OPEN_TRAILING_SLASH_BUG
59# define OPEN_TRAILING_SLASH_BUG false
60#endif
61
58#ifndef REPLACE_OPEN_DIRECTORY 62#ifndef REPLACE_OPEN_DIRECTORY
59# define REPLACE_OPEN_DIRECTORY 0 63# define REPLACE_OPEN_DIRECTORY false
60#endif 64#endif
61 65
66static int
67lstatif (char const *filename, struct stat *st, int flags)
68{
69 return flags & O_NOFOLLOW ? lstat (filename, st) : stat (filename, st);
70}
71
62int 72int
63open (const char *filename, int flags, ...) 73open (const char *filename, int flags, ...)
64{ 74{
65 /* 0 = unknown, 1 = yes, -1 = no. */ 75 mode_t mode = 0;
66#if GNULIB_defined_O_CLOEXEC
67 int have_cloexec = -1;
68#else
69 static int have_cloexec;
70#endif
71 76
72 mode_t mode;
73 int fd;
74
75 mode = 0;
76 if (flags & O_CREAT) 77 if (flags & O_CREAT)
77 { 78 {
78 va_list arg; 79 va_list arg;
@@ -99,7 +100,6 @@ open (const char *filename, int flags, ...)
99 filename = "NUL"; 100 filename = "NUL";
100#endif 101#endif
101 102
102#if OPEN_TRAILING_SLASH_BUG
103 /* Fail if one of O_CREAT, O_WRONLY, O_RDWR is specified and the filename 103 /* Fail if one of O_CREAT, O_WRONLY, O_RDWR is specified and the filename
104 ends in a slash, as POSIX says such a filename must name a directory 104 ends in a slash, as POSIX says such a filename must name a directory
105 <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>: 105 <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>:
@@ -118,21 +118,55 @@ open (const char *filename, int flags, ...)
118 directories, 118 directories,
119 - if O_WRONLY or O_RDWR is specified, open() must fail because the 119 - if O_WRONLY or O_RDWR is specified, open() must fail because the
120 file does not contain a '.' directory. */ 120 file does not contain a '.' directory. */
121 if ((flags & O_CREAT) 121 bool check_for_slash_bug;
122 || (flags & O_ACCMODE) == O_RDWR 122 if (OPEN_TRAILING_SLASH_BUG)
123 || (flags & O_ACCMODE) == O_WRONLY)
124 { 123 {
125 size_t len = strlen (filename); 124 size_t len = strlen (filename);
126 if (len > 0 && filename[len - 1] == '/') 125 check_for_slash_bug = len && filename[len - 1] == '/';
126 }
127 else
128 check_for_slash_bug = false;
129
130 if (check_for_slash_bug
131 && (flags & O_CREAT
132 || (flags & O_ACCMODE) == O_RDWR
133 || (flags & O_ACCMODE) == O_WRONLY))
134 {
135 errno = EISDIR;
136 return -1;
137 }
138
139 /* With the trailing slash bug or without working O_DIRECTORY, check with
140 stat first lest we hang trying to open a fifo. Although there is
141 a race between this and opening the file, we can do no better.
142 After opening the file we will check again with fstat. */
143 bool check_directory =
144 (check_for_slash_bug
145 || (!HAVE_WORKING_O_DIRECTORY && flags & O_DIRECTORY));
146 if (check_directory)
147 {
148 struct stat statbuf;
149 if (lstatif (filename, &statbuf, flags) < 0)
127 { 150 {
128 errno = EISDIR; 151 if (! (flags & O_CREAT && errno == ENOENT))
152 return -1;
153 }
154 else if (!S_ISDIR (statbuf.st_mode))
155 {
156 errno = ENOTDIR;
129 return -1; 157 return -1;
130 } 158 }
131 } 159 }
160
161 /* 0 = unknown, 1 = yes, -1 = no. */
162#if GNULIB_defined_O_CLOEXEC
163 int have_cloexec = -1;
164#else
165 static int have_cloexec;
132#endif 166#endif
133 167
134 fd = orig_open (filename, 168 int fd = orig_open (filename,
135 flags & ~(have_cloexec < 0 ? O_CLOEXEC : 0), mode); 169 flags & ~(have_cloexec < 0 ? O_CLOEXEC : 0), mode);
136 170
137 if (flags & O_CLOEXEC) 171 if (flags & O_CLOEXEC)
138 { 172 {
@@ -154,19 +188,21 @@ open (const char *filename, int flags, ...)
154#if REPLACE_FCHDIR 188#if REPLACE_FCHDIR
155 /* Implementing fchdir and fdopendir requires the ability to open a 189 /* Implementing fchdir and fdopendir requires the ability to open a
156 directory file descriptor. If open doesn't support that (as on 190 directory file descriptor. If open doesn't support that (as on
157 mingw), we use a dummy file that behaves the same as directories 191 mingw), use a dummy file that behaves the same as directories
158 on Linux (ie. always reports EOF on attempts to read()), and 192 on Linux (ie. always reports EOF on attempts to read()), and
159 override fstat() in fchdir.c to hide the fact that we have a 193 override fstat in fchdir.c to hide the dummy. */
160 dummy. */
161 if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES 194 if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES
162 && ((flags & O_ACCMODE) == O_RDONLY 195 && ((flags & (O_ACCMODE | O_CREAT)) == O_RDONLY
163 || (O_SEARCH != O_RDONLY && (flags & O_ACCMODE) == O_SEARCH))) 196 || (O_SEARCH != O_RDONLY
197 && (flags & (O_ACCMODE | O_CREAT)) == O_SEARCH)))
164 { 198 {
165 struct stat statbuf; 199 struct stat statbuf;
166 if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) 200 if (check_directory
201 || (lstatif (filename, &statbuf, flags) == 0
202 && S_ISDIR (statbuf.st_mode)))
167 { 203 {
168 /* Maximum recursion depth of 1. */ 204 /* Maximum recursion depth of 1. */
169 fd = open ("/dev/null", flags, mode); 205 fd = open ("/dev/null", flags & ~O_DIRECTORY, mode);
170 if (0 <= fd) 206 if (0 <= fd)
171 fd = _gl_register_fd (fd, filename); 207 fd = _gl_register_fd (fd, filename);
172 } 208 }
@@ -175,10 +211,8 @@ open (const char *filename, int flags, ...)
175 } 211 }
176#endif 212#endif
177 213
178#if OPEN_TRAILING_SLASH_BUG 214 /* If checking for directories, fail if fd does not refer to a directory.
179 /* If the filename ends in a slash and fd does not refer to a directory, 215 Rationale: A filename ending in slash cannot name a non-directory
180 then fail.
181 Rationale: POSIX says such a filename must name a directory
182 <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>: 216 <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>:
183 "A pathname that contains at least one non-<slash> character and that 217 "A pathname that contains at least one non-<slash> character and that
184 ends with one or more trailing <slash> characters shall not be resolved 218 ends with one or more trailing <slash> characters shall not be resolved
@@ -186,23 +220,18 @@ open (const char *filename, int flags, ...)
186 <slash> characters names an existing directory" 220 <slash> characters names an existing directory"
187 If the named file without the slash is not a directory, open() must fail 221 If the named file without the slash is not a directory, open() must fail
188 with ENOTDIR. */ 222 with ENOTDIR. */
189 if (fd >= 0) 223 if (check_directory && 0 <= fd)
190 { 224 {
191 /* We know len is positive, since open did not fail with ENOENT. */ 225 struct stat statbuf;
192 size_t len = strlen (filename); 226 int r = fstat (fd, &statbuf);
193 if (filename[len - 1] == '/') 227 if (r < 0 || !S_ISDIR (statbuf.st_mode))
194 { 228 {
195 struct stat statbuf; 229 int err = r < 0 ? errno : ENOTDIR;
196 230 close (fd);
197 if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) 231 errno = err;
198 { 232 return -1;
199 close (fd);
200 errno = ENOTDIR;
201 return -1;
202 }
203 } 233 }
204 } 234 }
205#endif
206 235
207#if REPLACE_FCHDIR 236#if REPLACE_FCHDIR
208 if (!REPLACE_OPEN_DIRECTORY && 0 <= fd) 237 if (!REPLACE_OPEN_DIRECTORY && 0 <= fd)
diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c
index ad7966152aa..282f4b2d2a5 100644
--- a/lib/qcopy-acl.c
+++ b/lib/qcopy-acl.c
@@ -26,6 +26,7 @@
26#if USE_XATTR 26#if USE_XATTR
27 27
28# include <attr/libattr.h> 28# include <attr/libattr.h>
29# include <dirent.h>
29# include <string.h> 30# include <string.h>
30 31
31# if HAVE_LINUX_XATTR_H 32# if HAVE_LINUX_XATTR_H
@@ -61,6 +62,7 @@ is_attr_permissions (const char *name, struct error_context *ctx)
61 a valid file descriptor, use file descriptor operations, else use 62 a valid file descriptor, use file descriptor operations, else use
62 filename based operations on SRC_NAME. Likewise for DEST_DESC and 63 filename based operations on SRC_NAME. Likewise for DEST_DESC and
63 DST_NAME. 64 DST_NAME.
65 MODE should be the source file's st_mode.
64 If access control lists are not available, fchmod the target file to 66 If access control lists are not available, fchmod the target file to
65 MODE. Also sets the non-permission bits of the destination file 67 MODE. Also sets the non-permission bits of the destination file
66 (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set. 68 (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set.
@@ -86,10 +88,29 @@ qcopy_acl (const char *src_name, int source_desc, const char *dst_name,
86 Functions attr_copy_* return 0 in case we copied something OR nothing 88 Functions attr_copy_* return 0 in case we copied something OR nothing
87 to copy */ 89 to copy */
88 if (ret == 0) 90 if (ret == 0)
89 ret = source_desc <= 0 || dest_desc <= 0 91 {
90 ? attr_copy_file (src_name, dst_name, is_attr_permissions, NULL) 92 ret = source_desc <= 0 || dest_desc <= 0
91 : attr_copy_fd (src_name, source_desc, dst_name, dest_desc, 93 ? attr_copy_file (src_name, dst_name, is_attr_permissions, NULL)
92 is_attr_permissions, NULL); 94 : attr_copy_fd (src_name, source_desc, dst_name, dest_desc,
95 is_attr_permissions, NULL);
96
97 /* Copying can fail with EOPNOTSUPP even when the source
98 permissions are trivial (Bug#78328). Don't report an error
99 in this case, as the chmod_or_fchmod suffices. */
100 if (ret < 0 && errno == EOPNOTSUPP)
101 {
102 /* fdfile_has_aclinfo cares only about DT_DIR, _GL_DT_NOTDIR,
103 and DT_LNK (but DT_LNK is not possible here),
104 so use _GL_DT_NOTDIR | DT_UNKNOWN for other file types. */
105 int flags = S_ISDIR (mode) ? DT_DIR : _GL_DT_NOTDIR | DT_UNKNOWN;
106
107 struct aclinfo ai;
108 if (!fdfile_has_aclinfo (source_desc, src_name, &ai, flags))
109 ret = 0;
110 aclinfo_free (&ai);
111 errno = EOPNOTSUPP;
112 }
113 }
93#else 114#else
94 /* no XATTR, so we proceed the old dusty way */ 115 /* no XATTR, so we proceed the old dusty way */
95 struct permission_context ctx; 116 struct permission_context ctx;
diff --git a/lib/regcomp.c b/lib/regcomp.c
index a23f289d7a1..878b65baf07 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -1001,21 +1001,25 @@ create_initial_state (re_dfa_t *dfa)
1001 Idx dest_idx = dfa->edests[node_idx].elems[0]; 1001 Idx dest_idx = dfa->edests[node_idx].elems[0];
1002 if (!re_node_set_contains (&init_nodes, dest_idx)) 1002 if (!re_node_set_contains (&init_nodes, dest_idx))
1003 { 1003 {
1004 reg_errcode_t merge_err 1004 err
1005 = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); 1005 = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
1006 if (merge_err != REG_NOERROR) 1006 if (err != REG_NOERROR)
1007 return merge_err; 1007 break;
1008 i = 0; 1008 i = 0;
1009 } 1009 }
1010 } 1010 }
1011 } 1011 }
1012 1012
1013 /* It must be the first time to invoke acquire_state. */ 1013 /* It must be the first time to invoke acquire_state. */
1014 dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); 1014 dfa->init_state
1015 /* We don't check ERR here, since the initial state must not be NULL. */ 1015 = (err == REG_NOERROR
1016 ? re_acquire_state_context (&err, dfa, &init_nodes, 0)
1017 : NULL);
1016 if (__glibc_unlikely (dfa->init_state == NULL)) 1018 if (__glibc_unlikely (dfa->init_state == NULL))
1017 return err; 1019 {
1018 if (dfa->init_state->has_constraint) 1020 /* Don't check ERR here, as the initial state must not be null. */
1021 }
1022 else if (dfa->init_state->has_constraint)
1019 { 1023 {
1020 dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, 1024 dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
1021 CONTEXT_WORD); 1025 CONTEXT_WORD);
@@ -1025,17 +1029,13 @@ create_initial_state (re_dfa_t *dfa)
1025 &init_nodes, 1029 &init_nodes,
1026 CONTEXT_NEWLINE 1030 CONTEXT_NEWLINE
1027 | CONTEXT_BEGBUF); 1031 | CONTEXT_BEGBUF);
1028 if (__glibc_unlikely (dfa->init_state_word == NULL
1029 || dfa->init_state_nl == NULL
1030 || dfa->init_state_begbuf == NULL))
1031 return err;
1032 } 1032 }
1033 else 1033 else
1034 dfa->init_state_word = dfa->init_state_nl 1034 dfa->init_state_word = dfa->init_state_nl
1035 = dfa->init_state_begbuf = dfa->init_state; 1035 = dfa->init_state_begbuf = dfa->init_state;
1036 1036
1037 re_node_set_free (&init_nodes); 1037 re_node_set_free (&init_nodes);
1038 return REG_NOERROR; 1038 return err;
1039} 1039}
1040 1040
1041/* If it is possible to do searching in single byte encoding instead of UTF-8 1041/* If it is possible to do searching in single byte encoding instead of UTF-8
@@ -1677,12 +1677,11 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
1677 { 1677 {
1678 err = duplicate_node_closure (dfa, node, node, node, 1678 err = duplicate_node_closure (dfa, node, node, node,
1679 dfa->nodes[node].constraint); 1679 dfa->nodes[node].constraint);
1680 if (__glibc_unlikely (err != REG_NOERROR))
1681 return err;
1682 } 1680 }
1683 1681
1684 /* Expand each epsilon destination nodes. */ 1682 /* Expand each epsilon destination nodes. */
1685 if (IS_EPSILON_NODE(dfa->nodes[node].type)) 1683 if (__glibc_likely (err == REG_NOERROR)
1684 && IS_EPSILON_NODE (dfa->nodes[node].type))
1686 for (i = 0; i < dfa->edests[node].nelem; ++i) 1685 for (i = 0; i < dfa->edests[node].nelem; ++i)
1687 { 1686 {
1688 re_node_set eclosure_elem; 1687 re_node_set eclosure_elem;
@@ -1700,14 +1699,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
1700 { 1699 {
1701 err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false); 1700 err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false);
1702 if (__glibc_unlikely (err != REG_NOERROR)) 1701 if (__glibc_unlikely (err != REG_NOERROR))
1703 return err; 1702 break;
1704 } 1703 }
1705 else 1704 else
1706 eclosure_elem = dfa->eclosures[edest]; 1705 eclosure_elem = dfa->eclosures[edest];
1707 /* Merge the epsilon closure of 'edest'. */ 1706 /* Merge the epsilon closure of 'edest'. */
1708 err = re_node_set_merge (&eclosure, &eclosure_elem); 1707 err = re_node_set_merge (&eclosure, &eclosure_elem);
1709 if (__glibc_unlikely (err != REG_NOERROR)) 1708 if (__glibc_unlikely (err != REG_NOERROR))
1710 return err; 1709 break;
1711 /* If the epsilon closure of 'edest' is incomplete, 1710 /* If the epsilon closure of 'edest' is incomplete,
1712 the epsilon closure of this node is also incomplete. */ 1711 the epsilon closure of this node is also incomplete. */
1713 if (dfa->eclosures[edest].nelem == 0) 1712 if (dfa->eclosures[edest].nelem == 0)
@@ -1717,12 +1716,18 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
1717 } 1716 }
1718 } 1717 }
1719 1718
1720 if (incomplete && !root) 1719 if (err != REG_NOERROR)
1721 dfa->eclosures[node].nelem = 0; 1720 re_node_set_free (&eclosure);
1722 else 1721 else
1723 dfa->eclosures[node] = eclosure; 1722 {
1724 *new_set = eclosure; 1723 if (incomplete && !root)
1725 return REG_NOERROR; 1724 dfa->eclosures[node].nelem = 0;
1725 else
1726 dfa->eclosures[node] = eclosure;
1727 *new_set = eclosure;
1728 }
1729
1730 return err;
1726} 1731}
1727 1732
1728/* Functions for token which are used in the parser. */ 1733/* Functions for token which are used in the parser. */
@@ -3275,6 +3280,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
3275 else 3280 else
3276 { 3281 {
3277 free_charset (mbcset); 3282 free_charset (mbcset);
3283 mbcset = NULL;
3278 /* Build a tree for simple bracket. */ 3284 /* Build a tree for simple bracket. */
3279 br_token.type = SIMPLE_BRACKET; 3285 br_token.type = SIMPLE_BRACKET;
3280 br_token.opr.sbcset = sbcset; 3286 br_token.opr.sbcset = sbcset;
@@ -3288,7 +3294,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
3288 *err = REG_ESPACE; 3294 *err = REG_ESPACE;
3289 parse_bracket_exp_free_return: 3295 parse_bracket_exp_free_return:
3290 re_free (sbcset); 3296 re_free (sbcset);
3291 free_charset (mbcset); 3297 if (__glibc_likely (mbcset != NULL))
3298 free_charset (mbcset);
3292 return NULL; 3299 return NULL;
3293} 3300}
3294 3301
diff --git a/lib/regexec.c b/lib/regexec.c
index c5ab9b6649f..0d14ac35fe9 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -2271,7 +2271,7 @@ merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
2271 these destinations and the results of the transition table. */ 2271 these destinations and the results of the transition table. */
2272 pstate = mctx->state_log[cur_idx]; 2272 pstate = mctx->state_log[cur_idx];
2273 log_nodes = pstate->entrance_nodes; 2273 log_nodes = pstate->entrance_nodes;
2274 if (next_state != NULL) 2274 if (next_state != NULL && next_state->entrance_nodes != NULL)
2275 { 2275 {
2276 table_nodes = next_state->entrance_nodes; 2276 table_nodes = next_state->entrance_nodes;
2277 *err = re_node_set_init_union (&next_nodes, table_nodes, 2277 *err = re_node_set_init_union (&next_nodes, table_nodes,
diff --git a/lib/stat-time.h b/lib/stat-time.h
index 69813932d5e..38315b9f569 100644
--- a/lib/stat-time.h
+++ b/lib/stat-time.h
@@ -117,6 +117,31 @@ get_stat_birthtime_ns (_GL_UNUSED struct stat const *st)
117# endif 117# endif
118} 118}
119 119
120/* Constructs a 'struct timespec' with the given contents.
121 This macro / function is private to stat-time.h. */
122#if !defined __cplusplus
123/* Use a C99 compound literal.
124 This is guaranteed to initialize also the padding bits, for example on
125 platforms where tv_sec is 64 bits and tv_nsec is 32 bits, thus avoiding
126 gcc -Wuse-of-uninitialized-value warnings. */
127# define _gl_make_timespec(sec,nsec) \
128 (struct timespec) { .tv_sec = (sec), .tv_nsec = (nsec) }
129#else
130/* C++ does not have C99 compound literals.
131 A constructor invocation
132 timespec { (sec), (nsec) }
133 would make assumptions about the order of the fields of 'struct timespec',
134 which are not guaranteed by POSIX. So, use an inline function. */
135static inline struct timespec
136_gl_make_timespec (time_t sec, long nsec)
137{
138 struct timespec ts;
139 ts.tv_sec = sec;
140 ts.tv_nsec = nsec;
141 return ts;
142}
143#endif
144
120/* Return *ST's access time. */ 145/* Return *ST's access time. */
121_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE 146_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
122get_stat_atime (struct stat const *st) 147get_stat_atime (struct stat const *st)
@@ -124,8 +149,7 @@ get_stat_atime (struct stat const *st)
124#ifdef STAT_TIMESPEC 149#ifdef STAT_TIMESPEC
125 return STAT_TIMESPEC (st, st_atim); 150 return STAT_TIMESPEC (st, st_atim);
126#else 151#else
127 return (struct timespec) { .tv_sec = st->st_atime, 152 return _gl_make_timespec (st->st_atime, get_stat_atime_ns (st));
128 .tv_nsec = get_stat_atime_ns (st) };
129#endif 153#endif
130} 154}
131 155
@@ -136,8 +160,7 @@ get_stat_ctime (struct stat const *st)
136#ifdef STAT_TIMESPEC 160#ifdef STAT_TIMESPEC
137 return STAT_TIMESPEC (st, st_ctim); 161 return STAT_TIMESPEC (st, st_ctim);
138#else 162#else
139 return (struct timespec) { .tv_sec = st->st_ctime, 163 return _gl_make_timespec (st->st_ctime, get_stat_ctime_ns (st));
140 .tv_nsec = get_stat_ctime_ns (st) };
141#endif 164#endif
142} 165}
143 166
@@ -148,8 +171,7 @@ get_stat_mtime (struct stat const *st)
148#ifdef STAT_TIMESPEC 171#ifdef STAT_TIMESPEC
149 return STAT_TIMESPEC (st, st_mtim); 172 return STAT_TIMESPEC (st, st_mtim);
150#else 173#else
151 return (struct timespec) { .tv_sec = st->st_mtime, 174 return _gl_make_timespec (st->st_mtime, get_stat_mtime_ns (st));
152 .tv_nsec = get_stat_mtime_ns (st) };
153#endif 175#endif
154} 176}
155 177
@@ -164,8 +186,7 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st)
164 || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC) 186 || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
165 t = STAT_TIMESPEC (st, st_birthtim); 187 t = STAT_TIMESPEC (st, st_birthtim);
166#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC 188#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
167 t = (struct timespec) { .tv_sec = st->st_birthtime, 189 t = _gl_make_timespec (st->st_birthtime, st->st_birthtimensec);
168 .tv_nsec = st->st_birthtimensec };
169#elif defined _WIN32 && ! defined __CYGWIN__ 190#elif defined _WIN32 && ! defined __CYGWIN__
170 /* Native Windows platforms (but not Cygwin) put the "file creation 191 /* Native Windows platforms (but not Cygwin) put the "file creation
171 time" in st_ctime (!). See 192 time" in st_ctime (!). See
@@ -173,11 +194,11 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st)
173# if _GL_WINDOWS_STAT_TIMESPEC 194# if _GL_WINDOWS_STAT_TIMESPEC
174 t = st->st_ctim; 195 t = st->st_ctim;
175# else 196# else
176 t = (struct timespec) { .tv_sec = st->st_ctime }; 197 t = _gl_make_timespec (st->st_ctime, 0);
177# endif 198# endif
178#else 199#else
179 /* Birth time is not supported. */ 200 /* Birth time is not supported. */
180 t = (struct timespec) { .tv_sec = -1, .tv_nsec = -1 }; 201 t = _gl_make_timespec (-1, -1);
181#endif 202#endif
182 203
183#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ 204#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
@@ -189,7 +210,7 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st)
189 sometimes returns junk in the birth time fields; work around this 210 sometimes returns junk in the birth time fields; work around this
190 bug if it is detected. */ 211 bug if it is detected. */
191 if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000)) 212 if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000))
192 t = (struct timespec) { .tv_sec = -1, .tv_nsec = -1 }; 213 t = _gl_make_timespec (-1, -1);
193#endif 214#endif
194 215
195 return t; 216 return t;
diff --git a/lib/stdckdint.in.h b/lib/stdckdint.in.h
index 83277b728ee..bb9089b4a13 100644
--- a/lib/stdckdint.in.h
+++ b/lib/stdckdint.in.h
@@ -15,10 +15,30 @@
15 You should have received a copy of the GNU Lesser General Public License 15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 17
18#ifndef _GL_STDCKDINT_H 18#if __GNUC__ >= 3
19#define _GL_STDCKDINT_H 19@PRAGMA_SYSTEM_HEADER@
20#endif
21@PRAGMA_COLUMNS@
20 22
21#include "intprops-internal.h" 23#ifndef _@GUARD_PREFIX@_STDCKDINT_H
24
25/* The include_next requires a split double-inclusion guard. */
26#if defined __cplusplus ? @HAVE_CXX_STDCKDINT_H@ : @HAVE_C_STDCKDINT_H@
27# @INCLUDE_NEXT@ @NEXT_STDCKDINT_H@
28#endif
29
30#ifndef _@GUARD_PREFIX@_STDCKDINT_H
31#define _@GUARD_PREFIX@_STDCKDINT_H
32
33/* Do nothing but include the system header if it works properly. */
34# if defined __cplusplus ? !@HAVE_WORKING_CXX_STDCKDINT_H@ : !@HAVE_WORKING_C_STDCKDINT_H@
35
36/* Avoid redefining macros. */
37# undef ckd_add
38# undef ckd_sub
39# undef ckd_mul
40
41# include "intprops-internal.h"
22 42
23/* Store into *R the low-order bits of A + B, A - B, A * B, respectively. 43/* Store into *R the low-order bits of A + B, A - B, A * B, respectively.
24 Return 1 if the result overflows, 0 otherwise. 44 Return 1 if the result overflows, 0 otherwise.
@@ -26,10 +46,13 @@
26 bit-precise integer type, or an enumeration type. 46 bit-precise integer type, or an enumeration type.
27 47
28 These are like the standard macros introduced in C23, except that 48 These are like the standard macros introduced in C23, except that
29 arguments should not have side effects. */ 49 arguments should not have side effects. The C++26 standard is
50 expected to add this header and it's macros. */
30 51
31#define ckd_add(r, a, b) ((bool) _GL_INT_ADD_WRAPV (a, b, r)) 52# define ckd_add(r, a, b) ((bool) _GL_INT_ADD_WRAPV (a, b, r))
32#define ckd_sub(r, a, b) ((bool) _GL_INT_SUBTRACT_WRAPV (a, b, r)) 53# define ckd_sub(r, a, b) ((bool) _GL_INT_SUBTRACT_WRAPV (a, b, r))
33#define ckd_mul(r, a, b) ((bool) _GL_INT_MULTIPLY_WRAPV (a, b, r)) 54# define ckd_mul(r, a, b) ((bool) _GL_INT_MULTIPLY_WRAPV (a, b, r))
34 55
35#endif /* _GL_STDCKDINT_H */ 56# endif /* defined __cplusplus ? @HAVE_WORKING_CXX_STDCKDINT_H@ : @HAVE_WORKING_C_STDCKDINT_H@ */
57#endif /* _@GUARD_PREFIX@_STDCKDINT_H */
58#endif /* _@GUARD_PREFIX@_STDCKDINT_H */
diff --git a/lib/stddef.in.h b/lib/stddef.in.h
index dc689b8df80..e8c55ff1cdc 100644
--- a/lib/stddef.in.h
+++ b/lib/stddef.in.h
@@ -188,38 +188,57 @@ typedef union
188#endif 188#endif
189 189
190/* ISO C 23 § 7.21.1 The unreachable macro */ 190/* ISO C 23 § 7.21.1 The unreachable macro */
191#ifndef unreachable 191/* This macro is only usable in C, not in C++.
192 There is no way to define it as a macro in C++, because that would break code
193 that does
194 #include <utility>
195 ... std::unreachable() ...
196 Similarly, there is no way to define it as an inline function in C++, because
197 that would break code that does
198 #include <utility>
199 using std::unreachable;
200 As a workaround, we define a macro gl_unreachable, that is like unreachable,
201 but is usable in both C and C++. */
192 202
193/* Code borrowed from verify.h. */ 203/* Code borrowed from verify.h. */
194# ifndef _GL_HAS_BUILTIN_UNREACHABLE 204#ifndef _GL_HAS_BUILTIN_UNREACHABLE
195# if defined __clang_major__ && __clang_major__ < 5 205# if defined __clang_major__ && __clang_major__ < 5
196# define _GL_HAS_BUILTIN_UNREACHABLE 0 206# define _GL_HAS_BUILTIN_UNREACHABLE 0
197# elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__) && !defined __clang__ 207# elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__) && !defined __clang__
198# define _GL_HAS_BUILTIN_UNREACHABLE 1 208# define _GL_HAS_BUILTIN_UNREACHABLE 1
199# elif defined __has_builtin 209# elif defined __has_builtin
200# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable) 210# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable)
201# else 211# else
202# define _GL_HAS_BUILTIN_UNREACHABLE 0 212# define _GL_HAS_BUILTIN_UNREACHABLE 0
203# endif
204# endif 213# endif
214#endif
205 215
206# if _GL_HAS_BUILTIN_UNREACHABLE 216#if _GL_HAS_BUILTIN_UNREACHABLE
207# define unreachable() __builtin_unreachable () 217# define gl_unreachable() __builtin_unreachable ()
208# elif 1200 <= _MSC_VER 218#elif 1200 <= _MSC_VER
209# define unreachable() __assume (0) 219# define gl_unreachable() __assume (0)
210# else 220#elif !defined __cplusplus && @HAVE_C_UNREACHABLE@
221# define gl_unreachable() unreachable ()
222#else
211/* Declare abort(), without including <stdlib.h>. */ 223/* Declare abort(), without including <stdlib.h>. */
212extern 224extern
213# if defined __cplusplus 225# if defined __cplusplus
214"C" 226"C"
215# endif 227# endif
216_Noreturn 228_Noreturn
217void abort (void) 229void abort (void)
218# if defined __cplusplus && (__GLIBC__ >= 2) 230# if defined __cplusplus && (__GLIBC__ >= 2)
219_GL_ATTRIBUTE_NOTHROW 231_GL_ATTRIBUTE_NOTHROW
220# endif 232# endif
221; 233;
222# define unreachable() abort () 234# define gl_unreachable() abort ()
235#endif
236
237#if !defined __cplusplus && !@HAVE_C_UNREACHABLE@
238/* In C, define unreachable as a macro. */
239
240# ifndef unreachable
241# define unreachable() gl_unreachable ()
223# endif 242# endif
224 243
225#endif 244#endif
diff --git a/lib/string.in.h b/lib/string.in.h
index e7642211685..e3d94b76c17 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -215,25 +215,49 @@ _GL_EXTERN_C void free (void *);
215/* Declarations for ISO C N3322. */ 215/* Declarations for ISO C N3322. */
216#if defined __GNUC__ && __GNUC__ >= 15 && !defined __clang__ 216#if defined __GNUC__ && __GNUC__ >= 15 && !defined __clang__
217_GL_EXTERN_C void *memcpy (void *__dest, const void *__src, size_t __n) 217_GL_EXTERN_C void *memcpy (void *__dest, const void *__src, size_t __n)
218# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
219 _GL_ATTRIBUTE_NOTHROW
220# endif
218 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) 221 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3)
219 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); 222 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3);
220_GL_EXTERN_C void *memccpy (void *__dest, const void *__src, int __c, size_t __n) 223_GL_EXTERN_C void *memccpy (void *__dest, const void *__src, int __c, size_t __n)
224# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
225 _GL_ATTRIBUTE_NOTHROW
226# endif
221 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 4) 227 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 4)
222 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 4); 228 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 4);
223_GL_EXTERN_C void *memmove (void *__dest, const void *__src, size_t __n) 229_GL_EXTERN_C void *memmove (void *__dest, const void *__src, size_t __n)
230# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
231 _GL_ATTRIBUTE_NOTHROW
232# endif
224 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) 233 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3)
225 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); 234 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3);
226_GL_EXTERN_C char *strncpy (char *__dest, const char *__src, size_t __n) 235_GL_EXTERN_C char *strncpy (char *__dest, const char *__src, size_t __n)
236# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
237 _GL_ATTRIBUTE_NOTHROW
238# endif
227 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) 239 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3)
228 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); 240 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3);
229_GL_EXTERN_C char *strndup (const char *__s, size_t __n) 241_GL_EXTERN_C char *strndup (const char *__s, size_t __n)
242# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
243 _GL_ATTRIBUTE_NOTHROW
244# endif
230 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 2); 245 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 2);
231_GL_EXTERN_C char *strncat (char *__dest, const char *__src, size_t __n) 246_GL_EXTERN_C char *strncat (char *__dest, const char *__src, size_t __n)
247# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
248 _GL_ATTRIBUTE_NOTHROW
249# endif
232 _GL_ARG_NONNULL ((1)) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); 250 _GL_ARG_NONNULL ((1)) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3);
233_GL_EXTERN_C int memcmp (const void *__s1, const void *__s2, size_t __n) 251_GL_EXTERN_C int memcmp (const void *__s1, const void *__s2, size_t __n)
252# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
253 _GL_ATTRIBUTE_NOTHROW
254# endif
234 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) 255 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3)
235 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); 256 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3);
236_GL_EXTERN_C int strncmp (const char *__s1, const char *__s2, size_t __n) 257_GL_EXTERN_C int strncmp (const char *__s1, const char *__s2, size_t __n)
258# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
259 _GL_ATTRIBUTE_NOTHROW
260# endif
237 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) 261 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3)
238 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); 262 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3);
239# ifndef __cplusplus 263# ifndef __cplusplus
@@ -243,6 +267,9 @@ _GL_EXTERN_C void *memrchr (const void *__s, int __c, size_t __n)
243 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); 267 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3);
244# endif 268# endif
245_GL_EXTERN_C void *memset (void *__s, int __c, size_t __n) 269_GL_EXTERN_C void *memset (void *__s, int __c, size_t __n)
270# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
271 _GL_ATTRIBUTE_NOTHROW
272# endif
246 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); 273 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3);
247_GL_EXTERN_C void *memset_explicit (void *__s, int __c, size_t __n) 274_GL_EXTERN_C void *memset_explicit (void *__s, int __c, size_t __n)
248 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); 275 _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3);
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index 8bde5a7d631..c3c38fd653e 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -849,7 +849,11 @@ _GL_WARN_ON_USE (mknodat, "mknodat is not portable - "
849# elif @WINDOWS_64_BIT_ST_SIZE@ 849# elif @WINDOWS_64_BIT_ST_SIZE@
850 /* Above, we define stat to _stati64. */ 850 /* Above, we define stat to _stati64. */
851# if defined __MINGW32__ && defined _stati64 851# if defined __MINGW32__ && defined _stati64
852# ifndef _USE_32BIT_TIME_T 852# ifdef _USE_32BIT_TIME_T
853 /* The system headers possibly define _stati64 to _stat32i64. */
854# undef _stat32i64
855# define _stat32i64(name, st) rpl_stat (name, st)
856# else
853 /* The system headers define _stati64 to _stat64. */ 857 /* The system headers define _stati64 to _stat64. */
854# undef _stat64 858# undef _stat64
855# define _stat64(name, st) rpl_stat (name, st) 859# define _stat64(name, st) rpl_stat (name, st)
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index c135a770dc1..9f057d30cdf 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -95,6 +95,15 @@
95# include <stdio.h> 95# include <stdio.h>
96#endif 96#endif
97 97
98/* Native Windows platforms declare _chdir, _getcwd, _rmdir in
99 <io.h> and/or <direct.h>, not in <unistd.h>.
100 They also declare _access(), _chmod(), _close(), _dup(), _dup2(), _isatty(),
101 _lseek(), _read(), _unlink(), _write() in <io.h>. */
102#if defined _WIN32 && !defined __CYGWIN__
103# include <io.h>
104# include <direct.h>
105#endif
106
98/* FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Solaris 11.4, and glibc 2.41 107/* FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Solaris 11.4, and glibc 2.41
99 do not define O_CLOEXEC in <unistd.h>. */ 108 do not define O_CLOEXEC in <unistd.h>. */
100/* Cygwin 1.7.1 and Android 4.3 declare unlinkat in <fcntl.h>, not in 109/* Cygwin 1.7.1 and Android 4.3 declare unlinkat in <fcntl.h>, not in
@@ -120,15 +129,6 @@
120# undef __need_system_stdlib_h 129# undef __need_system_stdlib_h
121#endif 130#endif
122 131
123/* Native Windows platforms declare _chdir, _getcwd, _rmdir in
124 <io.h> and/or <direct.h>, not in <unistd.h>.
125 They also declare _access(), _chmod(), _close(), _dup(), _dup2(), _isatty(),
126 _lseek(), _read(), _unlink(), _write() in <io.h>. */
127#if defined _WIN32 && !defined __CYGWIN__
128# include <io.h>
129# include <direct.h>
130#endif
131
132/* Native Windows platforms declare _execl*, _execv* in <process.h>. */ 132/* Native Windows platforms declare _execl*, _execv* in <process.h>. */
133#if defined _WIN32 && !defined __CYGWIN__ 133#if defined _WIN32 && !defined __CYGWIN__
134# include <process.h> 134# include <process.h>