#include "umask-util.h"
#include "utf8.h"
+#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
+
int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
assert(f);
if (S_ISREG(st.st_mode)) {
/* Safety check */
- if (st.st_size > 4*1024*1024)
+ if (st.st_size > READ_FULL_BYTES_MAX)
return -E2BIG;
/* Start with the right file size, but be prepared for
char *t;
size_t k;
- t = realloc(buf, n+1);
+ t = realloc(buf, n + 1);
if (!t)
return -ENOMEM;
buf = t;
k = fread(buf + l, 1, n - l, f);
+ if (k > 0)
+ l += k;
- if (k <= 0) {
- if (ferror(f))
- return -errno;
+ if (ferror(f))
+ return -errno;
+ if (feof(f))
break;
- }
- l += k;
- n *= 2;
+ /* We aren't expecting fread() to return a short read outside
+ * of (error && eof), assert buffer is full and enlarge buffer.
+ */
+ assert(l == n);
/* Safety check */
- if (n > 4*1024*1024)
+ if (n >= READ_FULL_BYTES_MAX)
return -E2BIG;
+
+ n = MIN(n * 2, READ_FULL_BYTES_MAX);
}
buf[l] = 0;
return 0;
}
+static int merge_env_file_push(
+ const char *filename, unsigned line,
+ const char *key, char *value,
+ void *userdata,
+ int *n_pushed) {
+
+ char ***env = userdata;
+ char *expanded_value;
+
+ assert(env);
+
+ expanded_value = replace_env(value, *env, REPLACE_ENV_USE_ENVIRONMENT);
+ if (!expanded_value)
+ return -ENOMEM;
+
+ free_and_replace(value, expanded_value);
+
+ return load_env_file_push(filename, line, key, value, env, n_pushed);
+}
+
+int merge_env_file(
+ char ***env,
+ FILE *f,
+ const char *fname) {
+
+ return parse_env_file_internal(f, fname, NEWLINE, merge_env_file_push, env, NULL);
+}
+
static void write_env_var(FILE *f, const char *v) {
const char *p;
if (r < 0)
return r;
- fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
+ fd = mkostemp_safe(t);
if (fd < 0) {
free(t);
return -errno;
}
/* This is much like mkostemp() but is subject to umask(). */
-int mkostemp_safe(char *pattern, int flags) {
+int mkostemp_safe(char *pattern) {
_cleanup_umask_ mode_t u = 0;
int fd;
u = umask(077);
- fd = mkostemp(pattern, flags);
+ fd = mkostemp(pattern, O_CLOEXEC);
if (fd < 0)
return -errno;
char *t, *x;
uint64_t u;
unsigned i;
+ int r;
- assert(p);
assert(ret);
/* Turns this:
* /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
*/
+ if (!p) {
+ r = tmp_dir(&p);
+ if (r < 0)
+ return r;
+ }
+
if (!extra)
extra = "";
int open_tmpfile_unlinkable(const char *directory, int flags) {
char *p;
- int fd;
+ int fd, r;
- if (!directory)
- directory = "/tmp";
+ if (!directory) {
+ r = tmp_dir(&directory);
+ if (r < 0)
+ return r;
+ }
/* Returns an unlinked temporary file that cannot be linked into the file system anymore */
-#ifdef O_TMPFILE
/* Try O_TMPFILE first, if it is supported */
fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
if (fd >= 0)
return fd;
-#endif
/* Fall back to unguessable name + unlinking */
p = strjoina(directory, "/systemd-tmp-XXXXXX");
- fd = mkostemp_safe(p, flags);
+ fd = mkostemp_safe(p);
if (fd < 0)
return fd;
* which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
* "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
-#ifdef O_TMPFILE
{
_cleanup_free_ char *dn = NULL;
log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
}
-#endif
r = tempfn_random(target, NULL, &tmp);
if (r < 0)