1#include "cache.h" 2 3/* 4 * Do not use this for inspecting *tracked* content. When path is a 5 * symlink to a directory, we do not want to say it is a directory when 6 * dealing with tracked content in the working tree. 7 */ 8int is_directory(const char *path) 9{ 10 struct stat st; 11 return (!stat(path, &st) && S_ISDIR(st.st_mode)); 12} 13 14/* We allow "recursive" symbolic links. Only within reason, though. */ 15#define MAXDEPTH 5 16 17/* 18 * Return the real path (i.e., absolute path, with symlinks resolved 19 * and extra slashes removed) equivalent to the specified path. (If 20 * you want an absolute path but don't mind links, use 21 * absolute_path().) The return value is a pointer to a static 22 * buffer. 23 * 24 * The input and all intermediate paths must be shorter than MAX_PATH. 25 * The directory part of path (i.e., everything up to the last 26 * dir_sep) must denote a valid, existing directory, but the last 27 * component need not exist. If die_on_error is set, then die with an 28 * informative error message if there is a problem. Otherwise, return 29 * NULL on errors (without generating any output). 30 * 31 * If path is our buffer, then return path, as it's already what the 32 * user wants. 33 */ 34static const char *real_path_internal(const char *path, int die_on_error) 35{ 36 static struct strbuf sb = STRBUF_INIT; 37 char *retval = NULL; 38 39 /* 40 * If we have to temporarily chdir(), store the original CWD 41 * here so that we can chdir() back to it at the end of the 42 * function: 43 */ 44 struct strbuf cwd = STRBUF_INIT; 45 46 int depth = MAXDEPTH; 47 char *last_elem = NULL; 48 struct stat st; 49 50 /* We've already done it */ 51 if (path == sb.buf) 52 return path; 53 54 if (!*path) { 55 if (die_on_error) 56 die("The empty string is not a valid path"); 57 else 58 goto error_out; 59 } 60 61 strbuf_reset(&sb); 62 strbuf_addstr(&sb, path); 63 64 while (depth--) { 65 if (!is_directory(sb.buf)) { 66 char *last_slash = find_last_dir_sep(sb.buf); 67 if (last_slash) { 68 last_elem = xstrdup(last_slash + 1); 69 strbuf_setlen(&sb, last_slash - sb.buf + 1); 70 } else { 71 last_elem = xmemdupz(sb.buf, sb.len); 72 strbuf_reset(&sb); 73 } 74 } 75 76 if (sb.len) { 77 if (!cwd.len && strbuf_getcwd(&cwd)) { 78 if (die_on_error) 79 die_errno("Could not get current working directory"); 80 else 81 goto error_out; 82 } 83 84 if (chdir(sb.buf)) { 85 if (die_on_error) 86 die_errno("Could not switch to '%s'", 87 sb.buf); 88 else 89 goto error_out; 90 } 91 } 92 if (strbuf_getcwd(&sb)) { 93 if (die_on_error) 94 die_errno("Could not get current working directory"); 95 else 96 goto error_out; 97 } 98 99 if (last_elem) { 100 if (sb.len && !is_dir_sep(sb.buf[sb.len - 1])) 101 strbuf_addch(&sb, '/'); 102 strbuf_addstr(&sb, last_elem); 103 free(last_elem); 104 last_elem = NULL; 105 } 106 107 if (!lstat(sb.buf, &st) && S_ISLNK(st.st_mode)) { 108 struct strbuf next_sb = STRBUF_INIT; 109 ssize_t len = strbuf_readlink(&next_sb, sb.buf, 0); 110 if (len < 0) { 111 if (die_on_error) 112 die_errno("Invalid symlink '%s'", 113 sb.buf); 114 else 115 goto error_out; 116 } 117 strbuf_swap(&sb, &next_sb); 118 strbuf_release(&next_sb); 119 } else 120 break; 121 } 122 123 retval = sb.buf; 124error_out: 125 free(last_elem); 126 if (cwd.len && chdir(cwd.buf)) 127 die_errno("Could not change back to '%s'", cwd.buf); 128 strbuf_release(&cwd); 129 130 return retval; 131} 132 133const char *real_path(const char *path) 134{ 135 return real_path_internal(path, 1); 136} 137 138const char *real_path_if_valid(const char *path) 139{ 140 return real_path_internal(path, 0); 141} 142 143static const char *get_pwd_cwd(void) 144{ 145 static char cwd[PATH_MAX + 1]; 146 char *pwd; 147 struct stat cwd_stat, pwd_stat; 148 if (getcwd(cwd, PATH_MAX) == NULL) 149 return NULL; 150 pwd = getenv("PWD"); 151 if (pwd && strcmp(pwd, cwd)) { 152 stat(cwd, &cwd_stat); 153 if ((cwd_stat.st_dev || cwd_stat.st_ino) && 154 !stat(pwd, &pwd_stat) && 155 pwd_stat.st_dev == cwd_stat.st_dev && 156 pwd_stat.st_ino == cwd_stat.st_ino) { 157 strlcpy(cwd, pwd, PATH_MAX); 158 } 159 } 160 return cwd; 161} 162 163/* 164 * Use this to get an absolute path from a relative one. If you want 165 * to resolve links, you should use real_path. 166 * 167 * If the path is already absolute, then return path. As the user is 168 * never meant to free the return value, we're safe. 169 */ 170const char *absolute_path(const char *path) 171{ 172 static char buf[PATH_MAX + 1]; 173 174 if (!*path) { 175 die("The empty string is not a valid path"); 176 } else if (is_absolute_path(path)) { 177 if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) 178 die("Too long path: %.*s", 60, path); 179 } else { 180 size_t len; 181 const char *fmt; 182 const char *cwd = get_pwd_cwd(); 183 if (!cwd) 184 die_errno("Cannot determine the current working directory"); 185 len = strlen(cwd); 186 fmt = (len > 0 && is_dir_sep(cwd[len - 1])) ? "%s%s" : "%s/%s"; 187 if (snprintf(buf, PATH_MAX, fmt, cwd, path) >= PATH_MAX) 188 die("Too long path: %.*s", 60, path); 189 } 190 return buf; 191} 192 193/* 194 * Unlike prefix_path, this should be used if the named file does 195 * not have to interact with index entry; i.e. name of a random file 196 * on the filesystem. 197 */ 198const char *prefix_filename(const char *pfx, int pfx_len, const char *arg) 199{ 200 static struct strbuf path = STRBUF_INIT; 201#ifndef GIT_WINDOWS_NATIVE 202 if (!pfx_len || is_absolute_path(arg)) 203 return arg; 204 strbuf_reset(&path); 205 strbuf_add(&path, pfx, pfx_len); 206 strbuf_addstr(&path, arg); 207#else 208 char *p; 209 /* don't add prefix to absolute paths, but still replace '\' by '/' */ 210 strbuf_reset(&path); 211 if (is_absolute_path(arg)) 212 pfx_len = 0; 213 else if (pfx_len) 214 strbuf_add(&path, pfx, pfx_len); 215 strbuf_addstr(&path, arg); 216 for (p = path.buf + pfx_len; *p; p++) 217 if (*p == '\\') 218 *p = '/'; 219#endif 220 return path.buf; 221}