Annotation of embedaddon/libiconv/lib/relocatable.c, revision 1.1.1.3

1.1       misho       1: /* Provide relocatable packages.
1.1.1.3 ! misho       2:    Copyright (C) 2003-2006, 2008-2018 Free Software Foundation, Inc.
1.1       misho       3:    Written by Bruno Haible <bruno@clisp.org>, 2003.
                      4: 
                      5:    This program is free software; you can redistribute it and/or modify it
                      6:    under the terms of the GNU Library General Public License as published
                      7:    by the Free Software Foundation; either version 2, or (at your option)
                      8:    any later version.
                      9: 
                     10:    This program is distributed in the hope that it will be useful,
                     11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     13:    Library General Public License for more details.
                     14: 
1.1.1.3 ! misho      15:    You should have received a copy of the GNU Library General Public License
        !            16:    along with this program; if not, see <https://www.gnu.org/licenses/>.  */
1.1       misho      17: 
                     18: 
                     19: /* Tell glibc's <stdio.h> to provide a prototype for getline().
                     20:    This must come before <config.h> because <config.h> may include
                     21:    <features.h>, and once <features.h> has been included, it's too late.  */
                     22: #ifndef _GNU_SOURCE
1.1.1.2   misho      23: # define _GNU_SOURCE 1
1.1       misho      24: #endif
                     25: 
1.1.1.2   misho      26: #define _GL_USE_STDLIB_ALLOC 1
1.1       misho      27: #include <config.h>
                     28: 
                     29: /* Specification.  */
                     30: #include "relocatable.h"
                     31: 
                     32: #if ENABLE_RELOCATABLE
                     33: 
                     34: #include <stddef.h>
                     35: #include <stdio.h>
                     36: #include <stdlib.h>
                     37: #include <string.h>
                     38: 
                     39: #ifdef NO_XMALLOC
                     40: # define xmalloc malloc
                     41: #else
                     42: # include "xalloc.h"
                     43: #endif
                     44: 
1.1.1.3 ! misho      45: #if defined _WIN32 && !defined __CYGWIN__
1.1       misho      46: # define WIN32_LEAN_AND_MEAN
                     47: # include <windows.h>
                     48: #endif
                     49: 
1.1.1.3 ! misho      50: #ifdef __EMX__
        !            51: # define INCL_DOS
        !            52: # include <os2.h>
        !            53: 
        !            54: # define strcmp  stricmp
        !            55: # define strncmp strnicmp
        !            56: #endif
        !            57: 
1.1       misho      58: #if DEPENDS_ON_LIBCHARSET
                     59: # include <libcharset.h>
                     60: #endif
                     61: #if DEPENDS_ON_LIBICONV && HAVE_ICONV
                     62: # include <iconv.h>
                     63: #endif
                     64: #if DEPENDS_ON_LIBINTL && ENABLE_NLS
                     65: # include <libintl.h>
                     66: #endif
                     67: 
                     68: /* Faked cheap 'bool'.  */
                     69: #undef bool
                     70: #undef false
                     71: #undef true
                     72: #define bool int
                     73: #define false 0
                     74: #define true 1
                     75: 
                     76: /* Pathname support.
                     77:    ISSLASH(C)           tests whether C is a directory separator character.
                     78:    IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
                     79:  */
1.1.1.3 ! misho      80: #if (defined _WIN32 && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
        !            81:   /* Native Windows, OS/2, DOS */
