00001 /* 00002 * Copyright 2003, 2004, 2005, 2006 PathScale, Inc. All Rights Reserved. 00003 */ 00004 00005 /* Libiberty realpath. Like realpath, but more consistent behavior. 00006 Based on gdb_realpath from GDB. 00007 00008 Copyright 2003 Free Software Foundation, Inc. 00009 00010 This file is part of the libiberty library. 00011 00012 This program is free software; you can redistribute it and/or modify 00013 it under the terms of the GNU General Public License as published by 00014 the Free Software Foundation; either version 2 of the License, or 00015 (at your option) any later version. 00016 00017 This program is distributed in the hope that it will be useful, 00018 but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 GNU General Public License for more details. 00021 00022 You should have received a copy of the GNU General Public License 00023 along with this program; if not, write to the Free Software 00024 Foundation, Inc., 59 Temple Place - Suite 330, 00025 Boston, MA 02111-1307, USA. */ 00026 00027 /* 00028 00029 @deftypefn Replacement {const char*} lrealpath (const char *@var{name}) 00030 00031 Given a pointer to a string containing a pathname, returns a canonical 00032 version of the filename. Symlinks will be resolved, and ``.'' and ``..'' 00033 components will be simplified. The returned value will be allocated using 00034 @code{malloc}, or @code{NULL} will be returned on a memory allocation error. 00035 00036 @end deftypefn 00037 00038 */ 00039 00040 #include "config.h" 00041 #include "ansidecl.h" 00042 #include "libiberty.h" 00043 00044 #ifdef HAVE_LIMITS_H 00045 #include <limits.h> 00046 #endif 00047 #ifdef HAVE_STDLIB_H 00048 #include <stdlib.h> 00049 #endif 00050 #ifdef HAVE_UNISTD_H 00051 #include <unistd.h> 00052 #endif 00053 #ifdef HAVE_STRING_H 00054 #include <string.h> 00055 #endif 00056 00057 /* On GNU libc systems the declaration is only visible with _GNU_SOURCE. */ 00058 #if defined(HAVE_CANONICALIZE_FILE_NAME) \ 00059 && defined(NEED_DECLARATION_CANONICALIZE_FILE_NAME) 00060 extern char *canonicalize_file_name (const char *); 00061 #endif 00062 00063 #if defined(HAVE_REALPATH) 00064 # if defined (PATH_MAX) 00065 # define REALPATH_LIMIT PATH_MAX 00066 # else 00067 # if defined (MAXPATHLEN) 00068 # define REALPATH_LIMIT MAXPATHLEN 00069 # endif 00070 # endif 00071 #else 00072 /* cygwin has realpath, so it won't get here. */ 00073 # if defined (_WIN32) 00074 # define WIN32_LEAN_AND_MEAN 00075 # include <windows.h> /* for GetFullPathName */ 00076 # endif 00077 #endif 00078 00079 char * 00080 lrealpath (filename) 00081 const char *filename; 00082 { 00083 /* Method 1: The system has a compile time upper bound on a filename 00084 path. Use that and realpath() to canonicalize the name. This is 00085 the most common case. Note that, if there isn't a compile time 00086 upper bound, you want to avoid realpath() at all costs. */ 00087 #if defined(REALPATH_LIMIT) 00088 { 00089 char buf[REALPATH_LIMIT]; 00090 const char *rp = realpath (filename, buf); 00091 if (rp == NULL) 00092 rp = filename; 00093 return strdup (rp); 00094 } 00095 #endif /* REALPATH_LIMIT */ 00096 00097 /* Method 2: The host system (i.e., GNU) has the function 00098 canonicalize_file_name() which malloc's a chunk of memory and 00099 returns that, use that. */ 00100 #if defined(HAVE_CANONICALIZE_FILE_NAME) 00101 { 00102 char *rp = canonicalize_file_name (filename); 00103 if (rp == NULL) 00104 return strdup (filename); 00105 else 00106 return rp; 00107 } 00108 #endif 00109 00110 /* Method 3: Now we're getting desperate! The system doesn't have a 00111 compile time buffer size and no alternative function. Query the 00112 OS, using pathconf(), for the buffer limit. Care is needed 00113 though, some systems do not limit PATH_MAX (return -1 for 00114 pathconf()) making it impossible to pass a correctly sized buffer 00115 to realpath() (it could always overflow). On those systems, we 00116 skip this. */ 00117 #if defined (HAVE_REALPATH) && defined (HAVE_UNISTD_H) 00118 { 00119 /* Find out the max path size. */ 00120 long path_max = pathconf ("/", _PC_PATH_MAX); 00121 if (path_max > 0) 00122 { 00123 /* PATH_MAX is bounded. */ 00124 char *buf, *rp, *ret; 00125 buf = malloc (path_max); 00126 if (buf == NULL) 00127 return NULL; 00128 rp = realpath (filename, buf); 00129 ret = strdup (rp ? rp : filename); 00130 free (buf); 00131 return ret; 00132 } 00133 } 00134 #endif 00135 00136 /* The MS Windows method. If we don't have realpath, we assume we 00137 don't have symlinks and just canonicalize to a Windows absolute 00138 path. GetFullPath converts ../ and ./ in relative paths to 00139 absolute paths, filling in current drive if one is not given 00140 or using the current directory of a specified drive (eg, "E:foo"). 00141 It also converts all forward slashes to back slashes. */ 00142 #if defined (_WIN32) 00143 { 00144 char buf[MAX_PATH]; 00145 char* basename; 00146 DWORD len = GetFullPathName (filename, MAX_PATH, buf, &basename); 00147 if (len == 0 || len > MAX_PATH - 1) 00148 return strdup (filename); 00149 else 00150 { 00151 /* The file system is case-preserving but case-insensitive, 00152 Canonicalize to lowercase, using the codepage associated 00153 with the process locale. */ 00154 CharLowerBuff (buf, len); 00155 return strdup (buf); 00156 } 00157 } 00158 #endif 00159 00160 /* This system is a lost cause, just duplicate the filename. */ 00161 return strdup (filename); 00162 }
1.5.6