|
@@ -28,23 +28,27 @@
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
+#include "config.h"
|
|
|
+#include "configuration.h"
|
|
|
+#include "container-executor.h"
|
|
|
+
|
|
|
#include <errno.h>
|
|
|
#include <stdio.h>
|
|
|
#include <string.h>
|
|
|
#include <stdlib.h>
|
|
|
#include <unistd.h>
|
|
|
-#include "config.h"
|
|
|
-#include "configuration.h"
|
|
|
-#include "container-executor.h"
|
|
|
+
|
|
|
+#ifdef HAVE_SYS_SYSCTL_H
|
|
|
+#include <sys/types.h>
|
|
|
+#include <sys/param.h>
|
|
|
+#include <sys/sysctl.h>
|
|
|
+#endif
|
|
|
|
|
|
/*
|
|
|
* A generic function to read a link and return
|
|
|
* the value for use with System V procfs.
|
|
|
* With much thanks to Tom Killian, Roger Faulkner,
|
|
|
* and Ron Gomes, this is pretty generic code.
|
|
|
- *
|
|
|
- * The various BSDs do not have (reliably)
|
|
|
- * have /proc. Custom implementations follow.
|
|
|
*/
|
|
|
|
|
|
char *__get_exec_readproc(char *procfn) {
|
|
@@ -53,7 +57,7 @@ char *__get_exec_readproc(char *procfn) {
|
|
|
|
|
|
filename = malloc(EXECUTOR_PATH_MAX);
|
|
|
if (!filename) {
|
|
|
- fprintf(ERRORFILE,"cannot allocate memory for filename: %s\n",strerror(errno));
|
|
|
+ fprintf(ERRORFILE,"cannot allocate memory for filename before readlink: %s\n",strerror(errno));
|
|
|
exit(-1);
|
|
|
}
|
|
|
len = readlink(procfn, filename, EXECUTOR_PATH_MAX);
|
|
@@ -62,14 +66,45 @@ char *__get_exec_readproc(char *procfn) {
|
|
|
strerror(errno));
|
|
|
exit(-1);
|
|
|
} else if (len >= EXECUTOR_PATH_MAX) {
|
|
|
- fprintf(ERRORFILE,"Executable name %.*s is longer than %d characters.\n",
|
|
|
- EXECUTOR_PATH_MAX, filename, EXECUTOR_PATH_MAX);
|
|
|
+ fprintf(ERRORFILE,"Resolved path for %s [%s] is longer than %d characters.\n",
|
|
|
+ procfn, filename, EXECUTOR_PATH_MAX);
|
|
|
exit(-1);
|
|
|
}
|
|
|
filename[len] = '\0';
|
|
|
return filename;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+#ifdef HAVE_SYSCTL
|
|
|
+/*
|
|
|
+ * A generic function to ask the kernel via sysctl.
|
|
|
+ * This is used by most of the open source BSDs, as
|
|
|
+ * many do not reliably have a /proc mounted.
|
|
|
+ */
|
|
|
+
|
|
|
+char *__get_exec_sysctl(int *mib)
|
|
|
+{
|
|
|
+ char buffer[EXECUTOR_PATH_MAX];
|
|
|
+ char *filename;
|
|
|
+ size_t len;
|
|
|
+
|
|
|
+ len = sizeof(buffer);
|
|
|
+ if (sysctl(mib, 4, buffer, &len, NULL, 0) == -1) {
|
|
|
+ fprintf(ERRORFILE,"Can't get executable name from kernel: %s\n",
|
|
|
+ strerror(errno));
|
|
|
+ exit(-1);
|
|
|
+ }
|
|
|
+ filename=malloc(EXECUTOR_PATH_MAX);
|
|
|
+ if (!filename) {
|
|
|
+ fprintf(ERRORFILE,"cannot allocate memory for filename after sysctl: %s\n",strerror(errno));
|
|
|
+ exit(-1);
|
|
|
+ }
|
|
|
+ snprintf(filename,EXECUTOR_PATH_MAX,"%s",buffer);
|
|
|
+ return filename;
|
|
|
+}
|
|
|
+
|
|
|
+#endif /* HAVE_SYSCTL */
|
|
|
+
|
|
|
#ifdef __APPLE__
|
|
|
|
|
|
/*
|
|
@@ -80,13 +115,13 @@ char *__get_exec_readproc(char *procfn) {
|
|
|
|
|
|
#include <libproc.h>
|
|
|
|
|
|
-char* get_executable() {
|
|
|
+char* get_executable(char *argv0) {
|
|
|
char *filename;
|
|
|
pid_t pid;
|
|
|
|
|
|
filename = malloc(PROC_PIDPATHINFO_MAXSIZE);
|
|
|
if (!filename) {
|
|
|
- fprintf(ERRORFILE,"cannot allocate memory for filename: %s\n",strerror(errno));
|
|
|
+ fprintf(ERRORFILE,"cannot allocate memory for filename before proc_pidpath: %s\n",strerror(errno));
|
|
|
exit(-1);
|
|
|
}
|
|
|
pid = getpid();
|
|
@@ -98,13 +133,33 @@ char* get_executable() {
|
|
|
return filename;
|
|
|
}
|
|
|
|
|
|
+#elif defined(__FreeBSD__)
|
|
|
+
|
|
|
+char* get_executable(char *argv0) {
|
|
|
+ static int mib[] = {
|
|
|
+ CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1
|
|
|
+ };
|
|
|
+ return __get_exec_sysctl(mib);
|
|
|
+}
|
|
|
+
|
|
|
#elif defined(__linux)
|
|
|
|
|
|
|
|
|
-char* get_executable() {
|
|
|
+char* get_executable(char *argv0) {
|
|
|
return __get_exec_readproc("/proc/self/exe");
|
|
|
}
|
|
|
|
|
|
+#elif defined(__NetBSD__) && defined(KERN_PROC_PATHNAME)
|
|
|
+
|
|
|
+/* Only really new NetBSD kernels have KERN_PROC_PATHNAME */
|
|
|
+
|
|
|
+char* get_executable(char *argv0) {
|
|
|
+ static int mib[] = {
|
|
|
+ CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME,
|
|
|
+ };
|
|
|
+ return __get_exec_sysctl(mib);
|
|
|
+}
|
|
|
+
|
|
|
#elif defined(__sun)
|
|
|
|
|
|
/*
|
|
@@ -116,12 +171,45 @@ char* get_executable() {
|
|
|
* doesn't exist on Solaris hasn't read the proc(4) man page.)
|
|
|
*/
|
|
|
|
|
|
-char* get_executable() {
|
|
|
+char* get_executable(char *argv0) {
|
|
|
return __get_exec_readproc("/proc/self/path/a.out");
|
|
|
}
|
|
|
|
|
|
-#else
|
|
|
+#elif defined(HADOOP_CONF_DIR_IS_ABS)
|
|
|
|
|
|
-#error Cannot safely determine executable path on this operating system.
|
|
|
+/*
|
|
|
+ * This is the fallback for operating systems where
|
|
|
+ * we don't know how to ask the kernel where the executable
|
|
|
+ * is located. It is only used if the maven property
|
|
|
+ * container-executor.conf.dir is set to an absolute path
|
|
|
+ * for security reasons.
|
|
|
+ */
|
|
|
+
|
|
|
+char* get_executable (char *argv0) {
|
|
|
+ char *filename;
|
|
|
|
|
|
+#ifdef HAVE_CANONICALIZE_FILE_NAME
|
|
|
+ filename=canonicalize_file_name(argv0);
|
|
|
+#else
|
|
|
+ filename=realpath(argv0,NULL);
|
|
|
#endif
|
|
|
+
|
|
|
+ if (!filename) {
|
|
|
+ fprintf(ERRORFILE,"realpath of executable: %s\n",strerror(errno));
|
|
|
+ exit(-1);
|
|
|
+ }
|
|
|
+ return filename;
|
|
|
+}
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+/*
|
|
|
+ * If we ended up here, we're on an operating system that doesn't
|
|
|
+ * match any of the above. This means either the OS needs to get a
|
|
|
+ * code added or the container-executor.conf.dir maven property
|
|
|
+ * should be set to an absolute path.
|
|
|
+ */
|
|
|
+
|
|
|
+#error Cannot safely determine executable path with a relative HADOOP_CONF_DIR on this operating system.
|
|
|
+
|
|
|
+#endif /* platform checks */
|