diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2020-08-21 12:19:18 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2020-08-21 12:22:04 -0700 |
commit | 3e10174fb65f4eb601b1921271bdcf10c933b879 (patch) | |
tree | 4a0948c61c187fc1f9bbd6b73a9f7957c12b74f4 /lib/careadlinkat.c | |
parent | 348686b3f318195f4d341206744b8e98470c90f4 (diff) | |
download | emacs-3e10174fb65f4eb601b1921271bdcf10c933b879.tar.gz emacs-3e10174fb65f4eb601b1921271bdcf10c933b879.tar.bz2 emacs-3e10174fb65f4eb601b1921271bdcf10c933b879.zip |
Update from Gnulib
This incorporates:
2020-08-20 sigabbrev_np: New module
2020-08-20 stdalign: Fix 32-bit test failures clang versions < 8
2020-08-17 careadlinkat: speedup for GCC 10 with GCC_LINT
2020-08-17 Assume autoconf >= 2.64
* build-aux/config.guess, build-aux/config.sub, lib/careadlinkat.c:
* lib/stdalign.in.h, lib/string.in.h, m4/std-gnu11.m4, m4/string_h.m4:
Copy from Gnulib.
* lib/gnulib.mk.in: Regenerate.
Diffstat (limited to 'lib/careadlinkat.c')
-rw-r--r-- | lib/careadlinkat.c | 108 |
1 files changed, 62 insertions, 46 deletions
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c index 1aa04363dac..e43aa42d5c4 100644 --- a/lib/careadlinkat.c +++ b/lib/careadlinkat.c @@ -38,66 +38,41 @@ #include "allocator.h" -/* Assuming the current directory is FD, get the symbolic link value - of FILENAME as a null-terminated string and put it into a buffer. - If FD is AT_FDCWD, FILENAME is interpreted relative to the current - working directory, as in openat. - - If the link is small enough to fit into BUFFER put it there. - BUFFER's size is BUFFER_SIZE, and BUFFER can be null - if BUFFER_SIZE is zero. - - If the link is not small, put it into a dynamically allocated - buffer managed by ALLOC. It is the caller's responsibility to free - the returned value if it is nonnull and is not BUFFER. A null - ALLOC stands for the standard allocator. - - The PREADLINKAT function specifies how to read links. It operates - like POSIX readlinkat() - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html> - but can assume that its first argument is the same as FD. - - If successful, return the buffer address; otherwise return NULL and - set errno. */ - -char * -careadlinkat (int fd, char const *filename, +enum { STACK_BUF_SIZE = 1024 }; + +/* Act like careadlinkat (see below), with an additional argument + STACK_BUF that can be used as temporary storage. + + If GCC_LINT is defined, do not inline this function with GCC 10.1 + and later, to avoid creating a pointer to the stack that GCC + -Wreturn-local-addr incorrectly complains about. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644 + Although the noinline attribute can hurt performance a bit, no better way + to pacify GCC is known; even an explicit #pragma does not pacify GCC. + When the GCC bug is fixed this workaround should be limited to the + broken GCC versions. */ +#if (defined GCC_LINT || defined lint) && _GL_GNUC_PREREQ (10, 1) +__attribute__ ((__noinline__)) +#endif +static char * +readlink_stk (int fd, char const *filename, char *buffer, size_t buffer_size, struct allocator const *alloc, - ssize_t (*preadlinkat) (int, char const *, char *, size_t)) + ssize_t (*preadlinkat) (int, char const *, char *, size_t), + char stack_buf[STACK_BUF_SIZE]) { char *buf; size_t buf_size; size_t buf_size_max = SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; - char stack_buf[1024]; - -#if (defined GCC_LINT || defined lint) && _GL_GNUC_PREREQ (10, 1) - /* Pacify preadlinkat without creating a pointer to the stack - that a broken gcc -Wreturn-local-addr would cry wolf about. See: - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95044 - This workaround differs from the mainline code, but - no other way to pacify GCC 10.1.0 is known; even an explicit - #pragma does not pacify GCC. When the GCC bug is fixed this - workaround should be limited to the broken GCC versions. */ -# define WORK_AROUND_GCC_BUG_95044 -#endif if (! alloc) alloc = &stdlib_allocator; if (!buffer) { -#ifdef WORK_AROUND_GCC_BUG_95044 - buffer = alloc->allocate (sizeof stack_buf); -#else - /* Allocate the initial buffer on the stack. This way, in the - common case of a symlink of small size, we get away with a - single small malloc() instead of a big malloc() followed by a - shrinking realloc(). */ buffer = stack_buf; -#endif - buffer_size = sizeof stack_buf; + buffer_size = STACK_BUF_SIZE; } buf = buffer; @@ -172,3 +147,44 @@ careadlinkat (int fd, char const *filename, errno = ENOMEM; return NULL; } + + +/* Assuming the current directory is FD, get the symbolic link value + of FILENAME as a null-terminated string and put it into a buffer. + If FD is AT_FDCWD, FILENAME is interpreted relative to the current + working directory, as in openat. + + If the link is small enough to fit into BUFFER put it there. + BUFFER's size is BUFFER_SIZE, and BUFFER can be null + if BUFFER_SIZE is zero. + + If the link is not small, put it into a dynamically allocated + buffer managed by ALLOC. It is the caller's responsibility to free + the returned value if it is nonnull and is not BUFFER. A null + ALLOC stands for the standard allocator. + + The PREADLINKAT function specifies how to read links. It operates + like POSIX readlinkat() + <https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html> + but can assume that its first argument is the same as FD. + + If successful, return the buffer address; otherwise return NULL and + set errno. */ + +char * +careadlinkat (int fd, char const *filename, + char *buffer, size_t buffer_size, + struct allocator const *alloc, + ssize_t (*preadlinkat) (int, char const *, char *, size_t)) +{ + /* Allocate the initial buffer on the stack. This way, in the + common case of a symlink of small size, we get away with a + single small malloc instead of a big malloc followed by a + shrinking realloc. + + If GCC -Wreturn-local-addr warns about this buffer, the warning + is bogus; see readlink_stk. */ + char stack_buf[STACK_BUF_SIZE]; + return readlink_stk (fd, filename, buffer, buffer_size, alloc, + preadlinkat, stack_buf); +} |