X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fos_installation.c;h=ea6361a92db4424ef6006132db4b35eea93844d5;hb=cf5a23aa7d5d939038b78ff6ce47ceb5665281bb;hp=2c678386a207853e5f407adfef1ef10837393ca2;hpb=b8b5cde28eadfb0e2092df808f446115d87d0f0d;p=oweals%2Fgnunet.git diff --git a/src/util/os_installation.c b/src/util/os_installation.c index 2c678386a..ea6361a92 100644 --- a/src/util/os_installation.c +++ b/src/util/os_installation.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2006 Christian Grothoff (and other contributing authors) + Copyright (C) 2006-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -30,11 +30,7 @@ #include /* for u16_to_u8 */ #include "platform.h" -#include "gnunet_common.h" -#include "gnunet_configuration_lib.h" -#include "gnunet_disk_lib.h" -#include "gnunet_os_lib.h" -#include "gnunet_strings_lib.h" +#include "gnunet_util_lib.h" #if DARWIN #include #include @@ -47,6 +43,7 @@ #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) + #if LINUX /** * Try to determine path by reading /proc/PID/exe @@ -68,7 +65,7 @@ get_path_from_proc_maps () while (NULL != fgets (line, sizeof (line), f)) { if ((1 == - SSCANF (line, "%*x-%*x %*c%*c%*c%*c %*x %*2u:%*2u %*u%*[ ]%1023s", dir)) && + SSCANF (line, "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%1023s", dir)) && (NULL != (lgu = strstr (dir, "libgnunetutil")))) { lgu[0] = '\0'; @@ -104,7 +101,7 @@ get_path_from_proc_exe () lnk[size] = '\0'; while ((lnk[size] != '/') && (size > 0)) size--; - /* test for being in lib/gnunet/libexec/ */ + /* test for being in lib/gnunet/libexec/ or lib/MULTIARCH/gnunet/libexec */ if ( (size > strlen ("/gnunet/libexec/")) && (0 == strcmp ("/gnunet/libexec/", &lnk[size - strlen ("/gnunet/libexec/")])) ) @@ -119,12 +116,13 @@ get_path_from_proc_exe () } #endif -#if WINDOWS +#if WINDOWS static HINSTANCE dll_instance; -/* GNUNET_util_cl_init() in common_logging.c is preferred. +/** + * GNUNET_util_cl_init() in common_logging.c is preferred. * This function is only for thread-local storage (not used in GNUnet) * and hInstance saving. */ @@ -175,7 +173,7 @@ get_path_from_module_filename () real_pathlen = GetModuleFileNameW (dll_instance, modulepath, pathlen * sizeof (wchar_t)); } while (real_pathlen >= pathlen && pathlen < 16*1024); if (real_pathlen >= pathlen) - GNUNET_abort (); + GNUNET_assert (0); /* To be safe */ modulepath[real_pathlen] = '\0'; @@ -217,7 +215,7 @@ get_path_from_module_filename () /* modulepath is GNUNET_PREFIX */ u8_string = u16_to_u8 (modulepath, wcslen (modulepath), NULL, &u8_string_length); if (NULL == u8_string) - GNUNET_abort (); + GNUNET_assert (0); upath = GNUNET_malloc (u8_string_length + 1); memcpy (upath, u8_string, u8_string_length); @@ -230,6 +228,7 @@ get_path_from_module_filename () } #endif + #if DARWIN /** * Signature of the '_NSGetExecutablePath" function. @@ -295,7 +294,7 @@ get_path_from_dyld_image () c = _dyld_image_count (); for (i = 0; i < c; i++) { - if (_dyld_get_image_header (i) != &_mh_dylib_header) + if (((const void *) _dyld_get_image_header (i)) != (const void *)&_mh_dylib_header) continue; path = _dyld_get_image_name (i); if ( (NULL == path) || (0 == strlen (path)) ) @@ -419,8 +418,7 @@ os_get_gnunet_path () return ret; /* other attempts here */ LOG (GNUNET_ERROR_TYPE_ERROR, - _ - ("Could not determine installation path for %s. Set `%s' environment variable.\n"), + _("Could not determine installation path for %s. Set `%s' environment variable.\n"), "GNUnet", "GNUNET_PREFIX"); return NULL; } @@ -456,7 +454,7 @@ os_get_exec_path () /** * @brief get the path to a specific GNUnet installation directory or, - * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory + * with #GNUNET_OS_IPK_SELF_PREFIX, the current running apps installation directory * @author Milan * @return a pointer to the dir path (to be freed by the caller) */ @@ -467,6 +465,8 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) const char *dirname; char *execpath = NULL; char *tmp; + char *multiarch; + char *libdir; int isbasedir; /* if wanted, try to get the current app's bin/ */ @@ -515,6 +515,17 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) execpath[n - 4] = '\0'; n -= 4; } + multiarch = NULL; + if (NULL != (libdir = strstr (execpath, "/lib/"))) + { + /* test for multi-arch path of the form "PREFIX/lib/MULTIARCH/"; + here we need to re-add 'multiarch' to lib and libexec paths later! */ + multiarch = &libdir[5]; + if (NULL == strchr (multiarch, '/')) + libdir[0] = '\0'; /* Debian multiarch format, cut of from 'execpath' but preserve in multicarch */ + else + multiarch = NULL; /* maybe not, multiarch still has a '/', which is not OK */ + } /* in case this was a directory named foo-bin, remove "foo-" */ while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR)) execpath[--n] = '\0'; @@ -530,31 +541,50 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) case GNUNET_OS_IPK_LIBDIR: if (isbasedir) { - dirname = - DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; - tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); - sprintf (tmp, "%s%s", execpath, dirname); - if ( (GNUNET_YES != - GNUNET_DISK_directory_test (tmp, GNUNET_YES)) && - (4 == sizeof (void *)) ) + GNUNET_asprintf (&tmp, + "%s%s%s%s%s", + execpath, + DIR_SEPARATOR_STR "lib", + (NULL != multiarch) ? DIR_SEPARATOR_STR : "", + (NULL != multiarch) ? multiarch : "", + DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR); + if (GNUNET_YES == + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) + { + GNUNET_free (execpath); + return tmp; + } + GNUNET_free (tmp); + tmp = NULL; + if (4 == sizeof (void *)) { - GNUNET_free (tmp); dirname = DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; - tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); - sprintf (tmp, "%s%s", execpath, dirname); + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); } - if ( (GNUNET_YES != - GNUNET_DISK_directory_test (tmp, GNUNET_YES)) && - (8 == sizeof (void *)) ) + if (8 == sizeof (void *)) { dirname = DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); + } + + if ( (NULL != tmp) && + (GNUNET_YES == + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) ) + { + GNUNET_free (execpath); + return tmp; } GNUNET_free (tmp); } - else - dirname = DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; + dirname = DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; break; case GNUNET_OS_IPK_DATADIR: dirname = @@ -577,42 +607,63 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) if (isbasedir) { dirname = - DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ - "libexec" DIR_SEPARATOR_STR; - tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); - sprintf (tmp, "%s%s", execpath, dirname); - if ( (GNUNET_YES != - GNUNET_DISK_directory_test (tmp, GNUNET_YES)) && - (4 == sizeof (void *)) ) + DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR "libexec" DIR_SEPARATOR_STR; + GNUNET_asprintf (&tmp, + "%s%s%s%s", + execpath, + DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR, + (NULL != multiarch) ? multiarch : "", + dirname); + if (GNUNET_YES == + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) + { + GNUNET_free (execpath); + return tmp; + } + GNUNET_free (tmp); + tmp = NULL; + if (4 == sizeof (void *)) { - GNUNET_free (tmp); dirname = DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ "libexec" DIR_SEPARATOR_STR; - tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); - sprintf (tmp, "%s%s", execpath, dirname); + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); } - if ( (GNUNET_YES != - GNUNET_DISK_directory_test (tmp, GNUNET_YES)) && - (8 == sizeof (void *)) ) + if (8 == sizeof (void *)) { dirname = DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ "libexec" DIR_SEPARATOR_STR; + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); + } + if ( (NULL != tmp) && + (GNUNET_YES == + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) ) + { + GNUNET_free (execpath); + return tmp; } + GNUNET_free (tmp); } - else - dirname = - DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ - "libexec" DIR_SEPARATOR_STR; + dirname = + DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ + "libexec" DIR_SEPARATOR_STR; break; default: GNUNET_free (execpath); return NULL; } - tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); - sprintf (tmp, "%s%s", execpath, dirname); + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); GNUNET_free (execpath); return tmp; } @@ -629,21 +680,24 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) char * GNUNET_OS_get_libexec_binary_path (const char *progname) { + static char *cache; char *libexecdir; char *binary; - if (DIR_SEPARATOR == progname[0]) - return GNUNET_strdup (progname); - if (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (progname, GNUNET_NO, NULL, NULL)) + if ( (DIR_SEPARATOR == progname[0]) || + (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (progname, GNUNET_NO, NULL, NULL)) ) return GNUNET_strdup (progname); - libexecdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR); + if (NULL != cache) + libexecdir = cache; + else + libexecdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR); if (NULL == libexecdir) return GNUNET_strdup (progname); GNUNET_asprintf (&binary, "%s%s", libexecdir, progname); - GNUNET_free (libexecdir); + cache = libexecdir; return binary; } @@ -661,12 +715,14 @@ GNUNET_OS_get_libexec_binary_path (const char *progname) * binary with the -d flag. -d omits a programs main loop and only * executes all privileged operations in an binary. * @param params parameters used for w32 privilege checking (can be NULL for != w32 ) - * @return GNUNET_YES if the file is SUID (*nix) or can be executed with current privileges (W32), - * GNUNET_NO if not SUID (but binary exists), - * GNUNET_SYSERR on error (no such binary or not executable) + * @return #GNUNET_YES if the file is SUID (*nix) or can be executed with current privileges (W32), + * #GNUNET_NO if not SUID (but binary exists), + * #GNUNET_SYSERR on error (no such binary or not executable) */ int -GNUNET_OS_check_helper_binary (const char *binary, int check_suid, const char *params) +GNUNET_OS_check_helper_binary (const char *binary, + int check_suid, + const char *params) { struct stat statbuf; char *p; @@ -708,7 +764,8 @@ GNUNET_OS_check_helper_binary (const char *binary, int check_suid, const char *p #endif if (NULL == p) { - LOG (GNUNET_ERROR_TYPE_INFO, _("Could not find binary `%s' in PATH!\n"), + LOG (GNUNET_ERROR_TYPE_INFO, + _("Could not find binary `%s' in PATH!\n"), binary); return GNUNET_SYSERR; } @@ -745,16 +802,16 @@ GNUNET_OS_check_helper_binary (const char *binary, int check_suid, const char *p char parameters[512]; PROCESS_INFORMATION proc; DWORD exit_value; - - GNUNET_snprintf (parameters, - sizeof (parameters), + + GNUNET_snprintf (parameters, + sizeof (parameters), "-d %s", params); memset (&start, 0, sizeof (start)); start.cb = sizeof (start); memset (&proc, 0, sizeof (proc)); - - // Start the child process. + + // Start the child process. if ( ! (CreateProcess( p, // current windows (2k3 and up can handle / instead of \ in paths)) parameters, // execute dryrun/priviliege checking mode NULL, // Process handle not inheritable @@ -762,12 +819,12 @@ GNUNET_OS_check_helper_binary (const char *binary, int check_suid, const char *p FALSE, // Set handle inheritance to FALSE CREATE_DEFAULT_ERROR_MODE, // No creation flags NULL, // Use parent's environment block - NULL, // Use parent's starting directory + NULL, // Use parent's starting directory &start, // Pointer to STARTUPINFO structure &proc ) // Pointer to PROCESS_INFORMATION structure - )) + )) { - LOG (GNUNET_ERROR_TYPE_ERROR, + LOG (GNUNET_ERROR_TYPE_ERROR, _("CreateProcess failed for binary %s (%d).\n"), p, GetLastError()); return GNUNET_SYSERR; @@ -775,17 +832,17 @@ GNUNET_OS_check_helper_binary (const char *binary, int check_suid, const char *p // Wait until child process exits. WaitForSingleObject( proc.hProcess, INFINITE ); - + if ( ! GetExitCodeProcess (proc.hProcess, &exit_value)){ - LOG (GNUNET_ERROR_TYPE_ERROR, - _("GetExitCodeProcess failed for binary %s (%d).\n"), + LOG (GNUNET_ERROR_TYPE_ERROR, + _("GetExitCodeProcess failed for binary %s (%d).\n"), p, GetLastError() ); return GNUNET_SYSERR; } - // Close process and thread handles. + // Close process and thread handles. CloseHandle( proc.hProcess ); CloseHandle( proc.hThread ); - + if (!exit_value) return GNUNET_YES; #endif