From 758e3b043aa66169b17310154723abbf19ad9fdc Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Thu, 18 Apr 2019 18:42:57 -0700 Subject: [PATCH] Convert migrated lib.c functions to use struct Buffer Fix mutt_getcwd() to return NULL on failure. Change mutt_rmtree(), mutt_mkwrapdir(), safe_open(), and safe_symlink() to use struct Buffer so they don't have filename length limitations. Co-authored-by: Richard Russon --- mutt/file.c | 102 ++++++++++++++++++++++++++++++++-------------------- mutt/path.c | 8 +++-- mutt/path.h | 2 +- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/mutt/file.c b/mutt/file.c index 7d7a55048..4beb60deb 100644 --- a/mutt/file.c +++ b/mutt/file.c @@ -46,6 +46,7 @@ #include "logging.h" #include "memory.h" #include "message.h" +#include "path.h" #include "string2.h" char *C_Tmpdir; ///< Config: Directory for temporary files @@ -82,20 +83,19 @@ static bool compare_stat(struct stat *osb, struct stat *nsb) * mkwrapdir - Create a temporary directory next to a file name * @param path Existing filename * @param newfile New filename - * @param nflen Length of new filename * @param newdir New directory name - * @param ndlen Length of new directory name * @retval 0 Success * @retval -1 Error */ -static int mkwrapdir(const char *path, char *newfile, size_t nflen, char *newdir, size_t ndlen) +static int mkwrapdir(const char *path, struct Buffer *newfile, struct Buffer *newdir) { const char *basename = NULL; - char parent[PATH_MAX]; + int rc = 0; - mutt_str_strfcpy(parent, path, sizeof(parent)); + struct Buffer *parent = mutt_buffer_pool_get(); + mutt_buffer_strcpy(parent, NONULL(path)); - char *p = strrchr(parent, '/'); + char *p = strrchr(parent->data, '/'); if (p) { *p = '\0'; @@ -103,24 +103,23 @@ static int mkwrapdir(const char *path, char *newfile, size_t nflen, char *newdir } else { - mutt_str_strfcpy(parent, ".", sizeof(parent)); + mutt_buffer_strcpy(parent, "."); basename = path; } - snprintf(newdir, ndlen, "%s/%s", parent, ".muttXXXXXX"); - if (!mkdtemp(newdir)) + mutt_buffer_printf(newdir, "%s/%s", mutt_b2s(parent), ".muttXXXXXX"); + if (!mkdtemp(newdir->data)) { mutt_debug(LL_DEBUG1, "mkdtemp() failed\n"); - return -1; + rc = -1; + goto cleanup; } - if (snprintf(newfile, nflen, "%s/%s", newdir, NONULL(basename)) >= nflen) - { - rmdir(newdir); - mutt_debug(LL_DEBUG1, "string was truncated\n"); - return -1; - } - return 0; + mutt_buffer_printf(newfile, "%s/%s", mutt_b2s(newdir), NONULL(basename)); + +cleanup: + mutt_buffer_pool_release(&parent); + return rc; } /** @@ -305,18 +304,23 @@ int mutt_file_symlink(const char *oldpath, const char *newpath) } else { - char abs_oldpath[PATH_MAX]; + struct Buffer *abs_oldpath = mutt_buffer_pool_get(); - if (!getcwd(abs_oldpath, sizeof(abs_oldpath)) || - ((strlen(abs_oldpath) + 1 + strlen(oldpath) + 1) > sizeof(abs_oldpath))) + if (!mutt_path_getcwd(abs_oldpath)) { + mutt_buffer_pool_release(&abs_oldpath); return -1; } - strcat(abs_oldpath, "/"); - strcat(abs_oldpath, oldpath); - if (symlink(abs_oldpath, newpath) == -1) + mutt_buffer_addch(abs_oldpath, '/'); + mutt_buffer_addstr(abs_oldpath, oldpath); + if (symlink(mutt_b2s(abs_oldpath), newpath) == -1) + { + mutt_buffer_pool_release(&abs_oldpath); return -1; + } + + mutt_buffer_pool_release(&abs_oldpath); } if ((stat(oldpath, &osb) == -1) || (stat(newpath, &nsb) == -1) || @@ -458,7 +462,7 @@ int mutt_file_rmtree(const char *path) return -1; struct dirent *de = NULL; - char cur[PATH_MAX]; + struct Buffer *cur = NULL; struct stat statbuf; int rc = 0; @@ -468,29 +472,36 @@ int mutt_file_rmtree(const char *path) mutt_debug(LL_DEBUG1, "error opening directory %s\n", path); return -1; } + + /* We avoid using the buffer pool for this function, because it + * invokes recursively to an unknown depth. */ + cur = mutt_buffer_new(); + mutt_buffer_increase_size(cur, PATH_MAX); + while ((de = readdir(dirp))) { if ((strcmp(".", de->d_name) == 0) || (strcmp("..", de->d_name) == 0)) continue; - snprintf(cur, sizeof(cur), "%s/%s", path, de->d_name); + mutt_buffer_printf(cur, "%s/%s", path, de->d_name); /* XXX make nonrecursive version */ - if (stat(cur, &statbuf) == -1) + if (stat(mutt_b2s(cur), &statbuf) == -1) { rc = 1; continue; } if (S_ISDIR(statbuf.st_mode)) - rc |= mutt_file_rmtree(cur); + rc |= mutt_file_rmtree(mutt_b2s(cur)); else - rc |= unlink(cur); + rc |= unlink(mutt_b2s(cur)); } closedir(dirp); rc |= rmdir(path); + mutt_buffer_free(&cur); return rc; } @@ -505,39 +516,52 @@ int mutt_file_open(const char *path, int flags) { struct stat osb, nsb; int fd; + struct Buffer *safe_file = NULL; + struct Buffer *safe_dir = NULL; if (flags & O_EXCL) { - char safe_file[PATH_MAX]; - char safe_dir[PATH_MAX]; + safe_file = mutt_buffer_pool_get(); + safe_dir = mutt_buffer_pool_get(); - if (mkwrapdir(path, safe_file, sizeof(safe_file), safe_dir, sizeof(safe_dir)) == -1) - return -1; + if (mkwrapdir(path, safe_file, safe_dir) == -1) + { + fd = -1; + goto cleanup; + } - fd = open(safe_file, flags, 0600); + fd = open(mutt_b2s(safe_file), flags, 0600); if (fd < 0) { - rmdir(safe_dir); - return fd; + rmdir(mutt_b2s(safe_dir)); + goto cleanup; } /* NFS and I believe cygwin do not handle movement of open files well */ close(fd); - if (put_file_in_place(path, safe_file, safe_dir) == -1) - return -1; + if (put_file_in_place(path, mutt_b2s(safe_file), mutt_b2s(safe_dir)) == -1) + { + fd = -1; + goto cleanup; + } } fd = open(path, flags & ~O_EXCL, 0600); if (fd < 0) - return fd; + goto cleanup; /* make sure the file is not symlink */ if (((lstat(path, &osb) < 0) || (fstat(fd, &nsb) < 0)) || !compare_stat(&osb, &nsb)) { close(fd); - return -1; + fd = -1; + goto cleanup; } +cleanup: + mutt_buffer_pool_release(&safe_file); + mutt_buffer_pool_release(&safe_dir); + return fd; } diff --git a/mutt/path.c b/mutt/path.c index e27113a7f..22693725b 100644 --- a/mutt/path.c +++ b/mutt/path.c @@ -36,6 +36,7 @@ #include #include #include +#include "path.h" #include "buffer.h" #include "logging.h" #include "memory.h" @@ -590,11 +591,12 @@ char *mutt_path_escape(const char *src) /** * mutt_path_getcwd - Get the current working directory * @param cwd Buffer for the result + * @retval ptr String of current working directory */ -void mutt_path_getcwd(struct Buffer *cwd) +const char *mutt_path_getcwd(struct Buffer *cwd) { if (!cwd) - return; + return NULL; mutt_buffer_increase_size(cwd, PATH_MAX); char *retval = getcwd(cwd->data, cwd->dsize); @@ -607,4 +609,6 @@ void mutt_path_getcwd(struct Buffer *cwd) mutt_buffer_fix_dptr(cwd); else mutt_buffer_reset(cwd); + + return retval; } diff --git a/mutt/path.h b/mutt/path.h index b2cdd509e..6203b91fc 100644 --- a/mutt/path.h +++ b/mutt/path.h @@ -35,7 +35,7 @@ char * mutt_path_concat(char *d, const char *dir, const char *fname, size_t char * mutt_path_concatn(char *dst, size_t dstlen, const char *dir, size_t dirlen, const char *fname, size_t fnamelen); char * mutt_path_dirname(const char *path); char * mutt_path_escape(const char *src); -void mutt_path_getcwd(struct Buffer *cwd); +const char *mutt_path_getcwd(struct Buffer *cwd); bool mutt_path_parent(char *buf, size_t buflen); bool mutt_path_pretty(char *buf, size_t buflen, const char *homedir); size_t mutt_path_realpath(char *buf); -- 2.40.0