aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--liberty.c67
1 files changed, 58 insertions, 9 deletions
diff --git a/liberty.c b/liberty.c
index d151c00..c5da820 100644
--- a/liberty.c
+++ b/liberty.c
@@ -731,6 +731,21 @@ set_blocking (int fd, bool blocking)
return prev;
}
+static bool
+xwrite (int fd, const char *data, size_t len, struct error **e)
+{
+ size_t written = 0;
+ while (written < len)
+ {
+ ssize_t res = write (fd, data + written, len - written);
+ if (res >= 0)
+ written += res;
+ else if (errno != EINTR)
+ return error_set (e, "%s", strerror (errno));
+ }
+ return true;
+}
+
static void
xclose (int fd)
{
@@ -2925,6 +2940,13 @@ base64_encode (const void *data, size_t len, struct str *output)
// --- Utilities ---------------------------------------------------------------
static void
+cstr_set (char **s, char *new)
+{
+ free (*s);
+ *s = new;
+}
+
+static void
cstr_split (const char *s, const char *delimiters, bool ignore_empty,
struct strv *out)
{
@@ -3263,16 +3285,8 @@ resolve_relative_data_filename (const char *filename)
}
static char *
-resolve_relative_runtime_filename (const char *filename)
+resolve_relative_runtime_filename_finish (struct str path)
{
- struct str path = str_make ();
- const char *runtime_dir = getenv ("XDG_RUNTIME_DIR");
- if (runtime_dir && *runtime_dir == '/')
- str_append (&path, runtime_dir);
- else
- get_xdg_home_dir (&path, "XDG_DATA_HOME", ".local/share");
- str_append_printf (&path, "/%s/%s", PROGRAM_NAME, filename);
-
// Try to create the file's ancestors;
// typically the user will want to immediately create a file in there
const char *last_slash = strrchr (path.str, '/');
@@ -3286,6 +3300,41 @@ resolve_relative_runtime_filename (const char *filename)
}
static char *
+resolve_relative_runtime_filename (const char *filename)
+{
+ struct str path = str_make ();
+ const char *runtime_dir = getenv ("XDG_RUNTIME_DIR");
+ if (runtime_dir && *runtime_dir == '/')
+ str_append (&path, runtime_dir);
+ else
+ get_xdg_home_dir (&path, "XDG_DATA_HOME", ".local/share");
+
+ str_append_printf (&path, "/%s/%s", PROGRAM_NAME, filename);
+ return resolve_relative_runtime_filename_finish (path);
+}
+
+/// This differs from resolve_relative_runtime_filename() in that we expect
+/// the filename to be something like a pattern for mkstemp(), so the resulting
+/// path can reside in a system-wide directory with no risk of a conflict.
+/// However, we have to take care about permissions. Do we even need this?
+static char *
+resolve_relative_runtime_template (const char *template)
+{
+ struct str path = str_make ();
+ const char *runtime_dir = getenv ("XDG_RUNTIME_DIR");
+ const char *tmpdir = getenv ("TMPDIR");
+ if (runtime_dir && *runtime_dir == '/')
+ str_append_printf (&path, "%s/%s", runtime_dir, PROGRAM_NAME);
+ else if (tmpdir && *tmpdir == '/')
+ str_append_printf (&path, "%s/%s.%d", tmpdir, PROGRAM_NAME, geteuid ());
+ else
+ str_append_printf (&path, "/tmp/%s.%d", PROGRAM_NAME, geteuid ());
+
+ str_append_printf (&path, "/%s", template);
+ return resolve_relative_runtime_filename_finish (path);
+}
+
+static char *
try_expand_tilde (const char *filename)
{
size_t until_slash = strcspn (filename, "/");