diff options
Diffstat (limited to 'libmailutils/string/mkfilename.c')
-rw-r--r-- | libmailutils/string/mkfilename.c | 63 |
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; } |