struct stat st;
char fullpath[PATH_MAX];
- mutt_file_concat_path(fullpath, folder, path, sizeof(fullpath));
+ mutt_path_concat(fullpath, folder, path, sizeof(fullpath));
if (stat(fullpath, &st) == 0)
return S_ISDIR(st.st_mode);
continue;
}
- mutt_file_concat_path(buffer, d, de->d_name, sizeof(buffer));
+ mutt_path_concat(buffer, d, de->d_name, sizeof(buffer));
if (lstat(buffer, &s) == -1)
continue;
#endif
else
{
- mutt_file_concat_path(buf, LastDir, state.entry[menu->current].name,
+ mutt_path_concat(buf, LastDir, state.entry[menu->current].name,
sizeof(buf));
}
else
{
char tmp[PATH_MAX];
- mutt_file_concat_path(tmp, LastDir,
+ mutt_path_concat(tmp, LastDir,
state.entry[menu->current].name, sizeof(tmp));
mutt_str_strfcpy(LastDir, tmp, sizeof(LastDir));
}
mutt_str_strfcpy(file, state.entry[menu->current].name, filelen);
#endif
else
- mutt_file_concat_path(file, LastDir, state.entry[menu->current].name, filelen);
+ mutt_path_concat(file, LastDir, state.entry[menu->current].name, filelen);
/* fallthrough */
case OP_EXIT:
if (ff.tagged)
{
char full[PATH_MAX];
- mutt_file_concat_path(full, LastDir, ff.name, sizeof(full));
+ mutt_path_concat(full, LastDir, ff.name, sizeof(full));
mutt_expand_path(full, sizeof(full));
tfiles[k++] = mutt_str_strdup(full);
}
/* in case dir is relative, make it relative to LastDir,
* not current working dir */
char tmp[PATH_MAX];
- mutt_file_concat_path(tmp, LastDir, buf, sizeof(tmp));
+ mutt_path_concat(tmp, LastDir, buf, sizeof(tmp));
mutt_str_strfcpy(buf, tmp, sizeof(buf));
}
/* Resolve path from <chdir>
{
char buf2[PATH_MAX];
- mutt_file_concat_path(buf2, LastDir, state.entry[menu->current].name,
+ mutt_path_concat(buf2, LastDir, state.entry[menu->current].name,
sizeof(buf2));
struct Body *b = mutt_make_file_attach(buf2);
if (b)
else
p = NONULL(Folder);
- mutt_file_concat_path(imap_path, p, buf + 1, sizeof(imap_path));
+ mutt_path_concat(imap_path, p, buf + 1, sizeof(imap_path));
}
else
mutt_str_strfcpy(imap_path, buf, sizeof(imap_path));
if (p)
{
char tmp[PATH_MAX];
- if (mutt_file_concatn_path(tmp, sizeof(tmp), exp_dirpart, strlen(exp_dirpart),
+ if (mutt_path_concatn(tmp, sizeof(tmp), exp_dirpart, strlen(exp_dirpart),
buf + 1, (size_t)(p - buf - 1)) == NULL)
{
return -1;
src = CURATTACH->content->d_filename;
else
src = CURATTACH->content->filename;
- mutt_str_strfcpy(fname, mutt_file_basename(NONULL(src)), sizeof(fname));
+ mutt_str_strfcpy(fname, mutt_path_basename(NONULL(src)), sizeof(fname));
ret = mutt_get_field(_("Send attachment with name: "), fname, sizeof(fname), MUTT_FILE);
if (ret == 0)
{
struct Address *addr = env->to ? env->to : (env->cc ? env->cc : env->bcc);
char buf[PATH_MAX];
mutt_safe_path(buf, sizeof(buf), addr);
- mutt_file_concat_path(path, NONULL(Folder), buf, pathlen);
+ mutt_path_concat(path, NONULL(Folder), buf, pathlen);
if (!ForceName && mx_access(path, W_OK) != 0)
mutt_str_strfcpy(path, Record, pathlen);
}
if (!ispipe)
{
struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
- if (!mutt_file_to_absolute_path(rcfile, np ? NONULL(np->data) : ""))
+ if (!mutt_path_to_absolute(rcfile, np ? NONULL(np->data) : ""))
{
mutt_error(_("Error: impossible to build path of '%s'"), rcfile_path);
return -1;
(url_check_scheme(scratch) == U_UNKNOWN)) /* probably a local file */
{
struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
- if (mutt_file_to_absolute_path(scratch, np ? NONULL(np->data) : "./"))
+ if (mutt_path_to_absolute(scratch, np ? NONULL(np->data) : "./"))
{
mutt_buffer_reset(buf);
mutt_buffer_addstr(buf, scratch);
if (!p)
{
#ifdef HOMESPOOL
- mutt_file_concat_path(buffer, NONULL(HomeDir), MAILPATH, sizeof(buffer));
+ mutt_path_concat(buffer, NONULL(HomeDir), MAILPATH, sizeof(buffer));
#else
- mutt_file_concat_path(buffer, MAILPATH, NONULL(Username), sizeof(buffer));
+ mutt_path_concat(buffer, MAILPATH, NONULL(Username), sizeof(buffer));
#endif
p = buffer;
}
return j;
}
-/**
- * mutt_file_concatn_path - Concatenate directory and filename
- * @param dst Buffer for result
- * @param dstlen Buffer length
- * @param dir Directory
- * @param dirlen Directory length
- * @param fname Filename
- * @param fnamelen Filename length
- * @retval NULL Error
- * @retval ptr Success, pointer to \a dst
- *
- * Write the concatenated pathname (dir + "/" + fname) into dst.
- * The slash is omitted when dir or fname is of 0 length.
- */
-char *mutt_file_concatn_path(char *dst, size_t dstlen, const char *dir,
- size_t dirlen, const char *fname, size_t fnamelen)
-{
- size_t req;
- size_t offset = 0;
-
- if (dstlen == 0)
- return NULL; /* probably should not mask errors like this */
-
- /* size check */
- req = dirlen + fnamelen + 1; /* +1 for the trailing nul */
- if (dirlen && fnamelen)
- req++; /* when both components are non-nul, we add a "/" in between */
- if (req > dstlen)
- { /* check for condition where the dst length is too short */
- /* Two options here:
- * 1) assert(0) or return NULL to signal error
- * 2) copy as much of the path as will fit
- * It doesn't appear that the return value is actually checked anywhere mutt_file_concat_path()
- * is called, so we should just copy set dst to nul and let the calling function fail later.
- */
- dst[0] = '\0'; /* safe since we bail out early if dstlen == 0 */
- return NULL;
- }
-
- if (dirlen)
- { /* when dir is not empty */
- memcpy(dst, dir, dirlen);
- offset = dirlen;
- if (fnamelen)
- dst[offset++] = '/';
- }
- if (fnamelen)
- { /* when fname is not empty */
- memcpy(dst + offset, fname, fnamelen);
- offset += fnamelen;
- }
- dst[offset] = '\0';
- return dst;
-}
-
-/**
- * mutt_file_concat_path - Join a directory name and a filename
- * @param d Buffer for the result
- * @param dir Directory name
- * @param fname File name
- * @param l Length of buffer
- * @retval ptr Destination buffer
- *
- * If both dir and fname are supplied, they are separated with '/'.
- * If either is missing, then the other will be copied exactly.
- */
-char *mutt_file_concat_path(char *d, const char *dir, const char *fname, size_t l)
-{
- const char *fmt = "%s/%s";
-
- if (!*fname || (*dir && dir[strlen(dir) - 1] == '/'))
- fmt = "%s%s";
-
- snprintf(d, l, fmt, dir, fname);
- return d;
-}
-
-/**
- * mutt_file_basename - Find the last component for a pathname
- * @param f String to be examined
- * @retval ptr Part of pathname after last '/' character
- */
-const char *mutt_file_basename(const char *f)
-{
- const char *p = strrchr(f, '/');
- if (p)
- return p + 1;
- else
- return f;
-}
-
/**
* mutt_file_mkdir - Recursively create directories
* @param path Directories to create
return mtime;
}
-/**
- * mutt_file_dirname - Return a path up to, but not including, the final '/'
- * @param path Path
- * @retval ptr The directory containing p
- *
- * Unlike the IEEE Std 1003.1-2001 specification of dirname(3), this
- * implementation does not modify its parameter, so callers need not manually
- * copy their paths into a modifiable buffer prior to calling this function.
- */
-char *mutt_file_dirname(const char *path)
-{
- char buf[PATH_MAX] = { 0 };
- mutt_str_strfcpy(buf, path, sizeof(buf));
- return mutt_str_strdup(dirname(buf));
-}
-
/**
* mutt_file_set_mtime - Set the modification time of one file from another
* @param from Filename whose mtime should be copied
return 0;
}
-/**
- * mutt_file_to_absolute_path - Convert relative filepath to an absolute path
- * @param path Relative path
- * @param reference Absolute path that \a path is relative to
- * @retval true Success
- * @retval false Failure
- *
- * Use POSIX functions to convert a path to absolute, relatively to another path
- *
- * @note \a path should be at least of PATH_MAX length
- */
-int mutt_file_to_absolute_path(char *path, const char *reference)
-{
- char abs_path[PATH_MAX];
- int path_len;
-
- /* if path is already absolute, don't do anything */
- if ((strlen(path) > 1) && (path[0] == '/'))
- {
- return true;
- }
-
- char *dirpath = mutt_file_dirname(reference);
- mutt_str_strfcpy(abs_path, dirpath, sizeof(abs_path));
- FREE(&dirpath);
- mutt_str_strncat(abs_path, sizeof(abs_path), "/", 1); /* append a / at the end of the path */
-
- path_len = sizeof(abs_path) - strlen(path);
-
- mutt_str_strncat(abs_path, sizeof(abs_path), path, path_len > 0 ? path_len : 0);
-
- path = realpath(abs_path, path);
- if (!path && (errno != ENOENT))
- {
- mutt_perror(_("Error: converting path to absolute"));
- return false;
- }
-
- return true;
-}
-
/**
* mutt_file_read_keyword - Read a keyword from a file
* @param file File to read
#define MUTT_CONT (1 << 0) /**< \-continuation */
#define MUTT_EOL (1 << 1) /**< don't strip `\n` / `\r\n` */
-const char *mutt_file_basename(const char *f);
int mutt_file_check_empty(const char *path);
int mutt_file_chmod(const char *path, mode_t mode);
int mutt_file_chmod_add(const char *path, mode_t mode);
int mutt_file_chmod_add_stat(const char *path, mode_t mode, struct stat *st);
int mutt_file_chmod_rm(const char *path, mode_t mode);
int mutt_file_chmod_rm_stat(const char *path, mode_t mode, struct stat *st);
-char * mutt_file_concat_path(char *d, const char *dir, const char *fname, size_t l);
-char * mutt_file_concatn_path(char *dst, size_t dstlen, const char *dir, size_t dirlen, const char *fname, size_t fnamelen);
int mutt_file_copy_bytes(FILE *in, FILE *out, size_t size);
int mutt_file_copy_stream(FILE *fin, FILE *fout);
time_t mutt_file_decrease_mtime(const char *f, struct stat *st);
-char * mutt_file_dirname(const char *path);
int mutt_file_fclose(FILE **f);
FILE * mutt_file_fopen(const char *path, const char *mode);
int mutt_file_fsync_close(FILE **f);
int mutt_file_sanitize_regex(char *dest, size_t destlen, const char *src);
void mutt_file_set_mtime(const char *from, const char *to);
int mutt_file_symlink(const char *oldpath, const char *newpath);
-int mutt_file_to_absolute_path(char *path, const char *reference);
void mutt_file_touch_atime(int fd);
void mutt_file_unlink(const char *s);
void mutt_file_unlink_empty(const char *path);
* | mutt/mbyte.c | @subpage mbyte |
* | mutt/md5.c | @subpage md5 |
* | mutt/memory.c | @subpage memory |
+ * | mutt/path.c | @subpage path |
* | mutt/regex.c | @subpage regex |
* | mutt/sha1.c | @subpage sha1 |
* | mutt/signal.c | @subpage signal |
#include "memory.h"
#include "message.h"
#include "queue.h"
+#include "path.h"
#include "regex3.h"
#include "sha1.h"
#include "signal2.h"
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * @page path Path manipulation functions
+ *
+ * Path manipulation functions
+ */
+
#include "config.h"
+#include <errno.h>
+#include <libgen.h>
#include <limits.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "mutt/mutt.h"
-#include "email/email.h"
-#include "alias.h"
-#include "globals.h"
-#include "hook.h"
-#include "imap/imap.h"
-#include "mx.h"
+#include "mutt/logging.h"
+#include "mutt/memory.h"
+#include "mutt/message.h"
+#include "mutt/string2.h"
/**
* mutt_path_tidy_slash - Remove unnecessary slashes and dots
return true;
}
+
+/**
+ * mutt_path_basename - Find the last component for a pathname
+ * @param f String to be examined
+ * @retval ptr Part of pathname after last '/' character
+ */
+const char *mutt_path_basename(const char *f)
+{
+ const char *p = strrchr(f, '/');
+ if (p)
+ return p + 1;
+ else
+ return f;
+}
+
+/**
+ * mutt_path_concat - Join a directory name and a filename
+ * @param d Buffer for the result
+ * @param dir Directory name
+ * @param fname File name
+ * @param l Length of buffer
+ * @retval ptr Destination buffer
+ *
+ * If both dir and fname are supplied, they are separated with '/'.
+ * If either is missing, then the other will be copied exactly.
+ */
+char *mutt_path_concat(char *d, const char *dir, const char *fname, size_t l)
+{
+ const char *fmt = "%s/%s";
+
+ if (!*fname || (*dir && dir[strlen(dir) - 1] == '/'))
+ fmt = "%s%s";
+
+ snprintf(d, l, fmt, dir, fname);
+ return d;
+}
+
+/**
+ * mutt_path_concatn - Concatenate directory and filename
+ * @param dst Buffer for result
+ * @param dstlen Buffer length
+ * @param dir Directory
+ * @param dirlen Directory length
+ * @param fname Filename
+ * @param fnamelen Filename length
+ * @retval NULL Error
+ * @retval ptr Success, pointer to \a dst
+ *
+ * Write the concatenated pathname (dir + "/" + fname) into dst.
+ * The slash is omitted when dir or fname is of 0 length.
+ */
+char *mutt_path_concatn(char *dst, size_t dstlen, const char *dir,
+ size_t dirlen, const char *fname, size_t fnamelen)
+{
+ size_t req;
+ size_t offset = 0;
+
+ if (dstlen == 0)
+ return NULL; /* probably should not mask errors like this */
+
+ /* size check */
+ req = dirlen + fnamelen + 1; /* +1 for the trailing nul */
+ if (dirlen && fnamelen)
+ req++; /* when both components are non-nul, we add a "/" in between */
+ if (req > dstlen)
+ { /* check for condition where the dst length is too short */
+ /* Two options here:
+ * 1) assert(0) or return NULL to signal error
+ * 2) copy as much of the path as will fit
+ * It doesn't appear that the return value is actually checked anywhere mutt_path_concat()
+ * is called, so we should just copy set dst to nul and let the calling function fail later.
+ */
+ dst[0] = '\0'; /* safe since we bail out early if dstlen == 0 */
+ return NULL;
+ }
+
+ if (dirlen)
+ { /* when dir is not empty */
+ memcpy(dst, dir, dirlen);
+ offset = dirlen;
+ if (fnamelen)
+ dst[offset++] = '/';
+ }
+ if (fnamelen)
+ { /* when fname is not empty */
+ memcpy(dst + offset, fname, fnamelen);
+ offset += fnamelen;
+ }
+ dst[offset] = '\0';
+ return dst;
+}
+
+/**
+ * mutt_path_dirname - Return a path up to, but not including, the final '/'
+ * @param path Path
+ * @retval ptr The directory containing p
+ *
+ * Unlike the IEEE Std 1003.1-2001 specification of dirname(3), this
+ * implementation does not modify its parameter, so callers need not manually
+ * copy their paths into a modifiable buffer prior to calling this function.
+ */
+char *mutt_path_dirname(const char *path)
+{
+ char buf[PATH_MAX] = { 0 };
+ mutt_str_strfcpy(buf, path, sizeof(buf));
+ return mutt_str_strdup(dirname(buf));
+}
+
+/**
+ * mutt_path_to_absolute - Convert relative filepath to an absolute path
+ * @param path Relative path
+ * @param reference Absolute path that \a path is relative to
+ * @retval true Success
+ * @retval false Failure
+ *
+ * Use POSIX functions to convert a path to absolute, relatively to another path
+ *
+ * @note \a path should be at least of PATH_MAX length
+ */
+int mutt_path_to_absolute(char *path, const char *reference)
+{
+ char abs_path[PATH_MAX];
+ int path_len;
+
+ /* if path is already absolute, don't do anything */
+ if ((strlen(path) > 1) && (path[0] == '/'))
+ {
+ return true;
+ }
+
+ char *dirpath = mutt_path_dirname(reference);
+ mutt_str_strfcpy(abs_path, dirpath, sizeof(abs_path));
+ FREE(&dirpath);
+ mutt_str_strncat(abs_path, sizeof(abs_path), "/", 1); /* append a / at the end of the path */
+
+ path_len = sizeof(abs_path) - strlen(path);
+
+ mutt_str_strncat(abs_path, sizeof(abs_path), path, path_len > 0 ? path_len : 0);
+
+ path = realpath(abs_path, path);
+ if (!path && (errno != ENOENT))
+ {
+ mutt_perror(_("Error: converting path to absolute"));
+ return false;
+ }
+
+ return true;
+}
+
#include <stdbool.h>
#include <stdio.h>
-bool mutt_path_tidy (char *buf);
-bool mutt_path_tidy_dotdot(char *buf);
-bool mutt_path_tidy_slash (char *buf);
-
-bool mutt_path_canon (char *buf, size_t buflen, const char *homedir);
-bool mutt_path_pretty(char *buf, size_t buflen, const char *homedir);
+const char *mutt_path_basename(const char *f);
+bool mutt_path_canon(char *buf, size_t buflen, const char *homedir);
+char * mutt_path_concat(char *d, const char *dir, const char *fname, size_t l);
+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);
+bool mutt_path_pretty(char *buf, size_t buflen, const char *homedir);
+bool mutt_path_tidy(char *buf);
+bool mutt_path_tidy_dotdot(char *buf);
+bool mutt_path_tidy_slash(char *buf);
+int mutt_path_to_absolute(char *path, const char *reference);
#endif /* _MUTT_PATH_H */
return (rc == MUTT_NO) ? 1 : -1;
char tmp[PATH_MAX];
- mutt_str_strfcpy(tmp, mutt_file_basename(NONULL(attname)), sizeof(tmp));
+ mutt_str_strfcpy(tmp, mutt_path_basename(NONULL(attname)), sizeof(tmp));
if (mutt_get_field(_("File under directory: "), tmp, sizeof(tmp),
MUTT_FILE | MUTT_CLEAR) != 0 ||
!tmp[0])
{
return -1;
}
- mutt_file_concat_path(fname, path, tmp, flen);
+ mutt_path_concat(fname, path, tmp, flen);
}
if (*append == 0 && access(fname, F_OK) == 0)
if (ret == 0)
{
/* create dir recursively */
- char *tmp_path = mutt_file_dirname(s);
+ char *tmp_path = mutt_path_dirname(s);
if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
{
/* report failure & abort */
{
if (directory && *directory)
{
- mutt_file_concat_path(buf, *directory, mutt_file_basename(body->filename),
+ mutt_path_concat(buf, *directory, mutt_path_basename(body->filename),
sizeof(buf));
}
else
{
int append = 0;
- mutt_str_strfcpy(buf, mutt_file_basename(NONULL(top->filename)), sizeof(buf));
+ mutt_str_strfcpy(buf, mutt_path_basename(NONULL(top->filename)), sizeof(buf));
prepend_curdir(buf, sizeof(buf));
if (mutt_get_field(_("Save to file: "), buf, sizeof(buf), MUTT_FILE | MUTT_CLEAR) != 0 ||