summaryrefslogtreecommitdiff
path: root/src/libnm-systemd-shared/src/basic/tmpfile-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-systemd-shared/src/basic/tmpfile-util.c')
-rw-r--r--src/libnm-systemd-shared/src/basic/tmpfile-util.c129
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) {