| diff -ur nano-1.3.12/src/files.c nano-1.3.12-fixed/src/files.c |
| --- nano-1.3.12/src/files.c 2006-06-14 09:19:43.000000000 -0400 |
| +++ nano-1.3.12-fixed/src/files.c 2006-07-05 11:44:17.000000000 -0400 |
| @@ -902,21 +902,29 @@ |
| * able to go there. */ |
| char *get_full_path(const char *origpath) |
| { |
| - char *d_here, *d_there = NULL; |
| + struct stat fileinfo; |
| + char *d_here, *d_there, *d_there_file = NULL; |
| + const char *last_slash; |
| + bool path_only; |
| |
| if (origpath == NULL) |
| return NULL; |
| |
| - /* Get the current directory. */ |
| + /* Get the current directory. If it doesn't exist, back up and try |
| + * again until we get a directory that does, and use that as the |
| + * current directory. */ |
| d_here = charalloc(PATH_MAX + 1); |
| d_here = getcwd(d_here, PATH_MAX + 1); |
| |
| - if (d_here != NULL) { |
| - const char *last_slash; |
| - char *d_there_file = NULL; |
| - bool path_only; |
| - struct stat fileinfo; |
| + while (d_here == NULL) { |
| + if (chdir("..") == -1) |
| + break; |
| + |
| + d_here = getcwd(d_here, PATH_MAX + 1); |
| + } |
| |
| + /* If we succeeded, canonicalize it in d_here. */ |
| + if (d_here != NULL) { |
| align(&d_here); |
| |
| /* If the current directory isn't "/", tack a slash onto the end |
| @@ -925,89 +933,91 @@ |
| d_here = charealloc(d_here, strlen(d_here) + 2); |
| strcat(d_here, "/"); |
| } |
| + /* Otherwise, set d_here to "". */ |
| + } else |
| + d_here = mallocstrcpy(NULL, ""); |
| |
| - d_there = real_dir_from_tilde(origpath); |
| + d_there = real_dir_from_tilde(origpath); |
| |
| - assert(d_there != NULL); |
| + assert(d_there != NULL); |
| |
| - /* Stat d_there. If stat() fails, assume that d_there refers to |
| - * a new file that hasn't been saved to disk yet. Set path_only |
| - * to TRUE if d_there refers to a directory, and FALSE if |
| - * d_there refers to a file. */ |
| - path_only = !stat(d_there, &fileinfo) && |
| - S_ISDIR(fileinfo.st_mode); |
| - |
| - /* If path_only is TRUE, make sure d_there ends in a slash. */ |
| - if (path_only) { |
| - size_t d_there_len = strlen(d_there); |
| - |
| - if (d_there[d_there_len - 1] != '/') { |
| - d_there = charealloc(d_there, d_there_len + 2); |
| - strcat(d_there, "/"); |
| - } |
| - } |
| + /* If stat()ing d_there fails, assume that d_there refers to a new |
| + * file that hasn't been saved to disk yet. Set path_only to TRUE |
| + * if d_there refers to a directory, and FALSE otherwise. */ |
| + path_only = stat(d_there, &fileinfo) == 0 && |
| + S_ISDIR(fileinfo.st_mode); |
| |
| - /* Search for the last slash in d_there. */ |
| - last_slash = strrchr(d_there, '/'); |
| + /* If path_only is TRUE, make sure d_there ends in a slash. */ |
| + if (path_only) { |
| + size_t d_there_len = strlen(d_there); |
| |
| - /* If we didn't find one, then make sure the answer is in the |
| - * format "d_here/d_there". */ |
| - if (last_slash == NULL) { |
| - assert(!path_only); |
| + if (d_there[d_there_len - 1] != '/') { |
| + d_there = charealloc(d_there, d_there_len + 2); |
| + strcat(d_there, "/"); |
| + } |
| + } |
| |
| - d_there_file = d_there; |
| - d_there = d_here; |
| - } else { |
| - /* If path_only is FALSE, then save the filename portion of |
| - * the answer, everything after the last slash, in |
| - * d_there_file. */ |
| - if (!path_only) |
| - d_there_file = mallocstrcpy(NULL, last_slash + 1); |
| - |
| - /* And remove the filename portion of the answer from |
| - * d_there. */ |
| - null_at(&d_there, last_slash - d_there + 1); |
| - |
| - /* Go to the path specified in d_there. */ |
| - if (chdir(d_there) == -1) { |
| - free(d_there); |
| - d_there = NULL; |
| - } else { |
| - /* Get the full path and save it in d_there. */ |
| - free(d_there); |
| + /* Search for the last slash in d_there. */ |
| + last_slash = strrchr(d_there, '/'); |
| |
| - d_there = charalloc(PATH_MAX + 1); |
| - d_there = getcwd(d_there, PATH_MAX + 1); |
| + /* If we didn't find one, then make sure the answer is in the format |
| + * "d_here/d_there". */ |
| + if (last_slash == NULL) { |
| + assert(!path_only); |
| |
| - if (d_there != NULL) { |
| - align(&d_there); |
| + d_there_file = d_there; |
| + d_there = d_here; |
| + } else { |
| + /* If path_only is FALSE, then save the filename portion of the |
| + * answer (everything after the last slash) in d_there_file. */ |
| + if (!path_only) |
| + d_there_file = mallocstrcpy(NULL, last_slash + 1); |
| + |
| + /* And remove the filename portion of the answer from |
| + * d_there. */ |
| + null_at(&d_there, last_slash - d_there + 1); |
| + |
| + /* Go to the path specified in d_there. */ |
| + if (chdir(d_there) == -1) { |
| + free(d_there); |
| + d_there = NULL; |
| + } else { |
| + free(d_there); |
| |
| - if (strcmp(d_there, "/") != 0) { |
| - /* Make sure d_there ends in a slash. */ |
| - d_there = charealloc(d_there, |
| - strlen(d_there) + 2); |
| - strcat(d_there, "/"); |
| - } |
| - } else |
| - /* If we couldn't get the full path, set path_only |
| - * to TRUE so that we clean up correctly, free all |
| - * allocated memory, and return NULL. */ |
| - path_only = TRUE; |
| - |
| - /* Finally, go back to the path specified in d_here, |
| - * where we were before. */ |
| - chdir(d_here); |
| - } |
| + /* Get the full path. */ |
| + d_there = charalloc(PATH_MAX + 1); |
| + d_there = getcwd(d_there, PATH_MAX + 1); |
| + |
| + /* If we succeeded, canonicalize it in d_there. */ |
| + if (d_there != NULL) { |
| + align(&d_there); |
| + |
| + /* If the current directory isn't "/", tack a slash onto |
| + * the end of it. */ |
| + if (strcmp(d_there, "/") != 0) { |
| + d_there = charealloc(d_there, strlen(d_there) + 2); |
| + strcat(d_there, "/"); |
| + } |
| + } else |
| + /* Otherwise, set path_only to TRUE, so that we clean up |
| + * correctly, free all allocated memory, and return |
| + * NULL. */ |
| + path_only = TRUE; |
| + |
| + /* Finally, go back to the path specified in d_here, |
| + * where we were before. We don't check for a chdir() |
| + * error, since we can do nothing then. */ |
| + chdir(d_here); |
| |
| /* Free d_here, since we're done using it. */ |
| free(d_here); |
| } |
| |
| - /* At this point, if path_only is FALSE and d_there exists, |
| + /* At this point, if path_only is FALSE and d_there isn't NULL, |
| * d_there contains the path portion of the answer and |
| * d_there_file contains the filename portion of the answer. If |
| - * this is the case, tack d_there_file onto the end of |
| - * d_there, so that d_there contains the complete answer. */ |
| + * this is the case, tack the latter onto the end of the former. |
| + * d_there will then contain the complete answer. */ |
| if (!path_only && d_there != NULL) { |
| d_there = charealloc(d_there, strlen(d_there) + |
| strlen(d_there_file) + 1); |