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 */ 8intis_directory(const char*path) 9{ 10struct stat st; 11return(!stat(path, &st) &&S_ISDIR(st.st_mode)); 12} 13 14/* removes the last path component from 'path' except if 'path' is root */ 15static voidstrip_last_component(struct strbuf *path) 16{ 17size_t offset =offset_1st_component(path->buf); 18size_t len = path->len; 19 20/* Find start of the last component */ 21while(offset < len && !is_dir_sep(path->buf[len -1])) 22 len--; 23/* Skip sequences of multiple path-separators */ 24while(offset < len &&is_dir_sep(path->buf[len -1])) 25 len--; 26 27strbuf_setlen(path, len); 28} 29 30/* get (and remove) the next component in 'remaining' and place it in 'next' */ 31static voidget_next_component(struct strbuf *next,struct strbuf *remaining) 32{ 33char*start = NULL; 34char*end = NULL; 35 36strbuf_reset(next); 37 38/* look for the next component */ 39/* Skip sequences of multiple path-separators */ 40for(start = remaining->buf;is_dir_sep(*start); start++) 41;/* nothing */ 42/* Find end of the path component */ 43for(end = start; *end && !is_dir_sep(*end); end++) 44;/* nothing */ 45 46strbuf_add(next, start, end - start); 47/* remove the component from 'remaining' */ 48strbuf_remove(remaining,0, end - remaining->buf); 49} 50 51/* We allow "recursive" symbolic links. Only within reason, though. */ 52#define MAXSYMLINKS 5 53 54/* 55 * Return the real path (i.e., absolute path, with symlinks resolved 56 * and extra slashes removed) equivalent to the specified path. (If 57 * you want an absolute path but don't mind links, use 58 * absolute_path().) The return value is a pointer to a static 59 * buffer. 60 * 61 * The directory part of path (i.e., everything up to the last 62 * dir_sep) must denote a valid, existing directory, but the last 63 * component need not exist. If die_on_error is set, then die with an 64 * informative error message if there is a problem. Otherwise, return 65 * NULL on errors (without generating any output). 66 * 67 * If path is our buffer, then return path, as it's already what the 68 * user wants. 69 */ 70static const char*real_path_internal(const char*path,int die_on_error) 71{ 72static struct strbuf resolved = STRBUF_INIT; 73struct strbuf remaining = STRBUF_INIT; 74struct strbuf next = STRBUF_INIT; 75struct strbuf symlink = STRBUF_INIT; 76char*retval = NULL; 77int num_symlinks =0; 78struct stat st; 79 80/* We've already done it */ 81if(path == resolved.buf) 82return path; 83 84if(!*path) { 85if(die_on_error) 86die("The empty string is not a valid path"); 87else 88goto error_out; 89} 90 91strbuf_reset(&resolved); 92 93if(is_absolute_path(path)) { 94/* absolute path; start with only root as being resolved */ 95int offset =offset_1st_component(path); 96strbuf_add(&resolved, path, offset); 97strbuf_addstr(&remaining, path + offset); 98}else{ 99/* relative path; can use CWD as the initial resolved path */ 100if(strbuf_getcwd(&resolved)) { 101if(die_on_error) 102die_errno("unable to get current working directory"); 103else 104goto error_out; 105} 106strbuf_addstr(&remaining, path); 107} 108 109/* Iterate over the remaining path components */ 110while(remaining.len >0) { 111get_next_component(&next, &remaining); 112 113if(next.len ==0) { 114continue;/* empty component */ 115}else if(next.len ==1&& !strcmp(next.buf,".")) { 116continue;/* '.' component */ 117}else if(next.len ==2&& !strcmp(next.buf,"..")) { 118/* '..' component; strip the last path component */ 119strip_last_component(&resolved); 120continue; 121} 122 123/* append the next component and resolve resultant path */ 124if(!is_dir_sep(resolved.buf[resolved.len -1])) 125strbuf_addch(&resolved,'/'); 126strbuf_addbuf(&resolved, &next); 127 128if(lstat(resolved.buf, &st)) { 129/* error out unless this was the last component */ 130if(errno != ENOENT || remaining.len) { 131if(die_on_error) 132die_errno("Invalid path '%s'", 133 resolved.buf); 134else 135goto error_out; 136} 137}else if(S_ISLNK(st.st_mode)) { 138 ssize_t len; 139strbuf_reset(&symlink); 140 141if(num_symlinks++ > MAXSYMLINKS) { 142if(die_on_error) 143die("More than%dnested symlinks " 144"on path '%s'", MAXSYMLINKS, path); 145else 146goto error_out; 147} 148 149 len =strbuf_readlink(&symlink, resolved.buf, 150 st.st_size); 151if(len <0) { 152if(die_on_error) 153die_errno("Invalid symlink '%s'", 154 resolved.buf); 155else 156goto error_out; 157} 158 159if(is_absolute_path(symlink.buf)) { 160/* absolute symlink; set resolved to root */ 161int offset =offset_1st_component(symlink.buf); 162strbuf_reset(&resolved); 163strbuf_add(&resolved, symlink.buf, offset); 164strbuf_remove(&symlink,0, offset); 165}else{ 166/* 167 * relative symlink 168 * strip off the last component since it will 169 * be replaced with the contents of the symlink 170 */ 171strip_last_component(&resolved); 172} 173 174/* 175 * if there are still remaining components to resolve 176 * then append them to symlink 177 */ 178if(remaining.len) { 179strbuf_addch(&symlink,'/'); 180strbuf_addbuf(&symlink, &remaining); 181} 182 183/* 184 * use the symlink as the remaining components that 185 * need to be resloved 186 */ 187strbuf_swap(&symlink, &remaining); 188} 189} 190 191 retval = resolved.buf; 192 193error_out: 194strbuf_release(&remaining); 195strbuf_release(&next); 196strbuf_release(&symlink); 197 198return retval; 199} 200 201const char*real_path(const char*path) 202{ 203returnreal_path_internal(path,1); 204} 205 206const char*real_path_if_valid(const char*path) 207{ 208returnreal_path_internal(path,0); 209} 210 211/* 212 * Use this to get an absolute path from a relative one. If you want 213 * to resolve links, you should use real_path. 214 */ 215const char*absolute_path(const char*path) 216{ 217static struct strbuf sb = STRBUF_INIT; 218strbuf_reset(&sb); 219strbuf_add_absolute_path(&sb, path); 220return sb.buf; 221} 222 223/* 224 * Unlike prefix_path, this should be used if the named file does 225 * not have to interact with index entry; i.e. name of a random file 226 * on the filesystem. 227 */ 228const char*prefix_filename(const char*pfx,int pfx_len,const char*arg) 229{ 230static struct strbuf path = STRBUF_INIT; 231#ifndef GIT_WINDOWS_NATIVE 232if(!pfx_len ||is_absolute_path(arg)) 233return arg; 234strbuf_reset(&path); 235strbuf_add(&path, pfx, pfx_len); 236strbuf_addstr(&path, arg); 237#else 238/* don't add prefix to absolute paths, but still replace '\' by '/' */ 239strbuf_reset(&path); 240if(is_absolute_path(arg)) 241 pfx_len =0; 242else if(pfx_len) 243strbuf_add(&path, pfx, pfx_len); 244strbuf_addstr(&path, arg); 245convert_slashes(path.buf + pfx_len); 246#endif 247return path.buf; 248}