git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 09/10] abspath: convert absolute_path() to strbuf

From
René Scharfe <l.s.r@web.de>
Date
Jul 28, 2014, 18:33 UTC
Message-ID
<53D69793.3010307@web.de>
In-Reply-To
<53D694A2.8030007@web.de>

Move most of the code of absolute_path() into the new function strbuf_add_absolute_path() and in the process transform it to use struct strbuf and xgetcwd() instead of a PATH_MAX-sized buffer, which can be too small on some file systems.

Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
 Documentation/technical/api-strbuf.txt |  6 +++++
 abspath.c                              | 46 +++-------------------------------
 strbuf.c                               | 25 ++++++++++++++++++
 strbuf.h                               |  2 ++
 4 files changed, 37 insertions(+), 42 deletions(-)
diff --git a/Documentation/technical/api-strbuf.txt b/Documentation/technical/api-strbuf.txt
index 49e477d..430302c 100644
--- a/Documentation/technical/api-strbuf.txt
+++ b/Documentation/technical/api-strbuf.txt
@@ -311,6 +311,12 @@ same behaviour as well.
 
 	Set the buffer to the path of the current working directory.
 
+`strbuf_add_absolute_path`
+
+	Add a path to a buffer, converting a relative path to an
+	absolute one in the process.  Symbolic links are not
+	resolved.
+
 `stripspace`::
 
 	Strip whitespace from a buffer. The second parameter controls if
diff --git a/abspath.c b/abspath.c
index 16e7fa2..197af68 100644
--- a/abspath.c
+++ b/abspath.c
@@ -140,54 +140,16 @@ const char *real_path_if_valid(const char *path)
 	return real_path_internal(path, 0);
 }
 
