11debfc3dSmrg /* Libiberty realpath. Like realpath, but more consistent behavior.
21debfc3dSmrg Based on gdb_realpath from GDB.
31debfc3dSmrg
4*8feb0f0bSmrg Copyright (C) 2003-2020 Free Software Foundation, Inc.
51debfc3dSmrg
61debfc3dSmrg This file is part of the libiberty library.
71debfc3dSmrg
81debfc3dSmrg This program is free software; you can redistribute it and/or modify
91debfc3dSmrg it under the terms of the GNU General Public License as published by
101debfc3dSmrg the Free Software Foundation; either version 2 of the License, or
111debfc3dSmrg (at your option) any later version.
121debfc3dSmrg
131debfc3dSmrg This program is distributed in the hope that it will be useful,
141debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
151debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
161debfc3dSmrg GNU General Public License for more details.
171debfc3dSmrg
181debfc3dSmrg You should have received a copy of the GNU General Public License
191debfc3dSmrg along with this program; if not, write to the Free Software
201debfc3dSmrg Foundation, Inc., 51 Franklin Street - Fifth Floor,
211debfc3dSmrg Boston, MA 02110-1301, USA. */
221debfc3dSmrg
231debfc3dSmrg /*
241debfc3dSmrg
251debfc3dSmrg @deftypefn Replacement {const char*} lrealpath (const char *@var{name})
261debfc3dSmrg
271debfc3dSmrg Given a pointer to a string containing a pathname, returns a canonical
281debfc3dSmrg version of the filename. Symlinks will be resolved, and ``.'' and ``..''
291debfc3dSmrg components will be simplified. The returned value will be allocated using
301debfc3dSmrg @code{malloc}, or @code{NULL} will be returned on a memory allocation error.
311debfc3dSmrg
321debfc3dSmrg @end deftypefn
331debfc3dSmrg
341debfc3dSmrg */
351debfc3dSmrg
361debfc3dSmrg #include "config.h"
371debfc3dSmrg #include "ansidecl.h"
381debfc3dSmrg #include "libiberty.h"
391debfc3dSmrg
401debfc3dSmrg #ifdef HAVE_LIMITS_H
411debfc3dSmrg #include <limits.h>
421debfc3dSmrg #endif
431debfc3dSmrg #ifdef HAVE_STDLIB_H
441debfc3dSmrg #include <stdlib.h>
451debfc3dSmrg #endif
461debfc3dSmrg #ifdef HAVE_UNISTD_H
471debfc3dSmrg #include <unistd.h>
481debfc3dSmrg #endif
491debfc3dSmrg #ifdef HAVE_STRING_H
501debfc3dSmrg #include <string.h>
511debfc3dSmrg #endif
521debfc3dSmrg
531debfc3dSmrg /* On GNU libc systems the declaration is only visible with _GNU_SOURCE. */
541debfc3dSmrg #if defined(HAVE_CANONICALIZE_FILE_NAME) \
551debfc3dSmrg && defined(NEED_DECLARATION_CANONICALIZE_FILE_NAME)
561debfc3dSmrg extern char *canonicalize_file_name (const char *);
571debfc3dSmrg #endif
581debfc3dSmrg
591debfc3dSmrg #if defined(HAVE_REALPATH)
601debfc3dSmrg # if defined (PATH_MAX)
611debfc3dSmrg # define REALPATH_LIMIT PATH_MAX
621debfc3dSmrg # else
631debfc3dSmrg # if defined (MAXPATHLEN)
641debfc3dSmrg # define REALPATH_LIMIT MAXPATHLEN
651debfc3dSmrg # endif
661debfc3dSmrg # endif
671debfc3dSmrg #else
681debfc3dSmrg /* cygwin has realpath, so it won't get here. */
691debfc3dSmrg # if defined (_WIN32)
701debfc3dSmrg # define WIN32_LEAN_AND_MEAN
711debfc3dSmrg # include <windows.h> /* for GetFullPathName */
721debfc3dSmrg # endif
731debfc3dSmrg #endif
741debfc3dSmrg
751debfc3dSmrg char *
lrealpath(const char * filename)761debfc3dSmrg lrealpath (const char *filename)
771debfc3dSmrg {
781debfc3dSmrg /* Method 1: The system has a compile time upper bound on a filename
791debfc3dSmrg path. Use that and realpath() to canonicalize the name. This is
801debfc3dSmrg the most common case. Note that, if there isn't a compile time
811debfc3dSmrg upper bound, you want to avoid realpath() at all costs. */
821debfc3dSmrg #if defined(REALPATH_LIMIT)
831debfc3dSmrg {
841debfc3dSmrg char buf[REALPATH_LIMIT];
851debfc3dSmrg const char *rp = realpath (filename, buf);
861debfc3dSmrg if (rp == NULL)
871debfc3dSmrg rp = filename;
881debfc3dSmrg return strdup (rp);
891debfc3dSmrg }
901debfc3dSmrg #endif /* REALPATH_LIMIT */
911debfc3dSmrg
921debfc3dSmrg /* Method 2: The host system (i.e., GNU) has the function
931debfc3dSmrg canonicalize_file_name() which malloc's a chunk of memory and
941debfc3dSmrg returns that, use that. */
951debfc3dSmrg #if defined(HAVE_CANONICALIZE_FILE_NAME)
961debfc3dSmrg {
971debfc3dSmrg char *rp = canonicalize_file_name (filename);
981debfc3dSmrg if (rp == NULL)
991debfc3dSmrg return strdup (filename);
1001debfc3dSmrg else
1011debfc3dSmrg return rp;
1021debfc3dSmrg }
1031debfc3dSmrg #endif
1041debfc3dSmrg
1051debfc3dSmrg /* Method 3: Now we're getting desperate! The system doesn't have a
1061debfc3dSmrg compile time buffer size and no alternative function. Query the
1071debfc3dSmrg OS, using pathconf(), for the buffer limit. Care is needed
1081debfc3dSmrg though, some systems do not limit PATH_MAX (return -1 for
1091debfc3dSmrg pathconf()) making it impossible to pass a correctly sized buffer
1101debfc3dSmrg to realpath() (it could always overflow). On those systems, we
1111debfc3dSmrg skip this. */
1121debfc3dSmrg #if defined (HAVE_REALPATH) && defined (HAVE_UNISTD_H)
1131debfc3dSmrg {
1141debfc3dSmrg /* Find out the max path size. */
1151debfc3dSmrg long path_max = pathconf ("/", _PC_PATH_MAX);
1161debfc3dSmrg if (path_max > 0)
1171debfc3dSmrg {
1181debfc3dSmrg /* PATH_MAX is bounded. */
1191debfc3dSmrg char *buf, *rp, *ret;
1201debfc3dSmrg buf = (char *) malloc (path_max);
1211debfc3dSmrg if (buf == NULL)
1221debfc3dSmrg return NULL;
1231debfc3dSmrg rp = realpath (filename, buf);
1241debfc3dSmrg ret = strdup (rp ? rp : filename);
1251debfc3dSmrg free (buf);
1261debfc3dSmrg return ret;
1271debfc3dSmrg }
1281debfc3dSmrg }
1291debfc3dSmrg #endif
1301debfc3dSmrg
1311debfc3dSmrg /* The MS Windows method. If we don't have realpath, we assume we
1321debfc3dSmrg don't have symlinks and just canonicalize to a Windows absolute
1331debfc3dSmrg path. GetFullPath converts ../ and ./ in relative paths to
1341debfc3dSmrg absolute paths, filling in current drive if one is not given
1351debfc3dSmrg or using the current directory of a specified drive (eg, "E:foo").
1361debfc3dSmrg It also converts all forward slashes to back slashes. */
1371debfc3dSmrg #if defined (_WIN32)
1381debfc3dSmrg {
1391debfc3dSmrg char buf[MAX_PATH];
1401debfc3dSmrg char* basename;
1411debfc3dSmrg DWORD len = GetFullPathName (filename, MAX_PATH, buf, &basename);
1421debfc3dSmrg if (len == 0 || len > MAX_PATH - 1)
1431debfc3dSmrg return strdup (filename);
1441debfc3dSmrg else
1451debfc3dSmrg {
1461debfc3dSmrg /* The file system is case-preserving but case-insensitive,
1471debfc3dSmrg Canonicalize to lowercase, using the codepage associated
1481debfc3dSmrg with the process locale. */
1491debfc3dSmrg CharLowerBuff (buf, len);
1501debfc3dSmrg return strdup (buf);
1511debfc3dSmrg }
1521debfc3dSmrg }
1531debfc3dSmrg #endif
1541debfc3dSmrg
1551debfc3dSmrg /* This system is a lost cause, just duplicate the filename. */
1561debfc3dSmrg return strdup (filename);
1571debfc3dSmrg }
158