char *p = NULL;
DIR *dirp = NULL;
struct dirent *de = NULL;
- int i, init = 0;
+ int init = 0;
size_t len;
- char dirpart[PATH_MAX], exp_dirpart[PATH_MAX];
- char filepart[PATH_MAX];
+ struct Buffer *dirpart = NULL;
+ struct Buffer *exp_dirpart = NULL;
+ struct Buffer *filepart = NULL;
+ struct Buffer *tmp = NULL;
#ifdef USE_IMAP
- char imap_path[PATH_MAX];
+ struct Buffer *imap_path = NULL;
+ int rc;
#endif
mutt_debug(LL_DEBUG2, "completing %s\n", buf);
#endif
#ifdef USE_IMAP
+ imap_path = mutt_buffer_pool_get();
/* we can use '/' as a delimiter, imap_complete rewrites it */
if ((*buf == '=') || (*buf == '+') || (*buf == '!'))
{
else
p = NONULL(C_Folder);
- mutt_path_concat(imap_path, p, buf + 1, sizeof(imap_path));
+ mutt_buffer_concat_path(imap_path, p, buf + 1);
}
else
- mutt_str_strfcpy(imap_path, buf, sizeof(imap_path));
+ mutt_buffer_strcpy(imap_path, buf);
- if (imap_path_probe(imap_path, NULL) == MUTT_IMAP)
- return imap_complete(buf, buflen, imap_path);
+ if (imap_path_probe(mutt_b2s(imap_path), NULL) == MUTT_IMAP)
+ {
+ rc = imap_complete(buf, buflen, mutt_b2s(imap_path));
+ mutt_buffer_pool_release(&imap_path);
+ return rc;
+ }
+
+ mutt_buffer_pool_release(&imap_path);
#endif
+ dirpart = mutt_buffer_pool_get();
+ exp_dirpart = mutt_buffer_pool_get();
+ filepart = mutt_buffer_pool_get();
+ tmp = mutt_buffer_pool_get();
+
if ((*buf == '=') || (*buf == '+') || (*buf == '!'))
{
- dirpart[0] = *buf;
- dirpart[1] = '\0';
+ mutt_buffer_addch(dirpart, *buf);
if (*buf == '!')
- mutt_str_strfcpy(exp_dirpart, C_Spoolfile, sizeof(exp_dirpart));
+ mutt_buffer_strcpy(exp_dirpart, NONULL(C_Spoolfile));
else
- mutt_str_strfcpy(exp_dirpart, C_Folder, sizeof(exp_dirpart));
+ mutt_buffer_strcpy(exp_dirpart, NONULL(C_Folder));
p = strrchr(buf, '/');
if (p)
{
- char tmp[PATH_MAX];
- if (!mutt_path_concatn(tmp, sizeof(tmp), exp_dirpart, strlen(exp_dirpart),
- buf + 1, (size_t)(p - buf - 1)))
- {
- return -1;
- }
- mutt_str_strfcpy(exp_dirpart, tmp, sizeof(exp_dirpart));
- mutt_str_substr_copy(buf, p + 1, dirpart, sizeof(dirpart));
- mutt_str_strfcpy(filepart, p + 1, sizeof(filepart));
+ mutt_buffer_concatn_path(tmp, mutt_b2s(exp_dirpart), mutt_buffer_len(exp_dirpart),
+ buf + 1, (size_t)(p - buf - 1));
+ mutt_buffer_strcpy(exp_dirpart, mutt_b2s(tmp));
+ mutt_buffer_substrcpy(dirpart, buf, p + 1);
+ mutt_buffer_strcpy(filepart, p + 1);
}
else
- mutt_str_strfcpy(filepart, buf + 1, sizeof(filepart));
- dirp = opendir(exp_dirpart);
+ mutt_buffer_strcpy(filepart, buf + 1);
+ dirp = opendir(mutt_b2s(exp_dirpart));
}
else
{
if (p == buf) /* absolute path */
{
p = buf + 1;
- mutt_str_strfcpy(dirpart, "/", sizeof(dirpart));
- exp_dirpart[0] = '\0';
- mutt_str_strfcpy(filepart, p, sizeof(filepart));
- dirp = opendir(dirpart);
+ mutt_buffer_strcpy(dirpart, "/");
+ mutt_buffer_strcpy(filepart, p);
+ dirp = opendir(mutt_b2s(dirpart));
}
else
{
- mutt_str_substr_copy(buf, p, dirpart, sizeof(dirpart));
- mutt_str_strfcpy(filepart, p + 1, sizeof(filepart));
- mutt_str_strfcpy(exp_dirpart, dirpart, sizeof(exp_dirpart));
- mutt_expand_path(exp_dirpart, sizeof(exp_dirpart));
- dirp = opendir(exp_dirpart);
+ mutt_buffer_substrcpy(dirpart, buf, p);
+ mutt_buffer_strcpy(filepart, p + 1);
+ mutt_buffer_strcpy(exp_dirpart, mutt_b2s(dirpart));
+ mutt_buffer_expand_path(exp_dirpart);
+ dirp = opendir(mutt_b2s(exp_dirpart));
}
}
else
{
/* no directory name, so assume current directory. */
- dirpart[0] = '\0';
- mutt_str_strfcpy(filepart, buf, sizeof(filepart));
+ mutt_buffer_strcpy(filepart, buf);
dirp = opendir(".");
}
}
if (!dirp)
{
- mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", exp_dirpart, strerror(errno), errno);
- return -1;
+ mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", mutt_b2s(exp_dirpart),
+ strerror(errno), errno);
+ goto cleanup;
}
/* special case to handle when there is no filepart yet. find the first
* file/directory which is not "." or ".." */
- len = mutt_str_strlen(filepart);
+ len = mutt_buffer_len(filepart);
if (len == 0)
{
while ((de = readdir(dirp)))
if ((mutt_str_strcmp(".", de->d_name) != 0) &&
(mutt_str_strcmp("..", de->d_name) != 0))
{
- mutt_str_strfcpy(filepart, de->d_name, sizeof(filepart));
+ mutt_buffer_strcpy(filepart, de->d_name);
init++;
break;
}
while ((de = readdir(dirp)))
{
- if (mutt_str_strncmp(de->d_name, filepart, len) == 0)
+ if (mutt_str_strncmp(de->d_name, mutt_b2s(filepart), len) == 0)
{
if (init)
{
- for (i = 0; filepart[i] && de->d_name[i]; i++)
+ char *cp = filepart->data;
+
+ for (int i = 0; (*cp != '\0') && (de->d_name[i] != '\0'); i++, cp++)
{
- if (filepart[i] != de->d_name[i])
+ if (*cp != de->d_name[i])
break;
}
- filepart[i] = '\0';
+ *cp = '\0';
+ mutt_buffer_fix_dptr(filepart);
}
else
{
- char tmp[PATH_MAX];
struct stat st;
- mutt_str_strfcpy(filepart, de->d_name, sizeof(filepart));
+ mutt_buffer_strcpy(filepart, de->d_name);
/* check to see if it is a directory */
- if (dirpart[0] != '\0')
+ if (!mutt_buffer_is_empty(dirpart))
{
- mutt_str_strfcpy(tmp, exp_dirpart, sizeof(tmp));
- mutt_str_strfcpy(tmp + strlen(tmp), "/", sizeof(tmp) - strlen(tmp));
+ mutt_buffer_strcpy(tmp, mutt_b2s(exp_dirpart));
+ mutt_buffer_addch(tmp, '/');
}
else
- tmp[0] = '\0';
- mutt_str_strfcpy(tmp + strlen(tmp), filepart, sizeof(tmp) - strlen(tmp));
- if ((stat(tmp, &st) != -1) && (st.st_mode & S_IFDIR))
- {
- mutt_str_strfcpy(filepart + strlen(filepart), "/",
- sizeof(filepart) - strlen(filepart));
- }
+ mutt_buffer_reset(tmp);
+ mutt_buffer_addstr(tmp, mutt_b2s(filepart));
+ if ((stat(mutt_b2s(tmp), &st) != -1) && (st.st_mode & S_IFDIR))
+ mutt_buffer_addch(filepart, '/');
init = 1;
}
}
}
closedir(dirp);
- if (dirpart[0] != '\0')
+ if (!mutt_buffer_is_empty(dirpart))
{
- mutt_str_strfcpy(buf, dirpart, buflen);
- if ((mutt_str_strcmp("/", dirpart) != 0) && (dirpart[0] != '=') && (dirpart[0] != '+'))
+ mutt_str_strfcpy(buf, mutt_b2s(dirpart), buflen);
+ if ((mutt_str_strcmp("/", mutt_b2s(dirpart)) != 0) &&
+ (mutt_b2s(dirpart)[0] != '=') && (mutt_b2s(dirpart)[0] != '+'))
+ {
mutt_str_strfcpy(buf + strlen(buf), "/", buflen - strlen(buf));
- mutt_str_strfcpy(buf + strlen(buf), filepart, buflen - strlen(buf));
+ }
+ mutt_str_strfcpy(buf + strlen(buf), mutt_b2s(filepart), buflen - strlen(buf));
}
else
- mutt_str_strfcpy(buf, filepart, buflen);
+ mutt_str_strfcpy(buf, mutt_b2s(filepart), buflen);
+
+cleanup:
+ mutt_buffer_pool_release(&dirpart);
+ mutt_buffer_pool_release(&exp_dirpart);
+ mutt_buffer_pool_release(&filepart);
+ mutt_buffer_pool_release(&tmp);
return init ? 0 : -1;
}
mutt_buffer_addstr_n(buf, s, len);
}
+/**
+ * mutt_buffer_substrcpy - Copy a partial string into a Buffer
+ * @param buf Buffer to overwrite
+ * @param beg Start of string to copy
+ * @param end End of string to copy
+ *
+ * Overwrites any existing content.
+ */
+void mutt_buffer_substrcpy(struct Buffer *buf, const char *beg, const char *end)
+{
+ mutt_buffer_reset(buf);
+ if (end > beg)
+ mutt_buffer_strcpy_n(buf, beg, end - beg);
+}
+
/**
* mutt_buffer_len - Calculate the length of a Buffer
* @param buf Buffer
mutt_buffer_printf(buf, fmt, dir, fname);
}
+
+/**
+ * mutt_buffer_concatn_path - Join a directory name and a filename
+ * @param buf Buffer for the result
+ * @param dir Directory name
+ * @param dirlen Directory name
+ * @param fname File name
+ * @param fnamelen File name
+ *
+ * If both dir and fname are supplied, they are separated with '/'.
+ * If either is missing, then the other will be copied exactly.
+ */
+void mutt_buffer_concatn_path(struct Buffer *buf, const char *dir,
+ size_t dirlen, const char *fname, size_t fnamelen)
+{
+ mutt_buffer_reset(buf);
+ if (dirlen != 0)
+ mutt_buffer_addstr_n(buf, dir, dirlen);
+ if ((dirlen != 0) && (fnamelen != 0))
+ mutt_buffer_addch(buf, '/');
+ if (fnamelen != 0)
+ mutt_buffer_addstr_n(buf, fname, fnamelen);
+}
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)
-{
- if (!dst || !dir || !fname)
- return NULL;
-
- 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