-static const char *get_pwd_cwd(void)
-{
-	static char cwd[PATH_MAX + 1];
-	char *pwd;
-	struct stat cwd_stat, pwd_stat;
-	if (getcwd(cwd, PATH_MAX) == NULL)
-		return NULL;
-	pwd = getenv("PWD");
-	if (pwd && strcmp(pwd, cwd)) {
-		stat(cwd, &cwd_stat);
-		if ((cwd_stat.st_dev || cwd_stat.st_ino) &&
-		    !stat(pwd, &pwd_stat) &&
-		    pwd_stat.st_dev == cwd_stat.st_dev &&
-		    pwd_stat.st_ino == cwd_stat.st_ino) {
-			strlcpy(cwd, pwd, PATH_MAX);
-		}
-	}
-	return cwd;
-}
-
 /*
  * Use this to get an absolute path from a relative one. If you want
  * to resolve links, you should use real_path.
- *
- * If the path is already absolute, then return path. As the user is
- * never meant to free the return value, we're safe.
  */
 const char *absolute_path(const char *path)
 {
-	static char buf[PATH_MAX + 1];
-
-	if (!*path) {
-		die("The empty string is not a valid path");
-	} else if (is_absolute_path(path)) {
-		if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-			die("Too long path: %.*s", 60, path);
-	} else {
-		size_t len;
-		const char *fmt;
-		const char *cwd = get_pwd_cwd();
-		if (!cwd)
-			die_errno("Cannot determine the current working directory");
-		len = strlen(cwd);
-		fmt = (len > 0 && is_dir_sep(cwd[len - 1])) ? "%s%s" : "%s/%s";
-		if (snprintf(buf, PATH_MAX, fmt, cwd, path) >= PATH_MAX)
-			die("Too long path: %.*s", 60, path);
-	}
-	return buf;
+	static struct strbuf sb;
+	strbuf_init(&sb, 0);
+	strbuf_add_absolute_path(&sb, path);
+	return sb.buf;
 }
 
 /*
diff --git a/strbuf.c b/strbuf.c
index 2bf4dfa..4d31443 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -576,6 +576,31 @@ void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes)
 	}
 }
 
+void strbuf_add_absolute_path(struct strbuf *sb, const char *path)
+{
+	if (!*path)
+		die("The empty string is not a valid path");
+	if (!is_absolute_path(path)) {
+		struct stat cwd_stat, pwd_stat;
+		size_t orig_len = sb->len;
+		char *cwd = xgetcwd();
+		char *pwd = getenv("PWD");
+		if (pwd && strcmp(pwd, cwd) &&
+		    !stat(cwd, &cwd_stat) &&
+		    (cwd_stat.st_dev || cwd_stat.st_ino) &&
+		    !stat(pwd, &pwd_stat) &&
+		    pwd_stat.st_dev == cwd_stat.st_dev &&
+		    pwd_stat.st_ino == cwd_stat.st_ino)
+			strbuf_addstr(sb, pwd);
+		else
+			strbuf_addstr(sb, cwd);
+		if (sb->len > orig_len && !is_dir_sep(sb->buf[sb->len - 1]))
+			strbuf_addch(sb, '/');
+		free(cwd);
+	}
+	strbuf_addstr(sb, path);
+}
+
 int printf_ln(const char *fmt, ...)
 {
 	int ret;
diff --git a/strbuf.h b/strbuf.h
index bc38bb9..7bdc1da 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -190,6 +190,8 @@ extern void strbuf_addstr_urlencode(struct strbuf *, const char *,
 				    int reserved);
 extern void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes);
 
+extern void strbuf_add_absolute_path(struct strbuf *sb, const char *path);
+
 __attribute__((format (printf,1,2)))
 extern int printf_ln(const char *fmt, ...);
 __attribute__((format (printf,2,3)))
-- 
2.0.2
Previous: René ScharfeNext: Jeff King
Message 22 of 28 in “getcwd without PATH_MAX”
  1. 0/10 getcwd without PATH_MAXRené Scharfe, Jul 28, 2014
  2. 01/10 strbuf: add strbuf_getcwd()René Scharfe, Jul 28, 2014
  3. 02/10 unix-sockets: use strbuf_getcwd()René Scharfe, Jul 28, 2014
  4. Jeff KingJul 28, 2014
  5. 03/10 setup: convert setup_git_directory_gently_1 et al. to strbufRené Scharfe, Jul 28, 2014
  6. Eric SunshineJul 28, 2014
  7. Torsten BögershausenAug 16, 2014
  8. René ScharfeAug 16, 2014
  9. Junio C HamanoAug 18, 2014
  10. 04/10 abspath: use strbuf_getcwd() to remember original working directoryRené Scharfe, Jul 28, 2014
  11. 05/10 abspath: convert real_path_internal() to strbufRené Scharfe, Jul 28, 2014
  12. Jeff KingJul 28, 2014
  13. René ScharfeJul 28, 2014
  14. Jeff KingJul 28, 2014
  15. Junio C HamanoJul 28, 2014
  16. René ScharfeJul 29, 2014
  17. Junio C HamanoJul 29, 2014
  18. fixup for 05/10: plug leakRené Scharfe, Jul 29, 2014
  19. 06/10 wrapper: add xgetcwd()René Scharfe, Jul 28, 2014
  20. 07/10 use xgetcwd() to get the current directory or dieRené Scharfe, Jul 28, 2014
  21. 08/10 use xgetcwd() to set $GIT_DIRRené Scharfe, Jul 28, 2014
  22. 09/10 abspath: convert absolute_path() to strbufRené Scharfe, Jul 28, 2014
  23. Jeff KingJul 28, 2014
  24. René ScharfeJul 28, 2014
  25. fixup for 09/10: plug leakRené Scharfe, Jul 29, 2014
  26. 10/10 use strbuf_add_absolute_path() to add absolute pathsRené Scharfe, Jul 28, 2014
  27. 04/10 abspath: use strbuf_getcwd() to remember original working directoryRené Scharfe, Jul 28, 2014
  28. Jeff KingJul 28, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.