alsactl: clean the boot / hotplug card specific configuration directory

The /var/lib/alsa/card<NUMBER>.conf.d directories should be emptied
when the card is initialized. Implement this functionality directly
to alsactl.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2021-04-13 11:15:55 +02:00
parent 0a6b63a2c4
commit a589d88862
6 changed files with 73 additions and 9 deletions

View file

@ -98,6 +98,10 @@ Print alsactl version number.
\fI\-f, \-\-file\fP
Select the configuration file to use. The default is /var/lib/alsa/asound.state.
.TP
\fI\-a, \-\-config-dir\fP
Select the boot / hotplug ALSA configuration directory to use. The default is /var/lib/alsa.
.TP
\fI\-l, \-\-lock\fP
Use the file locking to serialize the concurrent access to the state file (this

View file

@ -31,8 +31,11 @@
#include <sched.h>
#include "alsactl.h"
#ifndef SYS_ASOUND_DIR
#define SYS_ASOUND_DIR "/var/lib/alsa"
#endif
#ifndef SYS_ASOUNDRC
#define SYS_ASOUNDRC "/var/lib/alsa/asound.state"
#define SYS_ASOUNDRC SYS_ASOUND_DIR "/asound.state"
#endif
#ifndef SYS_PIDFILE
#define SYS_PIDFILE "/var/run/alsactl.pid"
@ -73,6 +76,7 @@ static struct arg args[] = {
{ 'v', "version", "print version of this program" },
{ HEADER, NULL, "Available state options:" },
{ FILEARG | 'f', "file", "configuration file (default " SYS_ASOUNDRC ")" },
{ FILEARG | 'a', "config-dir", "boot / hotplug configuration directory (default " SYS_ASOUND_DIR ")" },
{ 'l', "lock", "use file locking to serialize concurrent access" },
{ 'L', "no-lock", "do not use file locking to serialize concurrent access" },
{ FILEARG | 'O', "lock-state-file", "state lock file path (default " SYS_LOCKFILE ")" },
@ -227,6 +231,7 @@ int main(int argc, char *argv[])
"/dev/snd/hwC",
NULL
};
char *cfgdir = SYS_ASOUND_DIR;
char *cfgfile = SYS_ASOUNDRC;
char *initfile = DATADIR "/init/00main";
char *pidfile = SYS_PIDFILE;
@ -286,6 +291,9 @@ int main(int argc, char *argv[])
case 'f':
cfgfile = optarg;
break;
case 'a':
cfgdir = optarg;
break;
case 'l':
do_lock = 1;
break;
@ -420,7 +428,7 @@ int main(int argc, char *argv[])
snd_lib_error_set_handler(error_handler);
if (!strcmp(cmd, "init")) {
res = init(initfile, initflags | FLAG_UCM_FBOOT | FLAG_UCM_BOOT, cardname);
res = init(cfgdir, initfile, initflags | FLAG_UCM_FBOOT | FLAG_UCM_BOOT, cardname);
snd_config_update_free_global();
} else if (!strcmp(cmd, "store")) {
res = save_state(cfgfile, cardname);
@ -429,7 +437,7 @@ int main(int argc, char *argv[])
!strcmp(cmd, "nrestore")) {
if (removestate)
remove(statefile);
res = load_state(cfgfile, initfile, initflags, cardname, init_fallback);
res = load_state(cfgdir, cfgfile, initfile, initflags, cardname, init_fallback);
if (!strcmp(cmd, "rdaemon")) {
do_nice(use_nice, sched_idle);
res = state_daemon(cfgfile, cardname, period, pidfile);

View file

@ -46,12 +46,13 @@ const char *snd_card_iterator_next(struct snd_card_iterator *iter);
int snd_card_iterator_error(struct snd_card_iterator *iter);
int load_configuration(const char *file, snd_config_t **top, int *open_failed);
int init(const char *file, int flags, const char *cardname);
int init(const char *cfgdir, const char *file, int flags, const char *cardname);
int init_ucm(int flags, int cardno);
int state_lock(const char *file, int timeout);
int state_unlock(int fd, const char *file);
int save_state(const char *file, const char *cardname);
int load_state(const char *file, const char *initfile, int initflags,
int load_state(const char *cfgdir, const char *file,
const char *initfile, int initflags,
const char *cardname, int do_init);
int power(const char *argv[], int argc);
int monitor(const char *name);
@ -59,6 +60,7 @@ int state_daemon(const char *file, const char *cardname, int period,
const char *pidfile);
int state_daemon_kill(const char *pidfile, const char *cmd);
int clean(const char *cardname, char *const *extra_args);
int snd_card_clean_cfgdir(const char *cfgdir, int cardno);
/* utils */

View file

@ -1743,7 +1743,7 @@ static int parse(struct space *space, const char *filename)
return err ? err : -abs(space->exit_code);
}
int init(const char *filename, int flags, const char *cardname)
int init(const char *cfgdir, const char *filename, int flags, const char *cardname)
{
struct space *space;
struct snd_card_iterator iter;
@ -1752,6 +1752,12 @@ int init(const char *filename, int flags, const char *cardname)
sysfs_init();
err = snd_card_iterator_sinit(&iter, cardname);
while (snd_card_iterator_next(&iter)) {
err = snd_card_clean_cfgdir(cfgdir, iter.card);
if (err < 0) {
if (lasterr == 0)
lasterr = err;
continue;
}
err = init_ucm(flags, iter.card);
if (err == 0)
continue;

View file

@ -1618,7 +1618,8 @@ out:
return err;
}
int load_state(const char *file, const char *initfile, int initflags,
int load_state(const char *cfgdir, const char *file,
const char *initfile, int initflags,
const char *cardname, int do_init)
{
int err, finalerr = 0, open_failed;
@ -1640,7 +1641,7 @@ int load_state(const char *file, const char *initfile, int initflags,
while ((cardname1 = snd_card_iterator_next(&iter)) != NULL) {
if (!do_init)
break;
err = init(initfile, initflags | FLAG_UCM_FBOOT | FLAG_UCM_BOOT, cardname1);
err = init(cfgdir, initfile, initflags | FLAG_UCM_FBOOT | FLAG_UCM_BOOT, cardname1);
if (err < 0) {
finalerr = err;
initfailed(iter.card, "init", err);
@ -1661,7 +1662,7 @@ int load_state(const char *file, const char *initfile, int initflags,
init_ucm(initflags | FLAG_UCM_FBOOT, iter.card);
/* do a check if controls matches state file */
if (do_init && set_controls(iter.card, config, 0)) {
err = init(initfile, initflags | FLAG_UCM_BOOT, cardname1);
err = init(cfgdir, initfile, initflags | FLAG_UCM_BOOT, cardname1);
if (err < 0) {
initfailed(iter.card, "init", err);
finalerr = err;

View file

@ -284,3 +284,46 @@ int snd_card_iterator_error(struct snd_card_iterator *iter)
{
return iter->first ? (ignore_nocards ? 0 : -ENODEV) : 0;
}
static int cleanup_filename_filter(const struct dirent *dirent)
{
size_t flen;
if (dirent == NULL)
return 0;
if (dirent->d_type == DT_DIR)
return 0;
flen = strlen(dirent->d_name);
if (flen <= 5)
return 0;
if (strncmp(&dirent->d_name[flen-5], ".conf", 5) == 0)
return 1;
return 0;
}
int snd_card_clean_cfgdir(const char *cfgdir, int cardno)
{
char path[PATH_MAX];
struct dirent **list;
int lasterr = 0, n, j;
snprintf(path, sizeof(path), "%s/card%d.conf.d", cfgdir, cardno);
n = scandir(path, &list, cleanup_filename_filter, NULL);
if (n < 0) {
if (errno == ENOENT)
return 0;
return -errno;
}
for (j = 0; j < n; j++) {
snprintf(path, sizeof(path), "%s/card%d.conf.d/%s", cfgdir, cardno, list[j]->d_name);
if (remove(path)) {
error("Unable to remove file '%s'", path);
lasterr = -errno;
}
}
return lasterr;
}