summaryrefslogtreecommitdiff
path: root/libmailutils/string/mkfilename.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/string/mkfilename.c')
-rw-r--r--libmailutils/string/mkfilename.c63
1 files changed, 50 insertions, 13 deletions
diff --git a/libmailutils/string/mkfilename.c b/libmailutils/string/mkfilename.c
index 653ac7a2a..d24d2f48a 100644
--- a/libmailutils/string/mkfilename.c
+++ b/libmailutils/string/mkfilename.c
@@ -21,30 +21,67 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <mailutils/alloc.h>
#include <mailutils/util.h>
+/*
+ * Given directory name DIR, file name FILE and optional suffix SUF,
+ * return full pathname composed from these three. In the resulting
+ * string, DIR and FILE are separated by '/'. If SUF is supplied, it
+ * is concatenated to the resulting string without additional
+ * separators.
+ *
+ * Corner cases:
+ * all three arguments are NULL or empty
+ * Return NULL and set errno to EINVAL.
+ * dir is NULL
+ * Return FILE and SUF concatenated.
+ * file is NULL, suf is not NULL
+ * Same as mu_make_file_name_suf(dir, suf, NULL);
+ * file is NULL, suf is NULL
+ * Return allocated copy of DIR.
+ */
char *
mu_make_file_name_suf (const char *dir, const char *file, const char *suf)
{
char *tmp;
- size_t dirlen = strlen (dir);
- size_t suflen = suf ? strlen (suf) : 0;
- size_t fillen = strlen (file);
+ size_t dirlen, suflen, fillen;
size_t len;
- while (dirlen > 0 && dir[dirlen-1] == '/')
- dirlen--;
-
- len = dirlen + (dir[0] ? 1 : 0) + fillen + suflen;
- tmp = mu_alloc (len + 1);
+ dirlen = dir ? strlen (dir) : 0;
+ fillen = file ? strlen (file) : 0;
+ suflen = suf ? strlen (suf) : 0;
+
+ len = suflen + fillen;
+ if (dirlen == 0)
+ {
+ if (len == 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ }
+ else
+ {
+ if (len) len++; // account for the '/' separator
+ while (dirlen > 0 && dir[dirlen-1] == '/')
+ dirlen--;
+ }
+ len += dirlen;
+
+ tmp = malloc (len + 1);
if (tmp)
{
- memcpy (tmp, dir, dirlen);
- if (dir[0])
- tmp[dirlen++] = '/';
- memcpy (tmp + dirlen, file, fillen);
- if (suf)
+ if (dirlen)
+ {
+ memcpy (tmp, dir, dirlen);
+ if (fillen || suflen)
+ tmp[dirlen++] = '/';
+ }
+ if (fillen)
+ memcpy (tmp + dirlen, file, fillen);
+ if (suflen)
memcpy (tmp + dirlen + fillen, suf, suflen);
tmp[len] = 0;
}

Return to:

Send suggestions and report system problems to the System administrator.