return g_file_new_for_path (abspath);
}
+/* Wraps readlinkat(), and sets the `symlink-target` property
+ * of @target_info.
+ */
gboolean
ot_readlinkat_gfile_info (int dfd,
const char *path,
return TRUE;
}
-
/**
* ot_openat_read_stream:
* @dfd: Directory file descriptor
GCancellable *cancellable,
GError **error)
{
- int fd = -1;
- int flags = O_RDONLY | O_NOCTTY | O_CLOEXEC;
-
- if (!follow)
- flags |= O_NOFOLLOW;
-
- if (TEMP_FAILURE_RETRY (fd = openat (dfd, path, flags, 0)) < 0)
- return glnx_throw_errno_prefix (error, "openat(%s)", path);
-
- *out_istream = g_unix_input_stream_new (fd, TRUE);
+ glnx_fd_close int fd = -1;
+ if (!glnx_openat_rdonly (dfd, path, follow, &fd, error))
+ return FALSE;
+ *out_istream = g_unix_input_stream_new (glnx_steal_fd (&fd), TRUE);
return TRUE;
}
#include <stdlib.h>
#include <errno.h>
+/* Ensure that a pathname component @name does not contain the special Unix
+ * entries `.` or `..`, and does not contain `/`.
+ */
gboolean
ot_util_filename_validate (const char *name,
GError **error)
{
if (strcmp (name, ".") == 0)
- {
- return glnx_throw (error, "Invalid self-referential filename '.'");
- }
+ return glnx_throw (error, "Invalid self-referential filename '.'");
if (strcmp (name, "..") == 0)
- {
- return glnx_throw (error, "Invalid path uplink filename '..'");
- }
+ return glnx_throw (error, "Invalid path uplink filename '..'");
if (strchr (name, '/') != NULL)
- {
- return glnx_throw (error, "Invalid / in filename %s", name);
- }
+ return glnx_throw (error, "Invalid / in filename %s", name);
return TRUE;
}
char c)
{
GPtrArray *ret = g_ptr_array_new_with_free_func (g_free);
- const char *p;
+ const char *p;
do {
p = strchr (str, '/');
if (!p)
return ret;
}
+/* Given a pathname @path, split it into individual entries in @out_components,
+ * validating that it does not have backreferences (`..`) etc.
+ */
gboolean
ot_util_path_split_validate (const char *path,
GPtrArray **out_components,
GError **error)
{
- gboolean ret = FALSE;
- int i;
- g_autoptr(GPtrArray) ret_components = NULL;
-
if (strlen (path) > PATH_MAX)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Path '%s' is too long", path);
- goto out;
- }
+ return glnx_throw (error, "Path '%s' is too long", path);
- ret_components = ot_split_string_ptrarray (path, '/');
+ g_autoptr(GPtrArray) ret_components = ot_split_string_ptrarray (path, '/');
/* Canonicalize by removing '.' and '', throw an error on .. */
- for (i = ret_components->len-1; i >= 0; i--)
+ for (int i = ret_components->len-1; i >= 0; i--)
{
const char *name = ret_components->pdata[i];
if (strcmp (name, "..") == 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid uplink '..' in path %s", path);
- goto out;
- }
+ return glnx_throw (error, "Invalid uplink '..' in path %s", path);
if (strcmp (name, ".") == 0 || name[0] == '\0')
g_ptr_array_remove_index (ret_components, i);
}
- ret = TRUE;
ot_transfer_out_value(out_components, &ret_components);
- out:
- return ret;
+ return TRUE;
}
#include "otutil.h"
+/* Create a new GVariant empty GVariant of type a{sv} */
GVariant *
ot_gvariant_new_empty_string_dict (void)
{
return g_variant_builder_end (&builder);
}
+
+/* Create a new GVariant of type ay from the raw @data pointer */
GVariant *
ot_gvariant_new_bytearray (const guchar *data,
gsize len)
{
- gpointer data_copy;
- GVariant *ret;
-
- data_copy = g_memdup (data, len);
- ret = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), data_copy,
+ gpointer data_copy = g_memdup (data, len);
+ GVariant *ret = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), data_copy,
len, FALSE, g_free, data_copy);
return ret;
}
+/* Convert a GBytes into a GVariant of type ay (byte array) */
GVariant *
ot_gvariant_new_ay_bytes (GBytes *bytes)
{
gsize size;
- gconstpointer data;
- data = g_bytes_get_data (bytes, &size);
+ gconstpointer data = g_bytes_get_data (bytes, &size);
g_bytes_ref (bytes);
return g_variant_new_from_data (G_VARIANT_TYPE ("ay"), data, size,
TRUE, (GDestroyNotify)g_bytes_unref, bytes);
}
+/* Convert a GVariant of type a{sv} to a GHashTable */
GHashTable *
ot_util_variant_asv_to_hash_table (GVariant *variant)
{
- GHashTable *ret;
- GVariantIter *viter;
+
+ GHashTable *ret = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
+ g_autoptr(GVariantIter) viter = g_variant_iter_new (variant);
+
char *key;
GVariant *value;
-
- ret = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
- viter = g_variant_iter_new (variant);
while (g_variant_iter_next (viter, "{s@v}", &key, &value))
g_hash_table_replace (ret, key, g_variant_ref_sink (value));
-
- g_variant_iter_free (viter);
-
+
return ret;
}
return TRUE;
}
+/* Get an input stream for a GVariant */
GInputStream *
ot_variant_read (GVariant *variant)
{
- GMemoryInputStream *ret = NULL;
-
- ret = (GMemoryInputStream*)g_memory_input_stream_new_from_data (g_variant_get_data (variant),
- g_variant_get_size (variant),
- NULL);
+ GMemoryInputStream *ret = (GMemoryInputStream*)
+ g_memory_input_stream_new_from_data (g_variant_get_data (variant),
+ g_variant_get_size (variant),
+ NULL);
g_object_set_data_full ((GObject*)ret, "ot-variant-data",
g_variant_ref (variant), (GDestroyNotify) g_variant_unref);
return (GInputStream*)ret;
}
+/* GVariants are immutable; this function allows generating an open builder
+ * for a new variant, inherting the data from @variant.
+ */
GVariantBuilder *
ot_util_variant_builder_from_variant (GVariant *variant,
const GVariantType *type)
{
- GVariantBuilder *builder = NULL;
-
- builder = g_variant_builder_new (type);
-
+ GVariantBuilder *builder = g_variant_builder_new (type);
+
if (variant != NULL)
{
- gint i, n;
-
- n = g_variant_n_children (variant);
- for (i = 0; i < n; i++)
+ const int n = g_variant_n_children (variant);
+ for (int i = 0; i < n; i++)
{
- GVariant *child = g_variant_get_child_value (variant, i);
+ g_autoptr(GVariant) child = g_variant_get_child_value (variant, i);
g_variant_builder_add_value (builder, child);
- g_variant_unref (child);
}
}
-
+
return builder;
}
const char *str,
int *out_pos)
{
- gsize imax, imin;
- gsize imid = -1;
- gsize n;
-
- n = g_variant_n_children (array);
+ const gsize n = g_variant_n_children (array);
if (n == 0)
return FALSE;
- imax = n - 1;
- imin = 0;
+ gsize imax = n - 1;
+ gsize imin = 0;
+ gsize imid = -1;
while (imax >= imin)
{
- g_autoptr(GVariant) child = NULL;
const char *cur;
- int cmp;
imid = (imin + imax) / 2;
- child = g_variant_get_child_value (array, imid);
+ g_autoptr(GVariant) child = g_variant_get_child_value (array, imid);
g_variant_get_child (child, 0, "&s", &cur, NULL);
- cmp = strcmp (cur, str);
+ int cmp = strcmp (cur, str);
if (cmp < 0)
imin = imid + 1;
else if (cmp > 0)