summaryrefslogtreecommitdiffstats
path: root/src/modules/module-card-restore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/module-card-restore.c')
-rw-r--r--src/modules/module-card-restore.c110
1 files changed, 76 insertions, 34 deletions
diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
index ed0a31df..83acbd79 100644
--- a/src/modules/module-card-restore.c
+++ b/src/modules/module-card-restore.c
@@ -46,6 +46,7 @@
#include <pulsecore/card.h>
#include <pulsecore/namereg.h>
#include <pulsecore/database.h>
+#include <pulsecore/tagstruct.h>
#include "module-card-restore-symdef.h"
@@ -69,12 +70,12 @@ struct userdata {
pa_database *database;
};
-#define ENTRY_VERSION 1
+#define ENTRY_VERSION 2
struct entry {
uint8_t version;
- char profile[PA_NAME_MAX];
-} PA_GCC_PACKED ;
+ char *profile;
+};
static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
struct userdata *u = userdata;
@@ -91,9 +92,24 @@ static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct
pa_log_info("Synced.");
}
-static struct entry* read_entry(struct userdata *u, const char *name) {
+static struct entry* entry_new(void) {
+ struct entry *r = pa_xnew0(struct entry, 1);
+ r->version = ENTRY_VERSION;
+ return r;
+}
+
+static void entry_free(struct entry* e) {
+ pa_assert(e);
+
+ pa_xfree(e->profile);
+ pa_xfree(e);
+}
+
+static struct entry* entry_read(struct userdata *u, const char *name) {
pa_datum key, data;
- struct entry *e;
+ struct entry *e = NULL;
+ pa_tagstruct *t = NULL;
+ const char* profile;
pa_assert(u);
pa_assert(name);
@@ -106,31 +122,63 @@ static struct entry* read_entry(struct userdata *u, const char *name) {
if (!pa_database_get(u->database, &key, &data))
goto fail;
- if (data.size != sizeof(struct entry)) {
- pa_log_debug("Database contains entry for card %s of wrong size %lu != %lu. Probably due to upgrade, ignoring.", name, (unsigned long) data.size, (unsigned long) sizeof(struct entry));
- goto fail;
- }
+ t = pa_tagstruct_new(data.data, data.size);
+ e = entry_new();
- e = (struct entry*) data.data;
+ if (pa_tagstruct_getu8(t, &e->version) < 0 ||
+ e->version > ENTRY_VERSION ||
+ pa_tagstruct_gets(t, &profile) < 0) {
- if (e->version != ENTRY_VERSION) {
- pa_log_debug("Version of database entry for card %s doesn't match our version. Probably due to upgrade, ignoring.", name);
goto fail;
}
- if (!memchr(e->profile, 0, sizeof(e->profile))) {
- pa_log_warn("Database contains entry for card %s with missing NUL byte in profile name", name);
+ e->profile = pa_xstrdup(profile);
+
+ if (!pa_tagstruct_eof(t))
goto fail;
- }
+
+ pa_tagstruct_free(t);
+ pa_datum_free(&data);
return e;
fail:
+ pa_log_debug("Database contains invalid data for key: %s (probably pre-v1.0 data)", name);
+
+ if (e)
+ entry_free(e);
+ if (t)
+ pa_tagstruct_free(t);
pa_datum_free(&data);
return NULL;
}
+static pa_bool_t entry_write(struct userdata *u, const char *name, const struct entry *e) {
+ pa_tagstruct *t;
+ pa_datum key, data;
+ pa_bool_t r;
+
+ pa_assert(u);
+ pa_assert(name);
+ pa_assert(e);
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu8(t, e->version);
+ pa_tagstruct_puts(t, e->profile);
+
+ key.data = (char *) name;
+ key.size = strlen(name);
+
+ data.data = (void*)pa_tagstruct_data(t, &data.size);
+
+ r = (pa_database_set(u->database, &key, &data, TRUE) == 0);
+
+ pa_tagstruct_free(t);
+
+ return r;
+}
+
static void trigger_save(struct userdata *u) {
if (u->save_time_event)
return;
@@ -140,8 +188,7 @@ static void trigger_save(struct userdata *u) {
static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
struct userdata *u = userdata;
- struct entry entry, *old;
- pa_datum key, data;
+ struct entry *entry, *old;
pa_card *card;
pa_assert(c);
@@ -151,8 +198,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
t != (PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE))
return;
- pa_zero(entry);
- entry.version = ENTRY_VERSION;
+ entry = entry_new();
if (!(card = pa_idxset_get_by_index(c->cards, idx)))
return;
@@ -160,29 +206,25 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
if (!card->save_profile)
return;
- pa_strlcpy(entry.profile, card->active_profile ? card->active_profile->name : "", sizeof(entry.profile));
+ entry->profile = pa_xstrdup(card->active_profile ? card->active_profile->name : "");
- if ((old = read_entry(u, card->name))) {
+ if ((old = entry_read(u, card->name))) {
- if (strncmp(old->profile, entry.profile, sizeof(entry.profile)) == 0) {
- pa_xfree(old);
+ if (pa_streq(old->profile, entry->profile)) {
+ entry_free(old);
+ entry_free(entry);
return;
}
- pa_xfree(old);
+ entry_free(old);
}
- key.data = card->name;
- key.size = strlen(card->name);
-
- data.data = &entry;
- data.size = sizeof(entry);
-
pa_log_info("Storing profile for card %s.", card->name);
- pa_database_set(u->database, &key, &data, TRUE);
+ if (entry_write(u, card->name, entry))
+ trigger_save(u);
- trigger_save(u);
+ entry_free(entry);
}
static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new_data, struct userdata *u) {
@@ -190,7 +232,7 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new
pa_assert(new_data);
- if ((e = read_entry(u, new_data->name)) && e->profile[0]) {
+ if ((e = entry_read(u, new_data->name)) && e->profile[0]) {
if (!new_data->active_profile) {
pa_log_info("Restoring profile for card %s.", new_data->name);
@@ -199,7 +241,7 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new
} else
pa_log_debug("Not restoring profile for card %s, because already set.", new_data->name);
- pa_xfree(e);
+ entry_free(e);
}
return PA_HOOK_OK;