Building a testdir on FreeBSD 5.2.1, I see link errors of many programs:
test-access
test-areadlink
test-areadlink-with-size
test-atexit
test-cloexec
test-creat
test-md5-stream
test-sha1-stream
test-sha256-stream
test-sha512-stream
test-dup2
test-dup3
test-euidaccess
test-fclose
test-fcntl-safer
test-fcntl
test-fdatasync
test-fflush
test-fgetc
test-flock
test-fopen-gnu
test-fopen-safer
test-fopen
test-fpurge
test-fputc
test-fread
test-freading
test-freopen
test-fsync
test-ftell3
test-ftello3
test-fwrite
test-getdelim
test-getline
test-getndelim2
test-immutable
test-isatty
test-link
test-lstat
test-mkdir
test-mkfifo
test-mknod
test-nonblocking
test-open
test-perror2
test-posix_spawn-open1
test-posix_spawn-open2
test-posix_spawn-inherit0
test-posix_spawn-inherit1
test-posix_spawn-script
test-posix_spawnp-script
test-read
test-readlink
test-remove
test-rename
test-rmdir
test-sf-istream
test-sfl-istream
test-symlink
test-tempname
test-truncate
test-dup-safer
test-unlink
test-write
For example:
gcc -std=gnu99 -Wno-error -Wno-error -g -O2 -L/home/bruno/lib -L/usr/local/lib
-o test-unlink test-unlink.o libtests.a ../gllib/libgnu.a libtests.a
../gllib/libgnu.a libtests.a -lm -lm -lm -lm -lm -lm
../gllib/libgnu.a(openat-die.o): In function `openat_save_fail':
/usr/home/bruno/testdir-all/build/gllib/../../gllib/openat-die.c:37: undefined
reference to `libintl_dgettext'
../gllib/libgnu.a(openat-die.o): In function `openat_restore_fail':
/usr/home/bruno/testdir-all/build/gllib/../../gllib/openat-die.c:56: undefined
reference to `libintl_dgettext'
../gllib/libgnu.a(error.o): In function `print_errno_message':
/usr/home/bruno/testdir-all/build/gllib/../../gllib/error.c:208: undefined
reference to `libintl_dgettext'
gmake[4]: *** [test-unlink] Error 1
What's happening?
- unlink.o references readlinkat.
- readlinkat.o references openat_save_fail.
- openat-die.o references libintl_dgettext.
I can see three possible fixes:
(A) Add $(LIBINTL) as dependency of module 'issymlink'. Link all these
programs with $(LIBINTL).
(B) Move the issymlinkat definition to a .c file, out of the .h file.
(C) Move the issymlinkat declaration to a different .h file.
I prefer solution (C), although it is not backward-compatible and requires a
code change in coreutils (patch attached).
2025-12-04 Bruno Haible <[email protected]>
issymlinkat: Remove accidental dependency from issymlink on $(LIBINTL).
* lib/issymlinkat.h: New file, based on lib/issymlink.h.
* lib/issymlink.h (_GL_ISSYMLINKAT_INLINE, issymlinkat): Remove
definitions.
* lib/issymlinkat.c: Include issymlinkat.h instead of issymlink.h.
* lib/fchmodat.c: Likewise.
* lib/renameatu.c: Likewise.
* lib/unlinkat.c: Likewise.
* lib/lchmod.c: Include issymlinkat.h.
* modules/issymlinkat (Files): Add lib/issymlinkat.h. Remove
lib/issymlink.h.
(Include): Specify issymlinkat.h instead of issymlink.h.
* NEWS: Mention the change.
diff --git a/NEWS b/NEWS
index d954840bfa..5fea672149 100644
--- a/NEWS
+++ b/NEWS
@@ -78,6 +78,9 @@ User visible incompatible changes
Date Modules Changes
+2025-12-04 issymlinkat The include file is changed from "issymlink.h" to
+ "issymlinkat.h".
+
2025-11-01 nstrftime The return type is now signed not size_t,
c-nstrftime the failure return value is now -1 not 0,
fprintftime and errno is no longer preserved on success.
diff --git a/lib/fchmodat.c b/lib/fchmodat.c
index 9151778b8e..4aa764f851 100644
--- a/lib/fchmodat.c
+++ b/lib/fchmodat.c
@@ -46,7 +46,7 @@ orig_fchmodat (int dir, char const *file, mode_t mode, int
flags)
#include <intprops.h>
-#include "issymlink.h"
+#include "issymlinkat.h"
/* Invoke chmod or lchmod on FILE, using mode MODE, in the directory
open on descriptor FD. If possible, do it without changing the
diff --git a/lib/issymlink.h b/lib/issymlink.h
index af6dc96564..a3f97cb521 100644
--- a/lib/issymlink.h
+++ b/lib/issymlink.h
@@ -23,7 +23,7 @@
#endif
#include <errno.h>
-#include <unistd.h> /* for readlink, readlinkat */
+#include <unistd.h> /* for readlink */
_GL_INLINE_HEADER_BEGIN
@@ -31,11 +31,7 @@ _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
-#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.
@@ -44,9 +40,9 @@ _GL_INLINE_HEADER_BEGIN
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
+#ifdef __cplusplus
extern "C" {
-# endif
+#endif
_GL_ISSYMLINK_INLINE int issymlink (const char *filename)
_GL_ARG_NONNULL ((1));
_GL_ISSYMLINK_INLINE int
@@ -60,42 +56,8 @@ issymlink (const char *filename)
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
+#ifdef __cplusplus
}
-# endif
#endif
_GL_INLINE_HEADER_END
diff --git a/lib/issymlinkat.c b/lib/issymlinkat.c
index 8286356c8a..ebd937e91b 100644
--- a/lib/issymlinkat.c
+++ b/lib/issymlinkat.c
@@ -17,4 +17,4 @@
#include <config.h>
#define _GL_ISSYMLINKAT_INLINE _GL_EXTERN_INLINE
-#include "issymlink.h"
+#include "issymlinkat.h"
diff --git a/lib/issymlinkat.h b/lib/issymlinkat.h
new file mode 100644
index 0000000000..abbbbfff83
--- /dev/null
+++ b/lib/issymlinkat.h
@@ -0,0 +1,68 @@
+/* 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 <https://www.gnu.org/licenses/>. */
+
+#ifndef _ISSYMLINKAT_H
+#define _ISSYMLINKAT_H
+
+/* This file uses _GL_ARG_NONNULL, _GL_INLINE. */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
+#include <errno.h>
+#include <unistd.h> /* for readlinkat */
+
+
+_GL_INLINE_HEADER_BEGIN
+
+#ifndef _GL_ISSYMLINKAT_INLINE
+# define _GL_ISSYMLINKAT_INLINE _GL_INLINE
+#endif
+
+/* 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
+
+_GL_INLINE_HEADER_END
+
+#endif /* _ISSYMLINKAT_H */
diff --git a/lib/lchmod.c b/lib/lchmod.c
index deba4c50f5..acccef629c 100644
--- a/lib/lchmod.c
+++ b/lib/lchmod.c
@@ -30,6 +30,7 @@
#include <intprops.h>
#include "issymlink.h"
+#include "issymlinkat.h"
/* Work like chmod, except when FILE is a symbolic link.
In that case, on systems where permissions on symbolic links are unsupported
diff --git a/lib/renameatu.c b/lib/renameatu.c
index 29c4839269..ef40ad3d17 100644
--- a/lib/renameatu.c
+++ b/lib/renameatu.c
@@ -30,7 +30,7 @@
# include <sys/syscall.h>
#endif
-#include "issymlink.h"
+#include "issymlinkat.h"
static int
errno_fail (int e)
diff --git a/lib/unlinkat.c b/lib/unlinkat.c
index 3cf5fc5ea5..be4a8c2b63 100644
--- a/lib/unlinkat.c
+++ b/lib/unlinkat.c
@@ -30,7 +30,7 @@
#include <stdlib.h>
#include "filename.h"
-#include "issymlink.h"
+#include "issymlinkat.h"
#include "openat.h"
#if HAVE_UNLINKAT
diff --git a/modules/issymlinkat b/modules/issymlinkat
index c02e4e9678..b4e03c22b7 100644
--- a/modules/issymlinkat
+++ b/modules/issymlinkat
@@ -2,7 +2,7 @@ Description:
Test whether a file is a symbolic link.
Files:
-lib/issymlink.h
+lib/issymlinkat.h
lib/issymlinkat.c
Depends-on:
@@ -18,7 +18,7 @@ Makefile.am:
lib_SOURCES += issymlinkat.c
Include:
-"issymlink.h"
+"issymlinkat.h"
Link:
$(LTLIBINTL) when linking with libtool, $(LIBINTL) otherwise
>From 0b7847604250782c346200a1e3ee06745c6c5cb3 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Thu, 4 Dec 2025 21:14:45 +0100
Subject: [PATCH] maint: Update after gnulib changed
* src/copy.c: Include issymlinkat.h.
---
src/copy.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/copy.c b/src/copy.c
index 4c6f87c01..fde4a82c7 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -45,6 +45,7 @@
#include "hashcode-file.h"
#include "ignore-value.h"
#include "issymlink.h"
+#include "issymlinkat.h"
#include "quote.h"
#include "renameatu.h"
#include "root-uid.h"
--
2.52.0