Added autodetect installdirs component. Currently supports Solaris and Linux.
* Installation directories will be inferred from the actual location of the shared library that contains the component. * OPAL_PREFIX and other environment variables allow users to override the inferred directories. They should no longer be necessary in most cases, though. * Any directories that cannot be inferred will fall back to whatever is provided by the config installdirs component. This commit was SVN r21723.
Этот коммит содержится в:
родитель
b3e0c79275
Коммит
2250be582d
1
AUTHORS
1
AUTHORS
@ -32,6 +32,7 @@ gwatson Greg Watson LANL
|
||||
herault Thomas Herault INRIA
|
||||
hpcstork Sven Stork HLRS
|
||||
htor Torsten Hoefler IU, TUC
|
||||
igb Iain Bason Sun
|
||||
jdmason Jon Mason Chelsio
|
||||
jjhursey Josh Hursey IU, ORNL, LANL, LBNL
|
||||
jnysal Nysal Jan IBM
|
||||
|
7
NEWS
7
NEWS
@ -10,7 +10,7 @@ Copyright (c) 2004-2006 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
Copyright (c) 2006-2009 Cisco Systems, Inc. All rights reserved.
|
||||
Copyright (c) 2006 Voltaire, Inc. All rights reserved.
|
||||
Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
Copyright (c) 2006-2009 Sun Microsystems, Inc. All rights reserved.
|
||||
Use is subject to license terms.
|
||||
Copyright (c) 2006-2007 Los Alamos National Security, LLC. All rights
|
||||
reserved.
|
||||
@ -32,6 +32,11 @@ Trunk (not on release branches yet)
|
||||
- Added Cray Compute Node Linux (CNL) and ALPS Support.
|
||||
--> Expected: ???
|
||||
|
||||
- Added automatic detection of installation directories for
|
||||
Solaris and Linux. The OPAL_PREFIX and OPAL_DESTDIR
|
||||
environment variables no longer need to be set when binaries
|
||||
are installed in non-default locations.
|
||||
|
||||
1.5
|
||||
---
|
||||
|
||||
|
26
opal/mca/installdirs/autodetect/Makefile.am
Обычный файл
26
opal/mca/installdirs/autodetect/Makefile.am
Обычный файл
@ -0,0 +1,26 @@
|
||||
#
|
||||
# Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
noinst_LTLIBRARIES = libmca_installdirs_autodetect.la
|
||||
|
||||
libmca_installdirs_autodetect_la_SOURCES = opal_installdirs_autodetect_component.c
|
||||
|
||||
EXTRA_libmca_installdirs_autodetect_la_SOURCES = \
|
||||
opal_installdirs_solaris.c \
|
||||
opal_installdirs_linux.c \
|
||||
opal_installdirs_backtrace.c \
|
||||
opal_installdirs_walkcontext.c
|
||||
|
||||
libmca_installdirs_autodetect_la_LIBADD = \
|
||||
$(OMPI_INSTALLDIRS_AUTODETECT_PATH) \
|
||||
$(OMPI_INSTALLDIRS_AUTODETECT_PC)
|
||||
|
||||
libmca_installdirs_autodetect_la_DEPENDENCIES = \
|
||||
$(OMPI_INSTALLDIRS_AUTODETECT_PATH) \
|
||||
$(OMPI_INSTALLDIRS_AUTODETECT_PC)
|
65
opal/mca/installdirs/autodetect/configure.m4
Обычный файл
65
opal/mca/installdirs/autodetect/configure.m4
Обычный файл
@ -0,0 +1,65 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
AC_DEFUN([MCA_installdirs_autodetect_COMPILE_MODE], [
|
||||
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])
|
||||
$4="static"
|
||||
AC_MSG_RESULT([$$4])
|
||||
])
|
||||
|
||||
|
||||
# MCA_installdirs_autodetect_CONFIG(action-if-can-compile,
|
||||
# [action-if-cant-compile])
|
||||
# ------------------------------------------------
|
||||
#
|
||||
# Solaris uses a binary-format /proc/$$/map file that contains a
|
||||
# sequence of prmap_t structures. Those can be used to look up
|
||||
# associated files in /proc/$$/path, which are symbolic links to
|
||||
# the actual files.
|
||||
#
|
||||
# AIX has /proc/$$/map and /proc/$$/object, but no /proc/$$/path.
|
||||
# I don't know how to achieve autodetect functionality on AIX.
|
||||
#
|
||||
# Linux has /proc/self/maps that contains text with both virtual
|
||||
# addresses and paths. (Under Linux 2.0 there are no paths. I
|
||||
# don't know how to achieve autodetect functionality on such
|
||||
# systems.)
|
||||
|
||||
AC_DEFUN([MCA_installdirs_autodetect_CONFIG],[
|
||||
AC_CHECK_HEADERS(procfs.h,
|
||||
[AC_CHECK_FILE(/proc/$$/path,
|
||||
[procfs_path_happy="yes"
|
||||
OMPI_INSTALLDIRS_AUTODETECT_PATH=opal_installdirs_solaris.lo],
|
||||
[procfs_path_happy="no"])],
|
||||
[AC_CHECK_FILE(/proc/self/maps,
|
||||
[procfs_path_happy="yes"
|
||||
OMPI_INSTALLDIRS_AUTODETECT_PATH=opal_installdirs_linux.lo],
|
||||
[procfs_path_happy="no"])])
|
||||
|
||||
AS_IF([test "$procfs_path_happy" = "yes"],[
|
||||
# The following check is from opal/mca/backtrace/execinfo/configure.m4
|
||||
AC_CHECK_HEADERS([execinfo.h],[
|
||||
# FreeBSD has backtrace in -lexecinfo, usually in libc
|
||||
OMPI_CHECK_FUNC_LIB([backtrace], [execinfo],
|
||||
[findpc_happy="yes"
|
||||
OMPI_INSTALLDIRS_AUTODETECT_PC=opal_installdirs_backtrace.lo],
|
||||
[findpc_happy="no"])])
|
||||
|
||||
AS_IF([test "$backtrace_execinfo_happy" = "no"],[
|
||||
AC_CHECK_HEADERS([ucontext.h],[
|
||||
OMPI_CHECK_FUNC_LIB([walkcontext],,
|
||||
[findpc_happy="yes"
|
||||
OMPI_INSTALLDIRS_AUTODETECT_PC=opal_installdirs_walkcontext.lo],
|
||||
[findpc_happy="no"])])])])
|
||||
|
||||
AS_IF([test "$procfs_path_happy" = "yes" -a "$findpc_happy" = "yes"],[
|
||||
AC_SUBST([OMPI_INSTALLDIRS_AUTODETECT_PATH])
|
||||
AC_SUBST([OMPI_INSTALLDIRS_AUTODETECT_PC])
|
||||
$1],[$2])])
|
15
opal/mca/installdirs/autodetect/configure.params
Обычный файл
15
opal/mca/installdirs/autodetect/configure.params
Обычный файл
@ -0,0 +1,15 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# Copyright (c) 2006 Los Alamos National Security, LLC. All rights
|
||||
# reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
# Specific to this module
|
||||
|
||||
PARAM_CONFIG_PRIORITY=5
|
||||
PARAM_CONFIG_FILES="Makefile"
|
@ -0,0 +1,181 @@
|
||||
/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
* This module automatically detects the path to itself, and
|
||||
* instructs the base install_dirs module to infer the prefix
|
||||
* from that.
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#include "opal/constants.h"
|
||||
#include "opal/mca/mca.h"
|
||||
#include "opal/mca/installdirs/installdirs.h"
|
||||
#include "opal/util/basename.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int opal_installdirs_autodetect_open(void);
|
||||
|
||||
opal_installdirs_base_component_t mca_installdirs_autodetect_component = {
|
||||
/* First, the mca_component_t struct containing meta information
|
||||
about the component itself */
|
||||
{
|
||||
OPAL_INSTALLDIRS_BASE_VERSION_2_0_0,
|
||||
|
||||
/* Component name and version */
|
||||
"autodetect",
|
||||
OPAL_MAJOR_VERSION,
|
||||
OPAL_MINOR_VERSION,
|
||||
OPAL_RELEASE_VERSION,
|
||||
|
||||
/* Component open and close functions */
|
||||
opal_installdirs_autodetect_open,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
/* This component is Checkpointable */
|
||||
MCA_BASE_METADATA_PARAM_CHECKPOINT
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Determine whether the load object is an executable or a shared library.
|
||||
* The code only works for ELF files. The values and offsets are cribbed
|
||||
* from the "file" command's magic number file.
|
||||
*/
|
||||
|
||||
typedef enum { executable, shared_object, unknown_object } load_obj_t;
|
||||
|
||||
static load_obj_t
|
||||
whatis(const char *path)
|
||||
{
|
||||
int fd;
|
||||
char buf[18];
|
||||
uint16_t *kind;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return unknown_object;
|
||||
}
|
||||
|
||||
if (read(fd, buf, sizeof(buf)) < sizeof(buf)) {
|
||||
close(fd);
|
||||
return unknown_object;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (strncmp(buf, "\177ELF", 4) != 0) {
|
||||
return unknown_object;
|
||||
}
|
||||
|
||||
kind = (uint16_t*)&buf[16];
|
||||
if (2 == *kind) {
|
||||
return executable;
|
||||
} else if (3 == *kind) {
|
||||
return shared_object;
|
||||
} else {
|
||||
return unknown_object;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* OS-dependent function to get the address of some instruction in
|
||||
* this module. We cannot in general just do &func, because if the
|
||||
* module is in a shared library that can return some other address.
|
||||
* (On Solaris, for example, it will return the address of an entry in
|
||||
* the PLT of the program, rather than the shared library.)
|
||||
*/
|
||||
|
||||
uintptr_t opal_installdirs_autodetect_pc(void);
|
||||
|
||||
/*
|
||||
* OS-dependent function to find the path to the executable or shared
|
||||
* library that contains the given address in the process' address
|
||||
* space.
|
||||
*/
|
||||
|
||||
const char *opal_installdirs_autodetect_path(uintptr_t);
|
||||
|
||||
static int
|
||||
opal_installdirs_autodetect_open(void)
|
||||
{
|
||||
uintptr_t my_addr;
|
||||
const char *path;
|
||||
const char *my_dir;
|
||||
const char *infer_from;
|
||||
|
||||
if (getenv("OPAL_DESTDIR") != NULL) {
|
||||
/*
|
||||
* OPAL_DESTDIR does not play well with autodetect. We
|
||||
* certainly don't want it to be used as a prefix for the actual
|
||||
* installed path. We could try to inhibit it only for those
|
||||
* paths that cannot be inferred from the actual installed
|
||||
* path, but it is simpler just to assume the user wants no
|
||||
* auto detection if OPAL_DESTDIR is set.
|
||||
*/
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
my_addr = opal_installdirs_autodetect_pc();
|
||||
if (0 == my_addr) {
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
path = opal_installdirs_autodetect_path(my_addr);
|
||||
if (NULL == path) {
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
my_dir = opal_dirname(path);
|
||||
if (NULL == my_dir) {
|
||||
free(path);
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
switch(whatis(path)) {
|
||||
case executable:
|
||||
mca_installdirs_autodetect_component.install_dirs_data.bindir = my_dir;
|
||||
infer_from = "${infer-bindir}";
|
||||
mca_installdirs_autodetect_component.install_dirs_data.libdir = infer_from;
|
||||
break;
|
||||
case shared_object:
|
||||
mca_installdirs_autodetect_component.install_dirs_data.libdir = my_dir;
|
||||
infer_from = "${infer-libdir}";
|
||||
mca_installdirs_autodetect_component.install_dirs_data.bindir = infer_from;
|
||||
break;
|
||||
default:
|
||||
free(my_dir);
|
||||
free(path);
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
free(path);
|
||||
|
||||
mca_installdirs_autodetect_component.install_dirs_data.prefix = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.exec_prefix = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.sbindir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.libexecdir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.datarootdir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.datadir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.sysconfdir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.sharedstatedir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.localstatedir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.includedir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.infodir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.mandir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.pkgdatadir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.pkglibdir = infer_from;
|
||||
mca_installdirs_autodetect_component.install_dirs_data.pkgincludedir = infer_from;
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
23
opal/mca/installdirs/autodetect/opal_installdirs_backtrace.c
Обычный файл
23
opal/mca/installdirs/autodetect/opal_installdirs_backtrace.c
Обычный файл
@ -0,0 +1,23 @@
|
||||
/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#include <execinfo.h>
|
||||
|
||||
uintptr_t
|
||||
opal_installdirs_autodetect_pc()
|
||||
{
|
||||
void *pc = 0;
|
||||
|
||||
backtrace(&pc, 1);
|
||||
return pc;
|
||||
}
|
188
opal/mca/installdirs/autodetect/opal_installdirs_linux.c
Обычный файл
188
opal/mca/installdirs/autodetect/opal_installdirs_linux.c
Обычный файл
@ -0,0 +1,188 @@
|
||||
/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
* Read /proc/self/maps to find the path to the file containing
|
||||
* an address.
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
#include "opal_stdint.h"
|
||||
|
||||
#include "opal/constants.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
uintptr_t read_addr(FILE *);
|
||||
int skip_fields(FILE *, int);
|
||||
int read_path(FILE *);
|
||||
int skip_line(FILE *);
|
||||
|
||||
const char *
|
||||
opal_installdirs_autodetect_path(uintptr_t my_addr)
|
||||
{
|
||||
FILE *f;
|
||||
uintptr_t lo_start, lo_end;
|
||||
|
||||
f = fopen("/proc/self/maps", "r");
|
||||
if (NULL == f) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
lo_start = read_addr(f);
|
||||
if (0 == lo_start) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
lo_end = read_addr(f);
|
||||
if (0 == lo_end) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
if (lo_start <= my_addr && lo_end > my_addr) {
|
||||
const char *path, *my_dir;
|
||||
int e = skip_fields(f, 4);
|
||||
if (OPAL_SUCCESS != e) {
|
||||
fclose(f);
|
||||
return e;
|
||||
}
|
||||
path = read_path(f);
|
||||
fclose(f);
|
||||
return path;
|
||||
} else {
|
||||
int e = skip_line(f);
|
||||
if (OPAL_SUCCESS != e) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The following routines don't use isspace et al, because we don't
|
||||
* want the locale setting to influence them.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read a hex address from a file. We don't know how many
|
||||
* digits there will be. We only know that the result will
|
||||
* fit into a uintptr_t, and will not be zero.
|
||||
*
|
||||
* Return zero on error.
|
||||
*/
|
||||
|
||||
static uintptr_t
|
||||
read_addr(FILE *f)
|
||||
{
|
||||
int c;
|
||||
uintptr_t n = 0;
|
||||
|
||||
for (;;) {
|
||||
c = getc(f);
|
||||
if (EOF == c) {
|
||||
return 0;
|
||||
}
|
||||
if (' ' == c || '-' == c) {
|
||||
if (n > 0) {
|
||||
return n;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (c >= '0' && c <= '9') {
|
||||
n <<= 4;
|
||||
n += c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
n <<= 4;
|
||||
n += c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
n <<= 4;
|
||||
n += c - 'A' + 10;
|
||||
} else {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip n fields of input, where fields are separated by white space.
|
||||
*
|
||||
* Return OPAL_SUCCESS on success.
|
||||
*/
|
||||
|
||||
static int
|
||||
skip_fields(FILE *f, int n)
|
||||
{
|
||||
int c = getc(f);
|
||||
while (n-- > 0) {
|
||||
for (; c == ' ' || c == '\t'; c = getc(f));
|
||||
if (c == EOF || c == '\n') {
|
||||
return OPAL_ERR_NOT_AVAILABLE;
|
||||
}
|
||||
for(; c != ' ' && c != '\t' && c != '\n'; c = getc(f));
|
||||
}
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a path, and return it. Return NULL on error.
|
||||
*/
|
||||
|
||||
static int
|
||||
read_path(FILE *f)
|
||||
{
|
||||
char *path = malloc(100);
|
||||
int n = 100;
|
||||
int i = 0;
|
||||
int c = getc(f);
|
||||
|
||||
for (; (c == ' ' || c == '\t') && c != '\n' && c != EOF; c = getc(f));
|
||||
for (; c != '\n' && EOF != c; c = getc(f)) {
|
||||
if (i >= n) {
|
||||
n += 100;
|
||||
path = realloc(path, n);
|
||||
}
|
||||
if (NULL == path) {
|
||||
return NULL;
|
||||
}
|
||||
path[i++] = c;
|
||||
}
|
||||
if (i >= n) {
|
||||
n++;
|
||||
path = realloc(path, n);
|
||||
} else {
|
||||
path = realloc(path, i + 1);
|
||||
}
|
||||
if (NULL == path) {
|
||||
return NULL;
|
||||
}
|
||||
path[i] = '\0';
|
||||
return path;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip to the next line of input. Return OPAL_SUCCESS on success.
|
||||
*/
|
||||
|
||||
static int
|
||||
skip_line(FILE *f)
|
||||
{
|
||||
int c = 0;
|
||||
while (c != '\n') {
|
||||
c = getc(f);
|
||||
if (EOF == c) {
|
||||
return OPAL_ERR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
return OPAL_SUCCESS;
|
||||
}
|
91
opal/mca/installdirs/autodetect/opal_installdirs_solaris.c
Обычный файл
91
opal/mca/installdirs/autodetect/opal_installdirs_solaris.c
Обычный файл
@ -0,0 +1,91 @@
|
||||
/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
* Read /proc/<pid>/map and /proc/<pid>/path to find the file mapped
|
||||
* into the process over the given address.
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
#include "opal_stdint.h"
|
||||
|
||||
#include "opal/constants.h"
|
||||
|
||||
#include <procfs.h>
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
const char *
|
||||
opal_installdirs_autodetect_path(uintptr_t my_addr)
|
||||
{
|
||||
pid_t my_pid;
|
||||
char *map_path;
|
||||
prmap_t map;
|
||||
int map_fd;
|
||||
char *obj_name;
|
||||
ssize_t path_size, ls;
|
||||
char *path;
|
||||
|
||||
my_pid = getpid();
|
||||
asprintf(&map_path, "/proc/%d/map", my_pid);
|
||||
if (NULL == map_path) {
|
||||
return NULL;
|
||||
}
|
||||
map_fd = open(map_path, O_RDONLY);
|
||||
free(map_path);
|
||||
if (map_fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (read(map_fd, &map, sizeof(map)) < sizeof(map)) {
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
if (map.pr_vaddr <= my_addr && map.pr_vaddr + map.pr_size > my_addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(map_fd);
|
||||
asprintf(&obj_name, "/proc/%d/path/%s", my_pid, map.pr_mapname);
|
||||
if (NULL == obj_name) {
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
We don't know how long the path to the load object might be.
|
||||
Try allocating a reasonable length. If the readlink system
|
||||
call doesn't use the entire buffer passed to it then we know
|
||||
the path is complete.
|
||||
*/
|
||||
for (path_size = 100; ; path_size += 100) {
|
||||
path = malloc(path_size);
|
||||
if (NULL == path) {
|
||||
free(obj_name);
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
ls = readlink(obj_name, path, path_size);
|
||||
if (ls < 0) {
|
||||
free(obj_name);
|
||||
free(path);
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
if (ls < path_size) {
|
||||
path[ls] = '\0';
|
||||
break;
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
|
||||
free(obj_name);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
34
opal/mca/installdirs/autodetect/opal_installdirs_walkcontext.c
Обычный файл
34
opal/mca/installdirs/autodetect/opal_installdirs_walkcontext.c
Обычный файл
@ -0,0 +1,34 @@
|
||||
/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
||||
/*
|
||||
* Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#include <ucontext.h>
|
||||
|
||||
static int
|
||||
savepc(uintptr_t pc, int sig, void *storage)
|
||||
{
|
||||
*(uintptr_t*)storage = pc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
opal_installdirs_autodetect_pc()
|
||||
{
|
||||
ucontext_t ctx;
|
||||
uintptr_t value = 0;
|
||||
|
||||
if (getcontext(&ctx) == -1) {
|
||||
return 0;
|
||||
}
|
||||
walkcontext(&ctx, savepc, &value);
|
||||
return value;
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Los Alamos National Security, LLC. All rights
|
||||
* reserved.
|
||||
* reserved.
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2009 Sun Microsystem, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
*/
|
||||
@ -22,29 +23,59 @@ int opal_installdirs_base_output;
|
||||
opal_install_dirs_t opal_install_dirs;
|
||||
opal_list_t opal_installdirs_components;
|
||||
|
||||
#define CONDITIONAL_COPY(target, origin, field) \
|
||||
do { \
|
||||
if (origin.field != NULL && target.field == NULL) { \
|
||||
target.field = origin.field; \
|
||||
} \
|
||||
} while (0)
|
||||
char *
|
||||
opal_install_dirs_infer(const char *inferred_field,
|
||||
const char *infer_from_field,
|
||||
size_t infer_from_field_len,
|
||||
opal_install_dirs_t *component_installdirs);
|
||||
|
||||
/*
|
||||
* There is a memory leak when inferring a field. The function
|
||||
* opal_install_dirs_infer returns allocated memory. We will
|
||||
* later call opal_install_dirs_expand for the field, which
|
||||
* also allocates memory. We don't record which fields were
|
||||
* inferred, so we don't know whether to call free after calling
|
||||
* opal_install_dirs_expand.
|
||||
*/
|
||||
|
||||
#define CONDITIONAL_COPY(target, origin, field) \
|
||||
do { \
|
||||
if (origin.field != NULL) { \
|
||||
if (NULL != target.field && \
|
||||
strncmp(target.field, "${infer-", 8) == 0) { \
|
||||
const char *fe = strchr(target.field, '}'); \
|
||||
if (NULL != fe) { \
|
||||
const char *f = target.field + 8; \
|
||||
target.field = \
|
||||
opal_install_dirs_infer(#field, f, fe - f, &origin); \
|
||||
} else { \
|
||||
target.field = NULL; \
|
||||
} \
|
||||
} \
|
||||
if (NULL == target.field) { \
|
||||
target.field = origin.field; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
} while (0) \
|
||||
|
||||
int
|
||||
opal_installdirs_base_open(void)
|
||||
{
|
||||
int i, ret;
|
||||
mca_base_component_list_item_t *cli;
|
||||
opal_install_dirs_t expanded_dirs;
|
||||
|
||||
OBJ_CONSTRUCT(&opal_installdirs_components, opal_list_t);
|
||||
for (i = 0 ; mca_installdirs_base_static_components[i] != NULL ; ++i) {
|
||||
opal_installdirs_base_component_t *component =
|
||||
(opal_installdirs_base_component_t*)
|
||||
opal_installdirs_base_component_t *component =
|
||||
(opal_installdirs_base_component_t*)
|
||||
mca_installdirs_base_static_components[i];
|
||||
|
||||
/* Save it in a global list for ompi_info */
|
||||
cli = OBJ_NEW(mca_base_component_list_item_t);
|
||||
cli->cli_component = mca_installdirs_base_static_components[i];
|
||||
opal_list_append(&opal_installdirs_components,
|
||||
opal_list_append(&opal_installdirs_components,
|
||||
&cli->super);
|
||||
|
||||
if (NULL != component->component.mca_open_component) {
|
||||
@ -53,7 +84,7 @@ opal_installdirs_base_open(void)
|
||||
}
|
||||
|
||||
/* copy over the data, if something isn't already there */
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
prefix);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
exec_prefix);
|
||||
@ -67,63 +98,64 @@ opal_installdirs_base_open(void)
|
||||
datarootdir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
datadir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
sysconfdir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
sharedstatedir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
localstatedir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
libdir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
includedir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
infodir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
mandir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
pkgdatadir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
pkglibdir);
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
CONDITIONAL_COPY(opal_install_dirs, component->install_dirs_data,
|
||||
pkgincludedir);
|
||||
}
|
||||
|
||||
/* expand out all the fields */
|
||||
opal_install_dirs.prefix =
|
||||
expanded_dirs.prefix =
|
||||
opal_install_dirs_expand(opal_install_dirs.prefix);
|
||||
opal_install_dirs.exec_prefix =
|
||||
expanded_dirs.exec_prefix =
|
||||
opal_install_dirs_expand(opal_install_dirs.exec_prefix);
|
||||
opal_install_dirs.bindir =
|
||||
expanded_dirs.bindir =
|
||||
opal_install_dirs_expand(opal_install_dirs.bindir);
|
||||
opal_install_dirs.sbindir =
|
||||
expanded_dirs.sbindir =
|
||||
opal_install_dirs_expand(opal_install_dirs.sbindir);
|
||||
opal_install_dirs.libexecdir =
|
||||
expanded_dirs.libexecdir =
|
||||
opal_install_dirs_expand(opal_install_dirs.libexecdir);
|
||||
opal_install_dirs.datarootdir =
|
||||
expanded_dirs.datarootdir =
|
||||
opal_install_dirs_expand(opal_install_dirs.datarootdir);
|
||||
opal_install_dirs.datadir =
|
||||
expanded_dirs.datadir =
|
||||
opal_install_dirs_expand(opal_install_dirs.datadir);
|
||||
opal_install_dirs.sysconfdir =
|
||||
expanded_dirs.sysconfdir =
|
||||
opal_install_dirs_expand(opal_install_dirs.sysconfdir);
|
||||
opal_install_dirs.sharedstatedir =
|
||||
expanded_dirs.sharedstatedir =
|
||||
opal_install_dirs_expand(opal_install_dirs.sharedstatedir);
|
||||
opal_install_dirs.localstatedir =
|
||||
expanded_dirs.localstatedir =
|
||||
opal_install_dirs_expand(opal_install_dirs.localstatedir);
|
||||
opal_install_dirs.libdir =
|
||||
expanded_dirs.libdir =
|
||||
opal_install_dirs_expand(opal_install_dirs.libdir);
|
||||
opal_install_dirs.includedir =
|
||||
expanded_dirs.includedir =
|
||||
opal_install_dirs_expand(opal_install_dirs.includedir);
|
||||
opal_install_dirs.infodir =
|
||||
expanded_dirs.infodir =
|
||||
opal_install_dirs_expand(opal_install_dirs.infodir);
|
||||
opal_install_dirs.mandir =
|
||||
expanded_dirs.mandir =
|
||||
opal_install_dirs_expand(opal_install_dirs.mandir);
|
||||
opal_install_dirs.pkgdatadir =
|
||||
expanded_dirs.pkgdatadir =
|
||||
opal_install_dirs_expand(opal_install_dirs.pkgdatadir);
|
||||
opal_install_dirs.pkglibdir =
|
||||
expanded_dirs.pkglibdir =
|
||||
opal_install_dirs_expand(opal_install_dirs.pkglibdir);
|
||||
opal_install_dirs.pkgincludedir =
|
||||
expanded_dirs.pkgincludedir =
|
||||
opal_install_dirs_expand(opal_install_dirs.pkgincludedir);
|
||||
opal_install_dirs = expanded_dirs;
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "prefix: %s\n", opal_install_dirs.prefix);
|
||||
@ -179,7 +211,7 @@ opal_installdirs_base_close(void)
|
||||
free(opal_install_dirs.pkgincludedir);
|
||||
|
||||
for (item = opal_list_remove_first(&opal_installdirs_components);
|
||||
NULL != item;
|
||||
NULL != item;
|
||||
item = opal_list_remove_first(&opal_installdirs_components)) {
|
||||
OBJ_RELEASE(item);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Los Alamos National Security, LLC. All rights
|
||||
* reserved.
|
||||
* reserved.
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2007 Sun Microsystem, Inc. All rights reserved.
|
||||
* Copyright (c) 2007-2009 Sun Microsystem, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
*/
|
||||
@ -19,77 +19,269 @@
|
||||
#include "opal/mca/installdirs/base/base.h"
|
||||
#include "opal/mca/installdirs/installdirs.h"
|
||||
|
||||
#define EXPAND_STRING(field) \
|
||||
do { \
|
||||
if (NULL != (start_pos = strstr(retval, "${" #field "}"))) { \
|
||||
tmp = retval; \
|
||||
*start_pos = '\0'; \
|
||||
end_pos = start_pos + strlen("${" #field "}"); \
|
||||
asprintf(&retval, "%s%s%s", tmp, \
|
||||
opal_install_dirs.field + destdir_offset, \
|
||||
end_pos); \
|
||||
free(tmp); \
|
||||
changed = true; \
|
||||
} \
|
||||
} while (0)
|
||||
/*
|
||||
* Read a field from an opal_install_dirs_t structure.
|
||||
*
|
||||
* The field name is passed as a string + a length, and need not be
|
||||
* null terminated.
|
||||
*
|
||||
* The implementation is reasonaly efficient, but perhaps less
|
||||
* readable than a bunch of strncmp calls.
|
||||
*/
|
||||
|
||||
#define CHKTRAIL(s,n) if (strncmp(field, #s, field_length - n) != 0) return NULL
|
||||
|
||||
static const char *
|
||||
field_lookup(const char *field,
|
||||
int field_length,
|
||||
opal_install_dirs_t *install_dirs)
|
||||
{
|
||||
switch (*field++) {
|
||||
case 'b':
|
||||
CHKTRAIL(indir, 1);
|
||||
return install_dirs->bindir;
|
||||
case 'd':
|
||||
CHKTRAIL(atarootdir, 1);
|
||||
return install_dirs->datarootdir;
|
||||
case 'e':
|
||||
CHKTRAIL(xec_prefix, 1);
|
||||
return install_dirs->exec_prefix;
|
||||
case 'i':
|
||||
if ('n' != *field++) return NULL;
|
||||
switch (*field++) {
|
||||
case 'c':
|
||||
CHKTRAIL(ludedir, 3);
|
||||
return install_dirs->includedir;
|
||||
case 'f':
|
||||
CHKTRAIL(odir, 3);
|
||||
return install_dirs->infodir;
|
||||
}
|
||||
return NULL;
|
||||
case 'l':
|
||||
switch (*field++) {
|
||||
case 'o':
|
||||
CHKTRAIL(calstatedir, 2);
|
||||
return install_dirs->localstatedir;
|
||||
case 'i':
|
||||
switch (*field++) {
|
||||
case 'b':
|
||||
switch (*field++) {
|
||||
case 'd':
|
||||
CHKTRAIL(ir, 4);
|
||||
return install_dirs->libdir;
|
||||
case 'e':
|
||||
CHKTRAIL(xecdir, 4);
|
||||
return install_dirs->libexecdir;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
case 'm':
|
||||
CHKTRAIL(andir, 1);
|
||||
return install_dirs->mandir;
|
||||
|
||||
case 'p':
|
||||
switch (*field++) {
|
||||
case 'r':
|
||||
CHKTRAIL(efix, 2);
|
||||
return install_dirs->prefix;
|
||||
case 'k':
|
||||
if ('g' == *field++) {
|
||||
switch (*field++) {
|
||||
case 'd':
|
||||
CHKTRAIL(atadir, 4);
|
||||
return install_dirs->pkgdatadir;
|
||||
case 'l':
|
||||
CHKTRAIL(ibdir, 4);
|
||||
return install_dirs->pkglibdir;
|
||||
case 'i':
|
||||
CHKTRAIL(ncludedir, 4);
|
||||
return install_dirs->pkgincludedir;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
case 's':
|
||||
switch (*field++) {
|
||||
case 'b':
|
||||
CHKTRAIL(indir, 2);
|
||||
return install_dirs->sbindir;
|
||||
case 'h':
|
||||
CHKTRAIL(aredstatedir, 2);
|
||||
return install_dirs->sharedstatedir;
|
||||
case 'y':
|
||||
CHKTRAIL(sconfdir, 2);
|
||||
return install_dirs->sysconfdir;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets *output to the input string with any "${foo}" references expanded.
|
||||
* The expansion values come from the fields of install_dirs.
|
||||
*
|
||||
* If dont_expand is non-NULL, references to the field it names are
|
||||
* not expanded. (E.g., "${libdir}" will be copied as is to *output if
|
||||
* dont_expand is "libdir".)
|
||||
*/
|
||||
|
||||
static void
|
||||
install_dirs_expand(const char *input,
|
||||
char **output,
|
||||
size_t *output_len,
|
||||
size_t *j,
|
||||
opal_install_dirs_t *install_dirs,
|
||||
const char *dont_expand)
|
||||
{
|
||||
size_t len, i, m, n;
|
||||
const char *expansion;
|
||||
|
||||
if (0 == *output_len) {
|
||||
*output_len = 100;
|
||||
*output = malloc(*output_len);
|
||||
if (NULL == *output) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
len = strlen(input);
|
||||
for (i = 0 ; i < len ; ++i) {
|
||||
expansion = NULL;
|
||||
if ('$' == input[i] && '{' == input[i+1]) {
|
||||
for (n = 0; i + n + 2 < len; n++) {
|
||||
if ('}' == input[i+n+2]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (NULL == dont_expand ||
|
||||
strncmp(&input[i+2], dont_expand, n) != 0 ) {
|
||||
expansion = field_lookup(&input[i+2], n, install_dirs);
|
||||
} else {
|
||||
expansion = NULL;
|
||||
}
|
||||
}
|
||||
if (NULL != expansion) {
|
||||
install_dirs_expand(expansion, output, output_len, j, install_dirs,
|
||||
dont_expand);
|
||||
i += n + 2;
|
||||
} else {
|
||||
if (*j + 1 >= *output_len) {
|
||||
*output_len += 100;
|
||||
*output = realloc(*output, *output_len);
|
||||
if (NULL == *output) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
(*output)[(*j)++] = input[i];
|
||||
}
|
||||
}
|
||||
|
||||
(*output)[*j] = '\0';
|
||||
}
|
||||
|
||||
char *
|
||||
opal_install_dirs_expand(const char* input)
|
||||
{
|
||||
size_t len, i;
|
||||
bool needs_expand = false;
|
||||
char *retval = NULL;
|
||||
char *destdir = getenv("OPAL_DESTDIR");
|
||||
size_t destdir_offset = 0;
|
||||
size_t j = 0, retval_len = 0;
|
||||
|
||||
if (NULL != destdir && strlen(destdir) > 0) {
|
||||
destdir_offset = strlen(destdir);
|
||||
if (NULL != destdir) {
|
||||
j = strlen(destdir) + sizeof(OPAL_PATH_SEP) - 1;
|
||||
retval_len = j + 100;
|
||||
retval = malloc(retval_len);
|
||||
if (NULL == retval) {
|
||||
return NULL;
|
||||
}
|
||||
sprintf(retval, "%s%s", destdir, OPAL_PATH_SEP);
|
||||
}
|
||||
|
||||
len = strlen(input);
|
||||
for (i = 0 ; i < len ; ++i) {
|
||||
if (input[i] == '$') {
|
||||
needs_expand = true;
|
||||
install_dirs_expand(input, &retval, &retval_len, &j, &opal_install_dirs, NULL);
|
||||
if (NULL != retval) {
|
||||
retval = realloc(retval, j + 1);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *
|
||||
opal_install_dirs_infer(const char *inferred_field,
|
||||
const char *infer_from_field,
|
||||
size_t infer_from_field_len,
|
||||
opal_install_dirs_t *component_installdirs)
|
||||
{
|
||||
const char *infer_from_path;
|
||||
char *component_field = NULL;
|
||||
size_t component_field_len = 0;
|
||||
const char *installed_field = NULL;
|
||||
char *p, *q;
|
||||
size_t j = 0, inferred_field_len = strlen(inferred_field);
|
||||
size_t leading, trailing, installed_field_len, retval_len;
|
||||
char *retval;
|
||||
|
||||
infer_from_path = field_lookup(infer_from_field, infer_from_field_len,
|
||||
component_installdirs);
|
||||
install_dirs_expand(infer_from_path,
|
||||
&component_field,
|
||||
&component_field_len,
|
||||
&j,
|
||||
component_installdirs,
|
||||
inferred_field);
|
||||
|
||||
installed_field = field_lookup(infer_from_field, infer_from_field_len,
|
||||
&opal_install_dirs);
|
||||
|
||||
/*
|
||||
* Let's say component_field is, "/path/${prefix}/bin", and
|
||||
* infer_from_field is "bindir". Then we want to:
|
||||
*
|
||||
* 1. Make sure that opal_install_dirs.bindir starts with "/path/"
|
||||
*
|
||||
* 2. Make sure that opal_install_dirs.bindir ends with "/bin"
|
||||
*
|
||||
* 3. Return the string that appears between those
|
||||
*/
|
||||
|
||||
for (p = component_field; *p; p++) {
|
||||
if (*p == '$' && p[1] == '{' &&
|
||||
strncmp(p+2, inferred_field, inferred_field_len) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*p == '\0') {
|
||||
free(component_field);
|
||||
return NULL;
|
||||
}
|
||||
leading = p - component_field;
|
||||
trailing = component_field + strlen(component_field) - p -
|
||||
inferred_field_len - 3;
|
||||
|
||||
retval = strdup(input);
|
||||
if (NULL == retval) return NULL;
|
||||
|
||||
if (needs_expand) {
|
||||
bool changed = false;
|
||||
char *start_pos, *end_pos, *tmp;
|
||||
|
||||
do {
|
||||
changed = false;
|
||||
EXPAND_STRING(prefix);
|
||||
EXPAND_STRING(exec_prefix);
|
||||
EXPAND_STRING(bindir);
|
||||
EXPAND_STRING(sbindir);
|
||||
EXPAND_STRING(libexecdir);
|
||||
EXPAND_STRING(datarootdir);
|
||||
EXPAND_STRING(datadir);
|
||||
EXPAND_STRING(sysconfdir);
|
||||
EXPAND_STRING(sharedstatedir);
|
||||
EXPAND_STRING(localstatedir);
|
||||
EXPAND_STRING(libdir);
|
||||
EXPAND_STRING(includedir);
|
||||
EXPAND_STRING(infodir);
|
||||
EXPAND_STRING(mandir);
|
||||
EXPAND_STRING(pkgdatadir);
|
||||
EXPAND_STRING(pkglibdir);
|
||||
EXPAND_STRING(pkgincludedir);
|
||||
} while (changed);
|
||||
installed_field_len = strlen(installed_field);
|
||||
if (installed_field_len < trailing + leading) {
|
||||
free(component_field);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (NULL != destdir) {
|
||||
char *tmp = retval;
|
||||
retval = opal_os_path(false, destdir, tmp, NULL);
|
||||
free(tmp);
|
||||
if (strncmp(component_field, installed_field, leading) != 0) {
|
||||
free(component_field);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(p + inferred_field_len + 3,
|
||||
installed_field + installed_field_len - trailing) != 0) {
|
||||
free(component_field);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(component_field);
|
||||
retval_len = installed_field_len - leading - trailing;
|
||||
retval = malloc(retval_len + 1);
|
||||
if (NULL == retval) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(retval, installed_field + leading, retval_len);
|
||||
retval[retval_len] = '\0';
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user