>From 18f4d4133eae7d8ac228ed2986748c52825f3d0e Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 . (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 + progreloc: Speed up executable lookup on various platforms. + * lib/progreloc.c: Include . + (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 + 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 #include #include #include @@ -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//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//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//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//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//exe, at least in Cygwin >= 1.5. */ { -- 2.7.4