| From b00d99e8c5b045acdacae73d946dd8147a8885c8 Mon Sep 17 00:00:00 2001 |
| From: Erwin Waterlander <waterlan@xs4all.nl> |
| Date: Wed, 5 Aug 2015 23:36:03 +0100 |
| Subject: [PATCH 02/15] Relocate libintl |
| |
| The relocatex-libintl patch adds builtin relocation for executables to the |
| libintl dll. With this patch the programs are automatically relocatable. There |
| is no need anymore to add relocation code to your program when you use this |
| libintl DLL. |
| |
| The patch was ported from the GnuWin32 port of libintl, which has also builtin |
| relacation support. |
| |
| At the moment the relocation support is only active if you compile with MinGW |
| for Windows. If you compile for Unix/Linux/Cygwin the functionality is |
| unchanged. |
| |
| See also: |
| http://waterlan.home.xs4all.nl/libintl.html |
| http://sourceforge.net/tracker/?func=detail&atid=302435&aid=3003879&group_id=2435 |
| GnuWin32: http://gnuwin32.sourceforge.net/ |
| |
| Great thanks to GnuWin32 maintainer Kees Zeelenberg. |
| |
| Erwin Waterlander |
| waterlan@xs4all.nl |
| http://waterlan.home.xs4all.nl/ |
| |
| Additional "bogus paths for *nix-style paths" fix by Alexey Pavlov |
| |
| [jes: fix for 64-bit] |
| |
| Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> |
| --- |
| intl/Makefile.in | 8 +- |
| intl/bindtextdom.c | 22 ++++ |
| intl/canonicalize.c | 343 ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| intl/canonicalize.h | 18 +++ |
| intl/relocatex.c | 284 +++++++++++++++++++++++++++++++++++++++++++ |
| intl/relocatex.h | 41 +++++++ |
| 6 files changed, 715 insertions(+), 1 deletion(-) |
| create mode 100644 intl/canonicalize.c |
| create mode 100644 intl/canonicalize.h |
| create mode 100644 intl/relocatex.c |
| create mode 100644 intl/relocatex.h |
| |
| diff --git a/intl/Makefile.in b/intl/Makefile.in |
| index 3dd0b7f..e2b8666 100644 |
| --- a/intl/Makefile.in |
| +++ b/intl/Makefile.in |
| @@ -53,6 +53,7 @@ DEFS = -DHAVE_CONFIG_H |
| COMPILE = $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(DEFS-$@) $(INCLUDES) |
| |
| HEADERS = \ |
| + canonicalize.h \ |
| gmo.h \ |
| gettextP.h \ |
| hash-string.h \ |
| @@ -62,6 +63,7 @@ HEADERS = \ |
| eval-plural.h \ |
| localcharset.h \ |
| relocatable.h \ |
| + relocatex.h \ |
| libgnuintl.h |
| SOURCES = \ |
| bindtextdom.c \ |
| @@ -82,6 +84,8 @@ SOURCES = \ |
| plural-exp.c \ |
| localcharset.c \ |
| relocatable.c \ |
| + relocatex.c \ |
| + canonicalize.c \ |
| localename.c \ |
| log.c \ |
| osdep.c \ |
| @@ -105,6 +109,8 @@ OBJECTS = \ |
| plural-exp.o \ |
| localcharset.o \ |
| relocatable.o \ |
| + relocatex.o \ |
| + canonicalize.o \ |
| localename.o \ |
| log.o \ |
| osdep.o \ |
| @@ -165,7 +171,7 @@ install-info install-dvi install-ps install-pdf install-html: |
| $(OBJECTS): config.h libintl.h |
| bindtextdom.o dcgettext.o dcigettext.o dcngettext.o dgettext.o \ |
| dngettext.o finddomain.o gettext.o intl-compat.o loadmsgcat.o \ |
| -localealias.o ngettext.o textdomain.o: gettextP.h gmo.h loadinfo.h |
| +localealias.o ngettext.o textdomain.o: gettextP.h gmo.h loadinfo.h relocatex.h |
| dcigettext.o loadmsgcat.o: hash-string.h |
| explodename.o l10nflist.o: loadinfo.h |
| dcigettext.o loadmsgcat.o plural.o plural-exp.o: plural-exp.h |
| diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c |
| index 6faac57..b7a62d5 100644 |
| --- a/intl/bindtextdom.c |
| +++ b/intl/bindtextdom.c |
| @@ -23,6 +23,7 @@ |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <string.h> |
| +#include <unistd.h> |
| |
| #ifdef _LIBC |
| # include <libintl.h> |
| @@ -91,6 +92,12 @@ static void set_binding_values PARAMS ((const char *domainname, |
| const char **dirnamep, |
| const char **codesetp)); |
| |
| +#if ENABLE_RELOCATABLE |
| +# include "relocatex.h" |
| +#else |
| +# define relocate(pathname) (pathname) |
| +#endif |
| + |
| /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP |
| to be used for the DOMAINNAME message catalog. |
| If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not |
| @@ -352,8 +359,23 @@ BINDTEXTDOMAIN (domainname, dirname) |
| const char *domainname; |
| const char *dirname; |
| { |
| +/* |
| set_binding_values (domainname, &dirname, NULL); |
| return (char *) dirname; |
| +*/ |
| + if (!dirname || !access(dirname, R_OK)) { |
| + set_binding_values (domainname, &dirname, NULL); |
| + return (char *) dirname; |
| + } else { |
| + char *locale_dirname, *installdir = strdup (dirname), *s; |
| + if ((s = strrchr (installdir, '/'))) *s = '\0'; |
| + if ((s = strrchr (installdir, '/'))) *s = '\0'; |
| + locale_dirname = relocatex (installdir, dirname); |
| + set_binding_values (domainname, (const char **) &locale_dirname, NULL); |
| + if (installdir) |
| + free (installdir); |
| + return (char *) locale_dirname; |
| + } |
| } |
| |
| /* Specify the character encoding in which the messages from the |
| diff --git a/intl/canonicalize.c b/intl/canonicalize.c |
| new file mode 100644 |
| index 0000000..5217f30 |
| --- /dev/null |
| +++ b/intl/canonicalize.c |
| @@ -0,0 +1,343 @@ |
| +/* Return the canonical absolute name of a given file. |
| + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. |
| + This file is part of the GNU C Library. |
| + |
| + The GNU C Library is free software; you can redistribute it and/or |
| + modify it under the terms of the GNU Lesser General Public |
| + License as published by the Free Software Foundation; either |
| + version 2.1 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 |
| + Lesser General Public License for more details. |
| + |
| + You should have received a copy of the GNU Lesser General Public |
| + License along with the GNU C Library; if not, write to the Free |
| + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| + 02111-1307 USA. */ |
| + |
| +#include <stdlib.h> |
| +#include <string.h> |
| +#include <unistd.h> |
| +#include <limits.h> |
| +#include <sys/param.h> |
| +#include <sys/stat.h> |
| +#include <errno.h> |
| +#include <stddef.h> |
| +#include <malloc.h> |
| +#ifdef __WIN32__ |
| +# include <stdio.h> |
| +# include <windows.h> |
| +//# include <gw32.h> |
| +#endif /* __WIN32__ */ |
| +#include "canonicalize.h" |
| + |
| +#ifndef MAXSYMLINKS |
| +# define MAXSYMLINKS 20 |
| +#endif |
| + |
| +#ifndef __set_errno |
| +# define __set_errno(Val) errno = (Val) |
| +#endif |
| + |
| +# ifdef VMS |
| + /* We want the directory in Unix syntax, not in VMS syntax. */ |
| +# define __getcwd(buf, max) getcwd (buf, max, 0) |
| +# else |
| +# define __getcwd getcwd |
| +# endif |
| + |
| +#define weak_alias(local, symbol) |
| + |
| +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ |
| + /* Win32, Cygwin, OS/2, DOS */ |
| +# define ISDIRSEP(C) ((C) == '/' || (C) == '\\') |
| +#else |
| + /* Unix */ |
| +# define ISDIRSEP(C) ((C) == '/') |
| +#endif |
| + |
| +#ifdef __WIN32__ |
| +char *win2unixpath (char *FileName) |
| +{ |
| + char *s = FileName; |
| + while (*s) { |
| + if (*s == '\\') |
| + *s = '/'; |
| + *s++; |
| + } |
| + return FileName; |
| +} |
| +#endif |
| + |
| +/* Return the canonical absolute name of file NAME. A canonical name |
| + does not contain any `.', `..' components nor any repeated path |
| + separators ('/') or symlinks. All path components must exist. If |
| + RESOLVED is null, the result is malloc'd; otherwise, if the |
| + canonical name is PATH_MAX chars or more, returns null with `errno' |
| + set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, |
| + returns the name in RESOLVED. If the name cannot be resolved and |
| + RESOLVED is non-NULL, it contains the path of the first component |
| + that cannot be resolved. If the path can be resolved, RESOLVED |
| + holds the same value as the value returned. |
| + RESOLVED must be at least PATH_MAX long */ |
| + |
| +static char * |
| +canonicalize (const char *name, char *resolved) |
| +{ |
| + char *rpath, *dest, *extra_buf = NULL; |
| + const char *start, *end, *rpath_limit; |
| + long int path_max; |
| + int num_links = 0, old_errno; |
| + |
| + if (name == NULL) |
| + { |
| + /* As per Single Unix Specification V2 we must return an error if |
| + either parameter is a null pointer. We extend this to allow |
| + the RESOLVED parameter to be NULL in case the we are expected to |
| + allocate the room for the return value. */ |
| + __set_errno (EINVAL); |
| + return NULL; |
| + } |
| + |
| + if (name[0] == '\0') |
| + { |
| + /* As per Single Unix Specification V2 we must return an error if |
| + the name argument points to an empty string. */ |
| + __set_errno (ENOENT); |
| + return NULL; |
| + } |
| +#ifdef __WIN32__ |
| + { |
| + char *lpFilePart; |
| + int len; |
| +// fprintf(stderr, "name: %s\n", name); |
| + rpath = resolved ? __builtin_alloca (MAX_PATH) : malloc (MAX_PATH); |
| +// unix2winpath (name); |
| +// fprintf(stderr, "name: %s\n", name); |
| +len = GetFullPathName(name, MAX_PATH, rpath, &lpFilePart); |
| +/* GetFullPathName returns bogus paths for *nix-style paths, like |
| + * /foo/bar - it just prepends current drive to them. Keep them |
| + * intact (they need to be for relocation to work!). |
| + */ |
| +if (name[0] == '/') { |
| + strncpy (rpath, name, MAX_PATH - 1); |
| + rpath[MAX_PATH - 1] = '\0'; |
| + len = strlen (rpath); |
| +} |
| +// fprintf(stderr, "rpath: %s\n", rpath); |
| + if (len == 0) { |
| + //set_werrno; |
| + return NULL; |
| + } |
| + if (len > MAX_PATH) { |
| + if (resolved) |
| + __set_errno(ENAMETOOLONG); |
| + else { |
| + rpath = realloc(rpath, len + 2); |
| + GetFullPathName(name, len, rpath, &lpFilePart); |
| +// fprintf(stderr, "rpath: %s\n", rpath); |
| + } |
| + } |
| +// if ( ISDIRSEP(name[strlen(name)]) && !ISDIRSEP(rpath[len]) ) { |
| +// rpath[len] = '\\'; |
| +// rpath[len + 1] = 0; |
| +// } |
| + old_errno = errno; |
| + //if (!access (rpath, D_OK) && !ISDIRSEP(rpath[len - 1]) ){ |
| + if (!access (rpath, R_OK) && !ISDIRSEP(rpath[len - 1]) ){ |
| + rpath[len] = '\\'; |
| + rpath[len + 1] = 0; |
| + } |
| + errno = old_errno; |
| + win2unixpath (rpath); |
| +// fprintf(stderr, "rpath: %s\n", rpath); |
| + return resolved ? strcpy(resolved, rpath) : rpath ; |
| + } |
| +#else /* __WIN32__ */ |
| + |
| +#ifdef PATH_MAX |
| + path_max = PATH_MAX; |
| +#else |
| + path_max = pathconf (name, _PC_PATH_MAX); |
| + if (path_max <= 0) |
| + path_max = 1024; |
| +#endif |
| + |
| + rpath = resolved ? __builtin_alloca (path_max) : malloc (path_max); |
| + rpath_limit = rpath + path_max; |
| + |
| + if (name[0] != '/') |
| + { |
| + if (!__getcwd (rpath, path_max)) |
| + { |
| + rpath[0] = '\0'; |
| + goto error; |
| + } |
| + dest = strchr (rpath, '\0'); |
| + } |
| + else |
| + { |
| + rpath[0] = '/'; |
| + dest = rpath + 1; |
| + } |
| + |
| + for (start = end = name; *start; start = end) |
| + { |
| +#ifdef _LIBC |
| + struct stat64 st; |
| +#else |
| + struct stat st; |
| +#endif |
| + int n; |
| + |
| + /* Skip sequence of multiple path-separators. */ |
| + while (*start == '/') |
| + ++start; |
| + |
| + /* Find end of path component. */ |
| + for (end = start; *end && *end != '/'; ++end) |
| + /* Nothing. */; |
| + |
| + if (end - start == 0) |
| + break; |
| + else if (end - start == 1 && start[0] == '.') |
| + /* nothing */; |
| + else if (end - start == 2 && start[0] == '.' && start[1] == '.') |
| + { |
| + /* Back up to previous component, ignore if at root already. */ |
| + if (dest > rpath + 1) |
| + while ((--dest)[-1] != '/'); |
| + } |
| + else |
| + { |
| + size_t new_size; |
| + |
| + if (dest[-1] != '/') |
| + *dest++ = '/'; |
| + |
| + if (dest + (end - start) >= rpath_limit) |
| + { |
| + ptrdiff_t dest_offset = dest - rpath; |
| + |
| + if (resolved) |
| + { |
| + __set_errno (ENAMETOOLONG); |
| + if (dest > rpath + 1) |
| + dest--; |
| + *dest = '\0'; |
| + goto error; |
| + } |
| + new_size = rpath_limit - rpath; |
| + if (end - start + 1 > path_max) |
| + new_size += end - start + 1; |
| + else |
| + new_size += path_max; |
| + rpath = realloc (rpath, new_size); |
| + rpath_limit = rpath + new_size; |
| + if (rpath == NULL) |
| + return NULL; |
| + |
| + dest = rpath + dest_offset; |
| + } |
| + |
| +#ifdef _LIBC |
| + dest = __mempcpy (dest, start, end - start); |
| +#else |
| + memcpy (dest, start, end - start); |
| + dest += end - start; |
| +#endif |
| + *dest = '\0'; |
| + |
| +#ifdef _LIBC |
| + if (__lxstat64 (_STAT_VER, rpath, &st) < 0) |
| +#else |
| + if (lstat (rpath, &st) < 0) |
| +#endif |
| + goto error; |
| + |
| +#if HAVE_READLINK |
| + if (S_ISLNK (st.st_mode)) |
| + { |
| + char *buf = __builtin_alloca (path_max); |
| + size_t len; |
| + |
| + if (++num_links > MAXSYMLINKS) |
| + { |
| + __set_errno (ELOOP); |
| + goto error; |
| + } |
| + |
| + n = __readlink (rpath, buf, path_max); |
| + if (n < 0) |
| + goto error; |
| + buf[n] = '\0'; |
| + |
| + if (!extra_buf) |
| + extra_buf = __builtin_alloca (path_max); |
| + |
| + len = strlen (end); |
| + if ((long int) (n + len) >= path_max) |
| + { |
| + __set_errno (ENAMETOOLONG); |
| + goto error; |
| + } |
| + |
| + /* Careful here, end may be a pointer into extra_buf... */ |
| + memmove (&extra_buf[n], end, len + 1); |
| + name = end = memcpy (extra_buf, buf, n); |
| + |
| + if (buf[0] == '/') |
| + dest = rpath + 1; /* It's an absolute symlink */ |
| + else |
| + /* Back up to previous component, ignore if at root already: */ |
| + if (dest > rpath + 1) |
| + while ((--dest)[-1] != '/'); |
| + } |
| +#endif |
| + } |
| + } |
| + if (dest > rpath + 1 && dest[-1] == '/') |
| + --dest; |
| + *dest = '\0'; |
| + |
| + return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath; |
| + |
| +error: |
| + if (resolved) |
| + strcpy (resolved, rpath); |
| + else |
| + free (rpath); |
| + return NULL; |
| + |
| +#endif /* __WIN32__ */ |
| +} |
| + |
| + |
| +char * |
| +__realpath (const char *name, char *resolved) |
| +{ |
| + if (resolved == NULL) |
| + { |
| + __set_errno (EINVAL); |
| + return NULL; |
| + } |
| + |
| + return canonicalize (name, resolved); |
| +} |
| +weak_alias (__realpath, realpath) |
| + |
| + |
| +char * |
| +__canonicalize_file_name (const char *name) |
| +{ |
| + return canonicalize (name, NULL); |
| +} |
| +weak_alias (__canonicalize_file_name, canonicalize_file_name) |
| + |
| +char * |
| +canonicalize_file_name (const char *name) |
| +{ |
| + return canonicalize (name, NULL); |
| +} |
| diff --git a/intl/canonicalize.h b/intl/canonicalize.h |
| new file mode 100644 |
| index 0000000..ea707bf |
| --- /dev/null |
| +++ b/intl/canonicalize.h |
| @@ -0,0 +1,18 @@ |
| +#ifndef __CANONICALIZE_H__ |
| +#define __CANONICALIZE_H__ 1 |
| + |
| +#ifdef __cplusplus |
| +extern "C" { |
| +#endif |
| + |
| +char *canonicalize_file_name (const char *name); |
| + |
| +#ifdef __WIN32__ |
| +char *win2unixpath (char *path); |
| +#endif |
| + |
| +#ifdef __cplusplus |
| +} |
| +#endif |
| + |
| +#endif /* __CANONICALIZE_H__ */ |
| diff --git a/intl/relocatex.c b/intl/relocatex.c |
| new file mode 100644 |
| index 0000000..a2b7438 |
| --- /dev/null |
| +++ b/intl/relocatex.c |
| @@ -0,0 +1,284 @@ |
| +/* Provide relocatable packages. |
| + Copyright (C) 2003 Free Software Foundation, Inc. |
| + Written by Bruno Haible <bruno@clisp.org>, 2003. |
| + |
| + This program 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, or (at your option) |
| + any later version. |
| + |
| + This program 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 this program; if not, write to the Free Software |
| + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
| + USA. */ |
| + |
| + |
| +/* Specification. */ |
| +#include <errno.h> |
| +#define _GNU_SOURCE |
| +#include <stdlib.h> |
| +#include <string.h> |
| +#include <stdio.h> |
| +#include <unistd.h> |
| +/* #include <path.h> */ |
| +#include "relocatex.h" |
| +#include "canonicalize.h" |
| +/* #include <gw32.h> */ |
| + |
| + |
| +#if defined _WIN32 || defined __WIN32__ |
| +# define WIN32_LEAN_AND_MEAN |
| +# include <windows.h> |
| +//# define __GW32__ |
| +//# include <winx/errnox.h> |
| +#endif |
| +#define set_werrno |
| + |
| +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ |
| + /* Win32, Cygwin, OS/2, DOS */ |
| +# define ISDIRSEP(C) ((C) == '/' || (C) == '\\') |
| +#else |
| + /* Unix */ |
| +# define ISDIRSEP(C) ((C) == '/') |
| +#endif |
| + |
| +/* Original installation prefix. */ |
| +static char *orig_prefix = NULL; |
| +static size_t orig_prefix_len = 0; |
| +/* Current installation prefix. */ |
| +static char *curr_prefix = NULL; |
| +static size_t curr_prefix_len = 0; |
| +/* These prefixes do not end in a slash. Anything that will be concatenated |
| + to them must start with a slash. */ |
| + |
| + |
| +int win2posixpath (const char *winpath, char *posixpath) |
| +{ |
| + strcpy (posixpath, winpath); |
| + win2unixpath (posixpath); |
| + return 0; |
| +} |
| + |
| + |
| +/* Sets the original and the current installation prefix of this module. |
| + Relocation simply replaces a pathname starting with the original prefix |
| + by the corresponding pathname with the current prefix instead. Both |
| + prefixes should be directory names without trailing slash (i.e. use "" |
| + instead of "/"). */ |
| +static char * |
| +set_orig_prefix (const char *orig_prefix_arg) |
| +{ |
| + char *memory; |
| +// printf ("orig_prefix_arg: %s\n", orig_prefix_arg); |
| + if (!orig_prefix_arg) { |
| + orig_prefix = NULL; |
| + orig_prefix_len = 0; |
| + return NULL; |
| + } |
| + if (orig_prefix) |
| + free (orig_prefix); |
| + |
| + memory = canonicalize_file_name (orig_prefix_arg); |
| +// printf ("memory: %s\n", memory); |
| +// memory = (char *) malloc (orig_prefix_len + 1); |
| + if (!memory) { |
| + set_werrno; |
| + orig_prefix = NULL; |
| + orig_prefix_len = 0; |
| + return NULL; |
| + } |
| + win2unixpath (memory); |
| +// win2posixpath (orig_prefix_arg, memory); |
| + orig_prefix = memory; |
| + orig_prefix_len = strlen (orig_prefix); |
| +// printf ("orig_prefix: %s\n", orig_prefix); |
| + if (ISDIRSEP (orig_prefix[orig_prefix_len-1])) { |
| + orig_prefix[orig_prefix_len-1] = '\0'; |
| + orig_prefix_len--; |
| + } |
| +// printf ("orig_prefix: %s\n", orig_prefix); |
| +// printf ("orig_prefix_len: %d\n", orig_prefix_len); |
| + return orig_prefix; |
| +} |
| + |
| +#if defined __WIN32__ |
| +static char * |
| +set_current_prefix (const char *ModuleName) |
| +{ |
| + LPTSTR curr_prefix_arg, q, lpFilePart; |
| + DWORD len; |
| + int nDIRSEP = 0; |
| + |
| + if (curr_prefix) |
| + free (curr_prefix); |
| + curr_prefix_arg = malloc (MAX_PATH * sizeof (TCHAR)); |
| + if (!curr_prefix_arg) { |
| + set_werrno; |
| + curr_prefix = NULL; |
| + curr_prefix_len = 0; |
| + return NULL; |
| + } |
| + if (ModuleName) { |
| +// printf ("ModuleName: %s\n", ModuleName); |
| + len = SearchPath (NULL, ModuleName, ".DLL", MAX_PATH, curr_prefix_arg, &lpFilePart); |
| + if (len) { |
| +// printf ("ModulePath: %s\n", curr_prefix_arg); |
| +// printf ("FilePart: %s\n", lpFilePart); |
| + } |
| + } |
| + if (!ModuleName || !len) { |
| + len = GetModuleFileName (NULL, curr_prefix_arg, MAX_PATH); |
| + if (!len) { |
| + set_werrno; |
| + curr_prefix = NULL; |
| + curr_prefix_len = 0; |
| + return NULL; |
| + } |
| + } |
| +// strncpy (curr_prefix_arg, ModuleName, MAX_PATH); |
| +// printf ("curr_prefix_arg: %s\n", curr_prefix_arg); |
| + win2posixpath (curr_prefix_arg, curr_prefix_arg); |
| + curr_prefix = curr_prefix_arg; |
| + q = curr_prefix_arg + len - 1; |
| + /* strip name of executable and its directory */ |
| + while (!ISDIRSEP (*q) && (q > curr_prefix_arg) && nDIRSEP < 2) { |
| + q--; |
| + if (ISDIRSEP (*q)) { |
| + *q = '\0'; |
| + nDIRSEP++; |
| + } |
| + } |
| + curr_prefix_len = q - curr_prefix_arg; |
| +// printf ("curr_prefix: %s\n", curr_prefix); |
| +// printf ("curr_prefix_len: %d\n", curr_prefix_len); |
| + return curr_prefix; |
| +} |
| + |
| +char *getshortpath (const char *longpath) |
| +{ |
| + char *shortpath = NULL; |
| + DWORD len, res; |
| + |
| +// printf ("longpath: %s\n", longpath); |
| + len = GetShortPathName(longpath, shortpath, 0); |
| +// printf ("len: %ld\n", len); |
| + if (!len) { |
| +// WinErr ("getshortpath: len = 0"); |
| + set_werrno; |
| + return (char *) longpath; |
| + } |
| + shortpath = (char *) malloc (len + 1); |
| + if (!shortpath) { |
| +// WinErr ("getshortpath: malloc"); |
| + set_werrno; |
| + return (char *) longpath; |
| + } |
| + res = GetShortPathName(longpath, shortpath, len); |
| +// printf ("res: %ld\n", res); |
| + if (!res) { |
| +// WinErr ("getshortpath: res = 0"); |
| + free (shortpath); |
| + set_werrno; |
| + return (char *) longpath; |
| + } |
| +// printf ("shortpath: %s\n", shortpath); |
| + return shortpath; |
| +} |
| + |
| +char *relocaten (const char *ModuleName, const char *path) |
| +{ |
| + char *relative_path, *relocated_path, *relocated_short_path; |
| + int relative_path_len; |
| + |
| + if (!curr_prefix) |
| + set_current_prefix (ModuleName); |
| +// printf ("path: %s\n", path); |
| +// printf ("orig_prefix: %s\n", orig_prefix); |
| +// printf ("curr_prefix: %s\n", curr_prefix); |
| +// if (strncmp (orig_prefix, path, orig_prefix_len)) |
| +// if (strcmp (orig_prefix, path)) |
| +// return (char *) path; |
| + relative_path = (char *) path + orig_prefix_len; |
| +// printf ("relative_path: %s\n", relative_path); |
| + relative_path_len = strlen (relative_path); |
| + relocated_path = malloc (curr_prefix_len + relative_path_len + 1); |
| + strcpy (relocated_path, curr_prefix); |
| + strcat (relocated_path, relative_path); |
| +// printf ("relocated_path: %s\n", relocated_path); |
| + relocated_short_path = getshortpath (relocated_path); |
| +// printf ("relocated_short_path: %s\n", relocated_short_path); |
| + if (relocated_short_path) { |
| + if (relocated_short_path != relocated_path) |
| + free (relocated_path); |
| + return relocated_short_path; |
| + } else |
| + return relocated_path; |
| +} |
| + |
| +#else // __WIN32__ |
| +char *relocaten (const char *ModuleName, const char *path) |
| +{ |
| + // dummy function for Unix/Linux |
| + return (char *)path; |
| +} |
| +#endif |
| + |
| +char *relocaten2 (const char *ModuleName, const char *installdir, const char *path) |
| +{ |
| + set_orig_prefix (installdir); |
| + return relocaten (ModuleName, path); |
| +} |
| + |
| +char *relocatenx (const char *ModuleName, const char *installdir, const char *path) |
| +{ |
| + char *p; |
| + |
| + set_orig_prefix (installdir); |
| + if (access (path, R_OK)) |
| + p = relocaten (ModuleName, path); |
| + else |
| + p = (char *) path; |
| +// printf ("relocatenx: %s\n", p); |
| + return p; |
| +} |
| + |
| +char *relocate2 (const char *installdir, const char *path) |
| +{ |
| + return relocaten2 (NULL, installdir, path); |
| +} |
| + |
| +char *relocatex (const char *installdir, const char *path) |
| +{ |
| + return relocatenx (NULL, installdir, path); |
| +} |
| + |
| +char *relocatepx (const char *cprefix, const char *installdir, const char *path) |
| +{ |
| + if (curr_prefix) |
| + free (curr_prefix); |
| + curr_prefix = strdup (cprefix); |
| + return relocatex (installdir, path); |
| +} |
| + |
| +static char *get_orig_prefix (void) |
| +{ |
| + return orig_prefix; |
| +} |
| + |
| +static char *get_curr_prefix (void) |
| +{ |
| + return curr_prefix; |
| +} |
| + |
| +static char *set_curr_prefix (const char *ModuleName) |
| +{ |
| + if (curr_prefix) |
| + free (curr_prefix); |
| + set_current_prefix (ModuleName); |
| + return curr_prefix; |
| +} |
| diff --git a/intl/relocatex.h b/intl/relocatex.h |
| new file mode 100644 |
| index 0000000..5cc7c51 |
| --- /dev/null |
| +++ b/intl/relocatex.h |
| @@ -0,0 +1,41 @@ |
| +/* |
| + Copyright (C) 2006 Free Software Foundation, Inc. |
| + This file is part of the GnuWin C Library. |
| + |
| + The GnuWin C Library is free software; you can redistribute it and/or |
| + modify it under the terms of the GNU Lesser General Public |
| + License as published by the Free Software Foundation; either |
| + version 2.1 of the License, or (at your option) any later version. |
| + |
| + The GnuWin 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 |
| + Lesser General Public License for more details. |
| + |
| + You should have received a copy of the GNU Lesser General Public |
| + License along with the GnuWin32 C Library; if not, write to the Free |
| + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| + 02111-1307 USA. */ |
| + |
| +#ifndef __RELOCATE_H__ |
| +#define __RELOCATE_H__ 1 |
| + |
| +/* #include <libc-dll.h> */ |
| + |
| +#ifdef __cplusplus |
| +extern "C" { |
| +#endif |
| + |
| +char *relocaten (const char *ModuleName, const char *path); |
| +char *relocaten2 (const char *ModuleName, const char *installdir, const char *path); |
| +char *relocatenx (const char *ModuleName, const char *installdir, const char *path); |
| +char *relocate2 (const char *installdir, const char *path); |
| +char *relocatex (const char *installdir, const char *path); |
| + |
| +#ifdef __cplusplus |
| +} |
| +#endif |
| + |
| +//#endif /* __GW32__ */ |
| + |
| +#endif /* __RELOCATE_H__ */ |
| -- |
| 2.8.1 |
| |