diff options
Diffstat (limited to 'src/libnm-systemd-shared/src/basic/tmpfile-util.c')
-rw-r--r-- | src/libnm-systemd-shared/src/basic/tmpfile-util.c | 129 |
1 files changed, 65 insertions, 64 deletions
diff --git a/src/libnm-systemd-shared/src/basic/tmpfile-util.c b/src/libnm-systemd-shared/src/basic/tmpfile-util.c index e0a338c163..34d3016ba9 100644 --- a/src/libnm-systemd-shared/src/basic/tmpfile-util.c +++ b/src/libnm-systemd-shared/src/basic/tmpfile-util.c @@ -86,50 +86,91 @@ int fmkostemp_safe(char *pattern, const char *mode, FILE **ret_f) { return 0; } -int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { - _cleanup_free_ char *d = NULL, *fn = NULL, *nf = NULL; +static int tempfn_build(const char *p, const char *pre, const char *post, bool child, char **ret) { + _cleanup_free_ char *d = NULL, *fn = NULL, *nf = NULL, *result = NULL; + size_t len_pre, len_post, len_add; int r; + assert(p); assert(ret); /* * Turns this: * /foo/bar/waldo * - * Into this: - * /foo/bar/.#<extra>waldoXXXXXX + * Into this : + * /foo/bar/waldo/.#<pre><post> (child == true) + * /foo/bar/.#<pre>waldo<post> (child == false) */ - r = path_extract_directory(p, &d); - if (r < 0 && r != -EDESTADDRREQ) /* EDESTADDRREQ → No directory specified, just a filename */ - return r; + if (pre && strchr(pre, '/')) + return -EINVAL; - r = path_extract_filename(p, &fn); - if (r < 0) - return r; + if (post && strchr(post, '/')) + return -EINVAL; + + len_pre = strlen_ptr(pre); + len_post = strlen_ptr(post); + /* NAME_MAX is counted *without* the trailing NUL byte. */ + if (len_pre > NAME_MAX - STRLEN(".#") || + len_post > NAME_MAX - STRLEN(".#") - len_pre) + return -EINVAL; + + len_add = len_pre + len_post + STRLEN(".#"); + + if (child) { + d = strdup(p); + if (!d) + return -ENOMEM; + } else { + r = path_extract_directory(p, &d); + if (r < 0 && r != -EDESTADDRREQ) /* EDESTADDRREQ → No directory specified, just a filename */ + return r; - nf = strjoin(".#", strempty(extra), fn, "XXXXXX"); + r = path_extract_filename(p, &fn); + if (r < 0) + return r; + + if (strlen(fn) > NAME_MAX - len_add) + /* We cannot simply prepend and append strings to the filename. Let's truncate the filename. */ + fn[NAME_MAX - len_add] = '\0'; + } + + nf = strjoin(".#", strempty(pre), strempty(fn), strempty(post)); if (!nf) return -ENOMEM; - if (!filename_is_valid(nf)) /* New name is not valid? (Maybe because too long?) Refuse. */ - return -EINVAL; - - if (d) { + if (d) { if (!path_extend(&d, nf)) return -ENOMEM; - *ret = path_simplify(TAKE_PTR(d)); + result = path_simplify(TAKE_PTR(d)); } else - *ret = TAKE_PTR(nf); + result = TAKE_PTR(nf); + + if (!path_is_valid(result)) /* New path is not valid? (Maybe because too long?) Refuse. */ + return -EINVAL; + *ret = TAKE_PTR(result); return 0; } +int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { + /* + * Turns this: + * /foo/bar/waldo + * + * Into this: + * /foo/bar/.#<extra>waldoXXXXXX + */ + + return tempfn_build(p, extra, "XXXXXX", /* child = */ false, ret); +} + int tempfn_random(const char *p, const char *extra, char **ret) { - _cleanup_free_ char *d = NULL, *fn = NULL, *nf = NULL; - int r; + _cleanup_free_ char *s = NULL; + assert(p); assert(ret); /* @@ -140,37 +181,14 @@ int tempfn_random(const char *p, const char *extra, char **ret) { * /foo/bar/.#<extra>waldobaa2a261115984a9 */ - r = path_extract_directory(p, &d); - if (r < 0 && r != -EDESTADDRREQ) /* EDESTADDRREQ → No directory specified, just a filename */ - return r; - - r = path_extract_filename(p, &fn); - if (r < 0) - return r; - - if (asprintf(&nf, ".#%s%s%016" PRIx64, - strempty(extra), - fn, - random_u64()) < 0) + if (asprintf(&s, "%016" PRIx64, random_u64()) < 0) return -ENOMEM; - if (!filename_is_valid(nf)) /* Not valid? (maybe because too long now?) — refuse early */ - return -EINVAL; - - if (d) { - if (!path_extend(&d, nf)) - return -ENOMEM; - - *ret = path_simplify(TAKE_PTR(d)); - } else - *ret = TAKE_PTR(nf); - - return 0; + return tempfn_build(p, extra, s, /* child = */ false, ret); } int tempfn_random_child(const char *p, const char *extra, char **ret) { - char *t, *x; - uint64_t u; + _cleanup_free_ char *s = NULL; int r; assert(ret); @@ -187,27 +205,10 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) { return r; } - extra = strempty(extra); - - t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1); - if (!t) + if (asprintf(&s, "%016" PRIx64, random_u64()) < 0) return -ENOMEM; - if (isempty(p)) - x = stpcpy(stpcpy(t, ".#"), extra); - else - x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra); - - u = random_u64(); - for (unsigned i = 0; i < 16; i++) { - *(x++) = hexchar(u & 0xF); - u >>= 4; - } - - *x = 0; - - *ret = path_simplify(t); - return 0; + return tempfn_build(p, extra, s, /* child = */ true, ret); } int open_tmpfile_unlinkable(const char *directory, int flags) { |