From: Kevin McCarthy Date: Thu, 18 Apr 2019 22:35:22 +0000 (-0700) Subject: Relocate lib.c functions to muttlib.c to enable BUFFER use. X-Git-Tag: mutt-1-12-rel~54 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=92a5f7bb7478ff26855f2199599e6a6bd9a354e5;p=mutt Relocate lib.c functions to muttlib.c to enable BUFFER use. Relocate safe_symlink(), safe_open(), mutt_rmtree() and their dependent functions. This rearrangement is a bit awkward. Another approach for the future might be to convert lib.c into a muttlib.c aware file, and just copy the functions pgppubring.c uses inside itself. --- diff --git a/lib.c b/lib.c index 00c322db..ed93c846 100644 --- a/lib.c +++ b/lib.c @@ -396,45 +396,6 @@ compare_stat (struct stat *osb, struct stat *nsb) return 0; } -int safe_symlink(const char *oldpath, const char *newpath) -{ - struct stat osb, nsb; - - if (!oldpath || !newpath) - return -1; - - if (unlink(newpath) == -1 && errno != ENOENT) - return -1; - - if (oldpath[0] == '/') - { - if (symlink (oldpath, newpath) == -1) - return -1; - } - else - { - char abs_oldpath[_POSIX_PATH_MAX]; - - if ((getcwd (abs_oldpath, sizeof abs_oldpath) == NULL) || - (strlen (abs_oldpath) + 1 + strlen (oldpath) + 1 > sizeof abs_oldpath)) - return -1; - - strcat (abs_oldpath, "/"); /* __STRCAT_CHECKED__ */ - strcat (abs_oldpath, oldpath); /* __STRCAT_CHECKED__ */ - if (symlink (abs_oldpath, newpath) == -1) - return -1; - } - - if (stat(oldpath, &osb) == -1 || stat(newpath, &nsb) == -1 - || compare_stat(&osb, &nsb) == -1) - { - unlink(newpath); - return -1; - } - - return 0; -} - /* @@ -572,163 +533,6 @@ success: } -/* Create a temporary directory next to a file name */ - -static int mutt_mkwrapdir (const char *path, char *newfile, size_t nflen, - char *newdir, size_t ndlen) -{ - const char *basename; - char parent[_POSIX_PATH_MAX]; - char *p; - - strfcpy (parent, NONULL (path), sizeof (parent)); - - if ((p = strrchr (parent, '/'))) - { - *p = '\0'; - basename = p + 1; - } - else - { - strfcpy (parent, ".", sizeof (parent)); - basename = path; - } - - snprintf (newdir, ndlen, "%s/%s", parent, ".muttXXXXXX"); - if (mkdtemp(newdir) == NULL) - { - dprint(1, (debugfile, "mutt_mkwrapdir: mkdtemp() failed\n")); - return -1; - } - - if (snprintf (newfile, nflen, "%s/%s", newdir, NONULL(basename)) >= nflen) - { - rmdir(newdir); - dprint(1, (debugfile, "mutt_mkwrapdir: string was truncated\n")); - return -1; - } - return 0; -} - -/* remove a directory and everything under it */ -int mutt_rmtree (const char* path) -{ - DIR* dirp; - struct dirent* de; - char cur[_POSIX_PATH_MAX]; - struct stat statbuf; - int rc = 0; - - if (!(dirp = opendir (path))) - { - dprint (1, (debugfile, "mutt_rmtree: error opening directory %s\n", path)); - return -1; - } - while ((de = readdir (dirp))) - { - if (!strcmp (".", de->d_name) || !strcmp ("..", de->d_name)) - continue; - - snprintf (cur, sizeof (cur), "%s/%s", path, de->d_name); - /* XXX make nonrecursive version */ - - if (stat(cur, &statbuf) == -1) - { - rc = 1; - continue; - } - - if (S_ISDIR (statbuf.st_mode)) - rc |= mutt_rmtree (cur); - else - rc |= unlink (cur); - } - closedir (dirp); - - rc |= rmdir (path); - - return rc; -} - -static int mutt_put_file_in_place (const char *path, const char *safe_file, const char *safe_dir) -{ - int rv; - - rv = safe_rename (safe_file, path); - unlink (safe_file); - rmdir (safe_dir); - return rv; -} - -int safe_open (const char *path, int flags) -{ - struct stat osb, nsb; - int fd; - - if (flags & O_EXCL) - { - char safe_file[_POSIX_PATH_MAX]; - char safe_dir[_POSIX_PATH_MAX]; - - if (mutt_mkwrapdir (path, safe_file, sizeof (safe_file), - safe_dir, sizeof (safe_dir)) == -1) - return -1; - - if ((fd = open (safe_file, flags, 0600)) < 0) - { - rmdir (safe_dir); - return fd; - } - - /* NFS and I believe cygwin do not handle movement of open files well */ - close (fd); - if (mutt_put_file_in_place (path, safe_file, safe_dir) == -1) - return -1; - } - - if ((fd = open (path, flags & ~O_EXCL, 0600)) < 0) - return fd; - - /* make sure the file is not symlink */ - if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 || - compare_stat(&osb, &nsb) == -1) - { -/* dprint (1, (debugfile, "safe_open(): %s is a symlink!\n", path)); */ - close (fd); - return (-1); - } - - return (fd); -} - -/* when opening files for writing, make sure the file doesn't already exist - * to avoid race conditions. - */ -FILE *safe_fopen (const char *path, const char *mode) -{ - if (mode[0] == 'w') - { - int fd; - int flags = O_CREAT | O_EXCL; - -#ifdef O_NOFOLLOW - flags |= O_NOFOLLOW; -#endif - - if (mode[1] == '+') - flags |= O_RDWR; - else - flags |= O_WRONLY; - - if ((fd = safe_open (path, flags)) < 0) - return (NULL); - - return (fdopen (fd, mode)); - } - else - return (fopen (path, mode)); -} - static const char safe_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+@{}._-:%/"; void mutt_sanitize_filename (char *f, short slash) diff --git a/lib.h b/lib.h index f6b4096f..2a566d7f 100644 --- a/lib.h +++ b/lib.h @@ -169,8 +169,6 @@ void mutt_debug (FILE *, const char *, ...); /* The actual library functions. */ -FILE *safe_fopen (const char *, const char *); - char *mutt_concatn_path (char *, size_t, const char *, size_t, const char *, size_t); char *mutt_concat_path (char *, const char *, const char *, size_t); char *mutt_read_line (char *, size_t *, FILE *, int *, int); @@ -207,12 +205,9 @@ int mutt_strncasecmp (const char *, const char *, size_t); int mutt_strncmp (const char *, const char *, size_t); int mutt_strcoll (const char *, const char *); int safe_asprintf (char **, const char *, ...); -int safe_open (const char *, int); int safe_rename (const char *, const char *); -int safe_symlink (const char *, const char *); int safe_fclose (FILE **); int safe_fsync_close (FILE **); -int mutt_rmtree (const char *); size_t mutt_quote_filename (char *, size_t, const char *); size_t mutt_strlen (const char *); diff --git a/muttlib.c b/muttlib.c index 8ab8785f..f8ed5e96 100644 --- a/muttlib.c +++ b/muttlib.c @@ -46,6 +46,7 @@ #include #include #include +#include BODY *mutt_new_body (void) { @@ -2192,3 +2193,207 @@ void mutt_encode_path (char *dest, size_t dlen, const char *src) strfcpy (dest, (rc == 0) ? NONULL(p) : NONULL(src), dlen); FREE (&p); } + + +/************************************************************************ + * These functions are transplanted from lib.c, in order to modify them * + * to use BUFFERs. * + ************************************************************************/ + +/* remove a directory and everything under it */ +int mutt_rmtree (const char* path) +{ + DIR* dirp; + struct dirent* de; + char cur[_POSIX_PATH_MAX]; + struct stat statbuf; + int rc = 0; + + if (!(dirp = opendir (path))) + { + dprint (1, (debugfile, "mutt_rmtree: error opening directory %s\n", path)); + return -1; + } + while ((de = readdir (dirp))) + { + if (!strcmp (".", de->d_name) || !strcmp ("..", de->d_name)) + continue; + + snprintf (cur, sizeof (cur), "%s/%s", path, de->d_name); + /* XXX make nonrecursive version */ + + if (stat(cur, &statbuf) == -1) + { + rc = 1; + continue; + } + + if (S_ISDIR (statbuf.st_mode)) + rc |= mutt_rmtree (cur); + else + rc |= unlink (cur); + } + closedir (dirp); + + rc |= rmdir (path); + + return rc; +} + +/* Create a temporary directory next to a file name */ + +static int mutt_mkwrapdir (const char *path, char *newfile, size_t nflen, + char *newdir, size_t ndlen) +{ + const char *basename; + char parent[_POSIX_PATH_MAX]; + char *p; + + strfcpy (parent, NONULL (path), sizeof (parent)); + + if ((p = strrchr (parent, '/'))) + { + *p = '\0'; + basename = p + 1; + } + else + { + strfcpy (parent, ".", sizeof (parent)); + basename = path; + } + + snprintf (newdir, ndlen, "%s/%s", parent, ".muttXXXXXX"); + if (mkdtemp(newdir) == NULL) + { + dprint(1, (debugfile, "mutt_mkwrapdir: mkdtemp() failed\n")); + return -1; + } + + if (snprintf (newfile, nflen, "%s/%s", newdir, NONULL(basename)) >= nflen) + { + rmdir(newdir); + dprint(1, (debugfile, "mutt_mkwrapdir: string was truncated\n")); + return -1; + } + return 0; +} + +static int mutt_put_file_in_place (const char *path, const char *safe_file, const char *safe_dir) +{ + int rv; + + rv = safe_rename (safe_file, path); + unlink (safe_file); + rmdir (safe_dir); + return rv; +} + +int safe_open (const char *path, int flags) +{ + struct stat osb, nsb; + int fd; + + if (flags & O_EXCL) + { + char safe_file[_POSIX_PATH_MAX]; + char safe_dir[_POSIX_PATH_MAX]; + + if (mutt_mkwrapdir (path, safe_file, sizeof (safe_file), + safe_dir, sizeof (safe_dir)) == -1) + return -1; + + if ((fd = open (safe_file, flags, 0600)) < 0) + { + rmdir (safe_dir); + return fd; + } + + /* NFS and I believe cygwin do not handle movement of open files well */ + close (fd); + if (mutt_put_file_in_place (path, safe_file, safe_dir) == -1) + return -1; + } + + if ((fd = open (path, flags & ~O_EXCL, 0600)) < 0) + return fd; + + /* make sure the file is not symlink */ + if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 || + compare_stat(&osb, &nsb) == -1) + { +/* dprint (1, (debugfile, "safe_open(): %s is a symlink!\n", path)); */ + close (fd); + return (-1); + } + + return (fd); +} + +/* when opening files for writing, make sure the file doesn't already exist + * to avoid race conditions. + */ +FILE *safe_fopen (const char *path, const char *mode) +{ + if (mode[0] == 'w') + { + int fd; + int flags = O_CREAT | O_EXCL; + +#ifdef O_NOFOLLOW + flags |= O_NOFOLLOW; +#endif + + if (mode[1] == '+') + flags |= O_RDWR; + else + flags |= O_WRONLY; + + if ((fd = safe_open (path, flags)) < 0) + return (NULL); + + return (fdopen (fd, mode)); + } + else + return (fopen (path, mode)); +} + +int safe_symlink(const char *oldpath, const char *newpath) +{ + struct stat osb, nsb; + + if (!oldpath || !newpath) + return -1; + + if (unlink(newpath) == -1 && errno != ENOENT) + return -1; + + if (oldpath[0] == '/') + { + if (symlink (oldpath, newpath) == -1) + return -1; + } + else + { + char abs_oldpath[_POSIX_PATH_MAX]; + + if ((getcwd (abs_oldpath, sizeof abs_oldpath) == NULL) || + (strlen (abs_oldpath) + 1 + strlen (oldpath) + 1 > sizeof abs_oldpath)) + return -1; + + strcat (abs_oldpath, "/"); /* __STRCAT_CHECKED__ */ + strcat (abs_oldpath, oldpath); /* __STRCAT_CHECKED__ */ + if (symlink (abs_oldpath, newpath) == -1) + return -1; + } + + if (stat(oldpath, &osb) == -1 || stat(newpath, &nsb) == -1 + || compare_stat(&osb, &nsb) == -1) + { + unlink(newpath); + return -1; + } + + return 0; +} + +/* END lib.c transplant functions */ diff --git a/protos.h b/protos.h index 639fedb5..e6d9af98 100644 --- a/protos.h +++ b/protos.h @@ -411,6 +411,12 @@ pid_t mutt_create_filter_fd (const char *, FILE **, FILE **, FILE **, int, int, ADDRESS *alias_reverse_lookup (ADDRESS *); +/* lib.c files transplanted to muttlib.c */ +int mutt_rmtree (const char *); +FILE *safe_fopen (const char *, const char *); +int safe_open (const char *, int); +int safe_symlink (const char *, const char *); + /* base64.c */ void mutt_to_base64 (unsigned char*, const unsigned char*, size_t, size_t); int mutt_from_base64 (char*, const char*, size_t);