real_path: convert real_path_internal to strbuf_realpath
Change the name of real_path_internal to strbuf_realpath. In addition push the static strbuf up to its callers and instead take as a parameter a pointer to a strbuf to use for the final result. This change makes strbuf_realpath reentrant. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									05b458c104
								
							
						
					
					
						commit
						a1ae48410d
					
				
							
								
								
									
										53
									
								
								abspath.c
								
								
								
								
							
							
						
						
									
										53
									
								
								abspath.c
								
								
								
								
							|  | @ -55,21 +55,17 @@ static void get_next_component(struct strbuf *next, struct strbuf *remaining) | ||||||
|  * Return the real path (i.e., absolute path, with symlinks resolved |  * Return the real path (i.e., absolute path, with symlinks resolved | ||||||
|  * and extra slashes removed) equivalent to the specified path.  (If |  * and extra slashes removed) equivalent to the specified path.  (If | ||||||
|  * you want an absolute path but don't mind links, use |  * you want an absolute path but don't mind links, use | ||||||
|  * absolute_path().)  The return value is a pointer to a static |  * absolute_path().)  Places the resolved realpath in the provided strbuf. | ||||||
|  * buffer. |  | ||||||
|  * |  * | ||||||
|  * The directory part of path (i.e., everything up to the last |  * The directory part of path (i.e., everything up to the last | ||||||
|  * dir_sep) must denote a valid, existing directory, but the last |  * dir_sep) must denote a valid, existing directory, but the last | ||||||
|  * component need not exist.  If die_on_error is set, then die with an |  * component need not exist.  If die_on_error is set, then die with an | ||||||
|  * informative error message if there is a problem.  Otherwise, return |  * informative error message if there is a problem.  Otherwise, return | ||||||
|  * NULL on errors (without generating any output). |  * NULL on errors (without generating any output). | ||||||
|  * |  | ||||||
|  * If path is our buffer, then return path, as it's already what the |  | ||||||
|  * user wants. |  | ||||||
|  */ |  */ | ||||||
| static const char *real_path_internal(const char *path, int die_on_error) | char *strbuf_realpath(struct strbuf *resolved, const char *path, | ||||||
|  | 		      int die_on_error) | ||||||
| { | { | ||||||
| 	static struct strbuf resolved = STRBUF_INIT; |  | ||||||
| 	struct strbuf remaining = STRBUF_INIT; | 	struct strbuf remaining = STRBUF_INIT; | ||||||
| 	struct strbuf next = STRBUF_INIT; | 	struct strbuf next = STRBUF_INIT; | ||||||
| 	struct strbuf symlink = STRBUF_INIT; | 	struct strbuf symlink = STRBUF_INIT; | ||||||
|  | @ -77,10 +73,6 @@ static const char *real_path_internal(const char *path, int die_on_error) | ||||||
| 	int num_symlinks = 0; | 	int num_symlinks = 0; | ||||||
| 	struct stat st; | 	struct stat st; | ||||||
|  |  | ||||||
| 	/* We've already done it */ |  | ||||||
| 	if (path == resolved.buf) |  | ||||||
| 		return path; |  | ||||||
|  |  | ||||||
| 	if (!*path) { | 	if (!*path) { | ||||||
| 		if (die_on_error) | 		if (die_on_error) | ||||||
| 			die("The empty string is not a valid path"); | 			die("The empty string is not a valid path"); | ||||||
|  | @ -88,16 +80,16 @@ static const char *real_path_internal(const char *path, int die_on_error) | ||||||
| 			goto error_out; | 			goto error_out; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	strbuf_reset(&resolved); | 	strbuf_reset(resolved); | ||||||
|  |  | ||||||
| 	if (is_absolute_path(path)) { | 	if (is_absolute_path(path)) { | ||||||
| 		/* absolute path; start with only root as being resolved */ | 		/* absolute path; start with only root as being resolved */ | ||||||
| 		int offset = offset_1st_component(path); | 		int offset = offset_1st_component(path); | ||||||
| 		strbuf_add(&resolved, path, offset); | 		strbuf_add(resolved, path, offset); | ||||||
| 		strbuf_addstr(&remaining, path + offset); | 		strbuf_addstr(&remaining, path + offset); | ||||||
| 	} else { | 	} else { | ||||||
| 		/* relative path; can use CWD as the initial resolved path */ | 		/* relative path; can use CWD as the initial resolved path */ | ||||||
| 		if (strbuf_getcwd(&resolved)) { | 		if (strbuf_getcwd(resolved)) { | ||||||
| 			if (die_on_error) | 			if (die_on_error) | ||||||
| 				die_errno("unable to get current working directory"); | 				die_errno("unable to get current working directory"); | ||||||
| 			else | 			else | ||||||
|  | @ -116,21 +108,21 @@ static const char *real_path_internal(const char *path, int die_on_error) | ||||||
| 			continue; /* '.' component */ | 			continue; /* '.' component */ | ||||||
| 		} else if (next.len == 2 && !strcmp(next.buf, "..")) { | 		} else if (next.len == 2 && !strcmp(next.buf, "..")) { | ||||||
| 			/* '..' component; strip the last path component */ | 			/* '..' component; strip the last path component */ | ||||||
| 			strip_last_component(&resolved); | 			strip_last_component(resolved); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		/* append the next component and resolve resultant path */ | 		/* append the next component and resolve resultant path */ | ||||||
| 		if (!is_dir_sep(resolved.buf[resolved.len - 1])) | 		if (!is_dir_sep(resolved->buf[resolved->len - 1])) | ||||||
| 			strbuf_addch(&resolved, '/'); | 			strbuf_addch(resolved, '/'); | ||||||
| 		strbuf_addbuf(&resolved, &next); | 		strbuf_addbuf(resolved, &next); | ||||||
|  |  | ||||||
| 		if (lstat(resolved.buf, &st)) { | 		if (lstat(resolved->buf, &st)) { | ||||||
| 			/* error out unless this was the last component */ | 			/* error out unless this was the last component */ | ||||||
| 			if (errno != ENOENT || remaining.len) { | 			if (errno != ENOENT || remaining.len) { | ||||||
| 				if (die_on_error) | 				if (die_on_error) | ||||||
| 					die_errno("Invalid path '%s'", | 					die_errno("Invalid path '%s'", | ||||||
| 						  resolved.buf); | 						  resolved->buf); | ||||||
| 				else | 				else | ||||||
| 					goto error_out; | 					goto error_out; | ||||||
| 			} | 			} | ||||||
|  | @ -146,12 +138,12 @@ static const char *real_path_internal(const char *path, int die_on_error) | ||||||
| 					goto error_out; | 					goto error_out; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			len = strbuf_readlink(&symlink, resolved.buf, | 			len = strbuf_readlink(&symlink, resolved->buf, | ||||||
| 					      st.st_size); | 					      st.st_size); | ||||||
| 			if (len < 0) { | 			if (len < 0) { | ||||||
| 				if (die_on_error) | 				if (die_on_error) | ||||||
| 					die_errno("Invalid symlink '%s'", | 					die_errno("Invalid symlink '%s'", | ||||||
| 						  resolved.buf); | 						  resolved->buf); | ||||||
| 				else | 				else | ||||||
| 					goto error_out; | 					goto error_out; | ||||||
| 			} | 			} | ||||||
|  | @ -159,8 +151,8 @@ static const char *real_path_internal(const char *path, int die_on_error) | ||||||
| 			if (is_absolute_path(symlink.buf)) { | 			if (is_absolute_path(symlink.buf)) { | ||||||
| 				/* absolute symlink; set resolved to root */ | 				/* absolute symlink; set resolved to root */ | ||||||
| 				int offset = offset_1st_component(symlink.buf); | 				int offset = offset_1st_component(symlink.buf); | ||||||
| 				strbuf_reset(&resolved); | 				strbuf_reset(resolved); | ||||||
| 				strbuf_add(&resolved, symlink.buf, offset); | 				strbuf_add(resolved, symlink.buf, offset); | ||||||
| 				strbuf_remove(&symlink, 0, offset); | 				strbuf_remove(&symlink, 0, offset); | ||||||
| 			} else { | 			} else { | ||||||
| 				/* | 				/* | ||||||
|  | @ -168,7 +160,7 @@ static const char *real_path_internal(const char *path, int die_on_error) | ||||||
| 				 * strip off the last component since it will | 				 * strip off the last component since it will | ||||||
| 				 * be replaced with the contents of the symlink | 				 * be replaced with the contents of the symlink | ||||||
| 				 */ | 				 */ | ||||||
| 				strip_last_component(&resolved); | 				strip_last_component(resolved); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			/* | 			/* | ||||||
|  | @ -188,24 +180,29 @@ static const char *real_path_internal(const char *path, int die_on_error) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	retval = resolved.buf; | 	retval = resolved->buf; | ||||||
|  |  | ||||||
| error_out: | error_out: | ||||||
| 	strbuf_release(&remaining); | 	strbuf_release(&remaining); | ||||||
| 	strbuf_release(&next); | 	strbuf_release(&next); | ||||||
| 	strbuf_release(&symlink); | 	strbuf_release(&symlink); | ||||||
|  |  | ||||||
|  | 	if (!retval) | ||||||
|  | 		strbuf_reset(resolved); | ||||||
|  |  | ||||||
| 	return retval; | 	return retval; | ||||||
| } | } | ||||||
|  |  | ||||||
| const char *real_path(const char *path) | const char *real_path(const char *path) | ||||||
| { | { | ||||||
| 	return real_path_internal(path, 1); | 	static struct strbuf realpath = STRBUF_INIT; | ||||||
|  | 	return strbuf_realpath(&realpath, path, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
| const char *real_path_if_valid(const char *path) | const char *real_path_if_valid(const char *path) | ||||||
| { | { | ||||||
| 	return real_path_internal(path, 0); | 	static struct strbuf realpath = STRBUF_INIT; | ||||||
|  | 	return strbuf_realpath(&realpath, path, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										2
									
								
								cache.h
								
								
								
								
							|  | @ -1064,6 +1064,8 @@ static inline int is_absolute_path(const char *path) | ||||||
| 	return is_dir_sep(path[0]) || has_dos_drive_prefix(path); | 	return is_dir_sep(path[0]) || has_dos_drive_prefix(path); | ||||||
| } | } | ||||||
| int is_directory(const char *); | int is_directory(const char *); | ||||||
|  | char *strbuf_realpath(struct strbuf *resolved, const char *path, | ||||||
|  | 		      int die_on_error); | ||||||
| const char *real_path(const char *path); | const char *real_path(const char *path); | ||||||
| const char *real_path_if_valid(const char *path); | const char *real_path_if_valid(const char *path); | ||||||
| const char *absolute_path(const char *path); | const char *absolute_path(const char *path); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Brandon Williams
						Brandon Williams