]> granicus.if.org Git - neomutt/commitdiff
Convert mutt_complete() to use the buffer pool
authorKevin McCarthy <kevin@8t8.us>
Fri, 20 Sep 2019 01:52:24 +0000 (18:52 -0700)
committerRichard Russon <rich@flatcap.org>
Tue, 1 Oct 2019 10:25:08 +0000 (11:25 +0100)
Add helper functions mutt_buffer_substrcpy() and
mutt_buffer_concatn_path().

Remove mutt_concatn_path() because mutt_complete() was the only
caller.

Co-authored-by: Richard Russon <rich@flatcap.org>
complete.c
imap/imap.c
imap/imap.h
mutt/buffer.c
mutt/buffer.h
mutt/path.c
mutt/path.h
test/Makefile.autosetup
test/main.c
test/path/mutt_path_concatn.c [deleted file]

index e82c53a3bbce7f3d4469d36ca10a2293970af962..e9ec2f3c024bbc9dc32e22a936c7ed3b00cd97cd 100644 (file)
@@ -59,12 +59,15 @@ int mutt_complete(char *buf, size_t buflen)
   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);
@@ -75,6 +78,7 @@ int mutt_complete(char *buf, size_t buflen)
 #endif
 
 #ifdef USE_IMAP
+  imap_path = mutt_buffer_pool_get();
   /* we can use '/' as a delimiter, imap_complete rewrites it */
   if ((*buf == '=') || (*buf == '+') || (*buf == '!'))
   {
@@ -83,39 +87,45 @@ int mutt_complete(char *buf, size_t buflen)
     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
   {
@@ -125,38 +135,37 @@ int mutt_complete(char *buf, size_t buflen)
       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)))
@@ -164,7 +173,7 @@ int mutt_complete(char *buf, size_t buflen)
       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;
       }
@@ -173,53 +182,61 @@ int mutt_complete(char *buf, size_t buflen)
 
   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;
 }
index fa9a19241a8e9b4c5c0f1267e037275a2b1a3c88..850470afe46cabfd0f217cb7dafbcc0fdb99711f 100644 (file)
@@ -1435,7 +1435,7 @@ int imap_subscribe(char *path, bool subscribe)
  * Given a partial IMAP folder path, return a string which adds as much to the
  * path as is unique
  */
-int imap_complete(char *buf, size_t buflen, char *path)
+int imap_complete(char *buf, size_t buflen, const char *path)
 {
   struct ImapAccountData *adata = NULL;
   struct ImapMboxData *mdata = NULL;
index 5c6b6bf1c5e2f481b939f86fb4e463505b8caa73..90eca14333121dfc4f1fd1a571ffd6d05de26476 100644 (file)
@@ -88,7 +88,7 @@ int imap_path_status(const char *path, bool queue);
 int imap_mailbox_status(struct Mailbox *m, bool queue);
 int imap_search(struct Mailbox *m, const struct PatternList *pat);
 int imap_subscribe(char *path, bool subscribe);
-int imap_complete(char *buf, size_t buflen, char *path);
+int imap_complete(char *buf, size_t buflen, const char *path);
 int imap_fast_trash(struct Mailbox *m, char *dest);
 enum MailboxType imap_path_probe(const char *path, const struct stat *st);
 int imap_path_canon(char *buf, size_t buflen);
index 5855e0ce96c3b3ac8e6fa07e246e9bd3eb50d73f..3b7e08eb77f5af6779529bf328cf81c34754baa7 100644 (file)
@@ -328,6 +328,21 @@ void mutt_buffer_strcpy_n(struct Buffer *buf, const char *s, size_t len)
   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
@@ -374,3 +389,26 @@ void mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fn
 
   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);