1.1       misho      82: # define ISSLASH(C) ((C) == '/' || (C) == '\\')
                     83: # define HAS_DEVICE(P) \
                     84:     ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
                     85:      && (P)[1] == ':')
                     86: # define IS_PATH_WITH_DIR(P) \
                     87:     (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
                     88: # define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
                     89: #else
                     90:   /* Unix */
                     91: # define ISSLASH(C) ((C) == '/')
                     92: # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
                     93: # define FILE_SYSTEM_PREFIX_LEN(P) 0
                     94: #endif
                     95: 
1.1.1.3 ! misho      96: /* Whether to enable the more costly support for relocatable libraries.
        !            97:    It allows libraries to be have been installed with a different original
        !            98:    prefix than the program.  But it is quite costly, especially on Cygwin
        !            99:    platforms, see below.  Therefore we enable it by default only on native
        !           100:    Windows platforms.  */
        !           101: #ifndef ENABLE_COSTLY_RELOCATABLE
        !           102: # if defined _WIN32 && !defined __CYGWIN__
        !           103: #  define ENABLE_COSTLY_RELOCATABLE 1
        !           104: # else
        !           105: #  define ENABLE_COSTLY_RELOCATABLE 0
        !           106: # endif
        !           107: #endif
        !           108: 
1.1       misho     109: /* Original installation prefix.  */
                    110: static char *orig_prefix;
                    111: static size_t orig_prefix_len;
                    112: /* Current installation prefix.  */
                    113: static char *curr_prefix;
                    114: static size_t curr_prefix_len;
                    115: /* These prefixes do not end in a slash.  Anything that will be concatenated
                    116:    to them must start with a slash.  */
                    117: 
                    118: /* Sets the original and the current installation prefix of this module.
                    119:    Relocation simply replaces a pathname starting with the original prefix
                    120:    by the corresponding pathname with the current prefix instead.  Both
                    121:    prefixes should be directory names without trailing slash (i.e. use ""
                    122:    instead of "/").  */
                    123: static void
                    124: set_this_relocation_prefix (const char *orig_prefix_arg,
1.1.1.2   misho     125:                             const char *curr_prefix_arg)
1.1       misho     126: {
                    127:   if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
                    128:       /* Optimization: if orig_prefix and curr_prefix are equal, the
1.1.1.2   misho     129:          relocation is a nop.  */
1.1       misho     130:       && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
                    131:     {
                    132:       /* Duplicate the argument strings.  */
                    133:       char *memory;
                    134: 
                    135:       orig_prefix_len = strlen (orig_prefix_arg);
                    136:       curr_prefix_len = strlen (curr_prefix_arg);
                    137:       memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
                    138: #ifdef NO_XMALLOC
                    139:       if (memory != NULL)
                    140: #endif
1.1.1.2   misho     141:         {
                    142:           memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
                    143:           orig_prefix = memory;
                    144:           memory += orig_prefix_len + 1;
                    145:           memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
                    146:           curr_prefix = memory;
                    147:           return;
                    148:         }
1.1       misho     149:     }
                    150:   orig_prefix = NULL;
                    151:   curr_prefix = NULL;
                    152:   /* Don't worry about wasted memory here - this function is usually only
                    153:      called once.  */
                    154: }
                    155: 
                    156: /* Sets the original and the current installation prefix of the package.
                    157:    Relocation simply replaces a pathname starting with the original prefix
                    158:    by the corresponding pathname with the current prefix instead.  Both
                    159:    prefixes should be directory names without trailing slash (i.e. use ""
                    160:    instead of "/").  */
                    161: void
                    162: set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
                    163: {
                    164:   set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
                    165: 
                    166:   /* Now notify all dependent libraries.  */
                    167: #if DEPENDS_ON_LIBCHARSET
                    168:   libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
                    169: #endif
                    170: #if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
                    171:   libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
                    172: #endif
                    173: #if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
                    174:   libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
                    175: #endif
                    176: }
                    177: 
1.1.1.3 ! misho     178: #if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE)
1.1       misho     179: 
                    180: /* Convenience function:
                    181:    Computes the current installation prefix, based on the original
                    182:    installation prefix, the original installation directory of a particular
1.1.1.2   misho     183:    file, and the current pathname of this file.
                    184:    Returns it, freshly allocated.  Returns NULL upon failure.  */
1.1       misho     185: #ifdef IN_LIBRARY
                    186: #define compute_curr_prefix local_compute_curr_prefix
                    187: static
                    188: #endif
1.1.1.2   misho     189: char *
1.1       misho     190: compute_curr_prefix (const char *orig_installprefix,
1.1.1.2   misho     191:                      const char *orig_installdir,
                    192:                      const char *curr_pathname)
1.1       misho     193: {
1.1.1.2   misho     194:   char *curr_installdir;
1.1       misho     195:   const char *rel_installdir;
                    196: 
                    197:   if (curr_pathname == NULL)
                    198:     return NULL;
                    199: 
                    200:   /* Determine the relative installation directory, relative to the prefix.
                    201:      This is simply the difference between orig_installprefix and
                    202:      orig_installdir.  */
                    203:   if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
                    204:       != 0)
                    205:     /* Shouldn't happen - nothing should be installed outside $(prefix).  */
                    206:     return NULL;
                    207:   rel_installdir = orig_installdir + strlen (orig_installprefix);
                    208: 
                    209:   /* Determine the current installation directory.  */
                    210:   {
                    211:     const char *p_base = curr_pathname + FILE_SYSTEM_PREFIX_LEN (curr_pathname);
                    212:     const char *p = curr_pathname + strlen (curr_pathname);
                    213:     char *q;
                    214: 
                    215:     while (p > p_base)
                    216:       {
1.1.1.2   misho     217:         p--;
                    218:         if (ISSLASH (*p))
                    219:           break;
1.1       misho     220:       }
                    221: 
                    222:     q = (char *) xmalloc (p - curr_pathname + 1);
                    223: #ifdef NO_XMALLOC
                    224:     if (q == NULL)
                    225:       return NULL;
                    226: #endif
                    227:     memcpy (q, curr_pathname, p - curr_pathname);
                    228:     q[p - curr_pathname] = '\0';
                    229:     curr_installdir = q;
                    230:   }
                    231: 
                    232:   /* Compute the current installation prefix by removing the trailing
                    233:      rel_installdir from it.  */
                    234:   {
                    235:     const char *rp = rel_installdir + strlen (rel_installdir);
                    236:     const char *cp = curr_installdir + strlen (curr_installdir);
                    237:     const char *cp_base =
                    238:       curr_installdir + FILE_SYSTEM_PREFIX_LEN (curr_installdir);
                    239: 
                    240:     while (rp > rel_installdir && cp > cp_base)
                    241:       {
1.1.1.2   misho     242:         bool same = false;
                    243:         const char *rpi = rp;
                    244:         const char *cpi = cp;
                    245: 
                    246:         while (rpi > rel_installdir && cpi > cp_base)
                    247:           {
                    248:             rpi--;
                    249:             cpi--;
                    250:             if (ISSLASH (*rpi) || ISSLASH (*cpi))
                    251:               {
                    252:                 if (ISSLASH (*rpi) && ISSLASH (*cpi))
                    253:                   same = true;
                    254:                 break;
                    255:               }
                    256:             /* Do case-insensitive comparison if the file system is always or
                    257:                often case-insensitive.  It's better to accept the comparison
                    258:                if the difference is only in case, rather than to fail.  */
1.1.1.3 ! misho     259: #if defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
        !           260:             /* Native Windows, Cygwin, OS/2, DOS - case insignificant file system */
1.1.1.2   misho     261:             if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
                    262:                 != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
                    263:               break;
1.1       misho     264: #else
1.1.1.2   misho     265:             if (*rpi != *cpi)
                    266:               break;
1.1       misho     267: #endif
1.1.1.2   misho     268:           }
                    269:         if (!same)
                    270:           break;
                    271:         /* The last pathname component was the same.  opi and cpi now point
                    272:            to the slash before it.  */
                    273:         rp = rpi;
                    274:         cp = cpi;
1.1       misho     275:       }
                    276: 
                    277:     if (rp > rel_installdir)
1.1.1.2   misho     278:       {
                    279:         /* Unexpected: The curr_installdir does not end with rel_installdir.  */
                    280:         free (curr_installdir);
                    281:         return NULL;
                    282:       }
1.1       misho     283: 
                    284:     {
                    285:       size_t curr_prefix_len = cp - curr_installdir;
                    286:       char *curr_prefix;
                    287: 
                    288:       curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
                    289: #ifdef NO_XMALLOC
                    290:       if (curr_prefix == NULL)
1.1.1.2   misho     291:         {
                    292:           free (curr_installdir);
                    293:           return NULL;
                    294:         }
1.1       misho     295: #endif
                    296:       memcpy (curr_prefix, curr_installdir, curr_prefix_len);
                    297:       curr_prefix[curr_prefix_len] = '\0';
                    298: 
1.1.1.2   misho     299:       free (curr_installdir);
                    300: 
1.1       misho     301:       return curr_prefix;
                    302:     }
                    303:   }
                    304: }
                    305: 
                    306: #endif /* !IN_LIBRARY || PIC */
                    307: 
