mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-02-04 22:30:28 +01:00
state: use GKeyFile API to keep state in disk
This commit is contained in:
parent
2ec43ea885
commit
bef0b178ed
4 changed files with 95 additions and 78 deletions
|
|
@ -38,6 +38,7 @@ struct _WpState
|
|||
gchar *name;
|
||||
|
||||
gchar *location;
|
||||
GKeyFile *keyfile;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (WpState, wp_state, G_TYPE_OBJECT)
|
||||
|
|
@ -113,6 +114,7 @@ wp_state_finalize (GObject * object)
|
|||
|
||||
g_clear_pointer (&self->name, g_free);
|
||||
g_clear_pointer (&self->location, g_free);
|
||||
g_clear_pointer (&self->keyfile, g_key_file_free);
|
||||
|
||||
G_OBJECT_CLASS (wp_state_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
@ -120,6 +122,7 @@ wp_state_finalize (GObject * object)
|
|||
static void
|
||||
wp_state_init (WpState * self)
|
||||
{
|
||||
self->keyfile = g_key_file_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -204,6 +207,7 @@ wp_state_clear (WpState *self)
|
|||
/**
|
||||
* wp_state_save:
|
||||
* @self: the state
|
||||
* @group: the group name where the properties will be save
|
||||
* @props: (transfer none): the properties to save
|
||||
*
|
||||
* Saves new properties in the state, overwriting all previous data.
|
||||
|
|
@ -211,53 +215,30 @@ wp_state_clear (WpState *self)
|
|||
* Returns: TRUE if the properties could be saved, FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
wp_state_save (WpState *self, WpProperties *props)
|
||||
wp_state_save (WpState *self, const gchar *group, WpProperties *props)
|
||||
{
|
||||
g_autoptr (WpIterator) it = NULL;
|
||||
g_auto (GValue) item = G_VALUE_INIT;
|
||||
g_autofree gchar *tmp_name = NULL, *tmp_location = NULL;
|
||||
gulong tmp_size;
|
||||
int fd;
|
||||
FILE *f;
|
||||
|
||||
g_return_val_if_fail (WP_IS_STATE (self), FALSE);
|
||||
g_return_val_if_fail (group, FALSE);
|
||||
wp_state_ensure_location (self);
|
||||
|
||||
wp_info_object (self, "saving state into %s", self->location);
|
||||
|
||||
/* Get the temporary name and location */
|
||||
tmp_size = strlen (self->name) + 5;
|
||||
tmp_name = g_malloc (tmp_size);
|
||||
g_snprintf (tmp_name, tmp_size, "%s.tmp", self->name);
|
||||
tmp_location = get_new_location (tmp_name);
|
||||
g_return_val_if_fail (tmp_location, FALSE);
|
||||
g_key_file_remove_group (self->keyfile, group, NULL);
|
||||
|
||||
/* Open */
|
||||
fd = open (tmp_location, O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC, 0700);
|
||||
if (fd == -1) {
|
||||
wp_critical_object (self, "can't open %s", tmp_location);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Write */
|
||||
f = fdopen(fd, "w");
|
||||
/* Set the properties */
|
||||
for (it = wp_properties_iterate (props);
|
||||
wp_iterator_next (it, &item);
|
||||
g_value_unset (&item)) {
|
||||
const gchar *p = wp_properties_iterator_item_get_key (&item);
|
||||
while (*p) {
|
||||
if (*p == ' ' || *p == '\\')
|
||||
fputc('\\', f);
|
||||
fprintf(f, "%c", *p++);
|
||||
}
|
||||
fprintf(f, " %s\n", wp_properties_iterator_item_get_value (&item));
|
||||
const gchar *key = wp_properties_iterator_item_get_key (&item);
|
||||
const gchar *val = wp_properties_iterator_item_get_value (&item);
|
||||
g_key_file_set_string (self->keyfile, group, key, val);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
/* Rename temporary file */
|
||||
if (rename(tmp_location, self->location) < 0) {
|
||||
wp_critical_object("can't rename temporary file '%s' to '%s'", tmp_name,
|
||||
self->name);
|
||||
if (!g_key_file_save_to_file (self->keyfile, self->location, NULL)) {
|
||||
wp_critical_object (self, "can't save %s", self->location);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -267,54 +248,42 @@ wp_state_save (WpState *self, WpProperties *props)
|
|||
/**
|
||||
* wp_state_load:
|
||||
* @self: the state
|
||||
* @group: the group which the properties will be loaded from
|
||||
*
|
||||
* Loads the state data into new properties.
|
||||
*
|
||||
* Returns (transfer full): the new properties with the state data
|
||||
*/
|
||||
WpProperties *
|
||||
wp_state_load (WpState *self)
|
||||
wp_state_load (WpState *self, const gchar *group)
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_properties_new_empty ();
|
||||
int fd;
|
||||
FILE *f;
|
||||
char line[1024];
|
||||
gchar ** keys = NULL;
|
||||
|
||||
g_return_val_if_fail (WP_IS_STATE (self), NULL);
|
||||
g_return_val_if_fail (group, NULL);
|
||||
wp_state_ensure_location (self);
|
||||
|
||||
/* Open */
|
||||
wp_info_object (self, "loading state from %s", self->location);
|
||||
fd = open (self->location, O_CLOEXEC | O_RDONLY);
|
||||
if (fd == -1) {
|
||||
/* We consider empty state if fill does not exist */
|
||||
if (errno == ENOENT)
|
||||
return g_steal_pointer (&props);
|
||||
wp_critical_object (self, "can't open %s", self->location);
|
||||
return NULL;
|
||||
}
|
||||
if (!g_key_file_load_from_file (self->keyfile, self->location,
|
||||
G_KEY_FILE_NONE, NULL))
|
||||
return g_steal_pointer (&props);
|
||||
|
||||
/* Read */
|
||||
f = fdopen(fd, "r");
|
||||
while (fgets (line, sizeof(line)-1, f)) {
|
||||
char *val, *key, *k, *p;
|
||||
val = strrchr(line, '\n');
|
||||
if (val)
|
||||
*val = '\0';
|
||||
/* Load all keys */
|
||||
keys = g_key_file_get_keys (self->keyfile, group, NULL, NULL);
|
||||
if (!keys)
|
||||
return g_steal_pointer (&props);
|
||||
|
||||
key = k = p = line;
|
||||
while (*p) {
|
||||
if (*p == ' ')
|
||||
break;
|
||||
if (*p == '\\')
|
||||
p++;
|
||||
*k++ = *p++;
|
||||
}
|
||||
*k = '\0';
|
||||
val = ++p;
|
||||
for (guint i = 0; keys[i]; i++) {
|
||||
const gchar *key = keys[i];
|
||||
g_autofree gchar *val = NULL;
|
||||
val = g_key_file_get_string (self->keyfile, group, key, NULL);
|
||||
if (!val)
|
||||
continue;
|
||||
wp_properties_set (props, key, val);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
g_strfreev (keys);
|
||||
|
||||
return g_steal_pointer (&props);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@ WP_API
|
|||
void wp_state_clear (WpState *self);
|
||||
|
||||
WP_API
|
||||
gboolean wp_state_save (WpState *self, WpProperties *props);
|
||||
gboolean wp_state_save (WpState *self, const gchar *group, WpProperties *props);
|
||||
|
||||
WP_API
|
||||
WpProperties * wp_state_load (WpState *self);
|
||||
WpProperties * wp_state_load (WpState *self, const gchar *group);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ timeout_save_callback (WpDefaultProfile *self)
|
|||
WpDefaultProfilePrivate *priv =
|
||||
wp_default_profile_get_instance_private (self);
|
||||
|
||||
if (!wp_state_save (priv->state, priv->profiles))
|
||||
if (!wp_state_save (priv->state, "group", priv->profiles))
|
||||
wp_warning_object (self, "could not save profiles");
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
|
|
@ -305,7 +305,7 @@ wp_default_profile_init (WpDefaultProfile * self)
|
|||
priv->state = wp_state_new (STATE_NAME);
|
||||
|
||||
/* Load the saved profiles */
|
||||
priv->profiles = wp_state_load (priv->state);
|
||||
priv->profiles = wp_state_load (priv->state, "group");
|
||||
if (!priv->profiles) {
|
||||
wp_warning_object (self, "could not load profiles");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ test_state_basic (void)
|
|||
wp_properties_set (props, "key1", "value1");
|
||||
wp_properties_set (props, "key2", "value2");
|
||||
wp_properties_set (props, "key3", "value3");
|
||||
g_assert_true (wp_state_save (state, props));
|
||||
g_assert_true (wp_state_save (state, "group", props));
|
||||
}
|
||||
|
||||
/* Load */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_state_load (state);
|
||||
g_autoptr (WpProperties) props = wp_state_load (state, "group");
|
||||
g_assert_nonnull (props);
|
||||
g_assert_cmpstr (wp_properties_get (props, "key1"), ==, "value1");
|
||||
g_assert_cmpstr (wp_properties_get (props, "key2"), ==, "value2");
|
||||
|
|
@ -40,12 +40,12 @@ test_state_basic (void)
|
|||
{
|
||||
g_autoptr (WpProperties) props = wp_properties_new_empty ();
|
||||
wp_properties_set (props, "new-key", "new-value");
|
||||
g_assert_true (wp_state_save (state, props));
|
||||
g_assert_true (wp_state_save (state, "group", props));
|
||||
}
|
||||
|
||||
/* Re-Load */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_state_load (state);
|
||||
g_autoptr (WpProperties) props = wp_state_load (state, "group");
|
||||
g_assert_nonnull (props);
|
||||
g_assert_cmpstr (wp_properties_get (props, "new-key"), ==, "new-value");
|
||||
g_assert_null (wp_properties_get (props, "key1"));
|
||||
|
|
@ -57,7 +57,7 @@ test_state_basic (void)
|
|||
|
||||
/* Load empty */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_state_load (state);
|
||||
g_autoptr (WpProperties) props = wp_state_load (state, "group");
|
||||
g_assert_nonnull (props);
|
||||
g_assert_null (wp_properties_get (props, "new-key"));
|
||||
g_assert_null (wp_properties_get (props, "key1"));
|
||||
|
|
@ -78,12 +78,12 @@ test_state_empty (void)
|
|||
{
|
||||
g_autoptr (WpProperties) props = wp_properties_new_empty ();
|
||||
wp_properties_set (props, "key", "value");
|
||||
g_assert_true (wp_state_save (state, props));
|
||||
g_assert_true (wp_state_save (state, "group", props));
|
||||
}
|
||||
|
||||
/* Load */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_state_load (state);
|
||||
g_autoptr (WpProperties) props = wp_state_load (state, "group");
|
||||
g_assert_nonnull (props);
|
||||
g_assert_cmpstr (wp_properties_get (props, "key"), ==, "value");
|
||||
}
|
||||
|
|
@ -91,12 +91,12 @@ test_state_empty (void)
|
|||
/* Save empty */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_properties_new_empty ();
|
||||
g_assert_true (wp_state_save (state, props));
|
||||
g_assert_true (wp_state_save (state, "group", props));
|
||||
}
|
||||
|
||||
/* Load empty */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_state_load (state);
|
||||
g_autoptr (WpProperties) props = wp_state_load (state, "group");
|
||||
g_assert_nonnull (props);
|
||||
g_assert_null (wp_properties_get (props, "key"));
|
||||
}
|
||||
|
|
@ -114,12 +114,12 @@ test_state_spaces (void)
|
|||
{
|
||||
g_autoptr (WpProperties) props = wp_properties_new_empty ();
|
||||
wp_properties_set (props, "key", "value with spaces");
|
||||
g_assert_true (wp_state_save (state, props));
|
||||
g_assert_true (wp_state_save (state, "group", props));
|
||||
}
|
||||
|
||||
/* Load */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_state_load (state);
|
||||
g_autoptr (WpProperties) props = wp_state_load (state, "group");
|
||||
g_assert_nonnull (props);
|
||||
g_assert_cmpstr (wp_properties_get (props, "key"), ==, "value with spaces");
|
||||
}
|
||||
|
|
@ -127,6 +127,53 @@ test_state_spaces (void)
|
|||
wp_state_clear (state);
|
||||
}
|
||||
|
||||
static void
|
||||
test_state_group (void)
|
||||
{
|
||||
g_autoptr (WpState) state = wp_state_new ("group");
|
||||
g_assert_nonnull (state);
|
||||
|
||||
/* Save 1 */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_properties_new_empty ();
|
||||
wp_properties_set (props, "key1", "value1");
|
||||
g_assert_true (wp_state_save (state, "1", props));
|
||||
}
|
||||
|
||||
/* Save 2 */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_properties_new_empty ();
|
||||
wp_properties_set (props, "key2", "value2");
|
||||
g_assert_true (wp_state_save (state, "2", props));
|
||||
}
|
||||
|
||||
/* Load invalid group */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_state_load (state, "invalid");
|
||||
g_assert_nonnull (props);
|
||||
g_assert_null (wp_properties_get (props, "key1"));
|
||||
g_assert_null (wp_properties_get (props, "key2"));
|
||||
}
|
||||
|
||||
/* Load 1 */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_state_load (state, "1");
|
||||
g_assert_nonnull (props);
|
||||
g_assert_cmpstr (wp_properties_get (props, "key1"), ==, "value1");
|
||||
g_assert_null (wp_properties_get (props, "key2"));
|
||||
}
|
||||
|
||||
/* Load 2 */
|
||||
{
|
||||
g_autoptr (WpProperties) props = wp_state_load (state, "2");
|
||||
g_assert_nonnull (props);
|
||||
g_assert_cmpstr (wp_properties_get (props, "key2"), ==, "value2");
|
||||
g_assert_null (wp_properties_get (props, "key1"));
|
||||
}
|
||||
|
||||
wp_state_clear (state);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
|
|
@ -136,6 +183,7 @@ main (int argc, char *argv[])
|
|||
g_test_add_func ("/wp/state/basic", test_state_basic);
|
||||
g_test_add_func ("/wp/state/empty", test_state_empty);
|
||||
g_test_add_func ("/wp/state/spaces", test_state_spaces);
|
||||
g_test_add_func ("/wp/state/group", test_state_group);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue