From 86fc7959d2d0c64a836307c86de7035e1c8f7bd4 Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Wed, 17 Jan 2001 12:14:32 +0000 Subject: [PATCH] Moved up one level --- src/conf/conf.c | 1102 ----------------------------------------------- 1 file changed, 1102 deletions(-) delete mode 100644 src/conf/conf.c diff --git a/src/conf/conf.c b/src/conf/conf.c deleted file mode 100644 index f6ad8a9b..00000000 --- a/src/conf/conf.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * Configuration helper functions - * Copyright (c) 2000 by Abramo Bagnara - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include "asoundlib.h" -#include "local.h" -#include "list.h" - -#define SYS_ASOUNDRC "/etc/asound.conf" -#define USR_ASOUNDRC ".asoundrc" - -struct filedesc { - char *name; - FILE *fp; - unsigned int line, column; - struct filedesc *next; -}; - -typedef struct { - struct filedesc *current; - int unget; - int ch; - enum { - UNTERMINATED_STRING = -1, - UNTERMINATED_QUOTE = -2, - UNEXPECTED_CHAR = -3, - UNEXPECTED_EOF = -4, - } error; -} input_t; - -static int get_char(input_t *input) -{ - int c; - struct filedesc *fd; - if (input->unget) { - input->unget = 0; - return input->ch; - } - again: - fd = input->current; - c = getc(fd->fp); - switch (c) { - case '\n': - fd->column = 0; - fd->line++; - break; - case '\t': - fd->column += 8 - fd->column % 8; - break; - case EOF: - if (fd->next) { - fclose(fd->fp); - free(fd->name); - input->current = fd->next; - free(fd); - goto again; - } - break; - default: - fd->column++; - break; - } - return c; -} - -static void unget_char(int c, input_t *input) -{ - assert(!input->unget); - input->ch = c; - input->unget = 1; -} - -static int get_delimstring(char **string, int delim, input_t *input); - -static int get_char_skip_comments(input_t *input) -{ - int c; - while (1) { - c = get_char(input); - if (c == '<') { - char *file; - FILE *fp; - struct filedesc *fd; - int err = get_delimstring(&file, '>', input); - if (err < 0) - return err; - fp = fopen(file, "r"); - if (!fp) { - SYSERR("fopen %s", file); - return -errno; - } - fd = malloc(sizeof(*fd)); - fd->name = file; - fd->fp = fp; - fd->next = input->current; - fd->line = 1; - fd->column = 0; - input->current = fd; - continue; - } - if (c != '#') - break; - while (1) { - c = get_char(input); - if (c == EOF) - return c; - if (c == '\n') - break; - } - } - - return c; -} - - -static int get_nonwhite(input_t *input) -{ - int c; - while (1) { - c = get_char_skip_comments(input); - switch (c) { - case ' ': - case '\f': - case '\t': - case '\n': - case '\r': - break; - default: - return c; - } - } -} - -static int get_quotedchar(input_t *input) -{ - int c; - c = get_char(input); - switch (c) { - case 'n': - return '\n'; - case 't': - return '\t'; - case 'v': - return '\v'; - case 'b': - return '\b'; - case 'r': - return '\r'; - case 'f': - return '\f'; - case '0' ... '7': - { - int num = c - '0'; - int i = 1; - do { - c = get_char(input); - if (c < '0' || c > '7') { - unget_char(c, input); - break; - } - num = num * 8 + c - '0'; - i++; - } while (i < 3); - return num; - } - default: - return c; - } -} - -static int get_freestring(char **string, int id, input_t *input) -{ - const size_t bufsize = 256; - char _buf[bufsize]; - char *buf = _buf; - size_t alloc = bufsize; - size_t idx = 0; - int c; - while (1) { - c = get_char(input); - switch (c) { - case '.': - if (!id) - break; - case ' ': - case '\f': - case '\t': - case '\n': - case '\r': - case EOF: - case '=': - case '{': - case '}': - case ',': - case ';': - case '\'': - case '"': - case '\\': - case '#': - { - char *s = malloc(idx + 1); - unget_char(c, input); - memcpy(s, buf, idx); - s[idx] = '\0'; - *string = s; - return 0; - } - default: - break; - } - if (idx >= alloc) { - size_t old_alloc = alloc; - alloc += bufsize; - if (old_alloc == bufsize) { - buf = malloc(alloc); - memcpy(buf, _buf, old_alloc); - } else - buf = realloc(buf, alloc); - } - buf[idx++] = c; - } - return 0; -} - -static int get_delimstring(char **string, int delim, input_t *input) -{ - const size_t bufsize = 256; - char _buf[bufsize]; - char *buf = _buf; - size_t alloc = bufsize; - size_t idx = 0; - int c; - while (1) { - c = get_char(input); - switch (c) { - case EOF: - input->error = UNTERMINATED_STRING; - return -EINVAL; - case '\\': - c = get_quotedchar(input); - if (c < 0) { - input->error = UNTERMINATED_QUOTE; - return -EINVAL; - } - break; - default: - if (c == delim) { - char *s = malloc(idx + 1); - memcpy(s, buf, idx); - s[idx] = '\0'; - *string = s; - return 0; - } - } - if (idx >= alloc) { - size_t old_alloc = alloc; - alloc += bufsize; - if (old_alloc == bufsize) { - buf = malloc(alloc); - memcpy(buf, _buf, old_alloc); - } else - buf = realloc(buf, alloc); - } - buf[idx++] = c; - } - return 0; -} - -/* Return 0 for free string, 1 for delimited string */ -static int get_string(char **string, int id, input_t *input) -{ - int c = get_nonwhite(input); - int err; - switch (c) { - case EOF: - input->error = UNEXPECTED_EOF; - return -EINVAL; - case '=': -#if 0 - /* I'm not sure to want unnamed fields */ - *string = 0; - return 0; -#endif - case '.': - case '{': - case '}': - case ',': - case ';': - input->error = UNEXPECTED_CHAR; - return -EINVAL; - case '\'': - case '"': - err = get_delimstring(string, c, input); - if (err < 0) - return err; - return 1; - default: - unget_char(c, input); - err = get_freestring(string, id, input); - if (err < 0) - return err; - return 0; - } -} - -static int _snd_config_make(snd_config_t **config, char *id, - snd_config_type_t type) -{ - snd_config_t *n; - n = calloc(1, sizeof(*n)); - if (n == NULL) { - if (id) - free(id); - return -ENOMEM; - } - n->id = id; - n->type = type; - if (type == SND_CONFIG_TYPE_COMPOUND) - INIT_LIST_HEAD(&n->u.compound.fields); - *config = n; - return 0; -} - - -static int _snd_config_make_add(snd_config_t **config, char *id, - snd_config_type_t type, snd_config_t *father) -{ - snd_config_t *n; - int err; - assert(father->type == SND_CONFIG_TYPE_COMPOUND); - err = _snd_config_make(&n, id, type); - if (err < 0) - return err; - n->father = father; - list_add_tail(&n->list, &father->u.compound.fields); - *config = n; - return 0; -} - -static int _snd_config_search(snd_config_t *config, char *id, int len, snd_config_t **result) -{ - snd_config_iterator_t i; - snd_config_foreach(i, config) { - snd_config_t *n = snd_config_entry(i); - if (len < 0) { - if (strcmp(n->id, id) == 0) { - *result = n; - return 0; - } - } else { - if (strlen(n->id) != (size_t) len) - continue; - if (memcmp(n->id, id, len) == 0) { - *result = n; - return 0; - } - } - } - return -ENOENT; -} - -static int parse_defs(snd_config_t *father, input_t *input); - -static int parse_def(snd_config_t *father, input_t *input) -{ - char *id; - int c; - int err; - snd_config_t *n; - enum {MERGE, NOCREATE, REMOVE} mode; - while (1) { -#if 0 - c = get_nonwhite(input); - switch (c) { - case '?': - mode = NOCREATE; - break; - case '!': - mode = REMOVE; - break; - default: - mode = MERGE; - unget_char(c, input); - } -#else - mode = MERGE; -#endif - err = get_string(&id, 1, input); - if (err < 0) - return err; - c = get_nonwhite(input); - if (c != '.') - break; - if (_snd_config_search(father, id, -1, &n) == 0) { - if (mode != REMOVE) { - if (n->type != SND_CONFIG_TYPE_COMPOUND) { - ERR("%s is not a compound", id); - return -EINVAL; - } - n->u.compound.join = 1; - father = n; - free(id); - continue; - } - snd_config_delete(n); - } - if (mode == NOCREATE) { - ERR("%s does not exists", id); - free(id); - return -ENOENT; - } - err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_COMPOUND, father); - if (err < 0) - return err; - n->u.compound.join = 1; - father = n; - } - if (c == '=' ) - c = get_nonwhite(input); - if (_snd_config_search(father, id, -1, &n) == 0) { - if (mode == REMOVE) { - snd_config_delete(n); - n = NULL; - } - else - free(id); - } else { - n = NULL; - if (mode == NOCREATE) { - ERR("%s does not exists", id); - free(id); - return -ENOENT; - } - } - switch (c) { - case '{': - { - if (n) { - if (n->type != SND_CONFIG_TYPE_COMPOUND) { - ERR("%s is not a compound", id); - return -EINVAL; - } - } else { - err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_COMPOUND, father); - if (err < 0) - return err; - } - err = parse_defs(n, input); - if (err < 0) { - snd_config_delete(n); - return err; - } - c = get_nonwhite(input); - if (c != '}') { - snd_config_delete(n); - input->error = (c == EOF ? UNEXPECTED_EOF : UNEXPECTED_CHAR); - return -EINVAL; - } - break; - } - default: - { - char *s; - unget_char(c, input); - err = get_string(&s, 0, input); - if (err < 0) - return err; - if (!err && ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')) { - char *ptr; - long i; - errno = 0; - i = strtol(s, &ptr, 0); - if (*ptr == '.' || errno != 0) { - double r; - errno = 0; - r = strtod(s, &ptr); - if (errno == 0) { - free(s); - if (n) { - if (n->type != SND_CONFIG_TYPE_REAL) { - ERR("%s is not a real", id); - return -EINVAL; - } - } else { - err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_REAL, father); - if (err < 0) - return err; - } - n->u.real = r; - break; - } - } else if (*ptr == '\0') { - free(s); - if (n) { - if (n->type != SND_CONFIG_TYPE_INTEGER) { - ERR("%s is not an integer", id); - return -EINVAL; - } - } else { - err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER, father); - if (err < 0) - return err; - } - n->u.integer = i; - break; - } - } - if (n) { - if (n->type != SND_CONFIG_TYPE_STRING) { - ERR("%s is not a string", id); - free(s); - return -EINVAL; - } - } else { - err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_STRING, father); - if (err < 0) - return err; - } - if (n->u.string) - free(n->u.string); - n->u.string = s; - } - } - c = get_nonwhite(input); - switch (c) { - case ';': - case ',': - break; - default: - unget_char(c, input); - } - return err; -} - -static int parse_defs(snd_config_t *father, input_t *input) -{ - while (1) { - int c = get_nonwhite(input); - int err; - if (c == EOF) - return 0; - unget_char(c, input); - if (c == '}') - return 0; - err = parse_def(father, input); - if (err < 0) - return err; - } - return 0; -} - -int snd_config_top(snd_config_t **config) -{ - assert(config); - return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND); -} - -int snd_config_load(snd_config_t *config, FILE *fp) -{ - int err; - input_t input; - struct filedesc *fd; - assert(config && fp); - fd = malloc(sizeof(*fd)); - fd->name = NULL; - fd->fp = fp; - fd->line = 1; - fd->column = 0; - fd->next = NULL; - input.current = fd; - input.unget = 0; - input.error = 0; - err = parse_defs(config, &input); - fd = input.current; - if (err < 0) { - if (input.error < 0) { - char *str; - switch (input.error) { - case UNTERMINATED_STRING: - str = "Unterminated string"; - break; - case UNTERMINATED_QUOTE: - str = "Unterminated quote"; - break; - case UNEXPECTED_CHAR: - str = "Unexpected char"; - break; - case UNEXPECTED_EOF: - str = "Unexpected end of file"; - break; - default: - assert(0); - break; - } - ERR("%s:%d:%d:%s", fd->name ? fd->name : "", - fd->line, fd->column, str); - } - snd_config_delete(config); - goto _end; - } - if (get_char(&input) != EOF) { - ERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", - fd->line, fd->column); - snd_config_delete(config); - err = -EINVAL; - goto _end; - } - _end: - while (fd->next) { - fclose(fd->fp); - free(fd->name); - free(fd); - fd = fd->next; - } - free(fd); - return err; -} - -int snd_config_add(snd_config_t *father, snd_config_t *leaf) -{ - snd_config_iterator_t i; - assert(father && leaf); - snd_config_foreach(i, father) { - snd_config_t *n = snd_config_entry(i); - if (strcmp(leaf->id, n->id) == 0) - return -EEXIST; - } - leaf->father = father; - list_add_tail(&leaf->list, &father->u.compound.fields); - return 0; -} - -int snd_config_delete(snd_config_t *config) -{ - assert(config); - switch (config->type) { - case SND_CONFIG_TYPE_COMPOUND: - { - int err; - struct list_head *i; - i = config->u.compound.fields.next; - while (i != &config->u.compound.fields) { - struct list_head *nexti = i->next; - snd_config_t *leaf = snd_config_entry(i); - err = snd_config_delete(leaf); - if (err < 0) - return err; - i = nexti; - } - break; - } - case SND_CONFIG_TYPE_STRING: - if (config->u.string) - free(config->u.string); - break; - default: - break; - } - if (config->father) - list_del(&config->list); - return 0; -} - -int snd_config_make(snd_config_t **config, char *id, - snd_config_type_t type) -{ - char *id1; - assert(config); - if (id) { - id1 = strdup(id); - if (!id1) - return -ENOMEM; - } else - id1 = NULL; - return _snd_config_make(config, id1, type); -} - -int snd_config_integer_make(snd_config_t **config, char *id) -{ - return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER); -} - -int snd_config_real_make(snd_config_t **config, char *id) -{ - return snd_config_make(config, id, SND_CONFIG_TYPE_REAL); -} - -int snd_config_string_make(snd_config_t **config, char *id) -{ - return snd_config_make(config, id, SND_CONFIG_TYPE_STRING); -} - -int snd_config_compound_make(snd_config_t **config, char *id, - int join) -{ - int err; - err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND); - if (err < 0) - return err; - (*config)->u.compound.join = join; - return 0; -} - -int snd_config_integer_set(snd_config_t *config, long value) -{ - assert(config); - if (config->type != SND_CONFIG_TYPE_INTEGER) - return -EINVAL; - config->u.integer = value; - return 0; -} - -int snd_config_real_set(snd_config_t *config, double value) -{ - assert(config); - if (config->type != SND_CONFIG_TYPE_REAL) - return -EINVAL; - config->u.real = value; - return 0; -} - -int snd_config_string_set(snd_config_t *config, char *value) -{ - assert(config); - if (config->type != SND_CONFIG_TYPE_STRING) - return -EINVAL; - if (config->u.string) - free(config->u.string); - config->u.string = strdup(value); - if (!config->u.string) - return -ENOMEM; - return 0; -} - -int snd_config_set(snd_config_t *config, ...) -{ - va_list arg; - va_start(arg, config); - assert(config); - switch (config->type) { - case SND_CONFIG_TYPE_INTEGER: - config->u.integer = va_arg(arg, long); - break; - case SND_CONFIG_TYPE_REAL: - config->u.real = va_arg(arg, double); - break; - case SND_CONFIG_TYPE_STRING: - config->u.string = va_arg(arg, char *); - break; - default: - assert(0); - return -EINVAL; - } - va_end(arg); - return 0; -} - -int snd_config_integer_get(snd_config_t *config, long *ptr) -{ - assert(config && ptr); - if (config->type != SND_CONFIG_TYPE_INTEGER) - return -EINVAL; - *ptr = config->u.integer; - return 0; -} - -int snd_config_real_get(snd_config_t *config, double *ptr) -{ - assert(config && ptr); - if (config->type != SND_CONFIG_TYPE_REAL) - return -EINVAL; - *ptr = config->u.real; - return 0; -} - -int snd_config_string_get(snd_config_t *config, char **ptr) -{ - assert(config && ptr); - if (config->type != SND_CONFIG_TYPE_STRING) - return -EINVAL; - *ptr = config->u.string; - return 0; -} - -int snd_config_get(snd_config_t *config, void *ptr) -{ - assert(config && ptr); - switch (config->type) { - case SND_CONFIG_TYPE_INTEGER: - * (long*) ptr = config->u.integer; - break; - case SND_CONFIG_TYPE_REAL: - * (double*) ptr = config->u.real; - break; - case SND_CONFIG_TYPE_STRING: - * (char **) ptr = config->u.string; - break; - default: - assert(0); - return -EINVAL; - } - return 0; -} - -void string_print(char *str, int id, FILE *fp) -{ - unsigned char *p = str; - if (!id) { - switch (*p) { - case '0' ... '9': - case '-': - goto quoted; - } - } - loop: - switch (*p) { - case 0: - goto nonquoted; - case 1 ... 31: - case 127 ... 255: - case ' ': - case '=': - case '.': - case '{': - case '}': - case ';': - case ',': - case '\'': - case '"': - goto quoted; - default: - p++; - goto loop; - } - nonquoted: - fputs(str, fp); - return; - quoted: - putc('\'', fp); - p = str; - while (*p) { - int c; - c = *p; - switch (c) { - case '\n': - putc('\\', fp); - putc('n', fp); - break; - case '\t': - putc('\\', fp); - putc('t', fp); - break; - case '\v': - putc('\\', fp); - putc('v', fp); - break; - case '\b': - putc('\\', fp); - putc('b', fp); - break; - case '\r': - putc('\\', fp); - putc('r', fp); - break; - case '\f': - putc('\\', fp); - putc('f', fp); - break; - case '\'': - putc('\\', fp); - putc(c, fp); - break; - case 32 ... '\'' - 1: - case '\'' + 1 ... 126: - putc(c, fp); - break; - default: - fprintf(fp, "\\%04o", c); - break; - } - p++; - } - putc('\'', fp); -} - -static int _snd_config_save_leaves(snd_config_t *config, FILE *fp, unsigned int level, unsigned int joins); - -static int _snd_config_save_leaf(snd_config_t *n, FILE *fp, - unsigned int level) -{ - int err; - unsigned int k; - switch (n->type) { - case SND_CONFIG_TYPE_INTEGER: - fprintf(fp, "%ld", n->u.integer); - break; - case SND_CONFIG_TYPE_REAL: - fprintf(fp, "%16g", n->u.real); - break; - case SND_CONFIG_TYPE_STRING: - string_print(n->u.string, 0, fp); - break; - case SND_CONFIG_TYPE_COMPOUND: - putc('{', fp); - putc('\n', fp); - err = _snd_config_save_leaves(n, fp, level + 1, 0); - if (err < 0) - return err; - for (k = 0; k < level; ++k) { - putc('\t', fp); - } - putc('}', fp); - break; - } - return 0; -} - -static void id_print(snd_config_t *n, FILE *fp, unsigned int joins) -{ - if (joins > 0) { - assert(n->father); - id_print(n->father, fp, joins - 1); - putc('.', fp); - } - string_print(n->id, 1, fp); -} - -static int _snd_config_save_leaves(snd_config_t *config, FILE *fp, unsigned int level, unsigned int joins) -{ - unsigned int k; - int err; - snd_config_iterator_t i; - assert(config && fp); - snd_config_foreach(i, config) { - snd_config_t *n = snd_config_entry(i); - if (n->type == SND_CONFIG_TYPE_COMPOUND && - n->u.compound.join) { - err = _snd_config_save_leaves(n, fp, level, joins + 1); - if (err < 0) - return err; - continue; - } - for (k = 0; k < level; ++k) { - putc('\t', fp); - } - id_print(n, fp, joins); - putc(' ', fp); - putc('=', fp); - putc(' ', fp); - err = _snd_config_save_leaf(n, fp, level); - if (err < 0) - return err; - putc(';', fp); - putc('\n', fp); - } - return 0; -} - -int snd_config_save(snd_config_t *config, FILE *fp) -{ - assert(config && fp); - return _snd_config_save_leaves(config, fp, 0, 0); -} - -int snd_config_search(snd_config_t *config, char *key, snd_config_t **result) -{ - assert(config && key && result); - while (1) { - snd_config_t *n; - int err; - char *p = strchr(key, '.'); - if (config->type != SND_CONFIG_TYPE_COMPOUND) - return -ENOENT; - if (p) { - err = _snd_config_search(config, key, p - key, &n); - if (err < 0) - return err; - config = n; - key = p + 1; - } else - return _snd_config_search(config, key, -1, result); - } -} - -int snd_config_searchv(snd_config_t *config, - snd_config_t **result, ...) -{ - snd_config_t *n; - va_list arg; - assert(config && result); - va_start(arg, result); - while (1) { - char *k = va_arg(arg, char *); - int err; - if (!k) - break; - if (config->type != SND_CONFIG_TYPE_COMPOUND) - return -ENOENT; - err = _snd_config_search(config, k, -1, &n); - if (err < 0) - return err; - config = n; - } - va_end(arg); - *result = n; - return 0; -} - -snd_config_t *snd_config = 0; -static dev_t sys_asoundrc_device; -static ino_t sys_asoundrc_inode; -static time_t sys_asoundrc_mtime; -static dev_t usr_asoundrc_device; -static ino_t usr_asoundrc_inode; -static time_t usr_asoundrc_mtime; - -int snd_config_update() -{ - int err; - char *usr_asoundrc = NULL; - char *home = getenv("HOME"); - struct stat usr_st, sys_st; - int reload; - FILE *fp; - if (home) { - size_t len = strlen(home); - size_t len1 = strlen(USR_ASOUNDRC); - usr_asoundrc = alloca(len + len1 + 2); - memcpy(usr_asoundrc, home, len); - usr_asoundrc[len] = '/'; - memcpy(usr_asoundrc + len + 1, USR_ASOUNDRC, len1); - usr_asoundrc[len + 1 + len1] = '\0'; - } - reload = (snd_config == NULL); - if (stat(SYS_ASOUNDRC, &sys_st) == 0 && - (sys_st.st_dev != sys_asoundrc_device || - sys_st.st_ino != sys_asoundrc_inode || - sys_st.st_mtime != sys_asoundrc_mtime)) - reload = 1; - if (stat(usr_asoundrc, &usr_st) == 0 && - (usr_st.st_dev != usr_asoundrc_device || - usr_st.st_ino != usr_asoundrc_inode || - usr_st.st_mtime != usr_asoundrc_mtime)) - reload = 1; - if (!reload) - return 0; - if (snd_config) { - err = snd_config_delete(snd_config); - if (err < 0) - return err; - snd_config = 0; - } - err = snd_config_top(&snd_config); - if (err < 0) - return err; - fp = fopen(SYS_ASOUNDRC, "r"); - if (fp) { - err = snd_config_load(snd_config, fp); - fclose(fp); - if (err < 0) { - snd_config = NULL; - return err; - } - sys_asoundrc_device = sys_st.st_dev; - sys_asoundrc_inode = sys_st.st_ino; - sys_asoundrc_mtime = sys_st.st_mtime; - } - fp = fopen(usr_asoundrc, "r"); - if (fp) { - err = snd_config_load(snd_config, fp); - fclose(fp); - if (err < 0) { - snd_config = NULL; - return err; - } - usr_asoundrc_device = usr_st.st_dev; - usr_asoundrc_inode = usr_st.st_ino; - usr_asoundrc_mtime = usr_st.st_mtime; - } - return 0; -} -- 2.47.3