1.1.1.3 ! misho     308: #if defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE
1.1       misho     309: 
                    310: /* Full pathname of shared library, or NULL.  */
                    311: static char *shared_library_fullname;
                    312: 
1.1.1.3 ! misho     313: #if defined _WIN32 && !defined __CYGWIN__
        !           314: /* Native Windows only.
1.1.1.2   misho     315:    On Cygwin, it is better to use the Cygwin provided /proc interface, than
1.1.1.3 ! misho     316:    to use native Windows API and cygwin_conv_to_posix_path, because it
        !           317:    supports longer file names
        !           318:    (see <https://cygwin.com/ml/cygwin/2011-01/msg00410.html>).  */
1.1       misho     319: 
                    320: /* Determine the full pathname of the shared library when it is loaded.  */
                    321: 
                    322: BOOL WINAPI
                    323: DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
                    324: {
                    325:   (void) reserved;
                    326: 
                    327:   if (event == DLL_PROCESS_ATTACH)
                    328:     {
                    329:       /* The DLL is being loaded into an application's address range.  */
                    330:       static char location[MAX_PATH];
                    331: 
                    332:       if (!GetModuleFileName (module_handle, location, sizeof (location)))
1.1.1.2   misho     333:         /* Shouldn't happen.  */
                    334:         return FALSE;
1.1       misho     335: 
                    336:       if (!IS_PATH_WITH_DIR (location))
1.1.1.2   misho     337:         /* Shouldn't happen.  */
                    338:         return FALSE;
1.1       misho     339: 
1.1.1.2   misho     340:       shared_library_fullname = strdup (location);
1.1       misho     341:     }
                    342: 
                    343:   return TRUE;
                    344: }
                    345: 
