Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Julian Bouzas
WirePlumber
Commits
bef0b178
Commit
bef0b178
authored
Jan 08, 2021
by
Julian Bouzas
Browse files
state: use GKeyFile API to keep state in disk
parent
2ec43ea8
Changes
4
Hide whitespace changes
Inline
Side-by-side
lib/wp/state.c
View file @
bef0b178
...
...
@@ -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
;
}
/* 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'
;
key
=
k
=
p
=
line
;
while
(
*
p
)
{
if
(
*
p
==
' '
)
break
;
if
(
*
p
==
'\\'
)
p
++
;
*
k
++
=
*
p
++
;
}
*
k
=
'\0'
;
val
=
++
p
;
if
(
!
g_key_file_load_from_file
(
self
->
keyfile
,
self
->
location
,
G_KEY_FILE_NONE
,
NULL
))
return
g_steal_pointer
(
&
props
);
/* Load all keys */
keys
=
g_key_file_get_keys
(
self
->
keyfile
,
group
,
NULL
,
NULL
);
if
(
!
keys
)
return
g_steal_pointer
(
&
props
);
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
);
}
lib/wp/state.h
View file @
bef0b178
...
...
@@ -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
...
...
modules/module-default-profile.c
View file @
bef0b178
...
...
@@ -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
;
...
...
tests/wp/state.c
View file @
bef0b178
...
...
@@ -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
();
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment