[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] tweaks: make use of realpath() in our get_full_path() function
From: |
Benno Schulenberg |
Subject: |
[PATCH] tweaks: make use of realpath() in our get_full_path() function |
Date: |
Thu, 31 Mar 2022 17:14:43 +0200 |
Since 2008, realpath() with NULL as second parameter is part of the
POSIX standard. Operating systems have had nearly fourteen years to
catch up -- this should be time enough.
Using realpath() saves seventy lines of code and gets rid of some
weirdly complicated logic plus unwanted calls of chdir().
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
---
src/files.c | 106 +++++++++-------------------------------------------
1 file changed, 18 insertions(+), 88 deletions(-)
diff --git a/src/files.c b/src/files.c
index 9c598e1f..6641de01 100644
--- a/src/files.c
+++ b/src/files.c
@@ -1345,106 +1345,36 @@ void do_execute(void)
* absolute path (plus filename) when the path exists, and NULL when not. */
char *get_full_path(const char *origpath)
{
- char *allocation, *here, *target, *last_slash;
- char *just_filename = NULL;
- int attempts = 0;
+ char *untilded, *target, *slash;
struct stat fileinfo;
- bool path_only;
if (origpath == NULL)
return NULL;
- allocation = nmalloc(PATH_MAX + 1);
- here = getcwd(allocation, PATH_MAX + 1);
+ untilded = real_dir_from_tilde(origpath);
+ target = realpath(untilded, NULL);
+ slash = strrchr(untilded, '/');
- /* If getting the current directory failed, go up one level and try
again,
- * until we find an existing directory, and use that as the current
one. */
- while (here == NULL && attempts < 20) {
- IGNORE_CALL_RESULT(chdir(".."));
- here = getcwd(allocation, PATH_MAX + 1);
- attempts++;
- }
-
- /* If we found a directory, make sure its path ends in a slash. */
- if (here != NULL) {
- if (strcmp(here, "/") != 0) {
- here = nrealloc(here, strlen(here) + 2);
- strcat(here, "/");
- }
- } else {
- here = copy_of("");
- free(allocation);
- }
-
- target = real_dir_from_tilde(origpath);
-
- /* Determine whether the target path refers to a directory. If statting
- * target fails, however, assume that it refers to a new, unsaved
buffer. */
- path_only = (stat(target, &fileinfo) != -1 &&
S_ISDIR(fileinfo.st_mode));
-
- /* If the target is a directory, make sure its path ends in a slash. */
- if (path_only) {
- size_t length = strlen(target);
-
- if (target[length - 1] != '/') {
- target = nrealloc(target, length + 2);
- strcat(target, "/");
- }
- }
-
- last_slash = strrchr(target, '/');
-
- /* If the target path does not contain a slash, then it is a bare
filename
- * and must therefore be located in the working directory. */
- if (last_slash == NULL) {
- just_filename = target;
- target = here;
- } else {
- /* If target contains a filename, separate the two. */
- if (!path_only) {
- just_filename = copy_of(last_slash + 1);
- *(last_slash + 1) = '\0';
- }
-
- /* If we can't change to the target directory, give up.
Otherwise,
- * get the canonical path to this target directory. */
- if (chdir(target) == -1) {
- free(target);
- target = NULL;
- } else {
- free(target);
-
- allocation = nmalloc(PATH_MAX + 1);
- target = getcwd(allocation, PATH_MAX + 1);
-
- /* If we got a result, make sure it ends in a slash.
- * Otherwise, ensure that we return NULL. */
- if (target != NULL) {
- if (strcmp(target, "/") != 0) {
- target = nrealloc(target,
strlen(target) + 2);
- strcat(target, "/");
- }
- } else {
- path_only = TRUE;
- free(allocation);
- }
+ /* If realpath() returned NULL, try without the last component,
+ * as this can be a file that does not exist yet. */
+ if (!target && slash && slash[1]) {
+ *slash = '\0';
+ target = realpath(untilded, NULL);
- /* Finally, go back to where we were before. We don't
check
- * for an error, since we can't do anything if we get
one. */
- IGNORE_CALL_RESULT(chdir(here));
+ /* Upon success, re-add the last component of the original
path. */
+ if (target) {
+ target = nrealloc(target, strlen(target) + strlen(slash
+ 1) + 1);
+ strcat(target, slash + 1);
}
-
- free(here);
}
- /* If we were given more than a bare path, concatenate the target path
- * with the filename portion to get the full, absolute file path. */
- if (!path_only && target != NULL) {
- target = nrealloc(target, strlen(target) +
strlen(just_filename) + 1);
- strcat(target, just_filename);
+ /* Ensure that a directory path ends with a slash. */
+ if (target && stat(target, &fileinfo) == 0 &&
S_ISDIR(fileinfo.st_mode)) {
+ target = nrealloc(target, strlen(target) + 2);
+ strcat(target, "/");
}
- free(just_filename);
+ free(untilded);
return target;
}
--
2.34.1
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] tweaks: make use of realpath() in our get_full_path() function,
Benno Schulenberg <=