1.1.1.3 ! misho     346: #elif defined __EMX__
        !           347: 
        !           348: extern int  _CRT_init (void);
        !           349: extern void _CRT_term (void);
        !           350: extern void __ctordtorInit (void);
        !           351: extern void __ctordtorTerm (void);
        !           352: 
        !           353: unsigned long _System
        !           354: _DLL_InitTerm (unsigned long hModule, unsigned long ulFlag)
        !           355: {
        !           356:   static char location[CCHMAXPATH];
        !           357: 
        !           358:   switch (ulFlag)
        !           359:     {
        !           360:       case 0:
        !           361:         if (_CRT_init () == -1)
        !           362:           return 0;
        !           363: 
        !           364:         __ctordtorInit();
        !           365: 
        !           366:         /* See http://cyberkinetica.homeunix.net/os2tk45/cp1/1247_L2H_DosQueryModuleNameSy.html
        !           367:            for specification of DosQueryModuleName(). */
        !           368:         if (DosQueryModuleName (hModule, sizeof (location), location))
        !           369:           return 0;
        !           370: 
        !           371:         _fnslashify (location);
        !           372:         shared_library_fullname = strdup (location);
        !           373:         break;
        !           374: 
        !           375:       case 1:
        !           376:         __ctordtorTerm();
        !           377: 
        !           378:         _CRT_term ();
        !           379:         break;
        !           380:     }
        !           381: 
        !           382:   return 1;
        !           383: }
        !           384: 
