context: Implement device lists for usb

Signed-off-by: Hubert Figuière <hub@figuiere.net>
This commit is contained in:
Hubert Figuière
2024-03-25 21:41:20 -04:00
committed by Georges Basile Stavracas Neto
parent 19b447f49a
commit 1d56bd377e
7 changed files with 2818 additions and 9 deletions

View File

@@ -137,6 +137,8 @@ void flatpak_context_set_system_bus_policy (FlatpakContext *context,
void flatpak_context_set_a11y_bus_policy (FlatpakContext *context,
const char *name,
FlatpakPolicy policy);
char * flatpak_context_devices_to_usb_list (GHashTable *devices,
gboolean hidden);
void flatpak_context_to_args (FlatpakContext *context,
GPtrArray *args);
FlatpakRunFlags flatpak_context_get_run_flags (FlatpakContext *context);

View File

@@ -544,6 +544,32 @@ flatpak_context_add_nousb_query (FlatpakContext *context,
flatpak_context_add_query_to (context->hidden_usb_devices, usb_query);
}
static gboolean
flatpak_context_add_usb_list (FlatpakContext *context,
const char *list,
GError **error)
{
return flatpak_usb_parse_usb_list (list, context->enumerable_usb_devices,
context->hidden_usb_devices, error);
}
static gboolean
flatpak_context_add_usb_list_from_file (FlatpakContext *context,
const char *path,
GError **error)
{
g_autofree char *contents = NULL;
if (!flatpak_validate_path_characters (path, error))
return FALSE;
if (!g_file_get_contents (path, &contents, NULL, error))
return FALSE;
return flatpak_usb_parse_usb_list (contents, context->enumerable_usb_devices,
context->hidden_usb_devices, error);
}
static gboolean
flatpak_context_set_persistent (FlatpakContext *context,
const char *path,
@@ -1610,8 +1636,26 @@ option_nousb_cb (const char *option_name,
}
static gboolean
option_persist_cb (const gchar *option_name,
const gchar *value,
option_usb_list_file_cb (const char *option_name,
const char *value,
gpointer data,
GError **error)
{
return flatpak_context_add_usb_list_from_file (data, value, error);
}
static gboolean
option_usb_list_cb (const char *option_name,
const char *value,
gpointer data,
GError **error)
{
return flatpak_context_add_usb_list (data, value, error);
}
static gboolean
option_persist_cb (const char *option_name,
const char *value,
gpointer data,
GError **error)
{
@@ -1647,6 +1691,8 @@ static GOptionEntry context_options[] = {
{ "remove-policy", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_remove_generic_policy_cb, N_("Remove generic policy option"), N_("SUBSYSTEM.KEY=VALUE") },
{ "usb", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_usb_cb, N_("Add USB device to enumerables"), N_("VENDOR_ID:PRODUCT_ID") },
{ "nousb", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_nousb_cb, N_("Add USB device to hidden list"), N_("VENDOR_ID:PRODUCT_ID") },
{ "usb-list", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_usb_list_cb, N_("A list of USB device that are enumerable"), N_("LIST") },
{ "usb-list-file", 0, G_OPTION_FLAG_IN_MAIN | G_OPTION_FLAG_FILENAME, G_OPTION_ARG_CALLBACK, &option_usb_list_file_cb, N_("File containing a list of USB device to make enumerable"), N_("FILENAME") },
{ "persist", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_persist_cb, N_("Persist home directory subpath"), N_("FILENAME") },
/* This is not needed/used anymore, so hidden, but we accept it for backwards compat */
{ "no-desktop", 0, G_OPTION_FLAG_IN_MAIN | G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &option_no_desktop_deprecated, N_("Don't require a running session (no cgroups creation)"), NULL },
@@ -2510,12 +2556,33 @@ flatpak_context_allows_features (FlatpakContext *context,
return (context->features & features) == features;
}
char *
flatpak_context_devices_to_usb_list (GHashTable *devices,
gboolean hidden)
{
GString *list = g_string_new (NULL);
GHashTableIter iter;
gpointer value;
g_hash_table_iter_init (&iter, devices);
while (g_hash_table_iter_next (&iter, &value, NULL))
{
if (hidden)
g_string_append_printf (list, "!%s;", (const char *) value);
else
g_string_append_printf (list, "%s;", (const char *) value);
}
return g_string_free (list, FALSE);
}
void
flatpak_context_to_args (FlatpakContext *context,
GPtrArray *args)
{
GHashTableIter iter;
gpointer key, value;
char *usb_list = NULL;
flatpak_context_shared_to_args (context->shares, context->shares_valid, args);
flatpak_context_sockets_to_args (context->sockets, context->sockets_valid, args);
@@ -2585,13 +2652,13 @@ flatpak_context_to_args (FlatpakContext *context,
}
}
g_hash_table_iter_init (&iter, context->enumerable_usb_devices);
while (g_hash_table_iter_next (&iter, &value, NULL))
g_ptr_array_add (args, g_strdup_printf ("--usb=%s", (const char *) value));
usb_list = flatpak_context_devices_to_usb_list (context->enumerable_usb_devices, FALSE);
g_ptr_array_add (args, g_strdup_printf ("--usb-list=%s", usb_list));
g_free (usb_list);
g_hash_table_iter_init (&iter, context->hidden_usb_devices);
while (g_hash_table_iter_next (&iter, &value, NULL))
g_ptr_array_add (args, g_strdup_printf ("--nousb=%s", (const char *) value));
usb_list = flatpak_context_devices_to_usb_list (context->hidden_usb_devices, TRUE);
g_ptr_array_add (args, g_strdup_printf ("--usb-list=%s", usb_list));
g_free (usb_list);
}
void

View File

@@ -91,4 +91,7 @@ gboolean flatpak_usb_parse_usb_rule (const char *data,
gboolean flatpak_usb_parse_usb (const char *data,
FlatpakUsbQuery **out_usb_query,
GError **error);
gboolean flatpak_usb_parse_usb_list (const char *buffer,
GHashTable *enumerable,
GHashTable *hidden,
GError **error);

View File

@@ -21,6 +21,7 @@
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <gio/gio.h>
#include "libglnx.h"
#include "flatpak-usb-private.h"
@@ -297,6 +298,78 @@ flatpak_usb_parse_usb (const char *data,
return TRUE;
}
gboolean
flatpak_usb_parse_usb_list (const char *buffer,
GHashTable *enumerable,
GHashTable *hidden,
GError **error)
{
char *aux = NULL;
g_autoptr(FlatpakUsbQuery) usb_query = NULL;
g_autoptr(GInputStream) stream = NULL;
g_autoptr(GDataInputStream) buffered = NULL;
g_autoptr(GError) local_error = NULL;
stream = g_memory_input_stream_new_from_data (buffer, -1, NULL);
if (!stream)
return FALSE;
buffered = g_data_input_stream_new (G_INPUT_STREAM (stream));
while ((aux = g_data_input_stream_read_line (buffered, NULL, NULL, &local_error)))
{
g_autofree char *line = g_steal_pointer (&aux);
g_auto(GStrv) split = NULL;
gboolean blocking = FALSE;
if (line[0] == '#')
continue;
split = g_strsplit (line, ";", 0);
if (!split || !*split)
continue;
for (size_t i = 0; split[i] != NULL; i++)
{
const char *item = split[i];
blocking = item[0] == '!';
if (blocking)
item++;
if (flatpak_usb_parse_usb (item, &usb_query, NULL))
{
GString *string = g_string_new (NULL);
flatpak_usb_query_print (usb_query, string);
if (blocking)
{
g_hash_table_insert (hidden,
g_string_free (string, FALSE),
g_steal_pointer (&usb_query));
}
else
{
g_hash_table_insert (enumerable,
g_string_free (string, FALSE),
g_steal_pointer (&usb_query));
}
}
}
}
g_input_stream_close (G_INPUT_STREAM (buffered), NULL, error);
g_input_stream_close (G_INPUT_STREAM (stream), NULL, error);
if (local_error)
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
return TRUE;
}
void
flatpak_usb_rule_print (FlatpakUsbRule *usb_rule,
GString *string)

View File

@@ -358,6 +358,33 @@ key=v1;v2;
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--usb-list-file=FILENAME</option></term>
<listitem><para>
Adds USB device queries to the application metadata from the file
<arg choice="plain">FILE_NAME</arg>. The line syntax is exactly
equal to <option>--usb</option>. Additionally, if it starts
with ! then the query is like for <option>--nousb</option>.
Lines sthat starts with <literal>#</literal> are ignored,
like a comment. Comments will not be persisted.
Available since 1.15.11.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--usb-list=LIST</option></term>
<listitem><para>
Adds USB device queries to the application metadata from
<arg choice="plain">LIST</arg>. The syntax is exactly equal to
<option>--usb</option> with queries separated by
<literal>;</literal>. Additionally, if the query starts with
<literal>!</literal> then the query is like for
<option>--nousb</option>. Available since 1.15.11.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--env=VAR=VALUE</option></term>

2598
tests/gphoto2-list Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -501,6 +501,44 @@ test_validate_path_meta (void)
}
static void
test_usb_list (void)
{
const char *gtest_srcdir = NULL;
g_autofree char *test_file_path = NULL;
g_autofree char *content = NULL;
g_autofree char *list = NULL;
gboolean ret = FALSE;
g_autoptr(GError) error = NULL;
g_autoptr(GHashTable) enumerable = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) flatpak_usb_query_free);
g_autoptr(GHashTable) hidden = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) flatpak_usb_query_free);
gtest_srcdir = g_getenv ("G_TEST_SRCDIR");
g_assert (gtest_srcdir);
test_file_path = g_build_filename (gtest_srcdir, "gphoto2-list", NULL);
ret = g_file_get_contents (test_file_path, &content, NULL, &error);
g_assert (ret);
ret = flatpak_usb_parse_usb_list (content, enumerable, hidden, &error);
g_assert (ret);
g_assert_no_error (error);
g_assert_cmpint (g_hash_table_size (hidden), ==, 4);
g_assert_cmpint (g_hash_table_size (enumerable), ==, 2344);
list = flatpak_context_devices_to_usb_list (hidden, TRUE);
g_assert_cmpstr (list, ==, "!vnd:0502+dev:33c3;!vnd:4102+dev:1213;!vnd:0502+dev:365e;!vnd:0502+dev:387a;");
g_hash_table_remove_all (enumerable);
g_hash_table_remove_all (hidden);
ret = flatpak_usb_parse_usb_list (list, enumerable, hidden, &error);
g_assert_cmpint (g_hash_table_size (hidden), ==, 4);
g_assert_cmpint (g_hash_table_size (enumerable), ==, 0);
}
static void
test_usb_rules_all (void)
{
@@ -867,6 +905,7 @@ main (int argc, char *argv[])
g_test_add_func ("/context/validate-path-args", test_validate_path_args);
g_test_add_func ("/context/validate-path-meta", test_validate_path_meta);
g_test_add_func ("/context/usb-list", test_usb_list);
g_test_add_func ("/context/usb-rules/all", test_usb_rules_all);
g_test_add_func ("/context/usb-rules/cls", test_usb_rules_cls);
g_test_add_func ("/context/usb-rules/dev", test_usb_rules_dev);