lrealpath.c revision 130561
1130561Sobrien/* Libiberty realpath. Like realpath, but more consistent behavior. 2130561Sobrien Based on gdb_realpath from GDB. 3130561Sobrien 4130561Sobrien Copyright 2003 Free Software Foundation, Inc. 5130561Sobrien 6130561Sobrien This file is part of the libiberty library. 7130561Sobrien 8130561Sobrien This program is free software; you can redistribute it and/or modify 9130561Sobrien it under the terms of the GNU General Public License as published by 10130561Sobrien the Free Software Foundation; either version 2 of the License, or 11130561Sobrien (at your option) any later version. 12130561Sobrien 13130561Sobrien This program is distributed in the hope that it will be useful, 14130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 15130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130561Sobrien GNU General Public License for more details. 17130561Sobrien 18130561Sobrien You should have received a copy of the GNU General Public License 19130561Sobrien along with this program; if not, write to the Free Software 20130561Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 21130561Sobrien Boston, MA 02111-1307, USA. */ 22130561Sobrien 23130561Sobrien/* 24130561Sobrien 25130561Sobrien@deftypefn Replacement {const char*} lrealpath (const char *@var{name}) 26130561Sobrien 27130561SobrienGiven a pointer to a string containing a pathname, returns a canonical 28130561Sobrienversion of the filename. Symlinks will be resolved, and ``.'' and ``..'' 29130561Sobriencomponents will be simplified. The returned value will be allocated using 30130561Sobrien@code{malloc}, or @code{NULL} will be returned on a memory allocation error. 31130561Sobrien 32130561Sobrien@end deftypefn 33130561Sobrien 34130561Sobrien*/ 35130561Sobrien 36130561Sobrien#include "config.h" 37130561Sobrien#include "ansidecl.h" 38130561Sobrien#include "libiberty.h" 39130561Sobrien 40130561Sobrien#ifdef HAVE_LIMITS_H 41130561Sobrien#include <limits.h> 42130561Sobrien#endif 43130561Sobrien#ifdef HAVE_STDLIB_H 44130561Sobrien#include <stdlib.h> 45130561Sobrien#endif 46130561Sobrien#ifdef HAVE_UNISTD_H 47130561Sobrien#include <unistd.h> 48130561Sobrien#endif 49130561Sobrien#ifdef HAVE_STRING_H 50130561Sobrien#include <string.h> 51130561Sobrien#endif 52130561Sobrien 53130561Sobrien/* On GNU libc systems the declaration is only visible with _GNU_SOURCE. */ 54130561Sobrien#if defined(HAVE_CANONICALIZE_FILE_NAME) \ 55130561Sobrien && defined(NEED_DECLARATION_CANONICALIZE_FILE_NAME) 56130561Sobrienextern char *canonicalize_file_name (const char *); 57130561Sobrien#endif 58130561Sobrien 59130561Sobrien#if defined(HAVE_REALPATH) 60130561Sobrien# if defined (PATH_MAX) 61130561Sobrien# define REALPATH_LIMIT PATH_MAX 62130561Sobrien# else 63130561Sobrien# if defined (MAXPATHLEN) 64130561Sobrien# define REALPATH_LIMIT MAXPATHLEN 65130561Sobrien# endif 66130561Sobrien# endif 67130561Sobrien#endif 68130561Sobrien 69130561Sobrienchar * 70130561Sobrienlrealpath (filename) 71130561Sobrien const char *filename; 72130561Sobrien{ 73130561Sobrien /* Method 1: The system has a compile time upper bound on a filename 74130561Sobrien path. Use that and realpath() to canonicalize the name. This is 75130561Sobrien the most common case. Note that, if there isn't a compile time 76130561Sobrien upper bound, you want to avoid realpath() at all costs. */ 77130561Sobrien#if defined(REALPATH_LIMIT) 78130561Sobrien { 79130561Sobrien char buf[REALPATH_LIMIT]; 80130561Sobrien const char *rp = realpath (filename, buf); 81130561Sobrien if (rp == NULL) 82130561Sobrien rp = filename; 83130561Sobrien return strdup (rp); 84130561Sobrien } 85130561Sobrien#endif /* REALPATH_LIMIT */ 86130561Sobrien 87130561Sobrien /* Method 2: The host system (i.e., GNU) has the function 88130561Sobrien canonicalize_file_name() which malloc's a chunk of memory and 89130561Sobrien returns that, use that. */ 90130561Sobrien#if defined(HAVE_CANONICALIZE_FILE_NAME) 91130561Sobrien { 92130561Sobrien char *rp = canonicalize_file_name (filename); 93130561Sobrien if (rp == NULL) 94130561Sobrien return strdup (filename); 95130561Sobrien else 96130561Sobrien return rp; 97130561Sobrien } 98130561Sobrien#endif 99130561Sobrien 100130561Sobrien /* Method 3: Now we're getting desperate! The system doesn't have a 101130561Sobrien compile time buffer size and no alternative function. Query the 102130561Sobrien OS, using pathconf(), for the buffer limit. Care is needed 103130561Sobrien though, some systems do not limit PATH_MAX (return -1 for 104130561Sobrien pathconf()) making it impossible to pass a correctly sized buffer 105130561Sobrien to realpath() (it could always overflow). On those systems, we 106130561Sobrien skip this. */ 107130561Sobrien#if defined (HAVE_REALPATH) && defined (HAVE_UNISTD_H) 108130561Sobrien { 109130561Sobrien /* Find out the max path size. */ 110130561Sobrien long path_max = pathconf ("/", _PC_PATH_MAX); 111130561Sobrien if (path_max > 0) 112130561Sobrien { 113130561Sobrien /* PATH_MAX is bounded. */ 114130561Sobrien char *buf, *rp, *ret; 115130561Sobrien buf = malloc (path_max); 116130561Sobrien if (buf == NULL) 117130561Sobrien return NULL; 118130561Sobrien rp = realpath (filename, buf); 119130561Sobrien ret = strdup (rp ? rp : filename); 120130561Sobrien free (buf); 121130561Sobrien return ret; 122130561Sobrien } 123130561Sobrien } 124130561Sobrien#endif 125130561Sobrien 126130561Sobrien /* This system is a lost cause, just duplicate the filename. */ 127130561Sobrien return strdup (filename); 128130561Sobrien} 129