1.1.1.2   misho     385: #else /* Unix */
1.1       misho     386: 
                    387: static void
                    388: find_shared_library_fullname ()
                    389: {
1.1.1.2   misho     390: #if (defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__
                    391:   /* Linux has /proc/self/maps. glibc 2 and uClibc have the getline()
                    392:      function.
1.1.1.3 ! misho     393:      Cygwin >= 1.5 has /proc/self/maps and the getline() function too.
        !           394:      But it is costly: ca. 0.3 ms on Linux, 3 ms on Cygwin 1.5, and 5 ms on
        !           395:      Cygwin 1.7.  */
1.1       misho     396:   FILE *fp;
                    397: 
                    398:   /* Open the current process' maps file.  It describes one VMA per line.  */
                    399:   fp = fopen ("/proc/self/maps", "r");
                    400:   if (fp)
                    401:     {
                    402:       unsigned long address = (unsigned long) &find_shared_library_fullname;
                    403:       for (;;)
1.1.1.2   misho     404:         {
                    405:           unsigned long start, end;
                    406:           int c;
                    407: 
                    408:           if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
                    409:             break;
                    410:           if (address >= start && address <= end - 1)
                    411:             {
                    412:               /* Found it.  Now see if this line contains a filename.  */
                    413:               while (c = getc (fp), c != EOF && c != '\n' && c != '/')
                    414:                 continue;
                    415:               if (c == '/')
                    416:                 {
                    417:                   size_t size;
                    418:                   int len;
                    419: 
                    420:                   ungetc (c, fp);
                    421:                   shared_library_fullname = NULL; size = 0;
                    422:                   len = getline (&shared_library_fullname, &size, fp);
                    423:                   if (len >= 0)
                    424:                     {
                    425:                       /* Success: filled shared_library_fullname.  */
                    426:                       if (len > 0 && shared_library_fullname[len - 1] == '\n')
                    427:                         shared_library_fullname[len - 1] = '\0';
                    428:                     }
                    429:                 }
                    430:               break;
                    431:             }
                    432:           while (c = getc (fp), c != EOF && c != '\n')
                    433:             continue;
                    434:         }
1.1       misho     435:       fclose (fp);
                    436:     }
                    437: #endif
                    438: }
                    439: 
1.1.1.3 ! misho     440: #endif /* Native Windows / EMX / Unix */
1.1       misho     441: 
                    442: /* Return the full pathname of the current shared library.
                    443:    Return NULL if unknown.
1.1.1.3 ! misho     444:    Guaranteed to work only on Linux, EMX, Cygwin, and native Windows.  */
1.1       misho     445: static char *
                    446: get_shared_library_fullname ()
                    447: {
1.1.1.3 ! misho     448: #if !(defined _WIN32 && !defined __CYGWIN__) && !defined __EMX__
1.1       misho     449:   static bool tried_find_shared_library_fullname;
                    450:   if (!tried_find_shared_library_fullname)
                    451:     {
                    452:       find_shared_library_fullname ();
                    453:       tried_find_shared_library_fullname = true;
                    454:     }
                    455: #endif
                    456:   return shared_library_fullname;
                    457: }
                    458: 
                    459: #endif /* PIC */
                    460: 
                    461: /* Returns the pathname, relocated according to the current installation
1.1.1.2   misho     462:    directory.
                    463:    The returned string is either PATHNAME unmodified or a freshly allocated
                    464:    string that you can free with free() after casting it to 'char *'.  */
