diff options
Diffstat (limited to 'src/modules/module-card-restore.c')
-rw-r--r-- | src/modules/module-card-restore.c | 110 |
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; |