From: Bruno Haible Date: Thu, 14 Aug 2025 16:36:00 +0000 (+0200) Subject: issymlink, issymlinkat: New modules. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16db5fb3f0c91305e901c39f92fac6798e1fdafc;p=thirdparty%2Fgnulib.git issymlink, issymlinkat: New modules. * lib/sys_stat.in.h: Invoke _GL_INLINE_HEADER_BEGIN, _GL_INLINE_HEADER_END. Include , . (_GL_ISSYMLINK_INLINE, _GL_ISSYMLINKAT_INLINE): New macros. (issymlink, issymlinkat): New declarations. * lib/unistd.in.h: Do the #include , when needed for O_CLOEXEC, at the end of the file. So that when includes , the declarations of readlink() and readlinkat() on native Windows are already present. * lib/issymlink.c: New file. * lib/issymlinkat.c: New file. * m4/sys_stat_h.m4 (gl_SYS_STAT_H_REQUIRE_DEFAULTS): Initialize GNULIB_ISSYMLINK, GNULIB_ISSYMLINKAT. * modules/sys_stat-h (Depends-on): Add extern-inline. (Makefile.am): Substitute GNULIB_ISSYMLINK, GNULIB_ISSYMLINKAT. * modules/issymlink: New file. * modules/issymlinkat: New file. --- diff --git a/ChangeLog b/ChangeLog index 6084329d2e..09afcc04c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2025-08-14 Bruno Haible + + issymlink, issymlinkat: New modules. + * lib/sys_stat.in.h: Invoke _GL_INLINE_HEADER_BEGIN, + _GL_INLINE_HEADER_END. Include , . + (_GL_ISSYMLINK_INLINE, _GL_ISSYMLINKAT_INLINE): New macros. + (issymlink, issymlinkat): New declarations. + * lib/unistd.in.h: Do the #include , when needed for O_CLOEXEC, + at the end of the file. So that when includes , + the declarations of readlink() and readlinkat() on native Windows are + already present. + * lib/issymlink.c: New file. + * lib/issymlinkat.c: New file. + * m4/sys_stat_h.m4 (gl_SYS_STAT_H_REQUIRE_DEFAULTS): Initialize + GNULIB_ISSYMLINK, GNULIB_ISSYMLINKAT. + * modules/sys_stat-h (Depends-on): Add extern-inline. + (Makefile.am): Substitute GNULIB_ISSYMLINK, GNULIB_ISSYMLINKAT. + * modules/issymlink: New file. + * modules/issymlinkat: New file. + 2025-08-11 Paul Eggert manywarnings: update C warnings for GCC 15.2 diff --git a/lib/issymlink.c b/lib/issymlink.c new file mode 100644 index 0000000000..fba06fff64 --- /dev/null +++ b/lib/issymlink.c @@ -0,0 +1,20 @@ +/* Test whether a file is a symbolic link. + Copyright (C) 2025 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +#include + +#define _GL_ISSYMLINK_INLINE _GL_EXTERN_INLINE +#include diff --git a/lib/issymlinkat.c b/lib/issymlinkat.c new file mode 100644 index 0000000000..924df455da --- /dev/null +++ b/lib/issymlinkat.c @@ -0,0 +1,20 @@ +/* Test whether a file is a symbolic link. + Copyright (C) 2025 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#define _GL_ISSYMLINKAT_INLINE _GL_EXTERN_INLINE +#include diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h index c3c38fd653..1ffc255134 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -56,7 +56,7 @@ #define _@GUARD_PREFIX@_SYS_STAT_H /* This file uses _GL_ATTRIBUTE_NODISCARD, _GL_ATTRIBUTE_NOTHROW, - GNULIB_POSIXCHECK, HAVE_RAW_DECL_*. */ + _GL_INLINE, GNULIB_POSIXCHECK, HAVE_RAW_DECL_*. */ #if !_GL_CONFIG_H_INCLUDED #error "Please include config.h first." #endif @@ -91,6 +91,16 @@ /* The definition of _GL_WARN_ON_USE is copied here. */ +_GL_INLINE_HEADER_BEGIN + +#ifndef _GL_ISSYMLINK_INLINE +# define _GL_ISSYMLINK_INLINE _GL_INLINE +#endif +#ifndef _GL_ISSYMLINKAT_INLINE +# define _GL_ISSYMLINKAT_INLINE _GL_INLINE +#endif + + /* Before doing "#define mknod rpl_mknod" below, we need to include all headers that may declare mknod(). OS/2 kLIBC declares mknod() in , not in . */ @@ -430,6 +440,13 @@ struct stat #endif +#if @GNULIB_ISSYMLINK@ || @GNULIB_ISSYMLINKAT@ +/* For the inline definitions of issymlink, issymlinkat below. */ +# include +# include /* for readlink, readlinkat */ +#endif + + #if @GNULIB_CHMOD@ # if @REPLACE_CHMOD@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) @@ -626,6 +643,71 @@ _GL_WARN_ON_USE (getumask, "getumask is not portable - " #endif +#if @GNULIB_ISSYMLINK@ +/* Tests whether FILENAME represents a symbolic link. + This function is more reliable than lstat() / fstatat() followed by S_ISLNK, + because it avoids possible EOVERFLOW errors. + Returns + 1 if FILENAME is a symbolic link, + 0 if FILENAME exists and is not a symbolic link, + -1 with errno set if determination failed, in particular + -1 with errno = ENOENT or ENOTDIR if FILENAME does not exist. */ +# ifdef __cplusplus +extern "C" { +# endif +_GL_ISSYMLINK_INLINE int issymlink (const char *filename) + _GL_ARG_NONNULL ((1)); +_GL_ISSYMLINK_INLINE int +issymlink (const char *filename) +{ + char linkbuf[1]; + if (readlink (filename, linkbuf, sizeof (linkbuf)) >= 0) + return 1; + if (errno == EINVAL) + return 0; + else + return -1; +} +# ifdef __cplusplus +} +# endif +#endif + + +#if @GNULIB_ISSYMLINKAT@ +/* Tests whether FILENAME represents a symbolic link. + This function is more reliable than lstat() / fstatat() followed by S_ISLNK, + because it avoids possible EOVERFLOW errors. + If FILENAME is a relative file name, it is interpreted as relative to the + directory referred to by FD (where FD = AT_FDCWD denotes the current + directory). + Returns + 1 if FILENAME is a symbolic link, + 0 if FILENAME exists and is not a symbolic link, + -1 with errno set if determination failed, in particular + -1 with errno = ENOENT or ENOTDIR if FILENAME does not exist. */ +# ifdef __cplusplus +extern "C" { +# endif +_GL_ISSYMLINKAT_INLINE int issymlinkat (int fd, const char *filename) + _GL_ARG_NONNULL ((2)); +_GL_ISSYMLINKAT_INLINE int +issymlinkat (int fd, const char *filename) +{ + char linkbuf[1]; + if (readlinkat (fd, filename, linkbuf, sizeof (linkbuf)) >= 0) + return 1; + if (errno == EINVAL) + return 0; + else + return -1; +} +# ifdef __cplusplus +} +# endif +#endif + + #if @GNULIB_LCHMOD@ /* Change the mode of FILENAME to MODE, without dereferencing it if FILENAME denotes a symbolic link. */ @@ -1007,6 +1089,8 @@ _GL_WARN_ON_USE (utimensat, "utimensat is not portable - " #endif +_GL_INLINE_HEADER_END + #endif /* _@GUARD_PREFIX@_SYS_STAT_H */ #endif /* _@GUARD_PREFIX@_SYS_STAT_H */ #endif diff --git a/lib/unistd.in.h b/lib/unistd.in.h index 9f057d30cd..0cf2728020 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -104,15 +104,12 @@ # include #endif -/* FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Solaris 11.4, and glibc 2.41 - do not define O_CLOEXEC in . */ /* Cygwin 1.7.1 and Android 4.3 declare unlinkat in , not in . */ /* But avoid namespace pollution on glibc systems. */ -#if ! defined O_CLOEXEC \ - || ((@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) \ - && (defined __CYGWIN__ || defined __ANDROID__) \ - && ! defined __GLIBC__) +#if ((@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) \ + && (defined __CYGWIN__ || defined __ANDROID__) \ + && ! defined __GLIBC__) # include #endif @@ -2493,6 +2490,12 @@ _GL_CXXALIASWARN (write); _GL_INLINE_HEADER_END +/* FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Solaris 11.4, and glibc 2.41 + do not define O_CLOEXEC in . */ +#if ! defined O_CLOEXEC +# include +#endif + #endif /* _@GUARD_PREFIX@_UNISTD_H */ #endif /* _GL_INCLUDING_UNISTD_H */ #endif /* _@GUARD_PREFIX@_UNISTD_H */ diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4 index fdcc89545b..a2dd603d63 100644 --- a/m4/sys_stat_h.m4 +++ b/m4/sys_stat_h.m4 @@ -1,5 +1,5 @@ # sys_stat_h.m4 -# serial 42 -*- Autoconf -*- +# serial 43 -*- Autoconf -*- dnl Copyright (C) 2006-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -80,6 +80,8 @@ AC_DEFUN([gl_SYS_STAT_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FSTATAT]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FUTIMENS]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETUMASK]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_ISSYMLINK]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_ISSYMLINKAT]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_LCHMOD]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_LSTAT]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MKDIR]) diff --git a/modules/issymlink b/modules/issymlink new file mode 100644 index 0000000000..d7977e8986 --- /dev/null +++ b/modules/issymlink @@ -0,0 +1,25 @@ +Description: +Test whether a file is a symbolic link. + +Files: +lib/issymlink.c + +Depends-on: +sys_stat-h +fcntl-h +readlink + +configure.ac: +gl_SYS_STAT_MODULE_INDICATOR([issymlink]) + +Makefile.am: +lib_SOURCES += issymlink.c + +Include: + + +License: +LGPLv2+ + +Maintainer: +all diff --git a/modules/issymlinkat b/modules/issymlinkat new file mode 100644 index 0000000000..15740ac1be --- /dev/null +++ b/modules/issymlinkat @@ -0,0 +1,25 @@ +Description: +Test whether a file is a symbolic link. + +Files: +lib/issymlinkat.c + +Depends-on: +sys_stat-h +fcntl-h +readlinkat + +configure.ac: +gl_SYS_STAT_MODULE_INDICATOR([issymlinkat]) + +Makefile.am: +lib_SOURCES += issymlinkat.c + +Include: + + +License: +GPL + +Maintainer: +all diff --git a/modules/sys_stat-h b/modules/sys_stat-h index 5552db8e00..5257bad181 100644 --- a/modules/sys_stat-h +++ b/modules/sys_stat-h @@ -13,6 +13,7 @@ include_next snippet/arg-nonnull snippet/c++defs snippet/warn-on-use +extern-inline sys_types-h time-h @@ -42,6 +43,8 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \ -e 's/@''GNULIB_GETUMASK''@/$(GNULIB_GETUMASK)/g' \ + -e 's/@''GNULIB_ISSYMLINK''@/$(GNULIB_ISSYMLINK)/g' \ + -e 's/@''GNULIB_ISSYMLINKAT''@/$(GNULIB_ISSYMLINKAT)/g' \ -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \ -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \ -e 's/@''GNULIB_MKDIR''@/$(GNULIB_MKDIR)/g' \