1.1       misho     465: const char *
                    466: relocate (const char *pathname)
                    467: {
1.1.1.3 ! misho     468: #if defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE
1.1       misho     469:   static int initialized;
                    470: 
                    471:   /* Initialization code for a shared library.  */
                    472:   if (!initialized)
                    473:     {
                    474:       /* At this point, orig_prefix and curr_prefix likely have already been
1.1.1.2   misho     475:          set through the main program's set_program_name_and_installdir
                    476:          function.  This is sufficient in the case that the library has
                    477:          initially been installed in the same orig_prefix.  But we can do
                    478:          better, to also cover the cases that 1. it has been installed
                    479:          in a different prefix before being moved to orig_prefix and (later)
                    480:          to curr_prefix, 2. unlike the program, it has not moved away from
                    481:          orig_prefix.  */
1.1       misho     482:       const char *orig_installprefix = INSTALLPREFIX;
                    483:       const char *orig_installdir = INSTALLDIR;
1.1.1.2   misho     484:       char *curr_prefix_better;
1.1       misho     485: 
                    486:       curr_prefix_better =
1.1.1.2   misho     487:         compute_curr_prefix (orig_installprefix, orig_installdir,
                    488:                              get_shared_library_fullname ());
                    489: 
                    490:       set_relocation_prefix (orig_installprefix,
                    491:                              curr_prefix_better != NULL
                    492:                              ? curr_prefix_better
                    493:                              : curr_prefix);
1.1       misho     494: 
1.1.1.2   misho     495:       if (curr_prefix_better != NULL)
                    496:         free (curr_prefix_better);
1.1       misho     497: 
                    498:       initialized = 1;
                    499:     }
                    500: #endif
                    501: 
                    502:   /* Note: It is not necessary to perform case insensitive comparison here,
1.1.1.2   misho     503:      even for DOS-like file systems, because the pathname argument was
1.1       misho     504:      typically created from the same Makefile variable as orig_prefix came
                    505:      from.  */
                    506:   if (orig_prefix != NULL && curr_prefix != NULL
                    507:       && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
                    508:     {
                    509:       if (pathname[orig_prefix_len] == '\0')
1.1.1.2   misho     510:         {
                    511:           /* pathname equals orig_prefix.  */
                    512:           char *result = (char *) xmalloc (strlen (curr_prefix) + 1);
                    513: 
                    514: #ifdef NO_XMALLOC
                    515:           if (result != NULL)
                    516: #endif
                    517:             {
                    518:               strcpy (result, curr_prefix);
                    519:               return result;
                    520:             }
                    521:         }
                    522:       else if (ISSLASH (pathname[orig_prefix_len]))
                    523:         {
                    524:           /* pathname starts with orig_prefix.  */
                    525:           const char *pathname_tail = &pathname[orig_prefix_len];
                    526:           char *result =
                    527:             (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
1.1       misho     528: 
                    529: #ifdef NO_XMALLOC
1.1.1.2   misho     530:           if (result != NULL)
1.1       misho     531: #endif
1.1.1.2   misho     532:             {
                    533:               memcpy (result, curr_prefix, curr_prefix_len);
                    534:               strcpy (result + curr_prefix_len, pathname_tail);
                    535:               return result;
                    536:             }
                    537:         }
1.1       misho     538:     }
1.1.1.3 ! misho     539: 
        !           540: #ifdef __EMX__
        !           541: # ifdef __KLIBC__
        !           542: #  undef strncmp
        !           543: 
        !           544:   if (strncmp (pathname, "/@unixroot", 10) == 0
        !           545:       && (pathname[10] == '\0' || ISSLASH (pathname[10])))
        !           546:     {
        !           547:       /* kLIBC itself processes /@unixroot prefix */
        !           548:       return pathname;
        !           549:     }
        !           550:   else
        !           551: # endif
        !           552:   if (ISSLASH (pathname[0]))
        !           553:     {
        !           554:       const char *unixroot = getenv ("UNIXROOT");
        !           555: 
        !           556:       if (unixroot && HAS_DEVICE (unixroot) && unixroot[2] == '\0')
        !           557:         {
        !           558:           char *result = (char *) xmalloc (2 + strlen (pathname) + 1);
        !           559: #ifdef NO_XMALLOC
        !           560:           if (result != NULL)
        !           561: #endif
        !           562:             {
        !           563:               memcpy (result, unixroot, 2);
        !           564:               strcpy (result + 2, pathname);
        !           565:               return result;
        !           566:             }
        !           567:         }
        !           568:     }
        !           569: #endif
        !           570: 
1.1       misho     571:   /* Nothing to relocate.  */
                    572:   return pathname;
                    573: }
                    574: 
1.1.1.3 ! misho     575: /* Returns the pathname, relocated according to the current installation
        !           576:    directory.
        !           577:    This function sets *ALLOCATEDP to the allocated memory, or to NULL if
        !           578:    no memory allocation occurs.  So that, after you're done with the return
        !           579:    value, to reclaim allocated memory, you can do: free (*ALLOCATEDP).  */
        !           580: const char *
        !           581: relocate2 (const char *pathname, char **allocatedp)
        !           582: {
        !           583:   const char *result = relocate (pathname);
        !           584:   *allocatedp = (result != pathname ? (char *) result : NULL);
        !           585:   return result;
        !           586: }
        !           587: 
1.1       misho     588: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>