comparison lib/progreloc.c @ 40189:3ba41edecde6

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.
author Bruno Haible <bruno@clisp.org>
date Tue, 19 Feb 2019 21:42:54 +0100
parents e13b9344e430
children
comparison
equal deleted inserted replaced
40188:e13b9344e430 40189:3ba41edecde6
20 #include <config.h> 20 #include <config.h>
21 21
22 /* Specification. */ 22 /* Specification. */
23 #include "progname.h" 23 #include "progname.h"
24 24
25 #include <errno.h>
25 #include <stdbool.h> 26 #include <stdbool.h>
26 #include <stdio.h> 27 #include <stdio.h>
27 #include <stdlib.h> 28 #include <stdlib.h>
28 #include <string.h> 29 #include <string.h>
29 #include <fcntl.h> 30 #include <fcntl.h>
100 #undef set_program_name 101 #undef set_program_name
101 102
102 103
103 #if ENABLE_RELOCATABLE 104 #if ENABLE_RELOCATABLE
104 105
106 #ifdef __sun
107
108 /* Helper function, from gnulib module 'safe-read'. */
109 static size_t
110 safe_read (int fd, void *buf, size_t count)
111 {
112 for (;;)
113 {
114 ssize_t result = read (fd, buf, count);
115
116 if (0 <= result || errno != EINTR)
117 return result;
118 }
119 }
120
121 /* Helper function, from gnulib module 'full-read'. */
122 static size_t
123 full_read (int fd, void *buf, size_t count)
124 {
125 size_t total = 0;
126 const char *ptr = (const char *) buf;
127
128 while (count > 0)
129 {
130 size_t n = safe_read (fd, ptr, count);
131 if (n == (size_t) -1)
132 break;
133 if (n == 0)
134 {
135 errno = 0;
136 break;
137 }
138 total += n;
139 ptr += n;
140 count -= n;
141 }
142
143 return total;
144 }
145
146 #endif
147
105 #if defined __linux__ || defined __CYGWIN__ 148 #if defined __linux__ || defined __CYGWIN__
106 /* File descriptor of the executable. 149 /* File descriptor of the executable.
107 (Only used to verify that we find the correct executable.) */ 150 (Only used to verify that we find the correct executable.) */
108 static int executable_fd = -1; 151 static int executable_fd = -1;
109 #endif 152 #endif
203 if (executable_fd < 0) 246 if (executable_fd < 0)
204 executable_fd = open (buf, O_EXEC, 0); 247 executable_fd = open (buf, O_EXEC, 0);
205 } 248 }
206 } 249 }
207 # endif 250 # endif
208 # if defined __ANDROID__ 251 # if defined __ANDROID__ || defined __FreeBSD_kernel__
252 /* On Android and GNU/kFreeBSD, the executable is accessible as
253 /proc/<pid>/exe and /proc/self/exe. */
209 { 254 {
210 char *link; 255 char *link;
211 256
212 link = xreadlink ("/proc/self/exe"); 257 link = xreadlink ("/proc/self/exe");
213 if (link != NULL) 258 if (link != NULL)
214 return link; 259 return link;
215 } 260 }
216 # endif 261 # endif
217 # ifdef __CYGWIN__ 262 # if defined __FreeBSD__ || defined __DragonFly__
263 /* In FreeBSD >= 5.0, the executable is accessible as /proc/<pid>/file and
264 /proc/curproc/file. */
265 {
266 char *link;
267
268 link = xreadlink ("/proc/curproc/file");
269 if (link != NULL)
270 {
271 if (strcmp (link, "unknown") != 0)
272 return link;
273 free (link);
274 }
275 }
276 # endif
277 # if defined __NetBSD__
278 /* In NetBSD >= 4.0, the executable is accessible as /proc/<pid>/exe and
279 /proc/curproc/exe. */
280 {
281 char *link;
282
283 link = xreadlink ("/proc/curproc/exe");
284 if (link != NULL)
285 return link;
286 }
287 # endif
288 # if defined __sun
289 /* On Solaris >= 11.4, /proc/<pid>/execname and /proc/self/execname contains
290 the name of the executable, either as an absolute file name or relative to
291 the current directory. */
292 {
293 char namebuf[4096];
294 int fd = open ("/proc/self/execname", O_RDONLY, 0);
295 if (fd >= 0)
296 {
297 size_t len = full_read (fd, namebuf, sizeof (namebuf));
298 close (fd);
299 if (len > 0 && len < sizeof (namebuf))
300 {
301 namebuf[len] = '\0';
302 return canonicalize_file_name (namebuf);
303 }
304 }
305 }
306 # endif
307 # if defined __CYGWIN__
218 /* The executable is accessible as /proc/<pid>/exe, at least in 308 /* The executable is accessible as /proc/<pid>/exe, at least in
219 Cygwin >= 1.5. */ 309 Cygwin >= 1.5. */
220 { 310 {
221 char *link; 311 char *link;
222 312