856 lines
23 KiB
Diff
856 lines
23 KiB
Diff
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 \
|
|
@@ -61,6 +62,7 @@ HEADERS = \
|
|
eval-plural.h \
|
|
localcharset.h \
|
|
relocatable.h \
|
|
+ relocatex.h \
|
|
libgnuintl.h
|
|
SOURCES = \
|
|
bindtextdom.c \
|
|
@@ -81,6 +83,8 @@ SOURCES = \
|
|
plural-exp.c \
|
|
localcharset.c \
|
|
relocatable.c \
|
|
+ relocatex.c \
|
|
+ canonicalize.c \
|
|
localename.c \
|
|
log.c \
|
|
osdep.c \
|
|
@@ -104,6 +108,8 @@ OBJECTS = \
|
|
plural-exp.o \
|
|
localcharset.o \
|
|
relocatable.o \
|
|
+ relocatex.o \
|
|
+ canonicalize.o \
|
|
localename.o \
|
|
log.o \
|
|
osdep.o \
|
|
@@ -158,7 +164,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 (!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
|
|
|