+}
index e6c7329096e2026dd153d56022341f7f14d68e18..d423c77428ac38d8fee1cb26898fd03a7d9e7606 100644 (file)
@@ -59,8 +59,10 @@ int            mutt_buffer_add_printf   (struct Buffer *buf, const char *fmt, ..
 
 // Functions that OVERWRITE a Buffer
 void           mutt_buffer_concat_path  (struct Buffer *buf, const char *dir, const char *fname);
+void           mutt_buffer_concatn_path (struct Buffer *dst, const char *dir, size_t dirlen, const char *fname, size_t fnamelen);
 int            mutt_buffer_printf       (struct Buffer *buf, const char *fmt, ...);
 void           mutt_buffer_strcpy       (struct Buffer *buf, const char *s);
 void           mutt_buffer_strcpy_n     (struct Buffer *buf, const char *s, size_t len);
+void           mutt_buffer_substrcpy    (struct Buffer *buf, const char *beg, const char *end);
 
 #endif /* MUTT_LIB_BUFFER_H */
index e21a5f95b2749ac9781fc465cf937314d7e68588..59855066af6108f32f2131aae5a973ee30ec9c31 100644 (file)
@@ -341,63 +341,6 @@ char *mutt_path_concat(char *d, const char *dir, const char *fname, size_t l)
   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
index 6203b91fc7a4c857c0ec775c4848bd2cf3402638..5d4000e7cf316010870a753c8f986229e2b41fbb 100644 (file)
@@ -32,7 +32,6 @@ bool        mutt_path_abbr_folder(char *buf, size_t buflen, const char *folder);
 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);
 char *      mutt_path_escape(const char *src);
 const char *mutt_path_getcwd(struct Buffer *cwd);
index 941b4a52d7ade4c8250f7f511a7c69705c6db27e..70842f413623eaec02a4f630218e18ad5122f372 100644 (file)
@@ -301,7 +301,6 @@ PATH_OBJS   = test/path/mutt_path_abbr_folder.o \
                  test/path/mutt_path_basename.o \
                  test/path/mutt_path_canon.o \
                  test/path/mutt_path_concat.o \
-                 test/path/mutt_path_concatn.o \
                  test/path/mutt_path_dirname.o \
                  test/path/mutt_path_escape.o \
                  test/path/mutt_path_getcwd.o \
index ce2d9e54c9872694860a1ae87bb9d2174fc9eaa9..71d0a110a8742ba86d75c57159c5200116d9ee81 100644 (file)
   NEOMUTT_TEST_ITEM(test_mutt_path_basename)                                   \
   NEOMUTT_TEST_ITEM(test_mutt_path_canon)                                      \
   NEOMUTT_TEST_ITEM(test_mutt_path_concat)                                     \
-  NEOMUTT_TEST_ITEM(test_mutt_path_concatn)                                    \
   NEOMUTT_TEST_ITEM(test_mutt_path_dirname)                                    \
   NEOMUTT_TEST_ITEM(test_mutt_path_escape)                                     \
   NEOMUTT_TEST_ITEM(test_mutt_path_getcwd)                                     \
diff --git a/test/path/mutt_path_concatn.c b/test/path/mutt_path_concatn.c
deleted file mode 100644 (file)
index f8d247e..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * @file
- * Test code for mutt_path_concatn()
- *
- * @authors
- * Copyright (C) 2019 Richard Russon <rich@flatcap.org>
- *
- * @copyright
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define TEST_NO_MAIN
-#include "acutest.h"
-#include "config.h"
-#include "mutt/mutt.h"
-
-void test_mutt_path_concatn(void)
-{
-  // char *mutt_path_concatn(char *dst, size_t dstlen, const char *dir, size_t dirlen, const char *fname, size_t fnamelen);
-
-  {
-    TEST_CHECK(mutt_path_concatn(NULL, 10, "apple", 5, "banana", 6) == NULL);
-  }
-
-  {
-    char buf[32] = { 0 };
-    TEST_CHECK(mutt_path_concatn(buf, sizeof(buf), NULL, 5, "banana", 6) == NULL);
-  }
-
-  {
-    char buf[32] = { 0 };
-    TEST_CHECK(mutt_path_concatn(buf, sizeof(buf), "apple", 5, NULL, 6) == NULL);
-  }
-}