Changeset: 32dd30dd5d72 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=32dd30dd5d72
Modified Files:
        common/utils/mutils.c
        common/utils/mutils.h
Branch: Apr2011
Log Message:

get_bin_path: make sure the returned string is absolute

On Darwin and Solaris, the methods to retrieve the path to the
executable are not absolute by definition.  On Darwin it can contain a
leading ./, on both traversals in the path itself are copied as is (e.g.
/../../).
Make sure we realpath this, and make them absolute, such that the
assumptions we make in mserver5 and merovingian are correct.

Thanks Holger for pointing out this problem.


diffs (99 lines):

diff --git a/common/utils/mutils.c b/common/utils/mutils.c
--- a/common/utils/mutils.c
+++ b/common/utils/mutils.c
@@ -22,12 +22,21 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <stdlib.h>
 #include "mutils.h"
 
 #ifdef HAVE_MACH_O_DYLD_H
 # include <mach-o/dyld.h>  /* _NSGetExecutablePath on OSX >=10.5 */
 #endif
 
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>  /* realpath on OSX */
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>  /* PATH_MAX on Solaris */
+#endif
+
 #ifdef NATIVE_WIN32
 
 #include <stdio.h>
@@ -283,7 +292,10 @@
 
 #endif
 
-static char _bin_path[1024];
+#ifndef PATH_MAX
+# define PATH_MAX 1024
+#endif
+static char _bin_path[PATH_MAX];
 char *
 get_bin_path(void)
 {
@@ -294,9 +306,11 @@
                              (DWORD) sizeof(_bin_path)) != 0)
                return _bin_path;
 #elif defined(HAVE__NSGETEXECUTABLEPATH)  /* Darwin/OSX */
-       uint32_t size = sizeof(_bin_path);
-       if (_NSGetExecutablePath(_bin_path, &size) == 0)
-               return _bin_path;
+       char buf[PATH_MAX];
+       uint32_t size = PATH_MAX;
+       if (_NSGetExecutablePath(buf, &size) == 0 &&
+                       realpath(buf, _bin_path) != NULL)
+       return _bin_path;
 #elif defined(HAVE_SYS_SYSCTL_H) && defined(KERN_PROC_PATHNAME)  /* BSD */
        int mib[4];
        size_t cb = sizeof(_bin_path);
@@ -307,15 +321,27 @@
        if (sysctl(mib, 4, _bin_path, &cb, NULL, 0) == 0)
                return _bin_path;
 #elif defined(HAVE_GETEXECNAME)  /* Solaris */
+       char buf[PATH_MAX];
        const char *execn = getexecname();
-       /* copy, such that the caller can actually modify this string */
-       snprintf(_bin_path, sizeof(_bin_path), "%s", execn);
-       return _bin_path;
+       /* getexecname doesn't always return an absolute path, the only
+        * thing it seems to do is strip leading ./ from the invocation
+        * string. */
+       if (*execn != '/') {
+               if (getcwd(buf, PATH_MAX) != NULL) {
+                       snprintf(buf + strlen(buf), PATH_MAX, "/%s", execn);
+                       if (realpath(buf, _bin_path) != NULL)
+                               return(_bin_path);
+               }
+       } else {
+               if (realpath(execn, _bin_path) != NULL)
+                       return(_bin_path);
+       }
 #else  /* try Linux approach */
        if (readlink("/proc/self/exe",
                                _bin_path, sizeof(_bin_path)) != -1)
                        return _bin_path;
 #endif
-       /* could use argv[0] (passed) to deduce location based on PATH */
+       /* could use argv[0] (passed) to deduce location based on PATH, but
+        * that's a lot of work and unreliable */
        return NULL;
 }
diff --git a/common/utils/mutils.h b/common/utils/mutils.h
--- a/common/utils/mutils.h
+++ b/common/utils/mutils.h
@@ -72,6 +72,11 @@
 
 mutils_export int MT_lockf(char *filename, int mode, off_t off, off_t len);
 
+/* Retrieves the absolute path to the executable being run, with no
+ * extra /, /./, or /../ sequences.  On Darwin and Solaris this function
+ * needs to be called before any chdirs are performed.  Returns a
+ * pointer to a static buffer that is overwritten by subsequent calls to
+ * this function. */
 mutils_export char *get_bin_path(void);
 
 #endif /* _MUTILS_H_ */
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to