alsactl: Read only *.conf files when a directory is passed via INCLUDE

When alsactl init is invoked and a directory path is passed to INCLUDE
command in the config file, read only *.conf files in that directory.
This will avoid reading backup files or invalid files that have been
created accidentally.

Also by using scandir() with alphasort(), alsactl reads the files in
alphabetical order.  Thus it's highly recommended to use some number
prefix to the file name for assuring the order.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2012-06-14 13:14:48 +02:00
parent b72e221aab
commit c68a3d02d1
2 changed files with 34 additions and 11 deletions

View file

@ -474,7 +474,15 @@
<varlistentry> <varlistentry>
<term><option>INCLUDE</option></term> <term><option>INCLUDE</option></term>
<listitem> <listitem>
<para>Include specified filename or all files in specified directory</para> <para>Include the specified filename or files in specified directory.
</para>
<para>
When a directory is specified, only the files with the
extension ".conf" are read.
Also they are read in the alphabetical order.
Thus it's highly recommended to use some number prefix
(e.g. "01-something.conf") to assure the order of execucions.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View file

@ -1278,6 +1278,13 @@ static char *new_root_dir(const char *filename)
return res; return res;
} }
/* return non-zero if the file name has the extension ".conf" */
static int conf_name_filter(const struct dirent *d)
{
char *ext = strrchr(d->d_name, '.');
return ext && !strcmp(ext, ".conf");
}
static int parse_line(struct space *space, char *line, size_t linesize) static int parse_line(struct space *space, char *line, size_t linesize)
{ {
char *linepos; char *linepos;
@ -1480,8 +1487,7 @@ static int parse_line(struct space *space, char *line, size_t linesize)
if (strcasecmp(key, "INCLUDE") == 0) { if (strcasecmp(key, "INCLUDE") == 0) {
char *rootdir, *go_to; char *rootdir, *go_to;
const char *filename; const char *filename;
struct dirent *dirent; struct stat st;
DIR *dir;
int linenum; int linenum;
if (op != KEY_OP_ASSIGN) { if (op != KEY_OP_ASSIGN) {
Perror(space, "invalid INCLUDE operation"); Perror(space, "invalid INCLUDE operation");
@ -1498,18 +1504,27 @@ static int parse_line(struct space *space, char *line, size_t linesize)
go_to = space->go_to; go_to = space->go_to;
filename = space->filename; filename = space->filename;
linenum = space->linenum; linenum = space->linenum;
dir = opendir(string); if (stat(string, &st)) {
if (dir) { Perror(space, "invalid filename '%s'", string);
count = strlen(string);
while ((dirent = readdir(dir)) != NULL) {
if (strcmp(dirent->d_name, ".") == 0 ||
strcmp(dirent->d_name, "..") == 0)
continue; continue;
}
if (S_ISDIR(st.st_mode)) {
struct dirent **list;
int i, num;
num = scandir(string, &list, conf_name_filter,
alphasort);
if (num < 0) {
Perror(space, "invalid directory '%s'", string);
continue;
}
count = strlen(string);
for (i = 0; i < num; i++) {
string[count] = '\0'; string[count] = '\0';
strlcat(string, "/", sizeof(string)); strlcat(string, "/", sizeof(string));
strlcat(string, dirent->d_name, sizeof(string)); strlcat(string, list[i]->d_name, sizeof(string));
space->go_to = NULL; space->go_to = NULL;
space->rootdir = new_root_dir(string); space->rootdir = new_root_dir(string);
free(list[i]);
if (space->rootdir) { if (space->rootdir) {
err = parse(space, string); err = parse(space, string);
free(space->rootdir); free(space->rootdir);
@ -1522,7 +1537,7 @@ static int parse_line(struct space *space, char *line, size_t linesize)
if (err) if (err)
break; break;
} }
closedir(dir); free(list);
} else { } else {
space->go_to = NULL; space->go_to = NULL;
space->rootdir = new_root_dir(string); space->rootdir = new_root_dir(string);