This set of patches improve the platform specific code in progreloc.c. Most BSD systems and Solaris nowadays have a way to retrieve the name of the current executable, in a way similar to /proc/self/exe on Linux.
2019-02-19 Bruno Haible <[email protected]> progreloc: Simplify code for Android. * lib/progreloc.c (executable_fd): Don't define on Android. (maybe_executable, find_executable): Don't use executable_fd on Android. 2019-02-19 Bruno Haible <[email protected]> progreloc: Speed up executable lookup on various platforms. * lib/progreloc.c: Include <errno.h>. (safe_read, full_read): New functions. (find_executable): On GNU/kFreeBSD, FreeBSD, DragonFly, NetBSD, Solaris, prefer the information from the /proc file system to a PATH search.
>From cd46bf0ca5083162f3ac564ebbdeb6371085df45 Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Tue, 19 Feb 2019 21:38:53 +0100 Subject: [PATCH 1/2] progreloc: Simplify code for Android. * lib/progreloc.c (executable_fd): Don't define on Android. (maybe_executable, find_executable): Don't use executable_fd on Android. --- ChangeLog | 6 ++++++ lib/progreloc.c | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 64e9acf..9cb7ac8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2019-02-19 Bruno Haible <[email protected]> + + progreloc: Simplify code for Android. + * lib/progreloc.c (executable_fd): Don't define on Android. + (maybe_executable, find_executable): Don't use executable_fd on Android. + 2019-02-15 Bruno Haible <[email protected]> gnulib-tool: Support --import with just a few tests, not --with-tests. diff --git a/lib/progreloc.c b/lib/progreloc.c index 1c4db0c..0cd335e 100644 --- a/lib/progreloc.c +++ b/lib/progreloc.c @@ -102,7 +102,7 @@ extern char * canonicalize_file_name (const char *name); #if ENABLE_RELOCATABLE -#if defined __linux__ || defined __ANDROID__ || defined __CYGWIN__ +#if defined __linux__ || defined __CYGWIN__ /* File descriptor of the executable. (Only used to verify that we find the correct executable.) */ static int executable_fd = -1; @@ -118,7 +118,7 @@ maybe_executable (const char *filename) return false; #endif -#if defined __linux__ || defined __ANDROID__ || defined __CYGWIN__ +#if defined __linux__ || defined __CYGWIN__ if (executable_fd >= 0) { /* If we already have an executable_fd, check that filename points to @@ -180,7 +180,7 @@ find_executable (const char *argv0) return xstrdup (location); #else /* Unix */ -# if defined __linux__ || defined __ANDROID__ +# if defined __linux__ /* The executable is accessible as /proc/<pid>/exe. In newer Linux versions, also as /proc/self/exe. Linux >= 2.1 provides a symlink to the true pathname; older Linux versions give only device and ino, @@ -205,6 +205,15 @@ find_executable (const char *argv0) } } # endif +# if defined __ANDROID__ + { + char *link; + + link = xreadlink ("/proc/self/exe"); + if (link != NULL) + return link; + } +# endif # ifdef __CYGWIN__ /* The executable is accessible as /proc/<pid>/exe, at least in Cygwin >= 1.5. */ -- 2.7.4
>From 18f4d4133eae7d8ac228ed2986748c52825f3d0e Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Tue, 19 Feb 2019 21:42:54 +0100 Subject: [PATCH 2/2] progreloc: Speed up executable lookup on various platforms. * lib/progreloc.c: Include <errno.h>. (safe_read, full_read): New functions. (find_executable): On GNU/kFreeBSD, FreeBSD, DragonFly, NetBSD, Solaris, prefer the information from the /proc file system to a PATH search. --- ChangeLog | 8 +++++ lib/progreloc.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9cb7ac8..949dbae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2019-02-19 Bruno Haible <[email protected]> + progreloc: Speed up executable lookup on various platforms. + * lib/progreloc.c: Include <errno.h>. + (safe_read, full_read): New functions. + (find_executable): On GNU/kFreeBSD, FreeBSD, DragonFly, NetBSD, Solaris, + prefer the information from the /proc file system to a PATH search. + +2019-02-19 Bruno Haible <[email protected]> + progreloc: Simplify code for Android. * lib/progreloc.c (executable_fd): Don't define on Android. (maybe_executable, find_executable): Don't use executable_fd on Android. diff --git a/lib/progreloc.c b/lib/progreloc.c index 0cd335e..b3eb503 100644 --- a/lib/progreloc.c +++ b/lib/progreloc.c @@ -22,6 +22,7 @@ /* Specification. */ #include "progname.h" +#include <errno.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -102,6 +103,48 @@ extern char * canonicalize_file_name (const char *name); #if ENABLE_RELOCATABLE +#ifdef __sun + +/* Helper function, from gnulib module 'safe-read'. */ +static size_t +safe_read (int fd, void *buf, size_t count) +{ + for (;;) + { + ssize_t result = read (fd, buf, count); + + if (0 <= result || errno != EINTR) + return result; + } +} + +/* Helper function, from gnulib module 'full-read'. */ +static size_t +full_read (int fd, void *buf, size_t count) +{ + size_t total = 0; + const char *ptr = (const char *) buf; + + while (count > 0) + { + size_t n = safe_read (fd, ptr, count); + if (n == (size_t) -1) + break; + if (n == 0) + { + errno = 0; + break; + } + total += n; + ptr += n; + count -= n; + } + + return total; +} + +#endif + #if defined __linux__ || defined __CYGWIN__ /* File descriptor of the executable. (Only used to verify that we find the correct executable.) */ @@ -205,7 +248,9 @@ find_executable (const char *argv0) } } # endif -# if defined __ANDROID__ +# if defined __ANDROID__ || defined __FreeBSD_kernel__ + /* On Android and GNU/kFreeBSD, the executable is accessible as + /proc/<pid>/exe and /proc/self/exe. */ { char *link; @@ -214,7 +259,52 @@ find_executable (const char *argv0) return link; } # endif -# ifdef __CYGWIN__ +# if defined __FreeBSD__ || defined __DragonFly__ + /* In FreeBSD >= 5.0, the executable is accessible as /proc/<pid>/file and + /proc/curproc/file. */ + { + char *link; + + link = xreadlink ("/proc/curproc/file"); + if (link != NULL) + { + if (strcmp (link, "unknown") != 0) + return link; + free (link); + } + } +# endif +# if defined __NetBSD__ + /* In NetBSD >= 4.0, the executable is accessible as /proc/<pid>/exe and + /proc/curproc/exe. */ + { + char *link; + + link = xreadlink ("/proc/curproc/exe"); + if (link != NULL) + return link; + } +# endif +# if defined __sun + /* On Solaris >= 11.4, /proc/<pid>/execname and /proc/self/execname contains + the name of the executable, either as an absolute file name or relative to + the current directory. */ + { + char namebuf[4096]; + int fd = open ("/proc/self/execname", O_RDONLY, 0); + if (fd >= 0) + { + size_t len = full_read (fd, namebuf, sizeof (namebuf)); + close (fd); + if (len > 0 && len < sizeof (namebuf)) + { + namebuf[len] = '\0'; + return canonicalize_file_name (namebuf); + } + } + } +# endif +# if defined __CYGWIN__ /* The executable is accessible as /proc/<pid>/exe, at least in Cygwin >= 1.5. */ { -- 2.7.4
