11#include <libgen.h>
2- #include <unistd.h>
32
4- #if defined(__linux__ )
5- #include <limits.h>
6- #include <sys/stat.h>
7- #elif defined(__APPLE__ )
3+ #if defined(__APPLE__ )
84#include <mach-o/dyld.h>
95#elif defined(__FreeBSD__ )
106#include <sys/stat.h>
1612#include "pexerror.h"
1713#include "util.h"
1814
19- #ifdef __linux__
20-
21- /*
22- * get_path_max returns the maximum length of a relative path name when the given path is the
23- * current working directory (although the path need not actually be a directory, or even exist).
24- */
25- static int get_path_max (char * path ) {
26- int path_max = pathconf (path , _PC_PATH_MAX );
27-
28- if (path_max <= 0 ) {
29- // PATH_MAX may be defined in <limits.h>, but this is not a POSIX requirement. If it isn't
30- // defined, fall back to 4096 (as recommended by Linux's realpath(3) man page).
31- #ifdef PATH_MAX
32- path_max = PATH_MAX ;
33- #else
34- path_max = 4096 ;
35- #endif
36- }
37-
38- return path_max ;
39- }
40-
41- /*
42- * get_link_path resolves the symbolic link at the path lpath and stores the link's destination path
43- * in rpath. It returns NULL on success and an error on failure.
44- */
45- static err_t * get_link_path (char * lpath , char * * rpath ) {
46- struct stat sb = { 0 };
47- int slen = 0 ;
48- int rlen = 0 ;
49- err_t * err = NULL ;
50-
51- // Get the length of lpath's destination path so we can allocate a buffer of that length for
52- // readlink to write to (plus one byte, so we can determine whether readlink has truncated the
53- // path it writes, and also for the trailing null we'll append to the path afterwards). If lpath
54- // is a magic symlink (in which case sb.st_size is 0), assume the destination path is PATH_MAX
55- // bytes long - it's an overestimate, but at least the buffer will be large enough for readlink
56- // to safely write to.
57- if (lstat (lpath , & sb ) == -1 ) {
58- err = err_from_errno ("lstat" );
59- goto end ;
60- }
61- slen = (sb .st_size == 0 ? get_path_max (lpath ) : sb .st_size ) + 1 ;
62-
63- MALLOC (* rpath , char * , slen );
64-
65- if ((rlen = readlink (lpath , (* rpath ), slen )) == -1 ) {
66- err = err_from_errno ("readlink" );
67- goto end ;
68- }
69- // If readlink filled the buffer, it truncated the destination path it wrote. In this case, the
70- // value is untrustworthy, so we're better off not using it.
71- if (slen == rlen ) {
72- err = err_from_str ("readlink truncated destination path" );
73- goto end ;
74- }
75-
76- // Otherwise, add the trailing null to the destination path that readlink omitted.
77- (* rpath )[rlen ] = 0 ;
78-
79- end :
80- if (err != NULL ) {
81- FREE (* rpath );
82- }
83-
84- return err ;
85- }
86-
87- #endif /* __linux__ */
88-
8915/*
9016 * get_pex_dir stores the path to the .pex file in pex_dir. It returns NULL on success and an error
9117 * on failure.
@@ -96,8 +22,8 @@ err_t *get_pex_dir(char **pex_dir) {
9622 err_t * err = NULL ;
9723
9824#if defined(__linux__ )
99- if ((err = get_link_path ("/proc/self/exe" , & exe_path )) ! = NULL ) {
100- err = err_wrap ( "get_link_path" , err );
25+ if ((exe_path = realpath ("/proc/self/exe" , NULL )) = = NULL ) {
26+ err = err_from_errno ( "realpath /proc/self/exe" );
10127 goto end ;
10228 }
10329#elif defined(__APPLE__ )
0 commit comments