mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-22 04:50:07 +00:00
Update.
1998-08-27 19:42 Ulrich Drepper <drepper@cygnus.com> * elf/Makefile (distribute): Add dl-origin.h. * sysdeps/generic/dl-origin.h: New file. * sysdeps/unix/sysv/linux/dl-origin.h: New file. * elf/link.h (struct link_map): Add l_origin field. * elf/dl-load.c (expand_dynamic_string_token): New function. (decompose_path): Remove WHERE argument, take link map pointer instead. Call expand_dynamic_string_token instead of local_strdup to make copy of rpath. (_dl_init_paths): Call decompose_path with correct argument. (_dl_map_object_from_fd): Define static is EXTERNAL_MAP_FROM_FD is not defined. Check EI_OSABI and EI_ABIVERSION fields in header. (_dl_map_object): Call decompose_path with correct argument. Call expand_dynamic_string_token instead of local_strdup to also expand DST. * elf/dl-object.c (_dl_new_object): Determine l_origin for all maps but the main one. * elf/dl-support.c: Define _dl_origin_path. * elf/rtld.c: Likewise. Set _dl_origin_path based on LD_ORIGIN_PATH. * elf/dl-close (_dl_close): Free l_name and l_origin. * sysdeps/i386/useldt.h (THREAD_GETMEM, THREAD_SETMEM): Use P modifier in asm, not c. * sysdeps/mach/hurd/Makefile [subdirs==elf]: Define CFLAGS-dl-load.c to -DEXTERNAL_MAP_FROM_FD to make _dl_map_object_from_fd extern.
This commit is contained in:
parent
6075607b9a
commit
f787edde1d
30
ChangeLog
30
ChangeLog
@ -1,3 +1,33 @@
|
||||
1998-08-27 19:42 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* elf/Makefile (distribute): Add dl-origin.h.
|
||||
* sysdeps/generic/dl-origin.h: New file.
|
||||
* sysdeps/unix/sysv/linux/dl-origin.h: New file.
|
||||
* elf/link.h (struct link_map): Add l_origin field.
|
||||
* elf/dl-load.c (expand_dynamic_string_token): New function.
|
||||
(decompose_path): Remove WHERE argument, take link map pointer instead.
|
||||
Call expand_dynamic_string_token instead of local_strdup to make copy
|
||||
of rpath.
|
||||
(_dl_init_paths): Call decompose_path with correct argument.
|
||||
(_dl_map_object_from_fd): Define static is EXTERNAL_MAP_FROM_FD is
|
||||
not defined.
|
||||
Check EI_OSABI and EI_ABIVERSION fields in header.
|
||||
(_dl_map_object): Call decompose_path with correct argument.
|
||||
Call expand_dynamic_string_token instead of local_strdup to also
|
||||
expand DST.
|
||||
* elf/dl-object.c (_dl_new_object): Determine l_origin for all maps
|
||||
but the main one.
|
||||
* elf/dl-support.c: Define _dl_origin_path.
|
||||
* elf/rtld.c: Likewise. Set _dl_origin_path based on LD_ORIGIN_PATH.
|
||||
|
||||
* elf/dl-close (_dl_close): Free l_name and l_origin.
|
||||
|
||||
* sysdeps/i386/useldt.h (THREAD_GETMEM, THREAD_SETMEM): Use P
|
||||
modifier in asm, not c.
|
||||
|
||||
* sysdeps/mach/hurd/Makefile [subdirs==elf]: Define CFLAGS-dl-load.c
|
||||
to -DEXTERNAL_MAP_FROM_FD to make _dl_map_object_from_fd extern.
|
||||
|
||||
1998-08-26 17:48 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* elf/dl-close.c (_dl_close): Move map->l_nsearchlist value into local
|
||||
|
@ -38,7 +38,7 @@ rtld-routines := rtld $(dl-routines) dl-sysdep dl-environ dl-minimal
|
||||
distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
|
||||
dl-hash.h soinit.c sofini.c ldd.sh.in ldd.bash.in eval.c \
|
||||
genrtldtbl.awk atomicity.h dl-procinfo.h ldsodefs.h \
|
||||
dl-librecon.h interp.c sln.c
|
||||
dl-librecon.h interp.c sln.c dl-origin.h
|
||||
|
||||
extra-libs = libdl
|
||||
extra-libs-others = $(extra-libs)
|
||||
|
@ -88,6 +88,11 @@ _dl_close (struct link_map *map)
|
||||
for (i = 0; i < nsearchlist; ++i)
|
||||
--list[i]->l_opencount;
|
||||
|
||||
if (map->l_origin != NULL)
|
||||
free ((char *) map->l_origin);
|
||||
/* The name always is allocated. */
|
||||
free (map->l_name);
|
||||
|
||||
/* Check each element of the search list to see if all references to
|
||||
it are gone. */
|
||||
for (i = 0; i < nsearchlist; ++i)
|
||||
|
153
elf/dl-load.c
153
elf/dl-load.c
@ -31,6 +31,8 @@
|
||||
#include "dynamic-link.h"
|
||||
#include <stdio-common/_itoa.h>
|
||||
|
||||
#include <dl-origin.h>
|
||||
|
||||
|
||||
/* On some systems, no flag bits are given to specify file mapping. */
|
||||
#ifndef MAP_FILE
|
||||
@ -124,6 +126,116 @@ local_strdup (const char *s)
|
||||
return (char *) memcpy (new, s, len);
|
||||
}
|
||||
|
||||
/* Return copy of argument with all recognized dynamic string tokens
|
||||
($ORIGIN and $PLATFORM for now) replaced. On some platforms it
|
||||
might not be possible to determine the path from which the object
|
||||
belonging to the map is loaded. In this case the path element
|
||||
containing $ORIGIN is left out. */
|
||||
static char *
|
||||
expand_dynamic_string_token (struct link_map *l, const char *s)
|
||||
{
|
||||
/* We make two runs over the string. First we determine how large the
|
||||
resulting string is and then we copy it over. Since this is now
|
||||
frequently executed operation we are looking here not for performance
|
||||
but rather for code size. */
|
||||
const char *st, *sf;
|
||||
size_t cnt = 0;
|
||||
size_t origin_len;
|
||||
size_t total;
|
||||
char *result, *last_elem, *wp;
|
||||
|
||||
st = s;
|
||||
sf = strchr (s, '$');
|
||||
while (sf != NULL)
|
||||
{
|
||||
size_t len = 1;
|
||||
|
||||
if (((strncmp (&sf[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
|
||||
|| (strncmp (&sf[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
|
||||
&& (s[len] == '\0' || s[len] == '/' || s[len] == ':'))
|
||||
++cnt;
|
||||
|
||||
st = sf + len;
|
||||
sf = strchr (st, '$');
|
||||
}
|
||||
|
||||
/* If we do not have to replace anything simply copy the string. */
|
||||
if (cnt == 0)
|
||||
return local_strdup (s);
|
||||
|
||||
/* Now we make a guess how many extra characters on top of the length
|
||||
of S we need to represent the result. We know that we have CNT
|
||||
replacements. Each at most can use
|
||||
MAX (strlen (ORIGIN), strlen (_dl_platform))
|
||||
minus 7 (which is the length of "$ORIGIN").
|
||||
|
||||
First get the origin string if it is not available yet. This can
|
||||
only happen for the map of the executable. */
|
||||
if (l->l_origin == NULL)
|
||||
{
|
||||
assert (l->l_name[0] == '\0');
|
||||
l->l_origin = get_origin ();
|
||||
origin_len = l->l_origin ? strlen (l->l_origin) : 0;
|
||||
}
|
||||
else
|
||||
origin_len = l->l_origin == (char *) -1 ? 0 : strlen (l->l_origin);
|
||||
|
||||
total = strlen (s) + cnt * (MAX (origin_len, _dl_platformlen) - 7);
|
||||
result = (char *) malloc (total + 1);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Now fill the result path. While copying over the string we keep
|
||||
track of the start of the last path element. When we come accross
|
||||
a DST we copy over the value or (if the value is not available)
|
||||
leave the entire path element out. */
|
||||
last_elem = wp = result;
|
||||
do
|
||||
{
|
||||
if (*s == '$')
|
||||
{
|
||||
const char *repl;
|
||||
size_t len;
|
||||
|
||||
if (((strncmp (&s[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
|
||||
|| (strncmp (&s[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
|
||||
&& (s[len] == '\0' || s[len] == '/' || s[len] == ':'))
|
||||
{
|
||||
if ((repl = len == 7 ? l->l_origin : _dl_platform) != NULL
|
||||
&& repl != (const char *) -1)
|
||||
{
|
||||
wp = __stpcpy (wp, repl);
|
||||
s += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We cannot use this path element, the value of the
|
||||
replacement is unknown. */
|
||||
wp = last_elem;
|
||||
s += len;
|
||||
while (*s != '\0' && *s != ':')
|
||||
++s;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* No SDK we recognize. */
|
||||
*wp++ = *s++;
|
||||
}
|
||||
else if (*s == ':')
|
||||
{
|
||||
*wp++ = *s++;
|
||||
last_elem = wp;
|
||||
}
|
||||
else
|
||||
*wp++ = *s++;
|
||||
}
|
||||
while (*s != '\0');
|
||||
|
||||
*wp = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Add `name' to the list of names for a particular shared object.
|
||||
`name' is expected to have been allocated with malloc and will
|
||||
be freed if the shared object already has this name.
|
||||
@ -286,9 +398,10 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
|
||||
|
||||
static struct r_search_path_elem **
|
||||
internal_function
|
||||
decompose_rpath (const char *rpath, size_t additional_room, const char *where)
|
||||
decompose_rpath (const char *rpath, size_t additional_room, struct link_map *l)
|
||||
{
|
||||
/* Make a copy we can work with. */
|
||||
const char *where = l->l_name;
|
||||
char *copy;
|
||||
char *cp;
|
||||
struct r_search_path_elem **result;
|
||||
@ -318,8 +431,13 @@ decompose_rpath (const char *rpath, size_t additional_room, const char *where)
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a writable copy. At the same time expand possible dynamic
|
||||
string tokens. */
|
||||
copy = expand_dynamic_string_token (l, rpath);
|
||||
if (copy == NULL)
|
||||
_dl_signal_error (ENOMEM, NULL, "cannot create RPATH copy");
|
||||
|
||||
/* Count the number of necessary elements in the result array. */
|
||||
copy = local_strdup (rpath);
|
||||
nelems = 0;
|
||||
for (cp = copy; *cp != '\0'; ++cp)
|
||||
if (*cp == ':')
|
||||
@ -429,7 +547,7 @@ _dl_init_paths (const char *llp)
|
||||
decompose_rpath ((const char *)
|
||||
(l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr
|
||||
+ l->l_info[DT_RPATH]->d_un.d_val),
|
||||
nllp, l->l_name);
|
||||
nllp, l);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -497,6 +615,9 @@ _dl_init_paths (const char *llp)
|
||||
/* Map in the shared object NAME, actually located in REALNAME, and already
|
||||
opened on FD. */
|
||||
|
||||
#ifndef EXTERNAL_MAP_FROM_FD
|
||||
static
|
||||
#endif
|
||||
struct link_map *
|
||||
_dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
struct link_map *loader, int l_type)
|
||||
@ -591,6 +712,12 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
LOSE ("ELF file data encoding not " byteorder_name);
|
||||
if (header->e_ident[EI_VERSION] != EV_CURRENT)
|
||||
LOSE ("ELF file version ident not " STRING(EV_CURRENT));
|
||||
/* XXX We should be able so set system specific versions which are
|
||||
allowed here. */
|
||||
if (header->e_ident[EI_OSABI] != ELFOSABI_SYSV)
|
||||
LOSE ("ELF file OS ABI not " STRING(ELFOSABI_SYSV));
|
||||
if (header->e_ident[EI_ABIVERSION] != 0)
|
||||
LOSE ("ELF file ABI version not 0");
|
||||
if (header->e_version != EV_CURRENT)
|
||||
LOSE ("ELF file version not " STRING(EV_CURRENT));
|
||||
if (! elf_machine_matches_host (header->e_machine))
|
||||
@ -1076,7 +1203,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
|
||||
+ l->l_info[DT_STRTAB]->d_un.d_ptr
|
||||
+ l->l_info[DT_RPATH]->d_un.d_val);
|
||||
l->l_rpath_dirs =
|
||||
decompose_rpath ((const char *) ptrval, 0, l->l_name);
|
||||
decompose_rpath ((const char *) ptrval, 0, l);
|
||||
}
|
||||
|
||||
if (l->l_rpath_dirs != (struct r_search_path_elem **) -1l)
|
||||
@ -1127,15 +1254,17 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
|
||||
}
|
||||
else
|
||||
{
|
||||
fd = __open (name, O_RDONLY);
|
||||
if (fd != -1)
|
||||
/* The path may contain dynamic string tokens. */
|
||||
realname = (loader
|
||||
? expand_dynamic_string_token (loader, name)
|
||||
: local_strdup (name));
|
||||
if (realname == NULL)
|
||||
fd = -1;
|
||||
else
|
||||
{
|
||||
realname = local_strdup (name);
|
||||
if (realname == NULL)
|
||||
{
|
||||
__close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
fd = __open (realname, O_RDONLY);
|
||||
if (fd == -1)
|
||||
free (realname);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <elf/ldsodefs.h>
|
||||
|
||||
#include <assert.h>
|
||||
@ -61,5 +62,68 @@ _dl_new_object (char *realname, const char *libname, int type)
|
||||
l->l_next = new;
|
||||
}
|
||||
|
||||
/* The REALNAME is "" for the main link map. This name must be determined
|
||||
specially. */
|
||||
if (realname[0] == '\0')
|
||||
new->l_origin = NULL;
|
||||
else
|
||||
{
|
||||
char *origin;
|
||||
|
||||
if (realname[0] == '/')
|
||||
{
|
||||
/* It an absolute path. Use it. But we have to make a copy since
|
||||
we strip out the trailing slash. */
|
||||
size_t len = strlen (realname) + 1;
|
||||
origin = malloc (len);
|
||||
if (origin == NULL)
|
||||
origin = (char *) -1;
|
||||
else
|
||||
memcpy (origin, realname, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t realname_len = strlen (realname) + 1;
|
||||
size_t len = 128 + realname_len;
|
||||
char *result = NULL;
|
||||
|
||||
/* Get the current directory name. */
|
||||
origin = malloc (len);
|
||||
|
||||
while (origin != NULL
|
||||
&& (result = __getcwd (origin, len - realname_len)) == NULL
|
||||
&& errno == ERANGE)
|
||||
{
|
||||
len += 128;
|
||||
origin = (char *) realloc (origin, len);
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
/* We were not able to determine the current directory. */
|
||||
if (origin != NULL)
|
||||
free (origin);
|
||||
origin = (char *) -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now append the filename. */
|
||||
char *cp = strchr (origin, '\0');
|
||||
|
||||
if (cp [-1] != '/')
|
||||
*cp++ = '/';
|
||||
|
||||
memcpy (cp, realname, realname_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (origin != (char *) -1)
|
||||
/* Now remove the filename and the slash. Do this even if the
|
||||
string is something like "/foo" which leaves an empty string. */
|
||||
*strrchr (origin, '/') = '\0';
|
||||
|
||||
new->l_origin = origin;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
@ -63,6 +63,9 @@ struct link_map *_dl_profile_map;
|
||||
/* This is the address of the last stack address ever used. */
|
||||
void *__libc_stack_end;
|
||||
|
||||
/* Path where the binary is found. */
|
||||
const char *_dl_origin_path;
|
||||
|
||||
|
||||
static void non_dynamic_init (void) __attribute__ ((unused));
|
||||
|
||||
|
@ -161,6 +161,9 @@ struct link_map
|
||||
|
||||
/* Pointer to the version information if available. */
|
||||
ElfW(Half) *l_versyms;
|
||||
|
||||
/* String specifying the path where this object was found. */
|
||||
const char *l_origin;
|
||||
};
|
||||
|
||||
#endif /* link.h */
|
||||
|
@ -87,6 +87,7 @@ int _dl_debug_reloc;
|
||||
int _dl_debug_files;
|
||||
const char *_dl_inhibit_rpath; /* RPATH values which should be
|
||||
ignored. */
|
||||
const char *_dl_origin_path;
|
||||
|
||||
/* Set nonzero during loading and initialization of executable and
|
||||
libraries, cleared before the executable's entry point runs. This
|
||||
@ -1164,6 +1165,12 @@ process_envvars (enum mode *modep, int *lazyp)
|
||||
_dl_hwcap_mask = strtoul (&envline[14], NULL, 0);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
/* Path where the binary is found. */
|
||||
if (memcmp (&envline[3], "ORIGIN_PATH", 11) == 0)
|
||||
_dl_hwcap_mask = strtoul (&envline[15], NULL, 0);
|
||||
break;
|
||||
|
||||
case 12:
|
||||
/* Where to place the profiling data file. */
|
||||
if (memcmp (&envline[3], "DEBUG_OUTPUT", 12) == 0)
|
||||
|
@ -82,7 +82,7 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
|
||||
({ \
|
||||
__typeof__ (descr->member) __value; \
|
||||
if (sizeof (__value) == 1) \
|
||||
__asm__ __volatile__ ("movb %%gs:%c1,%b0" \
|
||||
__asm__ __volatile__ ("movb %%gs:%P1,%b0" \
|
||||
: "=r" (__value) \
|
||||
: "0" (0), \
|
||||
"i" (offsetof (struct _pthread_descr_struct, \
|
||||
@ -93,7 +93,7 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
|
||||
/* There should not be any value with a size other than 1 or 4. */ \
|
||||
abort (); \
|
||||
\
|
||||
__asm__ __volatile__ ("movl %%gs:%c1,%0" \
|
||||
__asm__ __volatile__ ("movl %%gs:%P1,%0" \
|
||||
: "=r" (__value) \
|
||||
: "i" (offsetof (struct _pthread_descr_struct, \
|
||||
member))); \
|
||||
@ -106,7 +106,7 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
|
||||
({ \
|
||||
__typeof__ (descr->member) __value = (value); \
|
||||
if (sizeof (__value) == 1) \
|
||||
__asm__ __volatile__ ("movb %0,%%gs:%c1" : \
|
||||
__asm__ __volatile__ ("movb %0,%%gs:%P1" : \
|
||||
: "r" (__value), \
|
||||
"i" (offsetof (struct _pthread_descr_struct, \
|
||||
member))); \
|
||||
@ -116,7 +116,7 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
|
||||
/* There should not be any value with a size other than 1 or 4. */ \
|
||||
abort (); \
|
||||
\
|
||||
__asm__ __volatile__ ("movl %0,%%gs:%c1" : \
|
||||
__asm__ __volatile__ ("movl %0,%%gs:%P1" : \
|
||||
: "r" (__value), \
|
||||
"i" (offsetof (struct _pthread_descr_struct, \
|
||||
member))); \
|
||||
|
47
sysdeps/generic/dl-origin.h
Normal file
47
sysdeps/generic/dl-origin.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* Find path of executable.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Generally it is not possible to implement this. We have to fall
|
||||
back on a solution where the user provides the information. */
|
||||
extern const char *_dl_origin_path;
|
||||
|
||||
static inline const char *
|
||||
get_origin (void)
|
||||
{
|
||||
char *result = (char *) -1;
|
||||
/* We use te environment variable LD_ORIGIN_PATH. If it is set make
|
||||
a copy and strip out trailing slashes. */
|
||||
if (_dl_origin_path != NULL)
|
||||
{
|
||||
size_t len = strlen (_dl_origin_path);
|
||||
result = malloc (len + 1);
|
||||
if (result == NULL)
|
||||
result = (char *) -1;
|
||||
else
|
||||
{
|
||||
char *cp = __mempcpy (result, _dl_origin_path, len);
|
||||
while (cp > result && cp[-1] == '/')
|
||||
--cp;
|
||||
*cp = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -124,6 +124,8 @@ $(inst_libdir)/libc.so: $(rpcuserlibs)
|
||||
# objects directly into the shared object.
|
||||
ifeq (elf,$(subdir))
|
||||
$(objpfx)librtld.os: $(rpcuserlibs:.so=_pic.a)
|
||||
|
||||
CFLAGS-dl-load.c = -DEXTERNAL_MAP_FROM_FD
|
||||
endif
|
||||
|
||||
# We need these libs to link static programs in the libc source tree, too.
|
||||
|
67
sysdeps/unix/sysv/linux/dl-origin.h
Normal file
67
sysdeps/unix/sysv/linux/dl-origin.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* Find path of executable.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* On Linux >= 2.1 systems which have the dcache implementation we can get
|
||||
the path of the application from the /proc/self/exe symlink. Try this
|
||||
first and fall back on the generic method if necessary. */
|
||||
extern const char *_dl_origin_path;
|
||||
|
||||
static inline const char *
|
||||
get_origin (void)
|
||||
{
|
||||
char linkval[PATH_MAX];
|
||||
char *result;
|
||||
|
||||
if (readlink ("/proc/self/exe", linkval, PATH_MAX) != -1
|
||||
&& result[0] != '[')
|
||||
{
|
||||
/* We can use this value. */
|
||||
char *last_slash = strrchr (linkval, '/');
|
||||
result = (char *) malloc (linkval - last_slash + 1);
|
||||
if (result == NULL)
|
||||
result = (char *) -1;
|
||||
else
|
||||
*((char *) __mempcpy (result, linkval, linkval - last_slash)) = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
result = (char *) -1;
|
||||
/* We use te environment variable LD_ORIGIN_PATH. If it is set make
|
||||
a copy and strip out trailing slashes. */
|
||||
if (_dl_origin_path != NULL)
|
||||
{
|
||||
size_t len = strlen (_dl_origin_path);
|
||||
result = malloc (len + 1);
|
||||
if (result == NULL)
|
||||
result = (char *) -1;
|
||||
else
|
||||
{
|
||||
char *cp = __mempcpy (result, _dl_origin_path, len);
|
||||
while (cp > result && cp[-1] == '/')
|
||||
--cp;
|
||||
*cp = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
Loading…
Reference in New Issue
Block a user