# HG changeset patch # User Bruno Haible # Date 1550608974 -3600 # Node ID 3ba41edecde63edcf4eb0cfc95a7ab98dea35315 # Parent e13b9344e430983c5e97fff9021d50461b4762c8 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. diff -r e13b9344e430 -r 3ba41edecde6 ChangeLog --- a/ChangeLog Tue Feb 19 21:38:53 2019 +0100 +++ b/ChangeLog Tue Feb 19 21:42:54 2019 +0100 @@ -1,3 +1,11 @@ +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. diff -r e13b9344e430 -r 3ba41edecde6 lib/progreloc.c --- a/lib/progreloc.c Tue Feb 19 21:38:53 2019 +0100 +++ b/lib/progreloc.c Tue Feb 19 21:42:54 2019 +0100 @@ -22,6 +22,7 @@ /* Specification. */ #include "progname.h" +#include #include #include #include @@ -102,6 +103,48 @@ #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 @@ } } # 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 @@ 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. */ {