Mercurial > gnulib
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 |