1/** 2 * \file conf.c 3 * \ingroup Configuration 4 * \brief Configuration helper functions 5 * \author Abramo Bagnara <abramo@alsa-project.org> 6 * \author Jaroslav Kysela <perex@perex.cz> 7 * \date 2000-2001 8 * 9 * Tree based, full nesting configuration functions. 10 * 11 * See the \ref conf page for more details. 12 */ 13/* 14 * Configuration helper functions 15 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>, 16 * Jaroslav Kysela <perex@perex.cz> 17 * 18 * 19 * This library is free software; you can redistribute it and/or modify 20 * it under the terms of the GNU Lesser General Public License as 21 * published by the Free Software Foundation; either version 2.1 of 22 * the License, or (at your option) any later version. 23 * 24 * This program is distributed in the hope that it will be useful, 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * GNU Lesser General Public License for more details. 28 * 29 * You should have received a copy of the GNU Lesser General Public 30 * License along with this library; if not, write to the Free Software 31 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 32 * 33 */ 34 35/*! \page conf Configuration files 36 37<P>Configuration files use a simple format allowing modern 38data description like nesting and array assignments.</P> 39 40\section conf_whitespace Whitespace 41 42Whitespace is the collective name given to spaces (blanks), horizontal and 43vertical tabs, newline characters, and comments. Whitespace can 44indicate where configuration tokens start and end, but beyond this function, 45any surplus whitespace is discarded. For example, the two sequences 46 47\code 48 a 1 b 2 49\endcode 50 51and 52 53\code 54 a 1 55 b 2 56\endcode 57 58are lexically equivalent and parse identically to give the four tokens: 59 60\code 61a 621 63b 642 65\endcode 66 67The ASCII characters representing whitespace can occur within literal 68strings, in which case they are protected from the normal parsing process 69(they remain as part of the string). For example: 70 71\code 72 name "John Smith" 73\endcode 74 75parses to two tokens, including the single literal-string token "John 76Smith". 77 78\section conf_linesplicing Line continuation with \ 79 80A special case occurs if a newline character in a string is preceded 81by a backslash (\). The backslash and the new line are both discarded, 82allowing two physical lines of text to be treated as one unit. 83 84\code 85"John \ 86Smith" 87\endcode 88 89is parsed as "John Smith". 90 91\section conf_comments Comments 92 93A single-line comment begins with the character #. The comment can start 94at any position, and extends to the end of the line. 95 96\code 97 a 1 # this is a comment 98\endcode 99 100\section conf_include Including configuration files 101 102To include another configuration file, write the file name in angle brackets. 103The prefix \c confdir: will reference the global configuration directory. 104 105\code 106</etc/alsa1.conf> 107<confdir:pcm/surround.conf> 108\endcode 109 110\section conf_punctuators Punctuators 111 112The configuration punctuators (also known as separators) are: 113 114\code 115 {} [] , ; = . ' " new-line form-feed carriage-return whitespace 116\endcode 117 118\subsection conf_braces Braces 119 120Opening and closing braces { } indicate the start and end of a compound 121statement: 122 123\code 124a { 125 b 1 126} 127\endcode 128 129\subsection conf_brackets Brackets 130 131Opening and closing brackets indicate a single array definition. The 132identifiers are automatically generated starting with zero. 133 134\code 135a [ 136 "first" 137 "second" 138] 139\endcode 140 141The above code is equal to 142 143\code 144a.0 "first" 145a.1 "second" 146\endcode 147 148\subsection conf_comma_semicolon Comma and semicolon 149 150The comma (,) or semicolon (;) can separate value assignments. It is not 151strictly required to use these separators because whitespace suffices to 152separate tokens. 153 154\code 155a 1; 156b 1, 157\endcode 158 159\subsection conf_equal Equal sign 160 161The equal sign (=) can separate variable declarations from 162initialization lists: 163 164\code 165a=1 166b=2 167\endcode 168 169Using equal signs is not required because whitespace suffices to separate 170tokens. 171 172\section conf_assigns Assignments 173 174The configuration file defines id (key) and value pairs. The id (key) can be 175composed from ASCII digits, characters from a to z and A to Z, and the 176underscore (_). The value can be either a string, an integer, a real number, 177or a compound statement. 178 179\subsection conf_single Single assignments 180 181\code 182a 1 # is equal to 183a=1 # is equal to 184a=1; # is equal to 185a 1, 186\endcode 187 188\subsection conf_compound Compound assignments (definitions using braces) 189 190\code 191a { 192 b = 1 193} 194a={ 195 b 1, 196} 197\endcode 198 199\section conf_compound1 Compound assignments (one key definitions) 200 201\code 202a.b 1 203a.b=1 204\endcode 205 206\subsection conf_array Array assignments (definitions using brackets) 207 208\code 209a [ 210 "first" 211 "second" 212] 213\endcode 214 215\subsection conf_array1 Array assignments (one key definitions) 216 217\code 218a.0 "first" 219a.1 "second" 220\endcode 221 222\section conf_mode Operation modes for parsing nodes 223 224By default, the node operation mode is 'merge+create', i.e., if 225a configuration node is not present a new one is created, otherwise 226the latest assignment is merged (if possible - type checking). The 227'merge+create' operation mode is specified with the prefix character plus (+). 228 229The operation mode 'merge' merges the node with the old one (which must 230exist). Type checking is done, so strings cannot be assigned to integers 231and so on. This mode is specified with the prefix character minus (-). 232 233The operation mode 'do not override' ignores a new configuration node 234if a configuration node with the same name exists. This mode is specified with 235the prefix character question mark (?). 236 237The operation mode 'override' always overrides the old configuration node 238with new contents. This mode is specified with the prefix character 239exclamation mark (!). 240 241\code 242defaults.pcm.!device 1 243\endcode 244 245\section conf_syntax_summary Syntax summary 246 247\code 248# Configuration file syntax 249 250# Include a new configuration file 251<filename> 252 253# Simple assignment 254name [=] value [,|;] 255 256# Compound assignment (first style) 257name [=] { 258 name1 [=] value [,|;] 259 ... 260} 261 262# Compound assignment (second style) 263name.name1 [=] value [,|;] 264 265# Array assignment (first style) 266name [ 267 value0 [,|;] 268 value1 [,|;] 269 ... 270] 271 272# Array assignment (second style) 273name.0 [=] value0 [,|;] 274name.1 [=] value1 [,|;] 275\endcode 276 277\section conf_syntax_ref References 278 279\ref confarg 280\ref conffunc 281\ref confhooks 282 283*/ 284 285/*! \page confarg Runtime arguments in configuration files 286 287<P>The ALSA library can accept runtime arguments for some configuration 288blocks. This extension is built on top of the basic configuration file 289syntax.<P> 290 291\section confarg_define Defining arguments 292 293Arguments are defined using the id (key) \c \@args and array values containing 294the string names of the arguments: 295 296\code 297@args [ CARD ] # or 298@args.0 CARD 299\endcode 300 301\section confarg_type Defining argument types and default values 302 303An argument's type is specified with the id (key) \c \@args and the argument 304name. The type and the default value are specified in the compound block: 305 306\code 307@args.CARD { 308 type string 309 default "abcd" 310} 311\endcode 312 313\section confarg_refer Referring to arguments 314 315Arguments are referred to with a dollar-sign ($) and the name of the argument: 316 317\code 318 card $CARD 319\endcode 320 321\section confarg_math simple math expressions 322 323The simple math expressions are identified using a unix shell like expression syntax 324with a dollar-sign ($) and bracket ([): 325 326\code 327 card "$[$CARD + 1]" 328\endcode 329 330\section confarg_usage Usage 331 332To use a block with arguments, write the argument values after the key, 333separated with a colon (:). For example, all these names for PCM interfaces 334give the same result: 335 336\code 337hw:0,1 338hw:CARD=0,DEV=1 339hw:{CARD 0 DEV 1} 340plug:"hw:0,1" 341plug:{SLAVE="hw:{CARD 0 DEV 1}"} 342\endcode 343 344As you see, arguments can be specified in their proper order or by name. 345Note that arguments enclosed in braces are parsed in the same way as in 346configuration files, but using the override method by default. 347 348\section confarg_example Example 349 350\code 351pcm.demo { 352 @args [ CARD DEVICE ] 353 @args.CARD { 354 type string 355 default "supersonic" 356 } 357 @args.DEVICE { 358 type integer 359 default 0 360 } 361 type hw 362 card $CARD 363 device $DEVICE 364} 365\endcode 366 367 368*/ 369 370/*! \page conffunc Runtime functions in configuration files 371 372<P>The ALSA library can modify the configuration at runtime. 373Several built-in functions are available.</P> 374 375<P>A function is defined with the id \c \@func and the function name. All other 376values in the current compound are used as configuration for the function. 377If the compound func.\<function_name\> is defined in the root node, then the 378library and function from this compound configuration are used, otherwise 379'snd_func_' is prefixed to the string and code from the ALSA library is used. 380The definition of a function looks like:</P> 381 382\code 383func.remove_first_char { 384 lib "/usr/lib/libasoundextend.so" 385 func "extend_remove_first_char" 386} 387\endcode 388 389*/ 390 391/*! \page confhooks Hooks in configuration files 392 393<P>The hook extension in the ALSA library allows expansion of configuration 394nodes at run-time. The existence of a hook is determined by the 395presence of a \@hooks compound node.</P> 396 397<P>This example defines a hook which loads two configuration files at the 398beginning:</P> 399 400\code 401@hooks [ 402 { 403 func load 404 files [ 405 "/etc/asound.conf" 406 "~/.asoundrc" 407 ] 408 errors false 409 } 410] 411\endcode 412 413\section confhooks_ref Function reference 414 415<UL> 416 <LI>The function load - \c snd_config_hook_load() - loads and parses the 417 given configuration files. 418 <LI>The function load_for_all_cards - \c snd_config_hook_load_for_all_cards() - 419 loads and parses the given configuration files for each installed sound 420 card. The driver name (the type of the sound card) is passed in the 421 private configuration node. 422</UL> 423 424*/ 425 426 427#include "local.h" 428#include <stdarg.h> 429#include <stdbool.h> 430#include <limits.h> 431#include <sys/stat.h> 432#include <dirent.h> 433#include <locale.h> 434#ifdef HAVE_LIBPTHREAD 435#include <pthread.h> 436#endif 437 438#ifndef DOC_HIDDEN 439 440#ifdef HAVE_LIBPTHREAD 441static pthread_mutex_t snd_config_update_mutex; 442static pthread_once_t snd_config_update_mutex_once = PTHREAD_ONCE_INIT; 443#endif 444 445struct _snd_config { 446 char *id; 447 snd_config_type_t type; 448 int refcount; /* default = 0 */ 449 union { 450 long integer; 451 long long integer64; 452 char *string; 453 double real; 454 const void *ptr; 455 struct { 456 struct list_head fields; 457 bool join; 458 } compound; 459 } u; 460 struct list_head list; 461 snd_config_t *parent; 462 int hop; 463}; 464 465struct filedesc { 466 char *name; 467 snd_input_t *in; 468 unsigned int line, column; 469 struct filedesc *next; 470 471 /* list of the include paths (configuration directories), 472 * defined by <searchdir:relative-path/to/top-alsa-conf-dir>, 473 * for searching its included files. 474 */ 475 struct list_head include_paths; 476}; 477 478/* path to search included files */ 479struct include_path { 480 char *dir; 481 struct list_head list; 482}; 483 484#define LOCAL_ERROR (-0x68000000) 485 486#define LOCAL_UNTERMINATED_STRING (LOCAL_ERROR - 0) 487#define LOCAL_UNTERMINATED_QUOTE (LOCAL_ERROR - 1) 488#define LOCAL_UNEXPECTED_CHAR (LOCAL_ERROR - 2) 489#define LOCAL_UNEXPECTED_EOF (LOCAL_ERROR - 3) 490 491typedef struct { 492 struct filedesc *current; 493 int unget; 494 int ch; 495} input_t; 496 497#ifdef HAVE_LIBPTHREAD 498 499static void snd_config_init_mutex(void) 500{ 501 pthread_mutexattr_t attr; 502 503 pthread_mutexattr_init(&attr); 504#ifdef HAVE_PTHREAD_MUTEX_RECURSIVE 505 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 506#endif 507 pthread_mutex_init(&snd_config_update_mutex, &attr); 508 pthread_mutexattr_destroy(&attr); 509} 510 511static inline void snd_config_lock(void) 512{ 513 pthread_once(&snd_config_update_mutex_once, snd_config_init_mutex); 514 pthread_mutex_lock(&snd_config_update_mutex); 515} 516 517static inline void snd_config_unlock(void) 518{ 519 pthread_mutex_unlock(&snd_config_update_mutex); 520} 521 522#else 523 524static inline void snd_config_lock(void) { } 525static inline void snd_config_unlock(void) { } 526 527#endif 528 529/* 530 * Add a directory to the paths to search included files. 531 * param fd - File object that owns these paths to search files included by it. 532 * param dir - Path of the directory to add. Allocated externally and need to 533* be freed manually later. 534 * return - Zero if successful, otherwise a negative error code. 535 * 536 * The direcotry should be a subdiretory of top configuration directory 537 * "/usr/share/alsa/". 538 */ 539static int add_include_path(struct filedesc *fd, const char *dir) 540{ 541 struct include_path *path; 542 struct filedesc *fd1; 543 struct list_head *pos; 544 545 /* check, if dir is already registered (also in parents) */ 546 for (fd1 = fd; fd1; fd1 = fd1->next) { 547 list_for_each(pos, &fd1->include_paths) { 548 path = list_entry(pos, struct include_path, list); 549 if (strcmp(path->dir, dir) == 0) 550 return 0; 551 } 552 } 553 554 path = calloc(1, sizeof(*path)); 555 if (!path) 556 return -ENOMEM; 557 558 path->dir = strdup(dir); 559 if (path->dir == NULL) { 560 free(path); 561 return -ENOMEM; 562 } 563 564 list_add_tail(&path->list, &fd->include_paths); 565 return 0; 566} 567 568/* 569 * Free all include paths of a file descriptor. 570 * param fd - File object that owns these paths to search files included by it. 571 */ 572static void free_include_paths(struct filedesc *fd) 573{ 574 struct list_head *pos, *npos, *base; 575 struct include_path *path; 576 577 base = &fd->include_paths; 578 list_for_each_safe(pos, npos, base) { 579 path = list_entry(pos, struct include_path, list); 580 list_del(&path->list); 581 if (path->dir) 582 free(path->dir); 583 free(path); 584 } 585} 586 587#endif /* DOC_HIDDEN */ 588 589/** 590 * \brief Returns the default top-level config directory 591 * \return The top-level config directory path string 592 * 593 * This function returns the string of the top-level config directory path. 594 * If the path is specified via the environment variable \c ALSA_CONFIG_DIR 595 * and the value is a valid path, it returns this value. If unspecified, it 596 * returns the default value, "/usr/share/alsa". 597 */ 598const char *snd_config_topdir(void) 599{ 600 static char *topdir; 601 602 if (!topdir) { 603 topdir = getenv("ALSA_CONFIG_DIR"); 604 if (!topdir || *topdir != '/' || strlen(topdir) >= PATH_MAX) 605 topdir = ALSA_CONFIG_DIR; 606 } 607 return topdir; 608} 609 610#ifndef DOC_HIDDEN 611 612static char *_snd_config_path(const char *name) 613{ 614 const char *root = snd_config_topdir(); 615 char *path = malloc(strlen(root) + strlen(name) + 2); 616 if (!path) 617 return NULL; 618 sprintf(path, "%s/%s", root, name); 619 return path; 620} 621 622/* 623 * Search and open a file, and creates a new input object reading from the file. 624 * param inputp - The functions puts the pointer to the new input object 625 * at the address specified by \p inputp. 626 * param file - Name of the configuration file. 627 * param include_paths - Optional, addtional directories to search the file. 628 * return - Zero if successful, otherwise a negative error code. 629 * 630 * This function will search and open the file in the following order 631 * of priority: 632 * 1. directly open the file by its name (only if absolute) 633 * 2. search for the file name in in additional configuration directories 634 * specified by users, via alsaconf syntax 635 * <searchdir:relative-path/to/user/share/alsa>; 636 * These directories should be subdirectories of /usr/share/alsa. 637 */ 638static int input_stdio_open(snd_input_t **inputp, const char *file, 639 struct filedesc *current) 640{ 641 struct list_head *pos; 642 struct include_path *path; 643 char full_path[PATH_MAX]; 644 int err; 645 646 if (file[0] == '/') 647 return snd_input_stdio_open(inputp, file, "r"); 648 649 /* search file in user specified include paths. These directories 650 * are subdirectories of /usr/share/alsa. 651 */ 652 err = -ENOENT; 653 while (current) { 654 list_for_each(pos, ¤t->include_paths) { 655 path = list_entry(pos, struct include_path, list); 656 if (!path->dir) 657 continue; 658 659 snprintf(full_path, PATH_MAX, "%s/%s", path->dir, file); 660 err = snd_input_stdio_open(inputp, full_path, "r"); 661 if (err == 0) 662 return 0; 663 } 664 current = current->next; 665 } 666 667 return err; 668} 669 670int _snd_safe_strtoll_base(const char *str, long long *val, int base) 671{ 672 char *end; 673 long v; 674 if (!*str) 675 return -EINVAL; 676 errno = 0; 677 v = strtoll(str, &end, base); 678 if (errno) 679 return -errno; 680 if (*end) 681 return -EINVAL; 682 *val = v; 683 return 0; 684} 685 686int _snd_safe_strtol_base(const char *str, long *val, int base) 687{ 688 char *end; 689 long v; 690 if (!*str) 691 return -EINVAL; 692 errno = 0; 693 v = strtol(str, &end, base); 694 if (errno) 695 return -errno; 696 if (*end) 697 return -EINVAL; 698 *val = v; 699 return 0; 700} 701 702int _snd_safe_strtod(const char *str, double *val) 703{ 704 char *end; 705 double v; 706#ifdef HAVE_USELOCALE 707 locale_t saved_locale, c_locale; 708#else 709 char *saved_locale; 710 char locstr[64]; /* enough? */ 711#endif 712 int err; 713 714 if (!*str) 715 return -EINVAL; 716#ifdef HAVE_USELOCALE 717 c_locale = newlocale(LC_NUMERIC_MASK, "C", 0); 718 saved_locale = uselocale(c_locale); 719#else 720 saved_locale = setlocale(LC_NUMERIC, NULL); 721 if (saved_locale) { 722 snprintf(locstr, sizeof(locstr), "%s", saved_locale); 723 setlocale(LC_NUMERIC, "C"); 724 } 725#endif 726 errno = 0; 727 v = strtod(str, &end); 728 err = -errno; 729#ifdef HAVE_USELOCALE 730 if (c_locale != (locale_t)0) { 731 uselocale(saved_locale); 732 freelocale(c_locale); 733 } 734#else 735 if (saved_locale) 736 setlocale(LC_NUMERIC, locstr); 737#endif 738 if (err) 739 return err; 740 if (*end) 741 return -EINVAL; 742 *val = v; 743 return 0; 744} 745 746static int get_char(input_t *input) 747{ 748 int c; 749 struct filedesc *fd; 750 if (input->unget) { 751 input->unget = 0; 752 return input->ch; 753 } 754 again: 755 fd = input->current; 756 c = snd_input_getc(fd->in); 757 switch (c) { 758 case '\n': 759 fd->column = 0; 760 fd->line++; 761 break; 762 case '\t': 763 fd->column += 8 - fd->column % 8; 764 break; 765 case EOF: 766 if (fd->next) { 767 snd_input_close(fd->in); 768 free(fd->name); 769 input->current = fd->next; 770 free(fd); 771 goto again; 772 } 773 return LOCAL_UNEXPECTED_EOF; 774 default: 775 fd->column++; 776 break; 777 } 778 return (unsigned char)c; 779} 780 781static void unget_char(int c, input_t *input) 782{ 783 assert(!input->unget); 784 input->ch = c; 785 input->unget = 1; 786} 787 788static int get_delimstring(char **string, int delim, input_t *input); 789 790static int get_char_skip_comments(input_t *input) 791{ 792 int c; 793 while (1) { 794 c = get_char(input); 795 if (c == '<') { 796 char *str; 797 snd_input_t *in; 798 struct filedesc *fd; 799 DIR *dirp; 800 int err = get_delimstring(&str, '>', input); 801 if (err < 0) 802 return err; 803 804 if (!strncmp(str, "searchdir:", 10)) { 805 /* directory to search included files */ 806 char *tmp = _snd_config_path(str + 10); 807 free(str); 808 if (tmp == NULL) 809 return -ENOMEM; 810 str = tmp; 811 812 dirp = opendir(str); 813 if (!dirp) { 814 SNDERR("Invalid search dir %s", str); 815 free(str); 816 return -EINVAL; 817 } 818 closedir(dirp); 819 820 err = add_include_path(input->current, str); 821 if (err < 0) { 822 SNDERR("Cannot add search dir %s", str); 823 free(str); 824 return err; 825 } 826 free(str); 827 continue; 828 } 829 830 if (!strncmp(str, "confdir:", 8)) { 831 /* file in the specified directory */ 832 char *tmp = _snd_config_path(str + 8); 833 free(str); 834 if (tmp == NULL) 835 return -ENOMEM; 836 str = tmp; 837 err = snd_input_stdio_open(&in, str, "r"); 838 } else { /* absolute or relative file path */ 839 err = input_stdio_open(&in, str, input->current); 840 } 841 842 if (err < 0) { 843 SNDERR("Cannot access file %s", str); 844 free(str); 845 return err; 846 } 847 fd = malloc(sizeof(*fd)); 848 if (!fd) { 849 free(str); 850 return -ENOMEM; 851 } 852 fd->name = str; 853 fd->in = in; 854 fd->next = input->current; 855 fd->line = 1; 856 fd->column = 0; 857 INIT_LIST_HEAD(&fd->include_paths); 858 input->current = fd; 859 continue; 860 } 861 if (c != '#') 862 break; 863 while (1) { 864 c = get_char(input); 865 if (c < 0) 866 return c; 867 if (c == '\n') 868 break; 869 } 870 } 871 872 return c; 873} 874 875 876static int get_nonwhite(input_t *input) 877{ 878 int c; 879 while (1) { 880 c = get_char_skip_comments(input); 881 switch (c) { 882 case ' ': 883 case '\f': 884 case '\t': 885 case '\n': 886 case '\r': 887 break; 888 default: 889 return c; 890 } 891 } 892} 893 894static inline int get_hexachar(input_t *input) 895{ 896 int c, num = 0; 897 898 c = get_char(input); 899 if (c >= '0' && c <= '9') num |= (c - '0') << 4; 900 else if (c >= 'a' && c <= 'f') num |= (c - 'a') << 4; 901 else if (c >= 'A' && c <= 'F') num |= (c - 'A') << 4; 902 c = get_char(input); 903 if (c >= '0' && c <= '9') num |= (c - '0') << 0; 904 else if (c >= 'a' && c <= 'f') num |= (c - 'a') << 0; 905 else if (c >= 'A' && c <= 'F') num |= (c - 'A') << 0; 906 return num; 907} 908 909static int get_quotedchar(input_t *input) 910{ 911 int c; 912 c = get_char(input); 913 switch (c) { 914 case 'n': 915 return '\n'; 916 case 't': 917 return '\t'; 918 case 'v': 919 return '\v'; 920 case 'b': 921 return '\b'; 922 case 'r': 923 return '\r'; 924 case 'f': 925 return '\f'; 926 case 'x': 927 return get_hexachar(input); 928 case '0': case '1': case '2': case '3': 929 case '4': case '5': case '6': case '7': 930 { 931 int num = c - '0'; 932 int i = 1; 933 do { 934 c = get_char(input); 935 if (c < '0' || c > '7') { 936 unget_char(c, input); 937 break; 938 } 939 num = num * 8 + c - '0'; 940 i++; 941 } while (i < 3); 942 return num; 943 } 944 default: 945 return c; 946 } 947} 948 949#define LOCAL_STR_BUFSIZE 64 950struct local_string { 951 char *buf; 952 size_t alloc; 953 size_t idx; 954 char tmpbuf[LOCAL_STR_BUFSIZE]; 955}; 956 957static void init_local_string(struct local_string *s) 958{ 959 memset(s, 0, sizeof(*s)); 960 s->buf = s->tmpbuf; 961 s->alloc = LOCAL_STR_BUFSIZE; 962} 963 964static void free_local_string(struct local_string *s) 965{ 966 if (s->buf != s->tmpbuf) 967 free(s->buf); 968} 969 970static int add_char_local_string(struct local_string *s, int c) 971{ 972 if (s->idx >= s->alloc) { 973 size_t nalloc = s->alloc * 2; 974 if (s->buf == s->tmpbuf) { 975 s->buf = malloc(nalloc); 976 if (s->buf == NULL) 977 return -ENOMEM; 978 memcpy(s->buf, s->tmpbuf, s->alloc); 979 } else { 980 char *ptr = realloc(s->buf, nalloc); 981 if (ptr == NULL) 982 return -ENOMEM; 983 s->buf = ptr; 984 } 985 s->alloc = nalloc; 986 } 987 s->buf[s->idx++] = c; 988 return 0; 989} 990 991static char *copy_local_string(struct local_string *s) 992{ 993 char *dst = malloc(s->idx + 1); 994 if (dst) { 995 memcpy(dst, s->buf, s->idx); 996 dst[s->idx] = '\0'; 997 } 998 return dst; 999} 1000 1001static int get_freestring(char **string, int id, input_t *input) 1002{ 1003 struct local_string str; 1004 int c; 1005 1006 init_local_string(&str); 1007 while (1) { 1008 c = get_char(input); 1009 if (c < 0) { 1010 if (c == LOCAL_UNEXPECTED_EOF) { 1011 *string = copy_local_string(&str); 1012 if (! *string) 1013 c = -ENOMEM; 1014 else 1015 c = 0; 1016 } 1017 break; 1018 } 1019 switch (c) { 1020 case '.': 1021 if (!id) 1022 break; 1023 /* fall through */ 1024 case ' ': 1025 case '\f': 1026 case '\t': 1027 case '\n': 1028 case '\r': 1029 case '=': 1030 case ',': 1031 case ';': 1032 case '{': 1033 case '}': 1034 case '[': 1035 case ']': 1036 case '\'': 1037 case '"': 1038 case '\\': 1039 case '#': 1040 *string = copy_local_string(&str); 1041 if (! *string) 1042 c = -ENOMEM; 1043 else { 1044 unget_char(c, input); 1045 c = 0; 1046 } 1047 goto _out; 1048 default: 1049 break; 1050 } 1051 if (add_char_local_string(&str, c) < 0) { 1052 c = -ENOMEM; 1053 break; 1054 } 1055 } 1056 _out: 1057 free_local_string(&str); 1058 return c; 1059} 1060 1061static int get_delimstring(char **string, int delim, input_t *input) 1062{ 1063 struct local_string str; 1064 int c; 1065 1066 init_local_string(&str); 1067 while (1) { 1068 c = get_char(input); 1069 if (c < 0) 1070 break; 1071 if (c == '\\') { 1072 c = get_quotedchar(input); 1073 if (c < 0) 1074 break; 1075 if (c == '\n') 1076 continue; 1077 } else if (c == delim) { 1078 *string = copy_local_string(&str); 1079 if (! *string) 1080 c = -ENOMEM; 1081 else 1082 c = 0; 1083 break; 1084 } 1085 if (add_char_local_string(&str, c) < 0) { 1086 c = -ENOMEM; 1087 break; 1088 } 1089 } 1090 free_local_string(&str); 1091 return c; 1092} 1093 1094/* Return 0 for free string, 1 for delimited string */ 1095static int get_string(char **string, int id, input_t *input) 1096{ 1097 int c = get_nonwhite(input), err; 1098 if (c < 0) 1099 return c; 1100 switch (c) { 1101 case '=': 1102 case ',': 1103 case ';': 1104 case '.': 1105 case '{': 1106 case '}': 1107 case '[': 1108 case ']': 1109 case '\\': 1110 return LOCAL_UNEXPECTED_CHAR; 1111 case '\'': 1112 case '"': 1113 err = get_delimstring(string, c, input); 1114 if (err < 0) 1115 return err; 1116 return 1; 1117 default: 1118 unget_char(c, input); 1119 err = get_freestring(string, id, input); 1120 if (err < 0) 1121 return err; 1122 return 0; 1123 } 1124} 1125 1126static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type) 1127{ 1128 snd_config_t *n; 1129 assert(config); 1130 n = calloc(1, sizeof(*n)); 1131 if (n == NULL) { 1132 if (*id) { 1133 free(*id); 1134 *id = NULL; 1135 } 1136 return -ENOMEM; 1137 } 1138 if (id) { 1139 n->id = *id; 1140 *id = NULL; 1141 } 1142 n->type = type; 1143 if (type == SND_CONFIG_TYPE_COMPOUND) 1144 INIT_LIST_HEAD(&n->u.compound.fields); 1145 *config = n; 1146 return 0; 1147} 1148 1149 1150static int _snd_config_make_add(snd_config_t **config, char **id, 1151 snd_config_type_t type, snd_config_t *parent) 1152{ 1153 snd_config_t *n; 1154 int err; 1155 assert(parent->type == SND_CONFIG_TYPE_COMPOUND); 1156 err = _snd_config_make(&n, id, type); 1157 if (err < 0) 1158 return err; 1159 n->parent = parent; 1160 list_add_tail(&n->list, &parent->u.compound.fields); 1161 *config = n; 1162 return 0; 1163} 1164 1165static int _snd_config_search(snd_config_t *config, 1166 const char *id, int len, snd_config_t **result) 1167{ 1168 snd_config_iterator_t i, next; 1169 snd_config_for_each(i, next, config) { 1170 snd_config_t *n = snd_config_iterator_entry(i); 1171 if (len < 0) { 1172 if (strcmp(n->id, id) != 0) 1173 continue; 1174 } else if (strlen(n->id) != (size_t) len || 1175 memcmp(n->id, id, (size_t) len) != 0) 1176 continue; 1177 if (result) 1178 *result = n; 1179 return 0; 1180 } 1181 return -ENOENT; 1182} 1183 1184static int parse_value(snd_config_t **_n, snd_config_t *parent, input_t *input, char **id, int skip) 1185{ 1186 snd_config_t *n = *_n; 1187 char *s; 1188 int err; 1189 1190 err = get_string(&s, 0, input); 1191 if (err < 0) 1192 return err; 1193 if (skip) { 1194 free(s); 1195 return 0; 1196 } 1197 if (err == 0 && ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')) { 1198 long long i; 1199 errno = 0; 1200 err = safe_strtoll(s, &i); 1201 if (err < 0) { 1202 double r; 1203 err = safe_strtod(s, &r); 1204 if (err >= 0) { 1205 free(s); 1206 if (n) { 1207 if (n->type != SND_CONFIG_TYPE_REAL) { 1208 SNDERR("%s is not a real", *id); 1209 return -EINVAL; 1210 } 1211 } else { 1212 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_REAL, parent); 1213 if (err < 0) 1214 return err; 1215 } 1216 n->u.real = r; 1217 *_n = n; 1218 return 0; 1219 } 1220 } else { 1221 free(s); 1222 if (n) { 1223 if (n->type != SND_CONFIG_TYPE_INTEGER && n->type != SND_CONFIG_TYPE_INTEGER64) { 1224 SNDERR("%s is not an integer", *id); 1225 return -EINVAL; 1226 } 1227 } else { 1228 if (i <= INT_MAX) 1229 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER, parent); 1230 else 1231 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER64, parent); 1232 if (err < 0) 1233 return err; 1234 } 1235 if (n->type == SND_CONFIG_TYPE_INTEGER) 1236 n->u.integer = (long) i; 1237 else 1238 n->u.integer64 = i; 1239 *_n = n; 1240 return 0; 1241 } 1242 } 1243 if (n) { 1244 if (n->type != SND_CONFIG_TYPE_STRING) { 1245 SNDERR("%s is not a string", *id); 1246 free(s); 1247 return -EINVAL; 1248 } 1249 } else { 1250 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_STRING, parent); 1251 if (err < 0) 1252 return err; 1253 } 1254 free(n->u.string); 1255 n->u.string = s; 1256 *_n = n; 1257 return 0; 1258} 1259 1260static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override); 1261static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int override); 1262 1263static int parse_array_def(snd_config_t *parent, input_t *input, int *idx, int skip, int override) 1264{ 1265 char *id = NULL; 1266 int c; 1267 int err; 1268 snd_config_t *n = NULL; 1269 1270 if (!skip) { 1271 snd_config_t *g; 1272 char static_id[12]; 1273 while (1) { 1274 snprintf(static_id, sizeof(static_id), "%i", *idx); 1275 if (_snd_config_search(parent, static_id, -1, &g) == 0) { 1276 if (override) { 1277 snd_config_delete(n); 1278 } else { 1279 /* merge */ 1280 (*idx)++; 1281 continue; 1282 } 1283 } 1284 break; 1285 } 1286 id = strdup(static_id); 1287 if (id == NULL) 1288 return -ENOMEM; 1289 } 1290 c = get_nonwhite(input); 1291 if (c < 0) { 1292 err = c; 1293 goto __end; 1294 } 1295 switch (c) { 1296 case '{': 1297 case '[': 1298 { 1299 char endchr; 1300 if (!skip) { 1301 if (n) { 1302 if (n->type != SND_CONFIG_TYPE_COMPOUND) { 1303 SNDERR("%s is not a compound", id); 1304 err = -EINVAL; 1305 goto __end; 1306 } 1307 } else { 1308 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent); 1309 if (err < 0) 1310 goto __end; 1311 } 1312 } 1313 if (c == '{') { 1314 err = parse_defs(n, input, skip, override); 1315 endchr = '}'; 1316 } else { 1317 err = parse_array_defs(n, input, skip, override); 1318 endchr = ']'; 1319 } 1320 c = get_nonwhite(input); 1321 if (c < 0) { 1322 err = c; 1323 goto __end; 1324 } 1325 if (c != endchr) { 1326 if (n) 1327 snd_config_delete(n); 1328 err = LOCAL_UNEXPECTED_CHAR; 1329 goto __end; 1330 } 1331 break; 1332 } 1333 default: 1334 unget_char(c, input); 1335 err = parse_value(&n, parent, input, &id, skip); 1336 if (err < 0) 1337 goto __end; 1338 break; 1339 } 1340 err = 0; 1341 __end: 1342 free(id); 1343 return err; 1344} 1345 1346static int parse_array_defs(snd_config_t *parent, input_t *input, int skip, int override) 1347{ 1348 int idx = 0; 1349 while (1) { 1350 int c = get_nonwhite(input), err; 1351 if (c < 0) 1352 return c; 1353 unget_char(c, input); 1354 if (c == ']') 1355 return 0; 1356 err = parse_array_def(parent, input, &idx, skip, override); 1357 if (err < 0) 1358 return err; 1359 idx++; 1360 } 1361 return 0; 1362} 1363 1364static int parse_def(snd_config_t *parent, input_t *input, int skip, int override) 1365{ 1366 char *id = NULL; 1367 int c; 1368 int err; 1369 snd_config_t *n; 1370 enum {MERGE_CREATE, MERGE, OVERRIDE, DONT_OVERRIDE} mode; 1371 while (1) { 1372 c = get_nonwhite(input); 1373 if (c < 0) 1374 return c; 1375 switch (c) { 1376 case '+': 1377 mode = MERGE_CREATE; 1378 break; 1379 case '-': 1380 mode = MERGE; 1381 break; 1382 case '?': 1383 mode = DONT_OVERRIDE; 1384 break; 1385 case '!': 1386 mode = OVERRIDE; 1387 break; 1388 default: 1389 mode = !override ? MERGE_CREATE : OVERRIDE; 1390 unget_char(c, input); 1391 } 1392 err = get_string(&id, 1, input); 1393 if (err < 0) 1394 return err; 1395 c = get_nonwhite(input); 1396 if (c != '.') 1397 break; 1398 if (skip) { 1399 free(id); 1400 continue; 1401 } 1402 if (_snd_config_search(parent, id, -1, &n) == 0) { 1403 if (mode == DONT_OVERRIDE) { 1404 skip = 1; 1405 free(id); 1406 continue; 1407 } 1408 if (mode != OVERRIDE) { 1409 if (n->type != SND_CONFIG_TYPE_COMPOUND) { 1410 SNDERR("%s is not a compound", id); 1411 return -EINVAL; 1412 } 1413 n->u.compound.join = true; 1414 parent = n; 1415 free(id); 1416 continue; 1417 } 1418 snd_config_delete(n); 1419 } 1420 if (mode == MERGE) { 1421 SNDERR("%s does not exists", id); 1422 err = -ENOENT; 1423 goto __end; 1424 } 1425 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent); 1426 if (err < 0) 1427 goto __end; 1428 n->u.compound.join = true; 1429 parent = n; 1430 } 1431 if (c == '=') { 1432 c = get_nonwhite(input); 1433 if (c < 0) 1434 return c; 1435 } 1436 if (!skip) { 1437 if (_snd_config_search(parent, id, -1, &n) == 0) { 1438 if (mode == DONT_OVERRIDE) { 1439 skip = 1; 1440 n = NULL; 1441 } else if (mode == OVERRIDE) { 1442 snd_config_delete(n); 1443 n = NULL; 1444 } 1445 } else { 1446 n = NULL; 1447 if (mode == MERGE) { 1448 SNDERR("%s does not exists", id); 1449 err = -ENOENT; 1450 goto __end; 1451 } 1452 } 1453 } 1454 switch (c) { 1455 case '{': 1456 case '[': 1457 { 1458 char endchr; 1459 if (!skip) { 1460 if (n) { 1461 if (n->type != SND_CONFIG_TYPE_COMPOUND) { 1462 SNDERR("%s is not a compound", id); 1463 err = -EINVAL; 1464 goto __end; 1465 } 1466 } else { 1467 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent); 1468 if (err < 0) 1469 goto __end; 1470 } 1471 } 1472 if (c == '{') { 1473 err = parse_defs(n, input, skip, override); 1474 endchr = '}'; 1475 } else { 1476 err = parse_array_defs(n, input, skip, override); 1477 endchr = ']'; 1478 } 1479 c = get_nonwhite(input); 1480 if (c != endchr) { 1481 if (n) 1482 snd_config_delete(n); 1483 err = LOCAL_UNEXPECTED_CHAR; 1484 goto __end; 1485 } 1486 break; 1487 } 1488 default: 1489 unget_char(c, input); 1490 err = parse_value(&n, parent, input, &id, skip); 1491 if (err < 0) 1492 goto __end; 1493 break; 1494 } 1495 c = get_nonwhite(input); 1496 switch (c) { 1497 case ';': 1498 case ',': 1499 break; 1500 default: 1501 unget_char(c, input); 1502 } 1503 __end: 1504 free(id); 1505 return err; 1506} 1507 1508static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override) 1509{ 1510 int c, err; 1511 while (1) { 1512 c = get_nonwhite(input); 1513 if (c < 0) 1514 return c == LOCAL_UNEXPECTED_EOF ? 0 : c; 1515 unget_char(c, input); 1516 if (c == '}') 1517 return 0; 1518 err = parse_def(parent, input, skip, override); 1519 if (err < 0) 1520 return err; 1521 } 1522 return 0; 1523} 1524 1525static void string_print(char *str, int id, snd_output_t *out) 1526{ 1527 int q; 1528 unsigned char *p = (unsigned char *)str; 1529 if (!p || !*p) { 1530 snd_output_puts(out, "''"); 1531 return; 1532 } 1533 if (!id) { 1534 switch (*p) { 1535 case '0': case '1': case '2': case '3': case '4': 1536 case '5': case '6': case '7': case '8': case '9': 1537 case '-': 1538 goto quoted; 1539 } 1540 } 1541 loop: 1542 switch (*p) { 1543 case 0: 1544 goto nonquoted; 1545 case ' ': 1546 case '=': 1547 case ';': 1548 case ',': 1549 case '.': 1550 case '{': 1551 case '}': 1552 case '[': 1553 case ']': 1554 case '\'': 1555 case '"': 1556 case '*': 1557 case '#': 1558 goto quoted; 1559 default: 1560 if (*p <= 31 || *p >= 127) 1561 goto quoted; 1562 p++; 1563 goto loop; 1564 } 1565 nonquoted: 1566 snd_output_puts(out, str); 1567 return; 1568 quoted: 1569 q = strchr(str, '\'') ? '"' : '\''; 1570 snd_output_putc(out, q); 1571 p = (unsigned char *)str; 1572 while (*p) { 1573 int c; 1574 c = *p; 1575 switch (c) { 1576 case '\n': 1577 snd_output_putc(out, '\\'); 1578 snd_output_putc(out, 'n'); 1579 break; 1580 case '\t': 1581 snd_output_putc(out, '\\'); 1582 snd_output_putc(out, 't'); 1583 break; 1584 case '\v': 1585 snd_output_putc(out, '\\'); 1586 snd_output_putc(out, 'v'); 1587 break; 1588 case '\b': 1589 snd_output_putc(out, '\\'); 1590 snd_output_putc(out, 'b'); 1591 break; 1592 case '\r': 1593 snd_output_putc(out, '\\'); 1594 snd_output_putc(out, 'r'); 1595 break; 1596 case '\f': 1597 snd_output_putc(out, '\\'); 1598 snd_output_putc(out, 'f'); 1599 break; 1600 default: 1601 if (c == q) { 1602 snd_output_putc(out, '\\'); 1603 snd_output_putc(out, c); 1604 } else { 1605 if (c >= 32 && c <= 126) 1606 snd_output_putc(out, c); 1607 else 1608 snd_output_printf(out, "\\%04o", c); 1609 } 1610 break; 1611 } 1612 p++; 1613 } 1614 snd_output_putc(out, q); 1615} 1616 1617static void level_print(snd_output_t *out, unsigned int level) 1618{ 1619 char a[level + 1]; 1620 memset(a, '\t', level); 1621 a[level] = '\0'; 1622 snd_output_puts(out, a); 1623} 1624 1625static int _snd_config_save_children(snd_config_t *config, snd_output_t *out, 1626 unsigned int level, unsigned int joins, 1627 int array); 1628 1629int _snd_config_save_node_value(snd_config_t *n, snd_output_t *out, 1630 unsigned int level) 1631{ 1632 int err, array; 1633 switch (n->type) { 1634 case SND_CONFIG_TYPE_INTEGER: 1635 snd_output_printf(out, "%ld", n->u.integer); 1636 break; 1637 case SND_CONFIG_TYPE_INTEGER64: 1638 snd_output_printf(out, "%lld", n->u.integer64); 1639 break; 1640 case SND_CONFIG_TYPE_REAL: 1641 snd_output_printf(out, "%-16g", n->u.real); 1642 break; 1643 case SND_CONFIG_TYPE_STRING: 1644 string_print(n->u.string, 0, out); 1645 break; 1646 case SND_CONFIG_TYPE_POINTER: 1647 SNDERR("cannot save runtime pointer type"); 1648 return -EINVAL; 1649 case SND_CONFIG_TYPE_COMPOUND: 1650 array = snd_config_is_array(n); 1651 snd_output_putc(out, array ? '[' : '{'); 1652 snd_output_putc(out, '\n'); 1653 err = _snd_config_save_children(n, out, level + 1, 0, array); 1654 if (err < 0) 1655 return err; 1656 level_print(out, level); 1657 snd_output_putc(out, array ? ']' : '}'); 1658 break; 1659 } 1660 return 0; 1661} 1662 1663static void id_print(snd_config_t *n, snd_output_t *out, unsigned int joins) 1664{ 1665 if (joins > 0) { 1666 assert(n->parent); 1667 id_print(n->parent, out, joins - 1); 1668 snd_output_putc(out, '.'); 1669 } 1670 string_print(n->id, 1, out); 1671} 1672 1673static int _snd_config_save_children(snd_config_t *config, snd_output_t *out, 1674 unsigned int level, unsigned int joins, 1675 int array) 1676{ 1677 int err; 1678 snd_config_iterator_t i, next; 1679 assert(config && out); 1680 snd_config_for_each(i, next, config) { 1681 snd_config_t *n = snd_config_iterator_entry(i); 1682 if (n->type == SND_CONFIG_TYPE_COMPOUND && 1683 n->u.compound.join) { 1684 err = _snd_config_save_children(n, out, level, joins + 1, 0); 1685 if (err < 0) 1686 return err; 1687 continue; 1688 } 1689 level_print(out, level); 1690 if (!array) { 1691 id_print(n, out, joins); 1692 snd_output_putc(out, ' '); 1693#if 0 1694 snd_output_putc(out, '='); 1695#endif 1696 } 1697 err = _snd_config_save_node_value(n, out, level); 1698 if (err < 0) 1699 return err; 1700#if 0 1701 snd_output_putc(out, ';'); 1702#endif 1703 snd_output_putc(out, '\n'); 1704 } 1705 return 0; 1706} 1707#endif /* DOC_HIDDEN */ 1708 1709 1710/** 1711 * \brief Substitutes one configuration node to another. 1712 * \param dst Handle to the destination node. 1713 * \param src Handle to the source node. Must not be the same as \a dst. 1714 * \return Zero if successful, otherwise a negative error code. 1715 * 1716 * If both nodes are compounds, the source compound node members will 1717 * be moved to the destination compound node. The original destination 1718 * compound node members will be deleted (overwritten). 1719 * 1720 * If the destination node is a compound and the source node is 1721 * an ordinary type, the compound members are deleted (including 1722 * their contents). 1723 * 1724 * Otherwise, the source node's value replaces the destination node's 1725 * value. 1726 * 1727 * In any case, a successful call to this function frees the source 1728 * node. 1729 */ 1730int snd_config_substitute(snd_config_t *dst, snd_config_t *src) 1731{ 1732 assert(dst && src); 1733 if (dst->type == SND_CONFIG_TYPE_COMPOUND) { 1734 int err = snd_config_delete_compound_members(dst); 1735 if (err < 0) 1736 return err; 1737 } 1738 if (dst->type == SND_CONFIG_TYPE_COMPOUND && 1739 src->type == SND_CONFIG_TYPE_COMPOUND) { /* overwrite */ 1740 snd_config_iterator_t i, next; 1741 snd_config_for_each(i, next, src) { 1742 snd_config_t *n = snd_config_iterator_entry(i); 1743 n->parent = dst; 1744 } 1745 src->u.compound.fields.next->prev = &dst->u.compound.fields; 1746 src->u.compound.fields.prev->next = &dst->u.compound.fields; 1747 } 1748 free(dst->id); 1749 if (dst->type == SND_CONFIG_TYPE_STRING) 1750 free(dst->u.string); 1751 dst->id = src->id; 1752 dst->type = src->type; 1753 dst->u = src->u; 1754 free(src); 1755 return 0; 1756} 1757 1758/** 1759 * \brief Converts an ASCII string to a configuration node type. 1760 * \param[in] ascii A string containing a configuration node type. 1761 * \param[out] type The node type corresponding to \a ascii. 1762 * \return Zero if successful, otherwise a negative error code. 1763 * 1764 * This function recognizes at least the following node types: 1765 * <dl> 1766 * <dt>integer<dt>#SND_CONFIG_TYPE_INTEGER 1767 * <dt>integer64<dt>#SND_CONFIG_TYPE_INTEGER64 1768 * <dt>real<dt>#SND_CONFIG_TYPE_REAL 1769 * <dt>string<dt>#SND_CONFIG_TYPE_STRING 1770 * <dt>compound<dt>#SND_CONFIG_TYPE_COMPOUND 1771 * </dl> 1772 * 1773 * \par Errors: 1774 * <dl> 1775 * <dt>-EINVAL<dd>Unknown note type in \a type. 1776 * </dl> 1777 */ 1778int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type) 1779{ 1780 assert(ascii && type); 1781 if (!strcmp(ascii, "integer")) { 1782 *type = SND_CONFIG_TYPE_INTEGER; 1783 return 0; 1784 } 1785 if (!strcmp(ascii, "integer64")) { 1786 *type = SND_CONFIG_TYPE_INTEGER64; 1787 return 0; 1788 } 1789 if (!strcmp(ascii, "real")) { 1790 *type = SND_CONFIG_TYPE_REAL; 1791 return 0; 1792 } 1793 if (!strcmp(ascii, "string")) { 1794 *type = SND_CONFIG_TYPE_STRING; 1795 return 0; 1796 } 1797 if (!strcmp(ascii, "compound")) { 1798 *type = SND_CONFIG_TYPE_COMPOUND; 1799 return 0; 1800 } 1801 return -EINVAL; 1802} 1803 1804/** 1805 * \brief Returns the type of a configuration node. 1806 * \param config Handle to the configuration node. 1807 * \return The node's type. 1808 * 1809 * \par Conforming to: 1810 * LSB 3.2 1811 */ 1812snd_config_type_t snd_config_get_type(const snd_config_t *config) 1813{ 1814 return config->type; 1815} 1816 1817static int check_array_item(const char *id, int index) 1818{ 1819 const char *p; 1820 long val; 1821 1822 for (p = id; *p; p++) { 1823 if (*p < '0' || *p > '9') 1824 return 0; 1825 } 1826 1827 if (safe_strtol(id, &val)) 1828 return 0; 1829 return val == index; 1830} 1831 1832/** 1833 * \brief Returns if the compound is an array (and count of items). 1834 * \param config Handle to the configuration node. 1835 * \return A count of items in array, zero when the compound is not an array, 1836 * otherwise a negative error code. 1837 */ 1838int snd_config_is_array(const snd_config_t *config) 1839{ 1840 int idx; 1841 snd_config_iterator_t i, next; 1842 snd_config_t *node; 1843 1844 assert(config); 1845 if (config->type != SND_CONFIG_TYPE_COMPOUND) 1846 return -EINVAL; 1847 idx = 0; 1848 snd_config_for_each(i, next, config) { 1849 node = snd_config_iterator_entry(i); 1850 if (!check_array_item(node->id, idx)) 1851 return 0; 1852 idx++; 1853 } 1854 return idx; 1855} 1856 1857/** 1858 * \brief Returns if the compound has no fields (is empty). 1859 * \param config Handle to the configuration node. 1860 * \return A positive value when true, zero when false, otherwise a negative error code. 1861 */ 1862int snd_config_is_empty(const snd_config_t *config) 1863{ 1864 assert(config); 1865 if (config->type != SND_CONFIG_TYPE_COMPOUND) 1866 return -EINVAL; 1867 return list_empty(&config->u.compound.fields); 1868} 1869 1870/** 1871 * \brief Returns the id of a configuration node. 1872 * \param[in] config Handle to the configuration node. 1873 * \param[out] id The function puts the pointer to the id string at the 1874 * address specified by \a id. 1875 * \return Zero if successful, otherwise a negative error code. 1876 * 1877 * The returned string is owned by the configuration node; the application 1878 * must not modify or delete it, and the string becomes invalid when the 1879 * node's id changes or when the node is freed. 1880 * 1881 * If the node does not have an id, \a *id is set to \c NULL. 1882 * 1883 * \par Conforming to: 1884 * LSB 3.2 1885 */ 1886int snd_config_get_id(const snd_config_t *config, const char **id) 1887{ 1888 assert(config && id); 1889 *id = config->id; 1890 return 0; 1891} 1892 1893/** 1894 * \brief Sets the id of a configuration node. 1895 * \param config Handle to the configuration node. 1896 * \param id The new node id, must not be \c NULL. 1897 * \return Zero if successful, otherwise a negative error code. 1898 * 1899 * This function stores a copy of \a id in the node. 1900 * 1901 * \par Errors: 1902 * <dl> 1903 * <dt>-EEXIST<dd>One of \a config's siblings already has the id \a id. 1904 * <dt>-EINVAL<dd>The id of a node with a parent cannot be set to \c NULL. 1905 * <dt>-ENOMEM<dd>Out of memory. 1906 * </dl> 1907 */ 1908int snd_config_set_id(snd_config_t *config, const char *id) 1909{ 1910 snd_config_iterator_t i, next; 1911 char *new_id; 1912 assert(config); 1913 if (id) { 1914 if (config->parent) { 1915 snd_config_for_each(i, next, config->parent) { 1916 snd_config_t *n = snd_config_iterator_entry(i); 1917 if (n != config && strcmp(id, n->id) == 0) 1918 return -EEXIST; 1919 } 1920 } 1921 new_id = strdup(id); 1922 if (!new_id) 1923 return -ENOMEM; 1924 } else { 1925 if (config->parent) 1926 return -EINVAL; 1927 new_id = NULL; 1928 } 1929 free(config->id); 1930 config->id = new_id; 1931 return 0; 1932} 1933 1934/** 1935 * \brief Creates a top level configuration node. 1936 * \param[out] config Handle to the new node. 1937 * \return Zero if successful, otherwise a negative error code. 1938 * 1939 * The returned node is an empty compound node without a parent and 1940 * without an id. 1941 * 1942 * \par Errors: 1943 * <dl> 1944 * <dt>-ENOMEM<dd>Out of memory. 1945 * </dl> 1946 * 1947 * \par Conforming to: 1948 * LSB 3.2 1949 */ 1950int snd_config_top(snd_config_t **config) 1951{ 1952 assert(config); 1953 return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND); 1954} 1955 1956#ifndef DOC_HIDDEN 1957int _snd_config_load_with_include(snd_config_t *config, snd_input_t *in, 1958 int override, const char * const *include_paths) 1959{ 1960 int err; 1961 input_t input; 1962 struct filedesc *fd, *fd_next; 1963 1964 assert(config && in); 1965 fd = malloc(sizeof(*fd)); 1966 if (!fd) 1967 return -ENOMEM; 1968 fd->name = NULL; 1969 fd->in = in; 1970 fd->line = 1; 1971 fd->column = 0; 1972 fd->next = NULL; 1973 INIT_LIST_HEAD(&fd->include_paths); 1974 if (include_paths) { 1975 for (; *include_paths; include_paths++) { 1976 err = add_include_path(fd, *include_paths); 1977 if (err < 0) 1978 goto _end; 1979 } 1980 } else { 1981 err = add_include_path(fd, snd_config_topdir()); 1982 if (err < 0) 1983 goto _end; 1984 } 1985 input.current = fd; 1986 input.unget = 0; 1987 err = parse_defs(config, &input, 0, override); 1988 fd = input.current; 1989 if (err < 0) { 1990 const char *str; 1991 switch (err) { 1992 case LOCAL_UNTERMINATED_STRING: 1993 str = "Unterminated string"; 1994 err = -EINVAL; 1995 break; 1996 case LOCAL_UNTERMINATED_QUOTE: 1997 str = "Unterminated quote"; 1998 err = -EINVAL; 1999 break; 2000 case LOCAL_UNEXPECTED_CHAR: 2001 str = "Unexpected char"; 2002 err = -EINVAL; 2003 break; 2004 case LOCAL_UNEXPECTED_EOF: 2005 str = "Unexpected end of file"; 2006 err = -EINVAL; 2007 break; 2008 default: 2009 str = strerror(-err); 2010 break; 2011 } 2012 SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str); 2013 goto _end; 2014 } 2015 err = get_char(&input); 2016 fd = input.current; 2017 if (err != LOCAL_UNEXPECTED_EOF) { 2018 SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column); 2019 err = -EINVAL; 2020 goto _end; 2021 } 2022 err = 0; 2023 _end: 2024 while (fd->next) { 2025 fd_next = fd->next; 2026 snd_input_close(fd->in); 2027 free(fd->name); 2028 free_include_paths(fd); 2029 free(fd); 2030 fd = fd_next; 2031 } 2032 2033 free_include_paths(fd); 2034 free(fd); 2035 return err; 2036} 2037#endif 2038 2039/** 2040 * \brief Loads a configuration tree. 2041 * \param config Handle to a top level configuration node. 2042 * \param in Input handle to read the configuration from. 2043 * \return Zero if successful, otherwise a negative error code. 2044 * 2045 * The definitions loaded from the input are added to \a config, which 2046 * must be a compound node. 2047 * 2048 * \par Errors: 2049 * Any errors encountered when parsing the input or returned by hooks or 2050 * functions. 2051 * 2052 * \par Conforming to: 2053 * LSB 3.2 2054 */ 2055int snd_config_load(snd_config_t *config, snd_input_t *in) 2056{ 2057 return _snd_config_load_with_include(config, in, 0, NULL); 2058} 2059 2060/** 2061 * \brief Loads a configuration tree from a string. 2062 * \param[out] config The function puts the handle to the configuration 2063 * node loaded from the file(s) at the address specified 2064 * by \a config. 2065 * \param[in] s String with the ASCII configuration 2066 * \param[in] size String size, if zero, a C string is expected (with termination) 2067 * \return Zero if successful, otherwise a negative error code. 2068 * 2069 * The definitions loaded from the string are put to \a config, which 2070 * is created as a new top node. 2071 * 2072 * \par Errors: 2073 * Any errors encountered when parsing the input or returned by hooks or 2074 * functions. 2075 */ 2076int snd_config_load_string(snd_config_t **config, const char *s, size_t size) 2077{ 2078 snd_input_t *input; 2079 snd_config_t *dst; 2080 int err; 2081 2082 assert(config && s); 2083 if (size == 0) 2084 size = strlen(s); 2085 err = snd_input_buffer_open(&input, s, size); 2086 if (err < 0) 2087 return err; 2088 err = snd_config_top(&dst); 2089 if (err < 0) { 2090 snd_input_close(input); 2091 return err; 2092 } 2093 err = snd_config_load(dst, input); 2094 snd_input_close(input); 2095 if (err < 0) { 2096 snd_config_delete(dst); 2097 return err; 2098 } 2099 *config = dst; 2100 return 0; 2101} 2102 2103/** 2104 * \brief Loads a configuration tree and overrides existing configuration nodes. 2105 * \param config Handle to a top level configuration node. 2106 * \param in Input handle to read the configuration from. 2107 * \return Zero if successful, otherwise a negative error code. 2108 * 2109 * This function loads definitions from \a in into \a config like 2110 * #snd_config_load, but the default mode for input nodes is 'override' 2111 * (!) instead of 'merge+create' (+). 2112 */ 2113int snd_config_load_override(snd_config_t *config, snd_input_t *in) 2114{ 2115 return _snd_config_load_with_include(config, in, 1, NULL); 2116} 2117 2118/** 2119 * \brief Adds a child to a compound configuration node. 2120 * \param parent Handle to a compound configuration node. 2121 * \param child Handle to the configuration node to be added. 2122 * \return Zero if successful, otherwise a negative error code. 2123 * 2124 * This function makes the node \a child a child of the node \a parent. 2125 * 2126 * The parent node then owns the child node, i.e., the child node gets 2127 * deleted together with its parent. 2128 * 2129 * \a child must have an id. 2130 * 2131 * \par Errors: 2132 * <dl> 2133 * <dt>-EINVAL<dd>\a child does not have an id. 2134 * <dt>-EINVAL<dd>\a child already has a parent. 2135 * <dt>-EEXIST<dd>\a parent already contains a child node with the same 2136 * id as \a child. 2137 * </dl> 2138 * 2139 * \par Conforming to: 2140 * LSB 3.2 2141 */ 2142int snd_config_add(snd_config_t *parent, snd_config_t *child) 2143{ 2144 snd_config_iterator_t i, next; 2145 assert(parent && child); 2146 if (!child->id || child->parent) 2147 return -EINVAL; 2148 snd_config_for_each(i, next, parent) { 2149 snd_config_t *n = snd_config_iterator_entry(i); 2150 if (strcmp(child->id, n->id) == 0) 2151 return -EEXIST; 2152 } 2153 child->parent = parent; 2154 list_add_tail(&child->list, &parent->u.compound.fields); 2155 return 0; 2156} 2157 2158/** 2159 * \brief Adds a child after another child configuration node. 2160 * \param after Handle to the start configuration node. 2161 * \param child Handle to the configuration node to be added. 2162 * \return Zero if successful, otherwise a negative error code. 2163 * 2164 * This function makes the node \a child a child of the parent of 2165 * the node \a after. 2166 * 2167 * The parent node then owns the child node, i.e., the child node gets 2168 * deleted together with its parent. 2169 * 2170 * \a child must have an id. 2171 * 2172 * \par Errors: 2173 * <dl> 2174 * <dt>-EINVAL<dd>\a child does not have an id. 2175 * <dt>-EINVAL<dd>\a child already has a parent. 2176 * <dt>-EEXIST<dd>\a parent already contains a child node with the same 2177 * id as \a child. 2178 * </dl> 2179 */ 2180int snd_config_add_after(snd_config_t *after, snd_config_t *child) 2181{ 2182 snd_config_iterator_t i, next; 2183 snd_config_t *parent; 2184 assert(after && child); 2185 parent = after->parent; 2186 assert(parent); 2187 if (!child->id || child->parent) 2188 return -EINVAL; 2189 snd_config_for_each(i, next, parent) { 2190 snd_config_t *n = snd_config_iterator_entry(i); 2191 if (strcmp(child->id, n->id) == 0) 2192 return -EEXIST; 2193 } 2194 child->parent = parent; 2195 list_insert(&child->list, &after->list, after->list.next); 2196 return 0; 2197} 2198 2199/** 2200 * \brief Adds a child before another child configuration node. 2201 * \param before Handle to the start configuration node. 2202 * \param child Handle to the configuration node to be added. 2203 * \return Zero if successful, otherwise a negative error code. 2204 * 2205 * This function makes the node \a child a child of the parent of 2206 * the node \a before. 2207 * 2208 * The parent node then owns the child node, i.e., the child node gets 2209 * deleted together with its parent. 2210 * 2211 * \a child must have an id. 2212 * 2213 * \par Errors: 2214 * <dl> 2215 * <dt>-EINVAL<dd>\a child does not have an id. 2216 * <dt>-EINVAL<dd>\a child already has a parent. 2217 * <dt>-EEXIST<dd>\a parent already contains a child node with the same 2218 * id as \a child. 2219 * </dl> 2220 */ 2221int snd_config_add_before(snd_config_t *before, snd_config_t *child) 2222{ 2223 snd_config_iterator_t i, next; 2224 snd_config_t *parent; 2225 assert(before && child); 2226 parent = before->parent; 2227 assert(parent); 2228 if (!child->id || child->parent) 2229 return -EINVAL; 2230 snd_config_for_each(i, next, parent) { 2231 snd_config_t *n = snd_config_iterator_entry(i); 2232 if (strcmp(child->id, n->id) == 0) 2233 return -EEXIST; 2234 } 2235 child->parent = parent; 2236 list_insert(&child->list, before->list.prev, &before->list); 2237 return 0; 2238} 2239 2240/* 2241 * append all src items to the end of dst arrray 2242 */ 2243static int _snd_config_array_merge(snd_config_t *dst, snd_config_t *src, int index) 2244{ 2245 snd_config_iterator_t si, snext; 2246 int err; 2247 2248 snd_config_for_each(si, snext, src) { 2249 snd_config_t *sn = snd_config_iterator_entry(si); 2250 char id[16]; 2251 snd_config_remove(sn); 2252 snprintf(id, sizeof(id), "%d", index++); 2253 err = snd_config_set_id(sn, id); 2254 if (err < 0) { 2255 snd_config_delete(sn); 2256 return err; 2257 } 2258 sn->parent = dst; 2259 list_add_tail(&sn->list, &dst->u.compound.fields); 2260 } 2261 snd_config_delete(src); 2262 return 0; 2263} 2264 2265/** 2266 * \brief In-place merge of two config handles 2267 * \param[out] dst Config handle for the merged contents 2268 * \param[in] src Config handle to merge into dst (may be NULL) 2269 * \param[in] override Override flag 2270 * \return Zero if successful, otherwise a negative error code. 2271 * 2272 * This function merges all fields from the source compound to the destination compound. 2273 * When the \a override flag is set, the related subtree in \a dst is replaced from \a src. 2274 * 2275 * When \a override is not set, the child compounds are traversed and merged. 2276 * 2277 * The configuration elements other than compounds are always substituted (overwritten) 2278 * from the \a src config handle. 2279 * 2280 * The src handle is deleted. 2281 * 2282 * Note: On error, config handles may be modified. 2283 * 2284 * \par Errors: 2285 * <dl> 2286 * <dt>-EEXIST<dd>identifier already exists (!override) 2287 * <dt>-ENOMEM<dd>not enough memory 2288 * </dl> 2289 */ 2290int snd_config_merge(snd_config_t *dst, snd_config_t *src, int override) 2291{ 2292 snd_config_iterator_t di, si, dnext, snext; 2293 bool found; 2294 int err, array; 2295 2296 assert(dst); 2297 if (src == NULL) 2298 return 0; 2299 if (dst->type != SND_CONFIG_TYPE_COMPOUND || src->type != SND_CONFIG_TYPE_COMPOUND) 2300 return snd_config_substitute(dst, src); 2301 array = snd_config_is_array(dst); 2302 if (array && snd_config_is_array(src)) 2303 return _snd_config_array_merge(dst, src, array); 2304 snd_config_for_each(si, snext, src) { 2305 snd_config_t *sn = snd_config_iterator_entry(si); 2306 found = false; 2307 snd_config_for_each(di, dnext, dst) { 2308 snd_config_t *dn = snd_config_iterator_entry(di); 2309 if (strcmp(sn->id, dn->id) == 0) { 2310 if (override || 2311 sn->type != SND_CONFIG_TYPE_COMPOUND || 2312 dn->type != SND_CONFIG_TYPE_COMPOUND) { 2313 snd_config_remove(sn); 2314 err = snd_config_substitute(dn, sn); 2315 if (err < 0) 2316 return err; 2317 } else { 2318 err = snd_config_merge(dn, sn, 0); 2319 if (err < 0) 2320 return err; 2321 } 2322 found = true; 2323 break; 2324 } 2325 } 2326 if (!found) { 2327 /* move config from src to dst */ 2328 snd_config_remove(sn); 2329 sn->parent = dst; 2330 list_add_tail(&sn->list, &dst->u.compound.fields); 2331 } 2332 } 2333 snd_config_delete(src); 2334 return 0; 2335} 2336 2337/** 2338 * \brief Removes a configuration node from its tree. 2339 * \param config Handle to the configuration node to be removed. 2340 * \return Zero if successful, otherwise a negative error code. 2341 * 2342 * This function makes \a config a top-level node, i.e., if \a config 2343 * has a parent, then \a config is removed from the list of the parent's 2344 * children. 2345 * 2346 * This functions does \e not free the removed node. 2347 * 2348 * \sa snd_config_delete 2349 */ 2350int snd_config_remove(snd_config_t *config) 2351{ 2352 assert(config); 2353 if (config->parent) 2354 list_del(&config->list); 2355 config->parent = NULL; 2356 return 0; 2357} 2358 2359/** 2360 * \brief Frees a configuration node. 2361 * \param config Handle to the configuration node to be deleted. 2362 * \return Zero if successful, otherwise a negative error code. 2363 * 2364 * This function frees a configuration node and all its resources. 2365 * 2366 * If the node is a child node, it is removed from the tree before being 2367 * deleted. 2368 * 2369 * If the node is a compound node, its descendants (the whole subtree) 2370 * are deleted recursively. 2371 * 2372 * The function is supposed to be called only for locally copied config 2373 * trees. For the global tree, take the reference via #snd_config_update_ref 2374 * and free it via #snd_config_unref. 2375 * 2376 * \par Conforming to: 2377 * LSB 3.2 2378 * 2379 * \sa snd_config_remove 2380 */ 2381int snd_config_delete(snd_config_t *config) 2382{ 2383 assert(config); 2384 if (config->refcount > 0) { 2385 config->refcount--; 2386 return 0; 2387 } 2388 switch (config->type) { 2389 case SND_CONFIG_TYPE_COMPOUND: 2390 { 2391 int err; 2392 struct list_head *i; 2393 i = config->u.compound.fields.next; 2394 while (i != &config->u.compound.fields) { 2395 struct list_head *nexti = i->next; 2396 snd_config_t *child = snd_config_iterator_entry(i); 2397 err = snd_config_delete(child); 2398 if (err < 0) 2399 return err; 2400 i = nexti; 2401 } 2402 break; 2403 } 2404 case SND_CONFIG_TYPE_STRING: 2405 free(config->u.string); 2406 break; 2407 default: 2408 break; 2409 } 2410 if (config->parent) 2411 list_del(&config->list); 2412 free(config->id); 2413 free(config); 2414 return 0; 2415} 2416 2417/** 2418 * \brief Deletes the children of a node. 2419 * \param config Handle to the compound configuration node. 2420 * \return Zero if successful, otherwise a negative error code. 2421 * 2422 * This function removes and frees all children of a configuration node. 2423 * 2424 * Any compound nodes among the children of \a config are deleted 2425 * recursively. 2426 * 2427 * After a successful call to this function, \a config is an empty 2428 * compound node. 2429 * 2430 * \par Errors: 2431 * <dl> 2432 * <dt>-EINVAL<dd>\a config is not a compound node. 2433 * </dl> 2434 */ 2435int snd_config_delete_compound_members(const snd_config_t *config) 2436{ 2437 int err; 2438 struct list_head *i; 2439 2440 assert(config); 2441 if (config->type != SND_CONFIG_TYPE_COMPOUND) 2442 return -EINVAL; 2443 i = config->u.compound.fields.next; 2444 while (i != &config->u.compound.fields) { 2445 struct list_head *nexti = i->next; 2446 snd_config_t *child = snd_config_iterator_entry(i); 2447 err = snd_config_delete(child); 2448 if (err < 0) 2449 return err; 2450 i = nexti; 2451 } 2452 return 0; 2453} 2454 2455/** 2456 * \brief Creates a configuration node. 2457 * \param[out] config The function puts the handle to the new node at 2458 * the address specified by \a config. 2459 * \param[in] id The id of the new node. 2460 * \param[in] type The type of the new node. 2461 * \return Zero if successful, otherwise a negative error code. 2462 * 2463 * This functions creates a new node of the specified type. 2464 * The new node has id \a id, which may be \c NULL. 2465 * 2466 * The value of the new node is zero (for numbers), or \c NULL (for 2467 * strings and pointers), or empty (for compound nodes). 2468 * 2469 * \par Errors: 2470 * <dl> 2471 * <dt>-ENOMEM<dd>Out of memory. 2472 * </dl> 2473 */ 2474int snd_config_make(snd_config_t **config, const char *id, 2475 snd_config_type_t type) 2476{ 2477 char *id1; 2478 assert(config); 2479 if (id) { 2480 id1 = strdup(id); 2481 if (!id1) 2482 return -ENOMEM; 2483 } else 2484 id1 = NULL; 2485 return _snd_config_make(config, &id1, type); 2486} 2487 2488/** 2489 * \brief Creates an integer configuration node. 2490 * \param[out] config The function puts the handle to the new node at 2491 * the address specified by \a config. 2492 * \param[in] id The id of the new node. 2493 * \return Zero if successful, otherwise a negative error code. 2494 * 2495 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and 2496 * with value \c 0. 2497 * 2498 * \par Errors: 2499 * <dl> 2500 * <dt>-ENOMEM<dd>Out of memory. 2501 * </dl> 2502 * 2503 * \par Conforming to: 2504 * LSB 3.2 2505 * 2506 * \sa snd_config_imake_integer 2507 */ 2508int snd_config_make_integer(snd_config_t **config, const char *id) 2509{ 2510 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER); 2511} 2512 2513/** 2514 * \brief Creates a 64-bit-integer configuration node. 2515 * \param[out] config The function puts the handle to the new node at 2516 * the address specified by \a config. 2517 * \param[in] id The id of the new node. 2518 * \return Zero if successful, otherwise a negative error code. 2519 * 2520 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64 2521 * and with value \c 0. 2522 * 2523 * \par Errors: 2524 * <dl> 2525 * <dt>-ENOMEM<dd>Out of memory. 2526 * </dl> 2527 * 2528 * \par Conforming to: 2529 * LSB 3.2 2530 * 2531 * \sa snd_config_imake_integer64 2532 */ 2533int snd_config_make_integer64(snd_config_t **config, const char *id) 2534{ 2535 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64); 2536} 2537 2538/** 2539 * \brief Creates a real number configuration node. 2540 * \param[out] config The function puts the handle to the new node at 2541 * the address specified by \a config. 2542 * \param[in] id The id of the new node. 2543 * \return Zero if successful, otherwise a negative error code. 2544 * 2545 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and 2546 * with value \c 0.0. 2547 * 2548 * \par Errors: 2549 * <dl> 2550 * <dt>-ENOMEM<dd>Out of memory. 2551 * </dl> 2552 * 2553 * \sa snd_config_imake_real 2554 */ 2555int snd_config_make_real(snd_config_t **config, const char *id) 2556{ 2557 return snd_config_make(config, id, SND_CONFIG_TYPE_REAL); 2558} 2559 2560/** 2561 * \brief Creates a string configuration node. 2562 * \param[out] config The function puts the handle to the new node at 2563 * the address specified by \a config. 2564 * \param[in] id The id of the new node. 2565 * \return Zero if successful, otherwise a negative error code. 2566 * 2567 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and 2568 * with value \c NULL. 2569 * 2570 * \par Errors: 2571 * <dl> 2572 * <dt>-ENOMEM<dd>Out of memory. 2573 * </dl> 2574 * 2575 * \par Conforming to: 2576 * LSB 3.2 2577 * 2578 * \sa snd_config_imake_string 2579 */ 2580int snd_config_make_string(snd_config_t **config, const char *id) 2581{ 2582 return snd_config_make(config, id, SND_CONFIG_TYPE_STRING); 2583} 2584 2585/** 2586 * \brief Creates a pointer configuration node. 2587 * \param[out] config The function puts the handle to the new node at 2588 * the address specified by \a config. 2589 * \param[in] id The id of the new node. 2590 * \return Zero if successful, otherwise a negative error code. 2591 * 2592 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and 2593 * with value \c NULL. 2594 * 2595 * \par Errors: 2596 * <dl> 2597 * <dt>-ENOMEM<dd>Out of memory. 2598 * </dl> 2599 * 2600 * \sa snd_config_imake_pointer 2601 */ 2602int snd_config_make_pointer(snd_config_t **config, const char *id) 2603{ 2604 return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER); 2605} 2606 2607/** 2608 * \brief Creates an empty compound configuration node. 2609 * \param[out] config The function puts the handle to the new node at 2610 * the address specified by \a config. 2611 * \param[in] id The id of the new node. 2612 * \param[in] join Join flag. 2613 * \return Zero if successful, otherwise a negative error code. 2614 * 2615 * This function creates a new empty node of type 2616 * #SND_CONFIG_TYPE_COMPOUND. 2617 * 2618 * \a join determines how the compound node's id is printed when the 2619 * configuration is saved to a text file. For example, if the join flag 2620 * of compound node \c a is zero, the output will look as follows: 2621 * \code 2622 * a { 2623 * b "hello" 2624 * c 42 2625 * } 2626 * \endcode 2627 * If, however, the join flag of \c a is nonzero, its id will be joined 2628 * with its children's ids, like this: 2629 * \code 2630 * a.b "hello" 2631 * a.c 42 2632 * \endcode 2633 * An \e empty compound node with its join flag set would result in no 2634 * output, i.e., after saving and reloading the configuration file, that 2635 * compound node would be lost. 2636 * 2637 * \par Errors: 2638 * <dl> 2639 * <dt>-ENOMEM<dd>Out of memory. 2640 * </dl> 2641 * 2642 * \par Conforming to: 2643 * LSB 3.2 2644 */ 2645int snd_config_make_compound(snd_config_t **config, const char *id, 2646 int join) 2647{ 2648 int err; 2649 err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND); 2650 if (err < 0) 2651 return err; 2652 (*config)->u.compound.join = join; 2653 return 0; 2654} 2655 2656/** 2657 * \brief Creates an empty compound configuration node in the path. 2658 * \param[out] config The function puts the handle to the new or 2659 * existing compound node at the address specified 2660 * by \a config. 2661 * \param[in] root The id of the new node. 2662 * \param[in] key The id of the new node. 2663 * \param[in] join Join flag. 2664 * \param[in] override Override flag. 2665 * \return Zero if successful, otherwise a negative error code. 2666 * 2667 * This function creates a new empty node of type 2668 * #SND_CONFIG_TYPE_COMPOUND if the path does not exist. Otherwise, 2669 * the node from the current configuration tree is returned without 2670 * any modification. The \a join argument is ignored in this case. 2671 * 2672 * \a join determines how the compound node's id is printed when the 2673 * configuration is saved to a text file. For example, if the join flag 2674 * of compound node \c a is zero, the output will look as follows: 2675 * \code 2676 * a { 2677 * b "hello" 2678 * c 42 2679 * } 2680 * \endcode 2681 * If, however, the join flag of \c a is nonzero, its id will be joined 2682 * with its children's ids, like this: 2683 * \code 2684 * a.b "hello" 2685 * a.c 42 2686 * \endcode 2687 * An \e empty compound node with its join flag set would result in no 2688 * output, i.e., after saving and reloading the configuration file, that 2689 * compound node would be lost. 2690 * 2691 * \par Errors: 2692 * <dl> 2693 * <dt>-ENOMEM<dd>Out of memory. 2694 * <dt>-EACCESS<dd>Path exists, but it's not a compound (!override) 2695 * </dl> 2696 */ 2697int snd_config_make_path(snd_config_t **config, snd_config_t *root, 2698 const char *key, int join, int override) 2699{ 2700 snd_config_t *n; 2701 const char *p; 2702 int err; 2703 2704 while (1) { 2705 p = strchr(key, '.'); 2706 if (p) { 2707 err = _snd_config_search(root, key, p - key, &n); 2708 if (err < 0) { 2709 size_t l = p - key; 2710 char *s = malloc(l + 1); 2711 if (s == NULL) 2712 return -ENOMEM; 2713 strncpy(s, key, l); 2714 s[l] = '\0'; 2715 err = snd_config_make_compound(&n, s, join); 2716 free(s); 2717 if (err < 0) 2718 return err; 2719 err = snd_config_add(root, n); 2720 if (err < 0) 2721 return err; 2722 } 2723 root = n; 2724 key = p + 1; 2725 } else { 2726 err = _snd_config_search(root, key, -1, config); 2727 if (err == 0) { 2728 if ((*config)->type != SND_CONFIG_TYPE_COMPOUND) { 2729 if (override) { 2730 err = snd_config_delete(*config); 2731 if (err < 0) 2732 return err; 2733 goto __make; 2734 } else { 2735 return -EACCES; 2736 } 2737 } 2738 return 0; 2739 } 2740__make: 2741 err = snd_config_make_compound(&n, key, join); 2742 if (err < 0) 2743 return err; 2744 err = snd_config_add(root, n); 2745 if (err < 0) 2746 return err; 2747 *config = n; 2748 return 0; 2749 } 2750 } 2751} 2752 2753/** 2754 * \brief Creates an integer configuration node with the given initial value. 2755 * \param[out] config The function puts the handle to the new node at 2756 * the address specified by \a config. 2757 * \param[in] id The id of the new node. 2758 * \param[in] value The initial value of the new node. 2759 * \return Zero if successful, otherwise a negative error code. 2760 * 2761 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and 2762 * with value \a value. 2763 * 2764 * \par Errors: 2765 * <dl> 2766 * <dt>-ENOMEM<dd>Out of memory. 2767 * </dl> 2768 * 2769 * \par Conforming to: 2770 * LSB 3.2 2771 */ 2772int snd_config_imake_integer(snd_config_t **config, const char *id, const long value) 2773{ 2774 int err; 2775 2776 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER); 2777 if (err < 0) 2778 return err; 2779 (*config)->u.integer = value; 2780 return 0; 2781} 2782 2783/** 2784 * \brief Creates a 64-bit-integer configuration node with the given initial value. 2785 * \param[out] config The function puts the handle to the new node at 2786 * the address specified by \a config. 2787 * \param[in] id The id of the new node. 2788 * \param[in] value The initial value of the new node. 2789 * \return Zero if successful, otherwise a negative error code. 2790 * 2791 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64 2792 * and with value \a value. 2793 * 2794 * \par Errors: 2795 * <dl> 2796 * <dt>-ENOMEM<dd>Out of memory. 2797 * </dl> 2798 * 2799 * \par Conforming to: 2800 * LSB 3.2 2801 */ 2802int snd_config_imake_integer64(snd_config_t **config, const char *id, const long long value) 2803{ 2804 int err; 2805 2806 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64); 2807 if (err < 0) 2808 return err; 2809 (*config)->u.integer64 = value; 2810 return 0; 2811} 2812 2813/** 2814 * \brief Creates a real number configuration node with the given initial value. 2815 * \param[out] config The function puts the handle to the new node at 2816 * the address specified by \a config. 2817 * \param[in] id The id of the new node. 2818 * \param[in] value The initial value of the new node. 2819 * \return Zero if successful, otherwise a negative error code. 2820 * 2821 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and 2822 * with value \a value. 2823 * 2824 * \par Errors: 2825 * <dl> 2826 * <dt>-ENOMEM<dd>Out of memory. 2827 * </dl> 2828 */ 2829int snd_config_imake_real(snd_config_t **config, const char *id, const double value) 2830{ 2831 int err; 2832 2833 err = snd_config_make(config, id, SND_CONFIG_TYPE_REAL); 2834 if (err < 0) 2835 return err; 2836 (*config)->u.real = value; 2837 return 0; 2838} 2839 2840/** 2841 * \brief Creates a string configuration node with the given initial value. 2842 * \param[out] config The function puts the handle to the new node at 2843 * the address specified by \a config. 2844 * \param[in] id The id of the new node. 2845 * \param[in] value The initial value of the new node. May be \c NULL. 2846 * \return Zero if successful, otherwise a negative error code. 2847 * 2848 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and 2849 * with a copy of the string \c value. 2850 * 2851 * \par Errors: 2852 * <dl> 2853 * <dt>-ENOMEM<dd>Out of memory. 2854 * </dl> 2855 * 2856 * \par Conforming to: 2857 * LSB 3.2 2858 */ 2859int snd_config_imake_string(snd_config_t **config, const char *id, const char *value) 2860{ 2861 int err; 2862 snd_config_t *tmp; 2863 2864 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING); 2865 if (err < 0) 2866 return err; 2867 if (value) { 2868 tmp->u.string = strdup(value); 2869 if (!tmp->u.string) { 2870 snd_config_delete(tmp); 2871 return -ENOMEM; 2872 } 2873 } else { 2874 tmp->u.string = NULL; 2875 } 2876 *config = tmp; 2877 return 0; 2878} 2879 2880/** 2881 * \brief Creates a string configuration node with the given initial value. 2882 * \param[out] config The function puts the handle to the new node at 2883 * the address specified by \a config. 2884 * \param[in] id The id of the new node. 2885 * \param[in] value The initial value of the new node. May be \c NULL. 2886 * \return Zero if successful, otherwise a negative error code. 2887 * 2888 * This function creates a new node of type #SND_CONFIG_TYPE_STRING. The node 2889 * contains with a copy of the string \c value, replacing any character other 2890 * than alphanumeric, space, or '-' with the character '_'. 2891 * 2892 * \par Errors: 2893 * <dl> 2894 * <dt>-ENOMEM<dd>Out of memory. 2895 * </dl> 2896 * 2897 * \par Conforming to: 2898 * LSB 3.2 2899 */ 2900int snd_config_imake_safe_string(snd_config_t **config, const char *id, const char *value) 2901{ 2902 int err; 2903 snd_config_t *tmp; 2904 char *c; 2905 2906 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING); 2907 if (err < 0) 2908 return err; 2909 if (value) { 2910 tmp->u.string = strdup(value); 2911 if (!tmp->u.string) { 2912 snd_config_delete(tmp); 2913 return -ENOMEM; 2914 } 2915 2916 for (c = tmp->u.string; *c; c++) { 2917 if (*c == ' ' || *c == '-' || *c == '_' || 2918 (*c >= '0' && *c <= '9') || 2919 (*c >= 'a' && *c <= 'z') || 2920 (*c >= 'A' && *c <= 'Z')) 2921 continue; 2922 *c = '_'; 2923 } 2924 } else { 2925 tmp->u.string = NULL; 2926 } 2927 *config = tmp; 2928 return 0; 2929} 2930 2931 2932/** 2933 * \brief Creates a pointer configuration node with the given initial value. 2934 * \param[out] config The function puts the handle to the new node at 2935 * the address specified by \a config. 2936 * \param[in] id The id of the new node. 2937 * \param[in] value The initial value of the new node. 2938 * \return Zero if successful, otherwise a negative error code. 2939 * 2940 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and 2941 * with value \c value. 2942 * 2943 * \par Errors: 2944 * <dl> 2945 * <dt>-ENOMEM<dd>Out of memory. 2946 * </dl> 2947 */ 2948int snd_config_imake_pointer(snd_config_t **config, const char *id, const void *value) 2949{ 2950 int err; 2951 2952 err = snd_config_make(config, id, SND_CONFIG_TYPE_POINTER); 2953 if (err < 0) 2954 return err; 2955 (*config)->u.ptr = value; 2956 return 0; 2957} 2958 2959/** 2960 * \brief Changes the value of an integer configuration node. 2961 * \param config Handle to the configuration node. 2962 * \param value The new value for the node. 2963 * \return Zero if successful, otherwise a negative error code. 2964 * 2965 * \par Errors: 2966 * <dl> 2967 * <dt>-EINVAL<dd>\a config is not an integer node. 2968 * </dl> 2969 * 2970 * \par Conforming to: 2971 * LSB 3.2 2972 */ 2973int snd_config_set_integer(snd_config_t *config, long value) 2974{ 2975 assert(config); 2976 if (config->type != SND_CONFIG_TYPE_INTEGER) 2977 return -EINVAL; 2978 config->u.integer = value; 2979 return 0; 2980} 2981 2982/** 2983 * \brief Changes the value of a 64-bit-integer configuration node. 2984 * \param config Handle to the configuration node. 2985 * \param value The new value for the node. 2986 * \return Zero if successful, otherwise a negative error code. 2987 * 2988 * \par Errors: 2989 * <dl> 2990 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node. 2991 * </dl> 2992 * 2993 * \par Conforming to: 2994 * LSB 3.2 2995 */ 2996int snd_config_set_integer64(snd_config_t *config, long long value) 2997{ 2998 assert(config); 2999 if (config->type != SND_CONFIG_TYPE_INTEGER64) 3000 return -EINVAL; 3001 config->u.integer64 = value; 3002 return 0; 3003} 3004 3005/** 3006 * \brief Changes the value of a real-number configuration node. 3007 * \param config Handle to the configuration node. 3008 * \param value The new value for the node. 3009 * \return Zero if successful, otherwise a negative error code. 3010 * 3011 * \par Errors: 3012 * <dl> 3013 * <dt>-EINVAL<dd>\a config is not a real-number node. 3014 * </dl> 3015 */ 3016int snd_config_set_real(snd_config_t *config, double value) 3017{ 3018 assert(config); 3019 if (config->type != SND_CONFIG_TYPE_REAL) 3020 return -EINVAL; 3021 config->u.real = value; 3022 return 0; 3023} 3024 3025/** 3026 * \brief Changes the value of a string configuration node. 3027 * \param config Handle to the configuration node. 3028 * \param value The new value for the node. May be \c NULL. 3029 * \return Zero if successful, otherwise a negative error code. 3030 * 3031 * This function deletes the old string in the node and stores a copy of 3032 * \a value string in the node. 3033 * 3034 * \par Errors: 3035 * <dl> 3036 * <dt>-EINVAL<dd>\a config is not a string node. 3037 * </dl> 3038 * 3039 * \par Conforming to: 3040 * LSB 3.2 3041 */ 3042int snd_config_set_string(snd_config_t *config, const char *value) 3043{ 3044 char *new_string; 3045 assert(config); 3046 if (config->type != SND_CONFIG_TYPE_STRING) 3047 return -EINVAL; 3048 if (value) { 3049 new_string = strdup(value); 3050 if (!new_string) 3051 return -ENOMEM; 3052 } else { 3053 new_string = NULL; 3054 } 3055 free(config->u.string); 3056 config->u.string = new_string; 3057 return 0; 3058} 3059 3060/** 3061 * \brief Changes the value of a pointer configuration node. 3062 * \param config Handle to the configuration node. 3063 * \param value The new value for the node. May be \c NULL. 3064 * \return Zero if successful, otherwise a negative error code. 3065 * 3066 * This function does not free the old pointer in the node. 3067 * 3068 * \par Errors: 3069 * <dl> 3070 * <dt>-EINVAL<dd>\a config is not a pointer node. 3071 * </dl> 3072 */ 3073int snd_config_set_pointer(snd_config_t *config, const void *value) 3074{ 3075 assert(config); 3076 if (config->type != SND_CONFIG_TYPE_POINTER) 3077 return -EINVAL; 3078 config->u.ptr = value; 3079 return 0; 3080} 3081 3082/** 3083 * \brief Changes the value of a configuration node. 3084 * \param config Handle to the configuration node. 3085 * \param ascii The new value for the node, as an ASCII string. 3086 * \return Zero if successful, otherwise a negative error code. 3087 * 3088 * This function changes the node's value to a new value that is parsed 3089 * from the string \a ascii. \a ascii must not be \c NULL, not even for 3090 * a string node. 3091 * 3092 * The node's type does not change, i.e., the string must contain a 3093 * valid value with the same type as the node's type. For a string 3094 * node, the node's new value is a copy of \a ascii. 3095 * 3096 * \par Errors: 3097 * <dl> 3098 * <dt>-EINVAL<dd>\a config is not a number or string node. 3099 * <dt>-EINVAL<dd>The value in \a ascii cannot be parsed. 3100 * <dt>-ERANGE<dd>The value in \a ascii is too big for the node's type. 3101 * <dt>-ENOMEM<dd>Out of memory. 3102 * </dl> 3103 * 3104 * \par Conforming to: 3105 * LSB 3.2 3106 */ 3107int snd_config_set_ascii(snd_config_t *config, const char *ascii) 3108{ 3109 assert(config && ascii); 3110 switch (config->type) { 3111 case SND_CONFIG_TYPE_INTEGER: 3112 { 3113 long i; 3114 int err = safe_strtol(ascii, &i); 3115 if (err < 0) 3116 return err; 3117 config->u.integer = i; 3118 } 3119 break; 3120 case SND_CONFIG_TYPE_INTEGER64: 3121 { 3122 long long i; 3123 int err = safe_strtoll(ascii, &i); 3124 if (err < 0) 3125 return err; 3126 config->u.integer64 = i; 3127 } 3128 break; 3129 case SND_CONFIG_TYPE_REAL: 3130 { 3131 double d; 3132 int err = safe_strtod(ascii, &d); 3133 if (err < 0) 3134 return err; 3135 config->u.real = d; 3136 break; 3137 } 3138 case SND_CONFIG_TYPE_STRING: 3139 { 3140 char *ptr = strdup(ascii); 3141 if (ptr == NULL) 3142 return -ENOMEM; 3143 free(config->u.string); 3144 config->u.string = ptr; 3145 } 3146 break; 3147 default: 3148 return -EINVAL; 3149 } 3150 return 0; 3151} 3152 3153/** 3154 * \brief Returns the value of an integer configuration node. 3155 * \param[in] config Handle to the configuration node. 3156 * \param[out] ptr The node's value. 3157 * \return Zero if successful, otherwise a negative error code. 3158 * 3159 * \par Errors: 3160 * <dl> 3161 * <dt>-EINVAL<dd>\a config is not an integer node. 3162 * </dl> 3163 * 3164 * \par Conforming to: 3165 * LSB 3.2 3166 */ 3167int snd_config_get_integer(const snd_config_t *config, long *ptr) 3168{ 3169 assert(config && ptr); 3170 if (config->type != SND_CONFIG_TYPE_INTEGER) 3171 return -EINVAL; 3172 *ptr = config->u.integer; 3173 return 0; 3174} 3175 3176/** 3177 * \brief Returns the value of a 64-bit-integer configuration node. 3178 * \param[in] config Handle to the configuration node. 3179 * \param[out] ptr The node's value. 3180 * \return Zero if successful, otherwise a negative error code. 3181 * 3182 * \par Errors: 3183 * <dl> 3184 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node. 3185 * </dl> 3186 * 3187 * \par Conforming to: 3188 * LSB 3.2 3189 */ 3190int snd_config_get_integer64(const snd_config_t *config, long long *ptr) 3191{ 3192 assert(config && ptr); 3193 if (config->type != SND_CONFIG_TYPE_INTEGER64) 3194 return -EINVAL; 3195 *ptr = config->u.integer64; 3196 return 0; 3197} 3198 3199/** 3200 * \brief Returns the value of a real-number configuration node. 3201 * \param[in] config Handle to the configuration node. 3202 * \param[out] ptr The node's value. 3203 * \return Zero if successful, otherwise a negative error code. 3204 * 3205 * \par Errors: 3206 * <dl> 3207 * <dt>-EINVAL<dd>\a config is not a real-number node. 3208 * </dl> 3209 */ 3210int snd_config_get_real(const snd_config_t *config, double *ptr) 3211{ 3212 assert(config && ptr); 3213 if (config->type != SND_CONFIG_TYPE_REAL) 3214 return -EINVAL; 3215 *ptr = config->u.real; 3216 return 0; 3217} 3218 3219/** 3220 * \brief Returns the value of a real or integer configuration node. 3221 * \param[in] config Handle to the configuration node. 3222 * \param[out] ptr The node's value. 3223 * \return Zero if successful, otherwise a negative error code. 3224 * 3225 * If the node's type is integer or integer64, the value is converted 3226 * to the \c double type on the fly. 3227 * 3228 * \par Errors: 3229 * <dl> 3230 * <dt>-EINVAL<dd>\a config is not a number node. 3231 * </dl> 3232 */ 3233int snd_config_get_ireal(const snd_config_t *config, double *ptr) 3234{ 3235 assert(config && ptr); 3236 if (config->type == SND_CONFIG_TYPE_REAL) 3237 *ptr = config->u.real; 3238 else if (config->type == SND_CONFIG_TYPE_INTEGER) 3239 *ptr = config->u.integer; 3240 else if (config->type == SND_CONFIG_TYPE_INTEGER64) 3241 *ptr = config->u.integer64; 3242 else 3243 return -EINVAL; 3244 return 0; 3245} 3246 3247/** 3248 * \brief Returns the value of a string configuration node. 3249 * \param[in] config Handle to the configuration node. 3250 * \param[out] ptr The function puts the node's value at the address 3251 * specified by \a ptr. 3252 * \return Zero if successful, otherwise a negative error code. 3253 * 3254 * The returned string is owned by the configuration node; the 3255 * application must not modify or delete it, and the string becomes 3256 * invalid when the node's value changes or when the node is freed. 3257 * 3258 * The string may be \c NULL. 3259 * 3260 * \par Errors: 3261 * <dl> 3262 * <dt>-EINVAL<dd>\a config is not a string node. 3263 * </dl> 3264 * 3265 * \par Conforming to: 3266 * LSB 3.2 3267 */ 3268int snd_config_get_string(const snd_config_t *config, const char **ptr) 3269{ 3270 assert(config && ptr); 3271 if (config->type != SND_CONFIG_TYPE_STRING) 3272 return -EINVAL; 3273 *ptr = config->u.string; 3274 return 0; 3275} 3276 3277/** 3278 * \brief Returns the value of a pointer configuration node. 3279 * \param[in] config Handle to the configuration node. 3280 * \param[out] ptr The function puts the node's value at the address 3281 * specified by \a ptr. 3282 * \return Zero if successful, otherwise a negative error code. 3283 * 3284 * \par Errors: 3285 * <dl> 3286 * <dt>-EINVAL<dd>\a config is not a string node. 3287 * </dl> 3288 */ 3289int snd_config_get_pointer(const snd_config_t *config, const void **ptr) 3290{ 3291 assert(config && ptr); 3292 if (config->type != SND_CONFIG_TYPE_POINTER) 3293 return -EINVAL; 3294 *ptr = config->u.ptr; 3295 return 0; 3296} 3297 3298/** 3299 * \brief Returns the value of a configuration node as a string. 3300 * \param[in] config Handle to the configuration node. 3301 * \param[out] ascii The function puts the pointer to the returned 3302 * string at the address specified by \a ascii. 3303 * \return Zero if successful, otherwise a negative error code. 3304 * 3305 * This function dynamically allocates the returned string. The 3306 * application is responsible for deleting it with \c free() when it is 3307 * no longer used. 3308 * 3309 * For a string node with \c NULL value, the returned string is \c NULL. 3310 * 3311 * Supported node types are #SND_CONFIG_TYPE_INTEGER, 3312 * #SND_CONFIG_TYPE_INTEGER64, #SND_CONFIG_TYPE_REAL, and 3313 * #SND_CONFIG_TYPE_STRING. 3314 * 3315 * \par Errors: 3316 * <dl> 3317 * <dt>-EINVAL<dd>\a config is not a (64-bit) integer or real number or 3318 * string node. 3319 * <dt>-ENOMEM<dd>Out of memory. 3320 * </dl> 3321 * 3322 * \par Conforming to: 3323 * LSB 3.2 3324 */ 3325int snd_config_get_ascii(const snd_config_t *config, char **ascii) 3326{ 3327 assert(config && ascii); 3328 switch (config->type) { 3329 case SND_CONFIG_TYPE_INTEGER: 3330 { 3331 char res[12]; 3332 int err; 3333 err = snprintf(res, sizeof(res), "%li", config->u.integer); 3334 if (err < 0 || err == sizeof(res)) { 3335 assert(0); 3336 return -ENOMEM; 3337 } 3338 *ascii = strdup(res); 3339 } 3340 break; 3341 case SND_CONFIG_TYPE_INTEGER64: 3342 { 3343 char res[32]; 3344 int err; 3345 err = snprintf(res, sizeof(res), "%lli", config->u.integer64); 3346 if (err < 0 || err == sizeof(res)) { 3347 assert(0); 3348 return -ENOMEM; 3349 } 3350 *ascii = strdup(res); 3351 } 3352 break; 3353 case SND_CONFIG_TYPE_REAL: 3354 { 3355 char res[32]; 3356 int err; 3357 err = snprintf(res, sizeof(res), "%-16g", config->u.real); 3358 if (err < 0 || err == sizeof(res)) { 3359 assert(0); 3360 return -ENOMEM; 3361 } 3362 if (res[0]) { /* trim the string */ 3363 char *ptr; 3364 ptr = res + strlen(res) - 1; 3365 while (ptr != res && *ptr == ' ') 3366 ptr--; 3367 if (*ptr != ' ') 3368 ptr++; 3369 *ptr = '\0'; 3370 } 3371 *ascii = strdup(res); 3372 } 3373 break; 3374 case SND_CONFIG_TYPE_STRING: 3375 if (config->u.string) 3376 *ascii = strdup(config->u.string); 3377 else { 3378 *ascii = NULL; 3379 return 0; 3380 } 3381 break; 3382 default: 3383 return -EINVAL; 3384 } 3385 if (*ascii == NULL) 3386 return -ENOMEM; 3387 return 0; 3388} 3389 3390/** 3391 * \brief Compares the id of a configuration node to a given string. 3392 * \param config Handle to the configuration node. 3393 * \param id ASCII id. 3394 * \return The same value as the result of the \c strcmp function, i.e., 3395 * less than zero if \a config's id is lexicographically less 3396 * than \a id, zero if \a config's id is equal to id, greater 3397 * than zero otherwise. 3398 */ 3399int snd_config_test_id(const snd_config_t *config, const char *id) 3400{ 3401 assert(config && id); 3402 if (config->id) 3403 return strcmp(config->id, id); 3404 else 3405 return -1; 3406} 3407 3408/** 3409 * \brief Dumps the contents of a configuration node or tree. 3410 * \param config Handle to the (root) configuration node. 3411 * \param out Output handle. 3412 * \return Zero if successful, otherwise a negative error code. 3413 * 3414 * This function writes a textual representation of \a config's value to 3415 * the output \a out. 3416 * 3417 * \par Errors: 3418 * <dl> 3419 * <dt>-EINVAL<dd>A node in the tree has a type that cannot be printed, 3420 * i.e., #SND_CONFIG_TYPE_POINTER. 3421 * </dl> 3422 * 3423 * \par Conforming to: 3424 * LSB 3.2 3425 */ 3426int snd_config_save(snd_config_t *config, snd_output_t *out) 3427{ 3428 assert(config && out); 3429 if (config->type == SND_CONFIG_TYPE_COMPOUND) { 3430 int array = snd_config_is_array(config); 3431 return _snd_config_save_children(config, out, 0, 0, array); 3432 } else { 3433 return _snd_config_save_node_value(config, out, 0); 3434 } 3435} 3436 3437/* 3438 * *** search macros *** 3439 */ 3440 3441#ifndef DOC_HIDDEN 3442 3443#define SND_CONFIG_SEARCH(config, key, result, extra_code) \ 3444{ \ 3445 snd_config_t *n; \ 3446 int err; \ 3447 const char *p; \ 3448 assert(config && key); \ 3449 while (1) { \ 3450 if (config->type != SND_CONFIG_TYPE_COMPOUND) \ 3451 return -ENOENT; \ 3452 { extra_code ; } \ 3453 p = strchr(key, '.'); \ 3454 if (p) { \ 3455 err = _snd_config_search(config, key, p - key, &n); \ 3456 if (err < 0) \ 3457 return err; \ 3458 config = n; \ 3459 key = p + 1; \ 3460 } else \ 3461 return _snd_config_search(config, key, -1, result); \ 3462 } \ 3463} 3464 3465#define SND_CONFIG_SEARCHA(root, config, key, result, fcn, extra_code) \ 3466{ \ 3467 snd_config_t *n; \ 3468 int err; \ 3469 const char *p; \ 3470 assert(config && key); \ 3471 while (1) { \ 3472 if (config->type != SND_CONFIG_TYPE_COMPOUND) { \ 3473 if (snd_config_get_string(config, &p) < 0) \ 3474 return -ENOENT; \ 3475 err = fcn(root, root, p, &config); \ 3476 if (err < 0) \ 3477 return err; \ 3478 } \ 3479 { extra_code ; } \ 3480 p = strchr(key, '.'); \ 3481 if (p) { \ 3482 err = _snd_config_search(config, key, p - key, &n); \ 3483 if (err < 0) \ 3484 return err; \ 3485 config = n; \ 3486 key = p + 1; \ 3487 } else \ 3488 return _snd_config_search(config, key, -1, result); \ 3489 } \ 3490} 3491 3492#define SND_CONFIG_SEARCHV(config, result, fcn) \ 3493{ \ 3494 snd_config_t *n; \ 3495 va_list arg; \ 3496 assert(config); \ 3497 va_start(arg, result); \ 3498 while (1) { \ 3499 const char *k = va_arg(arg, const char *); \ 3500 int err; \ 3501 if (!k) \ 3502 break; \ 3503 err = fcn(config, k, &n); \ 3504 if (err < 0) { \ 3505 va_end(arg); \ 3506 return err; \ 3507 } \ 3508 config = n; \ 3509 } \ 3510 va_end(arg); \ 3511 if (result) \ 3512 *result = n; \ 3513 return 0; \ 3514} 3515 3516#define SND_CONFIG_SEARCHVA(root, config, result, fcn) \ 3517{ \ 3518 snd_config_t *n; \ 3519 va_list arg; \ 3520 assert(config); \ 3521 va_start(arg, result); \ 3522 while (1) { \ 3523 const char *k = va_arg(arg, const char *); \ 3524 int err; \ 3525 if (!k) \ 3526 break; \ 3527 err = fcn(root, config, k, &n); \ 3528 if (err < 0) { \ 3529 va_end(arg); \ 3530 return err; \ 3531 } \ 3532 config = n; \ 3533 } \ 3534 va_end(arg); \ 3535 if (result) \ 3536 *result = n; \ 3537 return 0; \ 3538} 3539 3540#define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \ 3541{ \ 3542 snd_config_t *res = NULL; \ 3543 char *old_key; \ 3544 int err, first = 1, maxloop = 1000; \ 3545 assert(config && key); \ 3546 while (1) { \ 3547 old_key = strdup(key); \ 3548 if (old_key == NULL) { \ 3549 err = -ENOMEM; \ 3550 res = NULL; \ 3551 break; \ 3552 } \ 3553 err = first && base ? -EIO : fcn1(config, config, key, &res); \ 3554 if (err < 0) { \ 3555 if (!base) \ 3556 break; \ 3557 err = fcn2(config, config, &res, base, key, NULL); \ 3558 if (err < 0) \ 3559 break; \ 3560 } \ 3561 if (snd_config_get_string(res, &key) < 0) \ 3562 break; \ 3563 assert(key); \ 3564 if (!first && (strcmp(key, old_key) == 0 || maxloop <= 0)) { \ 3565 if (maxloop == 0) \ 3566 SNDERR("maximum loop count reached (circular configuration?)"); \ 3567 else \ 3568 SNDERR("key %s refers to itself", key); \ 3569 err = -EINVAL; \ 3570 res = NULL; \ 3571 break; \ 3572 } \ 3573 free(old_key); \ 3574 first = 0; \ 3575 maxloop--; \ 3576 } \ 3577 free(old_key); \ 3578 if (!res) \ 3579 return err; \ 3580 if (result) \ 3581 *result = res; \ 3582 return 0; \ 3583} 3584 3585#endif /* DOC_HIDDEN */ 3586 3587/** 3588 * \brief Searches for a node in a configuration tree. 3589 * \param[in] config Handle to the root of the configuration (sub)tree to search. 3590 * \param[in] key Search key: one or more node ids, separated with dots. 3591 * \param[out] result When \a result != \c NULL, the function puts the 3592 * handle to the node found at the address specified 3593 * by \a result. 3594 * \return Zero if successful, otherwise a negative error code. 3595 * 3596 * This function searches for a child node of \a config that is 3597 * identified by \a key, which contains either the id of a direct child 3598 * node of \a config, or a series of ids, separated with dots, where 3599 * each id specifies a node that is contained in the previous compound 3600 * node. 3601 * 3602 * In the following example, the comment after each node shows the 3603 * search key to find that node, assuming that \a config is a handle to 3604 * the compound node with id \c config: 3605 * \code 3606 * config { 3607 * a 42 # "a" 3608 * b { # "b" 3609 * c "cee" # "b.c" 3610 * d { # "b.d" 3611 * e 2.71828 # "b.d.e" 3612 * } 3613 * } 3614 * } 3615 * \endcode 3616 * 3617 * \par Errors: 3618 * <dl> 3619 * <dt>-ENOENT<dd>An id in \a key does not exist. 3620 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 3621 * not a compound node. 3622 * </dl> 3623 * 3624 * \par Conforming to: 3625 * LSB 3.2 3626 */ 3627int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result) 3628{ 3629 SND_CONFIG_SEARCH(config, key, result, ); 3630} 3631 3632/** 3633 * \brief Searches for a node in a configuration tree, expanding aliases. 3634 * \param[in] root Handle to the root configuration node containing 3635 * alias definitions. 3636 * \param[in] config Handle to the root of the configuration (sub)tree to search. 3637 * \param[in] key Search key: one or more node keys, separated with dots. 3638 * \param[out] result When \a result != \c NULL, the function puts the 3639 * handle to the node found at the address specified 3640 * by \a result. 3641 * \return Zero if successful, otherwise a negative error code. 3642 * 3643 * This functions searches for a child node of \a config like 3644 * #snd_config_search. However, any compound node can also be 3645 * identified by an alias, which is a string node whose value is taken 3646 * as the id of a compound node below \a root. 3647 * 3648 * \a root must be a compound node. 3649 * \a root and \a config may be the same node. 3650 * 3651 * For example, with the following configuration, the call 3652 * \code 3653 * snd_config_searcha(root, config, "a.b.c.d", &result); 3654 * \endcode 3655 * would return the node with id \c d: 3656 * \code 3657 * config { 3658 * a { 3659 * b bb 3660 * } 3661 * } 3662 * root { 3663 * bb { 3664 * c cc 3665 * } 3666 * cc ccc 3667 * ccc { 3668 * d { 3669 * x "icks" 3670 * } 3671 * } 3672 * } 3673 * \endcode 3674 * 3675 * \par Errors: 3676 * <dl> 3677 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist. 3678 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 3679 * not a compound or string node. 3680 * </dl> 3681 */ 3682int snd_config_searcha(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result) 3683{ 3684 SND_CONFIG_SEARCHA(root, config, key, result, snd_config_searcha, ); 3685} 3686 3687/** 3688 * \brief Searches for a node in a configuration tree. 3689 * \param[in] config Handle to the root of the configuration (sub)tree to search. 3690 * \param[out] result When \a result != \c NULL, the function puts the 3691 * handle to the node found at the address specified 3692 * by \a result. 3693 * \param[in] ... One or more concatenated dot-separated search keys, 3694 * terminated with \c NULL. 3695 * \return Zero if successful, otherwise a negative error code. 3696 * 3697 * This functions searches for a child node of \a config like 3698 * #snd_config_search, but the search key is the concatenation of all 3699 * passed search key strings. For example, the call 3700 * \code 3701 * snd_config_searchv(cfg, &res, "a", "b.c", "d.e", NULL); 3702 * \endcode 3703 * is equivalent to the call 3704 * \code 3705 * snd_config_search(cfg, "a.b.c.d.e", &res); 3706 * \endcode 3707 * 3708 * \par Errors: 3709 * <dl> 3710 * <dt>-ENOENT<dd>An id in a search key does not exist. 3711 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 3712 * not a compound node. 3713 * </dl> 3714 * 3715 * \par Conforming to: 3716 * LSB 3.2 3717 */ 3718int snd_config_searchv(snd_config_t *config, snd_config_t **result, ...) 3719{ 3720 SND_CONFIG_SEARCHV(config, result, snd_config_search); 3721} 3722 3723/** 3724 * \brief Searches for a node in a configuration tree, expanding aliases. 3725 * \param[in] root Handle to the root configuration node containing 3726 * alias definitions. 3727 * \param[in] config Handle to the root of the configuration (sub)tree to search. 3728 * \param[out] result When \a result != \c NULL, the function puts the 3729 * handle to the node found at the address specified 3730 * by \a result. 3731 * \param[in] ... One or more concatenated dot separated search keys, 3732 * terminated with \c NULL. 3733 * \return Zero if successful, otherwise a negative error code. 3734 * 3735 * This function searches for a child node of \a config, allowing 3736 * aliases, like #snd_config_searcha, but the search key is the 3737 * concatenation of all passed seach key strings, like with 3738 * #snd_config_searchv. 3739 * 3740 * \par Errors: 3741 * <dl> 3742 * <dt>-ENOENT<dd>An id in a search key does not exist. 3743 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 3744 * not a compound or string node. 3745 * </dl> 3746 */ 3747int snd_config_searchva(snd_config_t *root, snd_config_t *config, snd_config_t **result, ...) 3748{ 3749 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha); 3750} 3751 3752/** 3753 * \brief Searches for a node in a configuration tree, expanding aliases. 3754 * \param[in] config Handle to the root of the configuration (sub)tree to search. 3755 * \param[in] base Search key base, or \c NULL. 3756 * \param[in] key Search key suffix. 3757 * \param[out] result When \a result != \c NULL, the function puts the 3758 * handle to the node found at the address specified 3759 * by \a result. 3760 * \return Zero if successful, otherwise a negative error code. 3761 * 3762 * This functions searches for a child node of \a config, allowing 3763 * aliases, like #snd_config_searcha. However, alias definitions are 3764 * searched below \a config (there is no separate \a root parameter), 3765 * and \a base specifies a seach key that identifies a compound node 3766 * that is used to search for an alias definitions that is not found 3767 * directly below \a config and that does not contain a period. In 3768 * other words, when \c "id" is not found in \a config, this function 3769 * also tries \c "base.id". 3770 * 3771 * \par Errors: 3772 * <dl> 3773 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist. 3774 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 3775 * not a compound or string node. 3776 * </dl> 3777 */ 3778int snd_config_search_alias(snd_config_t *config, 3779 const char *base, const char *key, 3780 snd_config_t **result) 3781{ 3782 SND_CONFIG_SEARCH_ALIAS(config, base, key, result, 3783 snd_config_searcha, snd_config_searchva); 3784} 3785 3786static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data); 3787 3788/** 3789 * \brief Searches for a node in a configuration tree and expands hooks. 3790 * \param[in,out] config Handle to the root of the configuration 3791 * (sub)tree to search. 3792 * \param[in] key Search key: one or more node keys, separated with dots. 3793 * \param[out] result The function puts the handle to the node found at 3794 * the address specified by \a result. 3795 * \return Zero if successful, otherwise a negative error code. 3796 * 3797 * This functions searches for a child node of \a config like 3798 * #snd_config_search, but any compound nodes to be searched that 3799 * contain hooks are modified by the respective hook functions. 3800 * 3801 * \par Errors: 3802 * <dl> 3803 * <dt>-ENOENT<dd>An id in \a key does not exist. 3804 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 3805 * not a compound node. 3806 * </dl> 3807 * Additionally, any errors encountered when parsing the hook 3808 * definitions or returned by the hook functions. 3809 */ 3810int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result) 3811{ 3812 SND_CONFIG_SEARCH(config, key, result, \ 3813 err = snd_config_hooks(config, NULL); \ 3814 if (err < 0) \ 3815 return err; \ 3816 ); 3817} 3818 3819/** 3820 * \brief Searches for a node in a configuration tree, expanding aliases and hooks. 3821 * \param[in] root Handle to the root configuration node containing 3822 * alias definitions. 3823 * \param[in,out] config Handle to the root of the configuration 3824 * (sub)tree to search. 3825 * \param[in] key Search key: one or more node keys, separated with dots. 3826 * \param[out] result The function puts the handle to the node found at 3827 * the address specified by \a result. 3828 * \return Zero if successful, otherwise a negative error code. 3829 * 3830 * This function searches for a child node of \a config, allowing 3831 * aliases, like #snd_config_searcha, and expanding hooks, like 3832 * #snd_config_search_hooks. 3833 * 3834 * \par Errors: 3835 * <dl> 3836 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist. 3837 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 3838 * not a compound node. 3839 * </dl> 3840 * Additionally, any errors encountered when parsing the hook 3841 * definitions or returned by the hook functions. 3842 */ 3843int snd_config_searcha_hooks(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result) 3844{ 3845 SND_CONFIG_SEARCHA(root, config, key, result, 3846 snd_config_searcha_hooks, 3847 err = snd_config_hooks(config, NULL); \ 3848 if (err < 0) \ 3849 return err; \ 3850 ); 3851} 3852 3853/** 3854 * \brief Searches for a node in a configuration tree, expanding aliases and hooks. 3855 * \param[in] root Handle to the root configuration node containing 3856 * alias definitions. 3857 * \param[in,out] config Handle to the root of the configuration 3858 * (sub)tree to search. 3859 * \param[out] result The function puts the handle to the node found at 3860 * the address specified by \a result. 3861 * \param[in] ... One or more concatenated dot separated search keys, 3862 * terminated with \c NULL. 3863 * \return Zero if successful, otherwise a negative error code. 3864 * 3865 * This function searches for a child node of \a config, allowing 3866 * aliases and expanding hooks like #snd_config_searcha_hooks, but the 3867 * search key is the concatenation of all passed seach key strings, like 3868 * with #snd_config_searchv. 3869 * 3870 * \par Errors: 3871 * <dl> 3872 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist. 3873 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 3874 * not a compound node. 3875 * </dl> 3876 * Additionally, any errors encountered when parsing the hook 3877 * definitions or returned by the hook functions. 3878 */ 3879int snd_config_searchva_hooks(snd_config_t *root, snd_config_t *config, 3880 snd_config_t **result, ...) 3881{ 3882 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha_hooks); 3883} 3884 3885/** 3886 * \brief Searches for a node in a configuration tree, using an alias and expanding hooks. 3887 * \param[in] config Handle to the root of the configuration (sub)tree 3888 * to search. 3889 * \param[in] base Search key base, or \c NULL. 3890 * \param[in] key Search key suffix. 3891 * \param[out] result The function puts the handle to the node found at 3892 * the address specified by \a result. 3893 * \return Zero if successful, otherwise a negative error code. 3894 * 3895 * This functions searches for a child node of \a config, allowing 3896 * aliases, like #snd_config_search_alias, and expanding hooks, like 3897 * #snd_config_search_hooks. 3898 * 3899 * \par Errors: 3900 * <dl> 3901 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist. 3902 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 3903 * not a compound node. 3904 * </dl> 3905 * Additionally, any errors encountered when parsing the hook 3906 * definitions or returned by the hook functions. 3907 */ 3908int snd_config_search_alias_hooks(snd_config_t *config, 3909 const char *base, const char *key, 3910 snd_config_t **result) 3911{ 3912 SND_CONFIG_SEARCH_ALIAS(config, base, key, result, 3913 snd_config_searcha_hooks, 3914 snd_config_searchva_hooks); 3915} 3916 3917/** The name of the environment variable containing the files list for #snd_config_update. */ 3918#define ALSA_CONFIG_PATH_VAR "ALSA_CONFIG_PATH" 3919 3920/** 3921 * \brief Configuration top-level node (the global configuration). 3922 * 3923 * This variable contains a handle to the top-level configuration node, 3924 * as loaded from global configuration file. 3925 * 3926 * This variable is initialized or updated by #snd_config_update. 3927 * Functions like #snd_pcm_open (that use a device name from the global 3928 * configuration) automatically call #snd_config_update. Before the 3929 * first call to #snd_config_update, this variable is \c NULL. 3930 * 3931 * The global configuration files are specified in the environment 3932 * variable \c ALSA_CONFIG_PATH. If this is not set, the default value 3933 * is "/usr/share/alsa/alsa.conf". 3934 * 3935 * \warning Whenever the configuration tree is updated, all string 3936 * pointers and configuration node handles previously obtained from this 3937 * variable may become invalid. 3938 * 3939 * \par Conforming to: 3940 * LSB 3.2 3941 */ 3942snd_config_t *snd_config = NULL; 3943 3944#ifndef DOC_HIDDEN 3945struct finfo { 3946 char *name; 3947 dev_t dev; 3948 ino64_t ino; 3949 time_t mtime; 3950}; 3951 3952struct _snd_config_update { 3953 unsigned int count; 3954 struct finfo *finfo; 3955}; 3956#endif /* DOC_HIDDEN */ 3957 3958static snd_config_update_t *snd_config_global_update = NULL; 3959 3960static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data) 3961{ 3962 void *h = NULL; 3963 snd_config_t *c, *func_conf = NULL; 3964 char *buf = NULL, errbuf[256]; 3965 const char *lib = NULL, *func_name = NULL; 3966 const char *str; 3967 int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL; 3968 int err; 3969 3970 err = snd_config_search(config, "func", &c); 3971 if (err < 0) { 3972 SNDERR("Field func is missing"); 3973 return err; 3974 } 3975 err = snd_config_get_string(c, &str); 3976 if (err < 0) { 3977 SNDERR("Invalid type for field func"); 3978 return err; 3979 } 3980 assert(str); 3981 err = snd_config_search_definition(root, "hook_func", str, &func_conf); 3982 if (err >= 0) { 3983 snd_config_iterator_t i, next; 3984 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) { 3985 SNDERR("Invalid type for func %s definition", str); 3986 err = -EINVAL; 3987 goto _err; 3988 } 3989 snd_config_for_each(i, next, func_conf) { 3990 snd_config_t *n = snd_config_iterator_entry(i); 3991 const char *id = n->id; 3992 if (strcmp(id, "comment") == 0) 3993 continue; 3994 if (strcmp(id, "lib") == 0) { 3995 err = snd_config_get_string(n, &lib); 3996 if (err < 0) { 3997 SNDERR("Invalid type for %s", id); 3998 goto _err; 3999 } 4000 continue; 4001 } 4002 if (strcmp(id, "func") == 0) { 4003 err = snd_config_get_string(n, &func_name); 4004 if (err < 0) { 4005 SNDERR("Invalid type for %s", id); 4006 goto _err; 4007 } 4008 continue; 4009 } 4010 SNDERR("Unknown field %s", id); 4011 } 4012 } 4013 if (!func_name) { 4014 int len = 16 + strlen(str) + 1; 4015 buf = malloc(len); 4016 if (! buf) { 4017 err = -ENOMEM; 4018 goto _err; 4019 } 4020 snprintf(buf, len, "snd_config_hook_%s", str); 4021 buf[len-1] = '\0'; 4022 func_name = buf; 4023 } 4024 h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf)); 4025 func = h ? snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_HOOK)) : NULL; 4026 err = 0; 4027 if (!h) { 4028 SNDERR("Cannot open shared library %s (%s)", lib, errbuf); 4029 err = -ENOENT; 4030 } else if (!func) { 4031 SNDERR("symbol %s is not defined inside %s", func_name, lib); 4032 snd_dlclose(h); 4033 err = -ENXIO; 4034 } 4035 _err: 4036 if (func_conf) 4037 snd_config_delete(func_conf); 4038 if (err >= 0) { 4039 snd_config_t *nroot; 4040 err = func(root, config, &nroot, private_data); 4041 if (err < 0) 4042 SNDERR("function %s returned error: %s", func_name, snd_strerror(err)); 4043 snd_dlclose(h); 4044 if (err >= 0 && nroot) 4045 err = snd_config_substitute(root, nroot); 4046 } 4047 free(buf); 4048 if (err < 0) 4049 return err; 4050 return 0; 4051} 4052 4053static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data) 4054{ 4055 snd_config_t *n; 4056 snd_config_iterator_t i, next; 4057 int err, hit, idx = 0; 4058 4059 if ((err = snd_config_search(config, "@hooks", &n)) < 0) 4060 return 0; 4061 snd_config_lock(); 4062 snd_config_remove(n); 4063 do { 4064 hit = 0; 4065 snd_config_for_each(i, next, n) { 4066 snd_config_t *n = snd_config_iterator_entry(i); 4067 const char *id = n->id; 4068 long i; 4069 err = safe_strtol(id, &i); 4070 if (err < 0) { 4071 SNDERR("id of field %s is not and integer", id); 4072 err = -EINVAL; 4073 goto _err; 4074 } 4075 if (i == idx) { 4076 err = snd_config_hooks_call(config, n, private_data); 4077 if (err < 0) 4078 goto _err; 4079 idx++; 4080 hit = 1; 4081 } 4082 } 4083 } while (hit); 4084 err = 0; 4085 _err: 4086 snd_config_delete(n); 4087 snd_config_unlock(); 4088 return err; 4089} 4090 4091static int config_filename_filter(const struct dirent64 *dirent) 4092{ 4093 size_t flen; 4094 4095 if (dirent == NULL) 4096 return 0; 4097 if (dirent->d_type == DT_DIR) 4098 return 0; 4099 4100 flen = strlen(dirent->d_name); 4101 if (flen <= 5) 4102 return 0; 4103 4104 if (strncmp(&dirent->d_name[flen-5], ".conf", 5) == 0) 4105 return 1; 4106 4107 return 0; 4108} 4109 4110static int config_file_open(snd_config_t *root, const char *filename) 4111{ 4112 snd_input_t *in; 4113 int err; 4114 4115 err = snd_input_stdio_open(&in, filename, "r"); 4116 if (err >= 0) { 4117 err = snd_config_load(root, in); 4118 snd_input_close(in); 4119 if (err < 0) 4120 SNDERR("%s may be old or corrupted: consider to remove or fix it", filename); 4121 } else 4122 SNDERR("cannot access file %s", filename); 4123 4124 return err; 4125} 4126 4127static int config_file_load(snd_config_t *root, const char *fn, int errors) 4128{ 4129 struct stat64 st; 4130 struct dirent64 **namelist; 4131 int err, n; 4132 4133 if (!errors && access(fn, R_OK) < 0) 4134 return 1; 4135 if (stat64(fn, &st) < 0) { 4136 SNDERR("cannot stat file/directory %s", fn); 4137 return 1; 4138 } 4139 if (!S_ISDIR(st.st_mode)) 4140 return config_file_open(root, fn); 4141#ifndef DOC_HIDDEN 4142#if defined(_GNU_SOURCE) && !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__sun) && !defined(__ANDROID__) 4143#define SORTFUNC versionsort64 4144#else 4145#define SORTFUNC alphasort64 4146#endif 4147#endif 4148 n = scandir64(fn, &namelist, config_filename_filter, SORTFUNC); 4149 if (n > 0) { 4150 int j; 4151 err = 0; 4152 for (j = 0; j < n; ++j) { 4153 if (err >= 0) { 4154 int sl = strlen(fn) + strlen(namelist[j]->d_name) + 2; 4155 char *filename = malloc(sl); 4156 snprintf(filename, sl, "%s/%s", fn, namelist[j]->d_name); 4157 filename[sl-1] = '\0'; 4158 4159 err = config_file_open(root, filename); 4160 free(filename); 4161 } 4162 free(namelist[j]); 4163 } 4164 free(namelist); 4165 if (err < 0) 4166 return err; 4167 } 4168 return 0; 4169} 4170 4171static int config_file_load_user(snd_config_t *root, const char *fn, int errors) 4172{ 4173 char *fn2; 4174 int err; 4175 4176 err = snd_user_file(fn, &fn2); 4177 if (err < 0) 4178 return config_file_load(root, fn, errors); 4179 err = config_file_load(root, fn2, errors); 4180 free(fn2); 4181 return err; 4182} 4183 4184static int config_file_load_user_all(snd_config_t *_root, snd_config_t *_file, int errors) 4185{ 4186 snd_config_t *file = _file, *root = _root, *n; 4187 char *name, *name2, *remain, *rname = NULL; 4188 int err; 4189 4190 if (snd_config_get_type(_file) == SND_CONFIG_TYPE_COMPOUND) { 4191 if ((err = snd_config_search(_file, "file", &file)) < 0) { 4192 SNDERR("Field file not found"); 4193 return err; 4194 } 4195 if ((err = snd_config_search(_file, "root", &root)) >= 0) { 4196 err = snd_config_get_ascii(root, &rname); 4197 if (err < 0) { 4198 SNDERR("Field root is bad"); 4199 return err; 4200 } 4201 err = snd_config_make_compound(&root, rname, 0); 4202 if (err < 0) 4203 return err; 4204 } 4205 } 4206 if ((err = snd_config_get_ascii(file, &name)) < 0) 4207 goto _err; 4208 name2 = name; 4209 remain = strstr(name, "|||"); 4210 while (1) { 4211 if (remain) { 4212 *remain = '\0'; 4213 remain += 3; 4214 } 4215 err = config_file_load_user(root, name2, errors); 4216 if (err < 0) 4217 goto _err; 4218 if (err == 0) /* first hit wins */ 4219 break; 4220 if (!remain) 4221 break; 4222 name2 = remain; 4223 remain = strstr(remain, "|||"); 4224 } 4225_err: 4226 if (root != _root) { 4227 if (err == 0) { 4228 if (snd_config_get_type(root) == SND_CONFIG_TYPE_COMPOUND) { 4229 if (snd_config_is_empty(root)) 4230 goto _del; 4231 } 4232 err = snd_config_make_path(&n, _root, rname, 0, 1); 4233 if (err < 0) 4234 goto _del; 4235 err = snd_config_substitute(n, root); 4236 if (err == 0) 4237 goto _fin; 4238 } 4239_del: 4240 snd_config_delete(root); 4241 } 4242_fin: 4243 free(name); 4244 free(rname); 4245 return err; 4246} 4247 4248/** 4249 * \brief Loads and parses the given configurations files. 4250 * \param[in] root Handle to the root configuration node. 4251 * \param[in] config Handle to the configuration node for this hook. 4252 * \param[out] dst The function puts the handle to the configuration 4253 * node loaded from the file(s) at the address specified 4254 * by \a dst. 4255 * \param[in] private_data Handle to the private data configuration node. 4256 * \return Zero if successful, otherwise a negative error code. 4257 * 4258 * See \ref confhooks for an example. 4259 */ 4260int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) 4261{ 4262 snd_config_t *n; 4263 snd_config_iterator_t i, next; 4264 int err, idx = 0, errors = 1, hit; 4265 4266 assert(root && dst); 4267 if ((err = snd_config_search(config, "errors", &n)) >= 0) { 4268 errors = snd_config_get_bool(n); 4269 if (errors < 0) { 4270 SNDERR("Invalid bool value in field errors"); 4271 return errors; 4272 } 4273 } 4274 if ((err = snd_config_search(config, "files", &n)) < 0) { 4275 SNDERR("Unable to find field files in the pre-load section"); 4276 return -EINVAL; 4277 } 4278 if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) { 4279 SNDERR("Unable to expand filenames in the pre-load section"); 4280 return err; 4281 } 4282 if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { 4283 SNDERR("Invalid type for field filenames"); 4284 goto _err; 4285 } 4286 do { 4287 hit = 0; 4288 snd_config_for_each(i, next, n) { 4289 snd_config_t *n = snd_config_iterator_entry(i); 4290 const char *id = n->id; 4291 long i; 4292 err = safe_strtol(id, &i); 4293 if (err < 0) { 4294 SNDERR("id of field %s is not and integer", id); 4295 err = -EINVAL; 4296 goto _err; 4297 } 4298 if (i == idx) { 4299 err = config_file_load_user_all(root, n, errors); 4300 if (err < 0) 4301 goto _err; 4302 idx++; 4303 hit = 1; 4304 } 4305 } 4306 } while (hit); 4307 *dst = NULL; 4308 err = 0; 4309 _err: 4310 snd_config_delete(n); 4311 return err; 4312} 4313#ifndef DOC_HIDDEN 4314SND_DLSYM_BUILD_VERSION(snd_config_hook_load, SND_CONFIG_DLSYM_VERSION_HOOK); 4315#endif 4316 4317#ifndef DOC_HIDDEN 4318int snd_determine_driver(int card, char **driver); 4319#endif 4320 4321static snd_config_t *_snd_config_hook_private_data(int card, const char *driver) 4322{ 4323 snd_config_t *private_data, *v; 4324 int err; 4325 4326 err = snd_config_make_compound(&private_data, NULL, 0); 4327 if (err < 0) 4328 goto __err; 4329 err = snd_config_imake_integer(&v, "integer", card); 4330 if (err < 0) 4331 goto __err; 4332 err = snd_config_add(private_data, v); 4333 if (err < 0) { 4334 snd_config_delete(v); 4335 goto __err; 4336 } 4337 err = snd_config_imake_string(&v, "string", driver); 4338 if (err < 0) 4339 goto __err; 4340 err = snd_config_add(private_data, v); 4341 if (err < 0) { 4342 snd_config_delete(v); 4343 goto __err; 4344 } 4345 return private_data; 4346 4347__err: 4348 snd_config_delete(private_data); 4349 return NULL; 4350} 4351 4352static int _snd_config_hook_table(snd_config_t *root, snd_config_t *config, snd_config_t *private_data) 4353{ 4354 snd_config_t *n, *tn; 4355 const char *id; 4356 int err; 4357 4358 if (snd_config_search(config, "table", &n) < 0) 4359 return 0; 4360 if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) { 4361 SNDERR("Unable to expand table compound"); 4362 return err; 4363 } 4364 if (snd_config_search(n, "id", &tn) < 0 || 4365 snd_config_get_string(tn, &id) < 0) { 4366 SNDERR("Unable to find field table.id"); 4367 snd_config_delete(n); 4368 return -EINVAL; 4369 } 4370 if (snd_config_search(n, "value", &tn) < 0 || 4371 snd_config_get_type(tn) != SND_CONFIG_TYPE_STRING) { 4372 SNDERR("Unable to find field table.value"); 4373 snd_config_delete(n); 4374 return -EINVAL; 4375 } 4376 snd_config_remove(tn); 4377 if ((err = snd_config_set_id(tn, id)) < 0) { 4378 snd_config_delete(tn); 4379 snd_config_delete(n); 4380 return err; 4381 } 4382 snd_config_delete(n); 4383 if ((err = snd_config_add(root, tn)) < 0) { 4384 snd_config_delete(tn); 4385 return err; 4386 } 4387 return 0; 4388} 4389 4390/** 4391 * \brief Loads and parses the given configurations files for each 4392 * installed sound card. 4393 * \param[in] root Handle to the root configuration node. 4394 * \param[in] config Handle to the configuration node for this hook. 4395 * \param[out] dst The function puts the handle to the configuration 4396 * node loaded from the file(s) at the address specified 4397 * by \a dst. 4398 * \param[in] private_data Handle to the private data configuration node. 4399 * \return Zero if successful, otherwise a negative error code. 4400 * 4401 * This function works like #snd_config_hook_load, but the files are 4402 * loaded once for each sound card. The driver name is available with 4403 * the \c private_string function to customize the file name. 4404 */ 4405int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data ATTRIBUTE_UNUSED) 4406{ 4407 int card = -1, err; 4408 snd_config_t *loaded; // trace loaded cards 4409 4410 err = snd_config_top(&loaded); 4411 if (err < 0) 4412 return err; 4413 do { 4414 err = snd_card_next(&card); 4415 if (err < 0) 4416 goto __fin_err; 4417 if (card >= 0) { 4418 snd_config_t *n, *m, *private_data = NULL; 4419 const char *driver; 4420 char *fdriver = NULL; 4421 bool load; 4422 err = snd_determine_driver(card, &fdriver); 4423 if (err < 0) 4424 goto __fin_err; 4425 if (snd_config_search(root, fdriver, &n) >= 0) { 4426 if (snd_config_get_string(n, &driver) < 0) { 4427 if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND) { 4428 snd_config_get_id(n, &driver); 4429 goto __std; 4430 } 4431 goto __err; 4432 } 4433 while (1) { 4434 char *s = strchr(driver, '.'); 4435 if (s == NULL) 4436 break; 4437 driver = s + 1; 4438 } 4439 if (snd_config_search(root, driver, &n) >= 0) 4440 goto __err; 4441 } else { 4442 driver = fdriver; 4443 } 4444 __std: 4445 load = true; 4446 err = snd_config_imake_integer(&m, driver, 1); 4447 if (err < 0) 4448 goto __err; 4449 err = snd_config_add(loaded, m); 4450 if (err < 0) { 4451 if (err == -EEXIST) { 4452 snd_config_delete(m); 4453 load = false; 4454 } else { 4455 goto __err; 4456 } 4457 } 4458 private_data = _snd_config_hook_private_data(card, driver); 4459 if (!private_data) { 4460 err = -ENOMEM; 4461 goto __err; 4462 } 4463 err = _snd_config_hook_table(root, config, private_data); 4464 if (err < 0) 4465 goto __err; 4466 if (load) 4467 err = snd_config_hook_load(root, config, &n, private_data); 4468 __err: 4469 if (private_data) 4470 snd_config_delete(private_data); 4471 free(fdriver); 4472 if (err < 0) 4473 goto __fin_err; 4474 } 4475 } while (card >= 0); 4476 snd_config_delete(loaded); 4477 *dst = NULL; 4478 return 0; 4479__fin_err: 4480 snd_config_delete(loaded); 4481 return err; 4482} 4483#ifndef DOC_HIDDEN 4484SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK); 4485#endif 4486 4487/** 4488 * \brief Updates a configuration tree by rereading the configuration files (if needed). 4489 * \param[in,out] _top Address of the handle to the top-level node. 4490 * \param[in,out] _update Address of a pointer to private update information. 4491 * \param[in] cfgs A list of configuration file names, delimited with ':'. 4492 * If \p cfgs is \c NULL, the default global 4493 * configuration file is used. 4494 * \return 0 if \a _top was up to date, 1 if the configuration files 4495 * have been reread, otherwise a negative error code. 4496 * 4497 * The variables pointed to by \a _top and \a _update can be initialized 4498 * to \c NULL before the first call to this function. The private 4499 * update information holds information about all used configuration 4500 * files that allows this function to detects changes to them; this data 4501 * can be freed with #snd_config_update_free. 4502 * 4503 * The global configuration files are specified in the environment variable 4504 * \c ALSA_CONFIG_PATH. 4505 * 4506 * \warning If the configuration tree is reread, all string pointers and 4507 * configuration node handles previously obtained from this tree become 4508 * invalid. 4509 * 4510 * \par Errors: 4511 * Any errors encountered when parsing the input or returned by hooks or 4512 * functions. 4513 */ 4514int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, const char *cfgs) 4515{ 4516 int err; 4517 const char *configs, *c; 4518 unsigned int k; 4519 size_t l; 4520 snd_config_update_t *local; 4521 snd_config_update_t *update; 4522 snd_config_t *top; 4523 4524 assert(_top && _update); 4525 top = *_top; 4526 update = *_update; 4527 configs = cfgs; 4528 if (!configs) { 4529 configs = getenv(ALSA_CONFIG_PATH_VAR); 4530 if (!configs || !*configs) { 4531 const char *topdir = snd_config_topdir(); 4532 char *s = alloca(strlen(topdir) + 4533 strlen("alsa.conf") + 2); 4534 sprintf(s, "%s/alsa.conf", topdir); 4535 configs = s; 4536 } 4537 } 4538 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) { 4539 c += l; 4540 k++; 4541 if (!*c) 4542 break; 4543 c++; 4544 } 4545 if (k == 0) { 4546 local = NULL; 4547 goto _reread; 4548 } 4549 local = (snd_config_update_t *)calloc(1, sizeof(snd_config_update_t)); 4550 if (!local) 4551 return -ENOMEM; 4552 local->count = k; 4553 local->finfo = calloc(local->count, sizeof(struct finfo)); 4554 if (!local->finfo) { 4555 free(local); 4556 return -ENOMEM; 4557 } 4558 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) { 4559 char name[l + 1]; 4560 memcpy(name, c, l); 4561 name[l] = 0; 4562 err = snd_user_file(name, &local->finfo[k].name); 4563 if (err < 0) 4564 goto _end; 4565 c += l; 4566 k++; 4567 if (!*c) 4568 break; 4569 c++; 4570 } 4571 for (k = 0; k < local->count; ++k) { 4572 struct stat64 st; 4573 struct finfo *lf = &local->finfo[k]; 4574 if (stat64(lf->name, &st) >= 0) { 4575 lf->dev = st.st_dev; 4576 lf->ino = st.st_ino; 4577 lf->mtime = st.st_mtime; 4578 } else { 4579 SNDERR("Cannot access file %s", lf->name); 4580 free(lf->name); 4581 memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1)); 4582 k--; 4583 local->count--; 4584 } 4585 } 4586 if (!update) 4587 goto _reread; 4588 if (local->count != update->count) 4589 goto _reread; 4590 for (k = 0; k < local->count; ++k) { 4591 struct finfo *lf = &local->finfo[k]; 4592 struct finfo *uf = &update->finfo[k]; 4593 if (strcmp(lf->name, uf->name) != 0 || 4594 lf->dev != uf->dev || 4595 lf->ino != uf->ino || 4596 lf->mtime != uf->mtime) 4597 goto _reread; 4598 } 4599 err = 0; 4600 4601 _end: 4602 if (err < 0) { 4603 if (top) { 4604 snd_config_delete(top); 4605 *_top = NULL; 4606 } 4607 if (update) { 4608 snd_config_update_free(update); 4609 *_update = NULL; 4610 } 4611 } 4612 if (local) 4613 snd_config_update_free(local); 4614 return err; 4615 4616 _reread: 4617 *_top = NULL; 4618 *_update = NULL; 4619 if (update) { 4620 snd_config_update_free(update); 4621 update = NULL; 4622 } 4623 if (top) { 4624 snd_config_delete(top); 4625 top = NULL; 4626 } 4627 err = snd_config_top(&top); 4628 if (err < 0) 4629 goto _end; 4630 if (!local) 4631 goto _skip; 4632 for (k = 0; k < local->count; ++k) { 4633 snd_input_t *in; 4634 err = snd_input_stdio_open(&in, local->finfo[k].name, "r"); 4635 if (err >= 0) { 4636 err = snd_config_load(top, in); 4637 snd_input_close(in); 4638 if (err < 0) { 4639 SNDERR("%s may be old or corrupted: consider to remove or fix it", local->finfo[k].name); 4640 goto _end; 4641 } 4642 } else { 4643 SNDERR("cannot access file %s", local->finfo[k].name); 4644 } 4645 } 4646 _skip: 4647 err = snd_config_hooks(top, NULL); 4648 if (err < 0) { 4649 SNDERR("hooks failed, removing configuration"); 4650 goto _end; 4651 } 4652 *_top = top; 4653 *_update = local; 4654 return 1; 4655} 4656 4657/** 4658 * \brief Updates #snd_config by rereading the global configuration files (if needed). 4659 * \return 0 if #snd_config was up to date, 1 if #snd_config was 4660 * updated, otherwise a negative error code. 4661 * 4662 * \warning Whenever #snd_config is updated, all string pointers and 4663 * configuration node handles previously obtained from it may become 4664 * invalid. 4665 * For safer operations, use #snd_config_update_ref and release the config 4666 * via #snd_config_unref. 4667 * 4668 * \par Errors: 4669 * Any errors encountered when parsing the input or returned by hooks or 4670 * functions. 4671 * 4672 * \par Conforming to: 4673 * LSB 3.2 4674 */ 4675int snd_config_update(void) 4676{ 4677 int err; 4678 4679 snd_config_lock(); 4680 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL); 4681 snd_config_unlock(); 4682 return err; 4683} 4684 4685/** 4686 * \brief Updates #snd_config and takes its reference. 4687 * \return 0 if #snd_config was up to date, 1 if #snd_config was 4688 * updated, otherwise a negative error code. 4689 * 4690 * Unlike #snd_config_update, this function increases a reference counter 4691 * so that the obtained tree won't be deleted until unreferenced by 4692 * #snd_config_unref. 4693 * 4694 * This function is supposed to be thread-safe. 4695 */ 4696int snd_config_update_ref(snd_config_t **top) 4697{ 4698 int err; 4699 4700 if (top) 4701 *top = NULL; 4702 snd_config_lock(); 4703 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL); 4704 if (err >= 0) { 4705 if (snd_config) { 4706 if (top) { 4707 snd_config->refcount++; 4708 *top = snd_config; 4709 } 4710 } else { 4711 err = -ENODEV; 4712 } 4713 } 4714 snd_config_unlock(); 4715 return err; 4716} 4717 4718/** 4719 * \brief Take the reference of the config tree. 4720 * 4721 * Increases a reference counter of the given config tree. 4722 * 4723 * This function is supposed to be thread-safe. 4724 */ 4725void snd_config_ref(snd_config_t *cfg) 4726{ 4727 snd_config_lock(); 4728 if (cfg) 4729 cfg->refcount++; 4730 snd_config_unlock(); 4731} 4732 4733/** 4734 * \brief Unreference the config tree. 4735 * 4736 * Decreases a reference counter of the given config tree, and eventually 4737 * deletes the tree if all references are gone. This is the counterpart of 4738 * #snd_config_unref. 4739 * 4740 * Also, the config taken via #snd_config_update_ref must be unreferenced 4741 * by this function, too. 4742 * 4743 * This function is supposed to be thread-safe. 4744 */ 4745void snd_config_unref(snd_config_t *cfg) 4746{ 4747 snd_config_lock(); 4748 if (cfg) 4749 snd_config_delete(cfg); 4750 snd_config_unlock(); 4751} 4752 4753/** 4754 * \brief Frees a private update structure. 4755 * \param[in] update The private update structure to free. 4756 * \return Zero if successful, otherwise a negative error code. 4757 */ 4758int snd_config_update_free(snd_config_update_t *update) 4759{ 4760 unsigned int k; 4761 4762 assert(update); 4763 for (k = 0; k < update->count; k++) 4764 free(update->finfo[k].name); 4765 free(update->finfo); 4766 free(update); 4767 return 0; 4768} 4769 4770/** 4771 * \brief Frees the global configuration tree in #snd_config. 4772 * \return Zero if successful, otherwise a negative error code. 4773 * 4774 * This functions releases all resources of the global configuration 4775 * tree, and sets #snd_config to \c NULL. 4776 * 4777 * \par Conforming to: 4778 * LSB 3.2 4779 */ 4780int snd_config_update_free_global(void) 4781{ 4782 snd_config_lock(); 4783 if (snd_config) 4784 snd_config_delete(snd_config); 4785 snd_config = NULL; 4786 if (snd_config_global_update) 4787 snd_config_update_free(snd_config_global_update); 4788 snd_config_global_update = NULL; 4789 snd_config_unlock(); 4790 /* FIXME: better to place this in another place... */ 4791 snd_dlobj_cache_cleanup(); 4792 4793 return 0; 4794} 4795 4796/** 4797 * \brief Returns an iterator pointing to a node's first child. 4798 * \param[in] config Handle to a configuration node. 4799 * \return An iterator pointing to \a config's first child. 4800 * 4801 * \a config must be a compound node. 4802 * 4803 * The returned iterator is valid if it is not equal to the return value 4804 * of #snd_config_iterator_end on \a config. 4805 * 4806 * Use #snd_config_iterator_entry to get the handle of the node pointed 4807 * to. 4808 * 4809 * \par Conforming to: 4810 * LSB 3.2 4811 */ 4812snd_config_iterator_t snd_config_iterator_first(const snd_config_t *config) 4813{ 4814 assert(config->type == SND_CONFIG_TYPE_COMPOUND); 4815 return config->u.compound.fields.next; 4816} 4817 4818/** 4819 * \brief Returns an iterator pointing to the next sibling. 4820 * \param[in] iterator An iterator pointing to a child configuration node. 4821 * \return An iterator pointing to the next sibling of \a iterator. 4822 * 4823 * The returned iterator is valid if it is not equal to the return value 4824 * of #snd_config_iterator_end on the node's parent. 4825 * 4826 * Use #snd_config_iterator_entry to get the handle of the node pointed 4827 * to. 4828 * 4829 * \par Conforming to: 4830 * LSB 3.2 4831 */ 4832snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator) 4833{ 4834 return iterator->next; 4835} 4836 4837/** 4838 * \brief Returns an iterator that ends a node's children list. 4839 * \param[in] config Handle to a configuration node. 4840 * \return An iterator that indicates the end of \a config's children list. 4841 * 4842 * \a config must be a compound node. 4843 * 4844 * The return value can be understood as pointing past the last child of 4845 * \a config. 4846 * 4847 * \par Conforming to: 4848 * LSB 3.2 4849 */ 4850snd_config_iterator_t snd_config_iterator_end(const snd_config_t *config) 4851{ 4852 assert(config->type == SND_CONFIG_TYPE_COMPOUND); 4853 return (const snd_config_iterator_t)&config->u.compound.fields; 4854} 4855 4856/** 4857 * \brief Returns the configuration node handle pointed to by an iterator. 4858 * \param[in] iterator A configuration node iterator. 4859 * \return The configuration node handle pointed to by \a iterator. 4860 * 4861 * \par Conforming to: 4862 * LSB 3.2 4863 */ 4864snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator) 4865{ 4866 return list_entry(iterator, snd_config_t, list); 4867} 4868 4869#ifndef DOC_HIDDEN 4870typedef enum _snd_config_walk_pass { 4871 SND_CONFIG_WALK_PASS_PRE, 4872 SND_CONFIG_WALK_PASS_POST, 4873 SND_CONFIG_WALK_PASS_LEAF, 4874} snd_config_walk_pass_t; 4875#endif 4876 4877/* Return 1 if node needs to be attached to parent */ 4878/* Return 2 if compound is replaced with standard node */ 4879#ifndef DOC_HIDDEN 4880typedef int (*snd_config_walk_callback_t)(snd_config_t *src, 4881 snd_config_t *root, 4882 snd_config_t **dst, 4883 snd_config_walk_pass_t pass, 4884 snd_config_expand_fcn_t fcn, 4885 void *private_data); 4886#endif 4887 4888static int snd_config_walk(snd_config_t *src, 4889 snd_config_t *root, 4890 snd_config_t **dst, 4891 snd_config_walk_callback_t callback, 4892 snd_config_expand_fcn_t fcn, 4893 void *private_data) 4894{ 4895 int err; 4896 snd_config_iterator_t i, next; 4897 4898 switch (snd_config_get_type(src)) { 4899 case SND_CONFIG_TYPE_COMPOUND: 4900 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_PRE, fcn, private_data); 4901 if (err <= 0) 4902 return err; 4903 snd_config_for_each(i, next, src) { 4904 snd_config_t *s = snd_config_iterator_entry(i); 4905 snd_config_t *d = NULL; 4906 4907 err = snd_config_walk(s, root, (dst && *dst) ? &d : NULL, 4908 callback, fcn, private_data); 4909 if (err < 0) 4910 goto _error; 4911 if (err && d) { 4912 err = snd_config_add(*dst, d); 4913 if (err < 0) 4914 goto _error; 4915 } 4916 } 4917 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_POST, fcn, private_data); 4918 if (err <= 0) { 4919 _error: 4920 if (dst && *dst) 4921 snd_config_delete(*dst); 4922 } 4923 break; 4924 default: 4925 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_LEAF, fcn, private_data); 4926 break; 4927 } 4928 return err; 4929} 4930 4931static int _snd_config_copy(snd_config_t *src, 4932 snd_config_t *root ATTRIBUTE_UNUSED, 4933 snd_config_t **dst, 4934 snd_config_walk_pass_t pass, 4935 snd_config_expand_fcn_t fcn ATTRIBUTE_UNUSED, 4936 void *private_data ATTRIBUTE_UNUSED) 4937{ 4938 int err; 4939 const char *id = src->id; 4940 snd_config_type_t type = snd_config_get_type(src); 4941 switch (pass) { 4942 case SND_CONFIG_WALK_PASS_PRE: 4943 err = snd_config_make_compound(dst, id, src->u.compound.join); 4944 if (err < 0) 4945 return err; 4946 break; 4947 case SND_CONFIG_WALK_PASS_LEAF: 4948 err = snd_config_make(dst, id, type); 4949 if (err < 0) 4950 return err; 4951 switch (type) { 4952 case SND_CONFIG_TYPE_INTEGER: 4953 { 4954 long v; 4955 err = snd_config_get_integer(src, &v); 4956 assert(err >= 0); 4957 snd_config_set_integer(*dst, v); 4958 break; 4959 } 4960 case SND_CONFIG_TYPE_INTEGER64: 4961 { 4962 long long v; 4963 err = snd_config_get_integer64(src, &v); 4964 assert(err >= 0); 4965 snd_config_set_integer64(*dst, v); 4966 break; 4967 } 4968 case SND_CONFIG_TYPE_REAL: 4969 { 4970 double v; 4971 err = snd_config_get_real(src, &v); 4972 assert(err >= 0); 4973 snd_config_set_real(*dst, v); 4974 break; 4975 } 4976 case SND_CONFIG_TYPE_STRING: 4977 { 4978 const char *s; 4979 err = snd_config_get_string(src, &s); 4980 assert(err >= 0); 4981 err = snd_config_set_string(*dst, s); 4982 if (err < 0) 4983 return err; 4984 break; 4985 } 4986 default: 4987 assert(0); 4988 } 4989 break; 4990 default: 4991 break; 4992 } 4993 return 1; 4994} 4995 4996/** 4997 * \brief Creates a copy of a configuration node. 4998 * \param[out] dst The function puts the handle to the new configuration 4999 * node at the address specified by \a dst. 5000 * \param[in] src Handle to the source configuration node. 5001 * \return A non-negative value if successful, otherwise a negative error code. 5002 * 5003 * This function creates a deep copy, i.e., if \a src is a compound 5004 * node, all children are copied recursively. 5005 * 5006 * \par Errors: 5007 * <dl> 5008 * <dt>-ENOMEM<dd>Out of memory. 5009 * </dl> 5010 * 5011 * \par Conforming to: 5012 * LSB 3.2 5013 */ 5014int snd_config_copy(snd_config_t **dst, 5015 snd_config_t *src) 5016{ 5017 return snd_config_walk(src, NULL, dst, _snd_config_copy, NULL, NULL); 5018} 5019 5020static int _snd_config_expand_vars(snd_config_t **dst, const char *s, void *private_data) 5021{ 5022 snd_config_t *val, *vars = private_data; 5023 if (snd_config_search(vars, s, &val) < 0) { 5024 *dst = NULL; 5025 return 0; 5026 } 5027 return snd_config_copy(dst, val); 5028} 5029 5030static int _snd_config_expand(snd_config_t *src, 5031 snd_config_t *root ATTRIBUTE_UNUSED, 5032 snd_config_t **dst, 5033 snd_config_walk_pass_t pass, 5034 snd_config_expand_fcn_t fcn, 5035 void *private_data) 5036{ 5037 int err; 5038 const char *id = src->id; 5039 snd_config_type_t type = snd_config_get_type(src); 5040 switch (pass) { 5041 case SND_CONFIG_WALK_PASS_PRE: 5042 { 5043 if (id && strcmp(id, "@args") == 0) 5044 return 0; 5045 err = snd_config_make_compound(dst, id, src->u.compound.join); 5046 if (err < 0) 5047 return err; 5048 break; 5049 } 5050 case SND_CONFIG_WALK_PASS_LEAF: 5051 switch (type) { 5052 case SND_CONFIG_TYPE_INTEGER: 5053 { 5054 long v; 5055 err = snd_config_get_integer(src, &v); 5056 assert(err >= 0); 5057 err = snd_config_imake_integer(dst, id, v); 5058 if (err < 0) 5059 return err; 5060 break; 5061 } 5062 case SND_CONFIG_TYPE_INTEGER64: 5063 { 5064 long long v; 5065 err = snd_config_get_integer64(src, &v); 5066 assert(err >= 0); 5067 err = snd_config_imake_integer64(dst, id, v); 5068 if (err < 0) 5069 return err; 5070 break; 5071 } 5072 case SND_CONFIG_TYPE_REAL: 5073 { 5074 double v; 5075 err = snd_config_get_real(src, &v); 5076 assert(err >= 0); 5077 err = snd_config_imake_real(dst, id, v); 5078 if (err < 0) 5079 return err; 5080 break; 5081 } 5082 case SND_CONFIG_TYPE_STRING: 5083 { 5084 const char *s; 5085 snd_config_t *vars = private_data; 5086 snd_config_get_string(src, &s); 5087 if (s && *s == '$') { 5088 err = snd_config_evaluate_string(dst, s, fcn, vars); 5089 if (err < 0) 5090 return err; 5091 if (*dst == NULL) 5092 return 0; 5093 err = snd_config_set_id(*dst, id); 5094 if (err < 0) { 5095 snd_config_delete(*dst); 5096 return err; 5097 } 5098 } else { 5099 err = snd_config_imake_string(dst, id, s); 5100 if (err < 0) 5101 return err; 5102 } 5103 break; 5104 } 5105 default: 5106 assert(0); 5107 } 5108 break; 5109 default: 5110 break; 5111 } 5112 return 1; 5113} 5114 5115static int _snd_config_evaluate(snd_config_t *src, 5116 snd_config_t *root, 5117 snd_config_t **dst ATTRIBUTE_UNUSED, 5118 snd_config_walk_pass_t pass, 5119 snd_config_expand_fcn_t fcn ATTRIBUTE_UNUSED, 5120 void *private_data) 5121{ 5122 int err; 5123 if (pass == SND_CONFIG_WALK_PASS_PRE) { 5124 char *buf = NULL, errbuf[256]; 5125 const char *lib = NULL, *func_name = NULL; 5126 const char *str; 5127 int (*func)(snd_config_t **dst, snd_config_t *root, 5128 snd_config_t *src, snd_config_t *private_data) = NULL; 5129 void *h = NULL; 5130 snd_config_t *c, *func_conf = NULL; 5131 err = snd_config_search(src, "@func", &c); 5132 if (err < 0) 5133 return 1; 5134 err = snd_config_get_string(c, &str); 5135 if (err < 0) { 5136 SNDERR("Invalid type for @func"); 5137 return err; 5138 } 5139 assert(str); 5140 err = snd_config_search_definition(root, "func", str, &func_conf); 5141 if (err >= 0) { 5142 snd_config_iterator_t i, next; 5143 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) { 5144 SNDERR("Invalid type for func %s definition", str); 5145 err = -EINVAL; 5146 goto _err; 5147 } 5148 snd_config_for_each(i, next, func_conf) { 5149 snd_config_t *n = snd_config_iterator_entry(i); 5150 const char *id = n->id; 5151 if (strcmp(id, "comment") == 0) 5152 continue; 5153 if (strcmp(id, "lib") == 0) { 5154 err = snd_config_get_string(n, &lib); 5155 if (err < 0) { 5156 SNDERR("Invalid type for %s", id); 5157 goto _err; 5158 } 5159 continue; 5160 } 5161 if (strcmp(id, "func") == 0) { 5162 err = snd_config_get_string(n, &func_name); 5163 if (err < 0) { 5164 SNDERR("Invalid type for %s", id); 5165 goto _err; 5166 } 5167 continue; 5168 } 5169 SNDERR("Unknown field %s", id); 5170 } 5171 } 5172 if (!func_name) { 5173 int len = 9 + strlen(str) + 1; 5174 buf = malloc(len); 5175 if (! buf) { 5176 err = -ENOMEM; 5177 goto _err; 5178 } 5179 snprintf(buf, len, "snd_func_%s", str); 5180 buf[len-1] = '\0'; 5181 func_name = buf; 5182 } 5183 h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf)); 5184 if (h) 5185 func = snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_EVALUATE)); 5186 err = 0; 5187 if (!h) { 5188 SNDERR("Cannot open shared library %s (%s)", lib, errbuf); 5189 err = -ENOENT; 5190 goto _errbuf; 5191 } else if (!func) { 5192 SNDERR("symbol %s is not defined inside %s", func_name, lib); 5193 snd_dlclose(h); 5194 err = -ENXIO; 5195 goto _errbuf; 5196 } 5197 _err: 5198 if (func_conf) 5199 snd_config_delete(func_conf); 5200 if (err >= 0) { 5201 snd_config_t *eval; 5202 err = func(&eval, root, src, private_data); 5203 if (err < 0) 5204 SNDERR("function %s returned error: %s", func_name, snd_strerror(err)); 5205 snd_dlclose(h); 5206 if (err >= 0 && eval) 5207 err = snd_config_substitute(src, eval); 5208 } 5209 _errbuf: 5210 free(buf); 5211 if (err < 0) 5212 return err; 5213 return 0; 5214 } 5215 return 1; 5216} 5217 5218/** 5219 * \brief Evaluates a configuration node at runtime. 5220 * \param[in,out] config Handle to the source configuration node. 5221 * \param[in] root Handle to the root of the source configuration. 5222 * \param[in] private_data Handle to the private data node for runtime evaluation. 5223 * \param result Must be \c NULL. 5224 * \return A non-negative value if successful, otherwise a negative error code. 5225 * 5226 * This function evaluates any functions (\c \@func) in \a config and 5227 * replaces those nodes with the respective function results. 5228 */ 5229int snd_config_evaluate(snd_config_t *config, snd_config_t *root, 5230 snd_config_t *private_data, snd_config_t **result) 5231{ 5232 /* FIXME: Only in place evaluation is currently implemented */ 5233 assert(result == NULL); 5234 return snd_config_walk(config, root, result, _snd_config_evaluate, NULL, private_data); 5235} 5236 5237static int load_defaults(snd_config_t *subs, snd_config_t *defs) 5238{ 5239 snd_config_iterator_t d, dnext; 5240 snd_config_for_each(d, dnext, defs) { 5241 snd_config_t *def = snd_config_iterator_entry(d); 5242 snd_config_iterator_t f, fnext; 5243 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND) 5244 continue; 5245 snd_config_for_each(f, fnext, def) { 5246 snd_config_t *fld = snd_config_iterator_entry(f); 5247 const char *id = fld->id; 5248 if (strcmp(id, "type") == 0) 5249 continue; 5250 if (strcmp(id, "default") == 0) { 5251 snd_config_t *deflt; 5252 int err; 5253 err = snd_config_copy(&deflt, fld); 5254 if (err < 0) 5255 return err; 5256 err = snd_config_set_id(deflt, def->id); 5257 if (err < 0) { 5258 snd_config_delete(deflt); 5259 return err; 5260 } 5261 err = snd_config_add(subs, deflt); 5262 if (err < 0) { 5263 snd_config_delete(deflt); 5264 return err; 5265 } 5266 continue; 5267 } 5268 SNDERR("Unknown field %s", id); 5269 return -EINVAL; 5270 } 5271 } 5272 return 0; 5273} 5274 5275static void skip_blank(const char **ptr) 5276{ 5277 while (1) { 5278 switch (**ptr) { 5279 case ' ': 5280 case '\f': 5281 case '\t': 5282 case '\n': 5283 case '\r': 5284 break; 5285 default: 5286 return; 5287 } 5288 (*ptr)++; 5289 } 5290} 5291 5292static int parse_char(const char **ptr) 5293{ 5294 int c; 5295 assert(**ptr == '\\'); 5296 (*ptr)++; 5297 c = **ptr; 5298 switch (c) { 5299 case 'n': 5300 c = '\n'; 5301 break; 5302 case 't': 5303 c = '\t'; 5304 break; 5305 case 'v': 5306 c = '\v'; 5307 break; 5308 case 'b': 5309 c = '\b'; 5310 break; 5311 case 'r': 5312 c = '\r'; 5313 break; 5314 case 'f': 5315 c = '\f'; 5316 break; 5317 case '0': case '1': case '2': case '3': 5318 case '4': case '5': case '6': case '7': 5319 { 5320 int num = c - '0'; 5321 int i = 1; 5322 (*ptr)++; 5323 do { 5324 c = **ptr; 5325 if (c < '0' || c > '7') 5326 break; 5327 num = num * 8 + c - '0'; 5328 i++; 5329 (*ptr)++; 5330 } while (i < 3); 5331 return num; 5332 } 5333 default: 5334 break; 5335 } 5336 (*ptr)++; 5337 return c; 5338} 5339 5340static int parse_id(const char **ptr) 5341{ 5342 if (!**ptr) 5343 return -EINVAL; 5344 while (1) { 5345 switch (**ptr) { 5346 case '\f': 5347 case '\t': 5348 case '\n': 5349 case '\r': 5350 case ',': 5351 case '=': 5352 case '\0': 5353 return 0; 5354 default: 5355 break; 5356 } 5357 (*ptr)++; 5358 } 5359} 5360 5361static int parse_string(const char **ptr, char **val) 5362{ 5363 const size_t bufsize = 256; 5364 char _buf[bufsize]; 5365 char *buf = _buf; 5366 size_t alloc = bufsize; 5367 char delim = **ptr; 5368 size_t idx = 0; 5369 (*ptr)++; 5370 while (1) { 5371 int c = **ptr; 5372 switch (c) { 5373 case '\0': 5374 SNDERR("Unterminated string"); 5375 return -EINVAL; 5376 case '\\': 5377 c = parse_char(ptr); 5378 if (c < 0) { 5379 if (alloc > bufsize) 5380 free(buf); 5381 return c; 5382 } 5383 break; 5384 default: 5385 (*ptr)++; 5386 if (c == delim) { 5387 *val = malloc(idx + 1); 5388 if (!*val) 5389 return -ENOMEM; 5390 memcpy(*val, buf, idx); 5391 (*val)[idx] = 0; 5392 if (alloc > bufsize) 5393 free(buf); 5394 return 0; 5395 } 5396 } 5397 if (idx >= alloc) { 5398 size_t old_alloc = alloc; 5399 alloc *= 2; 5400 if (old_alloc == bufsize) { 5401 buf = malloc(alloc); 5402 if (!buf) 5403 return -ENOMEM; 5404 memcpy(buf, _buf, old_alloc); 5405 } else { 5406 char *buf2 = realloc(buf, alloc); 5407 if (!buf2) { 5408 free(buf); 5409 return -ENOMEM; 5410 } 5411 buf = buf2; 5412 } 5413 } 5414 buf[idx++] = c; 5415 } 5416} 5417 5418 5419/* Parse var=val or val */ 5420static int parse_arg(const char **ptr, unsigned int *varlen, char **val) 5421{ 5422 const char *str; 5423 int err, vallen; 5424 skip_blank(ptr); 5425 str = *ptr; 5426 if (*str == '"' || *str == '\'') { 5427 err = parse_string(ptr, val); 5428 if (err < 0) 5429 return err; 5430 *varlen = 0; 5431 return 0; 5432 } 5433 err = parse_id(ptr); 5434 if (err < 0) 5435 return err; 5436 vallen = *ptr - str; 5437 skip_blank(ptr); 5438 if (**ptr != '=') { 5439 *varlen = 0; 5440 goto _value; 5441 } 5442 *varlen = vallen; 5443 (*ptr)++; 5444 skip_blank(ptr); 5445 str = *ptr; 5446 if (*str == '"' || *str == '\'') { 5447 err = parse_string(ptr, val); 5448 if (err < 0) 5449 return err; 5450 return 0; 5451 } 5452 err = parse_id(ptr); 5453 if (err < 0) 5454 return err; 5455 vallen = *ptr - str; 5456 _value: 5457 *val = malloc(vallen + 1); 5458 if (!*val) 5459 return -ENOMEM; 5460 memcpy(*val, str, vallen); 5461 (*val)[vallen] = 0; 5462 return 0; 5463} 5464 5465 5466/* val1, val2, ... 5467 * var1=val1,var2=val2,... 5468 * { conf syntax } 5469 */ 5470static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs) 5471{ 5472 int err; 5473 int arg = 0; 5474 if (str == NULL) 5475 return 0; 5476 skip_blank(&str); 5477 if (!*str) 5478 return 0; 5479 if (*str == '{') { 5480 int len = strlen(str); 5481 snd_input_t *input; 5482 snd_config_iterator_t i, next; 5483 while (1) { 5484 switch (str[--len]) { 5485 case ' ': 5486 case '\f': 5487 case '\t': 5488 case '\n': 5489 case '\r': 5490 continue; 5491 default: 5492 break; 5493 } 5494 break; 5495 } 5496 if (str[len] != '}') 5497 return -EINVAL; 5498 err = snd_input_buffer_open(&input, str + 1, len - 1); 5499 if (err < 0) 5500 return err; 5501 err = snd_config_load_override(subs, input); 5502 snd_input_close(input); 5503 if (err < 0) 5504 return err; 5505 snd_config_for_each(i, next, subs) { 5506 snd_config_t *n = snd_config_iterator_entry(i); 5507 snd_config_t *d; 5508 const char *id = n->id; 5509 err = snd_config_search(defs, id, &d); 5510 if (err < 0) { 5511 SNDERR("Unknown parameter %s", id); 5512 return err; 5513 } 5514 } 5515 return 0; 5516 } 5517 5518 while (1) { 5519 char buf[256]; 5520 const char *var = buf; 5521 unsigned int varlen; 5522 snd_config_t *def, *sub, *typ; 5523 const char *new = str; 5524 const char *tmp; 5525 char *val = NULL; 5526 5527 sub = NULL; 5528 err = parse_arg(&new, &varlen, &val); 5529 if (err < 0) 5530 goto _err; 5531 if (varlen > 0) { 5532 assert(varlen < sizeof(buf)); 5533 memcpy(buf, str, varlen); 5534 buf[varlen] = 0; 5535 } else { 5536 sprintf(buf, "%d", arg); 5537 } 5538 err = snd_config_search_alias(defs, NULL, var, &def); 5539 if (err < 0) { 5540 SNDERR("Unknown parameter %s", var); 5541 goto _err; 5542 } 5543 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND) { 5544 SNDERR("Parameter %s definition is not correct", var); 5545 err = -EINVAL; 5546 goto _err; 5547 } 5548 var = def->id; 5549 err = snd_config_search(subs, var, &sub); 5550 if (err >= 0) 5551 snd_config_delete(sub); 5552 sub = NULL; 5553 err = snd_config_search(def, "type", &typ); 5554 if (err < 0) { 5555 _invalid_type: 5556 SNDERR("Parameter %s definition is missing a valid type info", var); 5557 goto _err; 5558 } 5559 err = snd_config_get_string(typ, &tmp); 5560 if (err < 0 || !tmp) 5561 goto _invalid_type; 5562 if (strcmp(tmp, "integer") == 0) { 5563 long v; 5564 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER); 5565 if (err < 0) 5566 goto _err; 5567 err = safe_strtol(val, &v); 5568 if (err < 0) { 5569 SNDERR("Parameter %s must be an integer", var); 5570 goto _err; 5571 } 5572 err = snd_config_set_integer(sub, v); 5573 if (err < 0) 5574 goto _err; 5575 } else if (strcmp(tmp, "integer64") == 0) { 5576 long long v; 5577 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER64); 5578 if (err < 0) 5579 goto _err; 5580 err = safe_strtoll(val, &v); 5581 if (err < 0) { 5582 SNDERR("Parameter %s must be an integer", var); 5583 goto _err; 5584 } 5585 err = snd_config_set_integer64(sub, v); 5586 if (err < 0) 5587 goto _err; 5588 } else if (strcmp(tmp, "real") == 0) { 5589 double v; 5590 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_REAL); 5591 if (err < 0) 5592 goto _err; 5593 err = safe_strtod(val, &v); 5594 if (err < 0) { 5595 SNDERR("Parameter %s must be a real", var); 5596 goto _err; 5597 } 5598 err = snd_config_set_real(sub, v); 5599 if (err < 0) 5600 goto _err; 5601 } else if (strcmp(tmp, "string") == 0) { 5602 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_STRING); 5603 if (err < 0) 5604 goto _err; 5605 err = snd_config_set_string(sub, val); 5606 if (err < 0) 5607 goto _err; 5608 } else { 5609 err = -EINVAL; 5610 goto _invalid_type; 5611 } 5612 err = snd_config_set_id(sub, var); 5613 if (err < 0) 5614 goto _err; 5615 err = snd_config_add(subs, sub); 5616 if (err < 0) { 5617 _err: 5618 if (sub) 5619 snd_config_delete(sub); 5620 free(val); 5621 return err; 5622 } 5623 free(val); 5624 if (!*new) 5625 break; 5626 if (*new != ',') 5627 return -EINVAL; 5628 str = new + 1; 5629 arg++; 5630 } 5631 return 0; 5632} 5633 5634/** 5635 * \brief Expands a configuration node, applying arguments and functions. 5636 * \param[in] config Handle to the configuration node. 5637 * \param[in] root Handle to the root configuration node. 5638 * \param[in] fcn Custom function to obtain the referred variable name 5639 * \param[in] private_data Private data node for the custom function 5640 * \param[out] result The function puts the handle to the result 5641 * configuration node at the address specified by 5642 * \a result. 5643 * \return A non-negative value if successful, otherwise a negative error code. 5644 * 5645 * If \a config has arguments (defined by a child with id \c \@args), 5646 * this function replaces any string node beginning with $ with the 5647 * respective argument value, or the default argument value, or nothing. 5648 * Furthermore, any functions are evaluated (see #snd_config_evaluate). 5649 * The resulting copy of \a config is returned in \a result. 5650 * 5651 * The new tree is not evaluated (\ref snd_config_evaluate). 5652 */ 5653int snd_config_expand_custom(snd_config_t *config, snd_config_t *root, 5654 snd_config_expand_fcn_t fcn, void *private_data, 5655 snd_config_t **result) 5656{ 5657 snd_config_t *res; 5658 int err; 5659 5660 err = snd_config_walk(config, root, &res, _snd_config_expand, fcn, private_data); 5661 if (err < 0) { 5662 SNDERR("Expand error (walk): %s", snd_strerror(err)); 5663 return err; 5664 } 5665 *result = res; 5666 return 1; 5667} 5668 5669/** 5670 * \brief Expands a configuration node, applying arguments and functions. 5671 * \param[in] config Handle to the configuration node. 5672 * \param[in] root Handle to the root configuration node. 5673 * \param[in] args Arguments string, can be \c NULL. 5674 * \param[in] private_data Handle to the private data node for functions. 5675 * \param[out] result The function puts the handle to the result 5676 * configuration node at the address specified by 5677 * \a result. 5678 * \return A non-negative value if successful, otherwise a negative error code. 5679 * 5680 * If \a config has arguments (defined by a child with id \c \@args), 5681 * this function replaces any string node beginning with $ with the 5682 * respective argument value, or the default argument value, or nothing. 5683 * Furthermore, any functions are evaluated (see #snd_config_evaluate). 5684 * The resulting copy of \a config is returned in \a result. 5685 */ 5686int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args, 5687 snd_config_t *private_data, snd_config_t **result) 5688{ 5689 int err; 5690 snd_config_t *defs, *subs = NULL, *res; 5691 err = snd_config_search(config, "@args", &defs); 5692 if (err < 0) { 5693 if (args != NULL) { 5694 SNDERR("Unknown parameters %s", args); 5695 return -EINVAL; 5696 } 5697 err = snd_config_copy(&res, config); 5698 if (err < 0) 5699 return err; 5700 } else { 5701 err = snd_config_top(&subs); 5702 if (err < 0) 5703 return err; 5704 err = load_defaults(subs, defs); 5705 if (err < 0) { 5706 SNDERR("Load defaults error: %s", snd_strerror(err)); 5707 goto _end; 5708 } 5709 err = parse_args(subs, args, defs); 5710 if (err < 0) { 5711 SNDERR("Parse arguments error: %s", snd_strerror(err)); 5712 goto _end; 5713 } 5714 err = snd_config_evaluate(subs, root, private_data, NULL); 5715 if (err < 0) { 5716 SNDERR("Args evaluate error: %s", snd_strerror(err)); 5717 goto _end; 5718 } 5719 err = snd_config_walk(config, root, &res, _snd_config_expand, _snd_config_expand_vars, subs); 5720 if (err < 0) { 5721 SNDERR("Expand error (walk): %s", snd_strerror(err)); 5722 goto _end; 5723 } 5724 } 5725 err = snd_config_evaluate(res, root, private_data, NULL); 5726 if (err < 0) { 5727 SNDERR("Evaluate error: %s", snd_strerror(err)); 5728 snd_config_delete(res); 5729 goto _end; 5730 } 5731 *result = res; 5732 err = 1; 5733 _end: 5734 if (subs) 5735 snd_config_delete(subs); 5736 return err; 5737} 5738 5739/** 5740 * \brief Searches for a definition in a configuration tree, using 5741 * aliases and expanding hooks and arguments. 5742 * \param[in] config Handle to the configuration (sub)tree to search. 5743 * \param[in] base Implicit key base, or \c NULL for none. 5744 * \param[in] name Key suffix, optionally with arguments. 5745 * \param[out] result The function puts the handle to the expanded found 5746 * node at the address specified by \a result. 5747 * \return A non-negative value if successful, otherwise a negative error code. 5748 * 5749 * This functions searches for a child node of \a config, allowing 5750 * aliases and expanding hooks, like #snd_config_search_alias_hooks. 5751 * 5752 * If \a name contains a colon (:), the rest of the string after the 5753 * colon contains arguments that are expanded as with 5754 * #snd_config_expand. 5755 * 5756 * In any case, \a result is a new node that must be freed by the 5757 * caller. 5758 * 5759 * \par Errors: 5760 * <dl> 5761 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist. 5762 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is 5763 * not a compound node. 5764 * </dl> 5765 * Additionally, any errors encountered when parsing the hook 5766 * definitions or arguments, or returned by (hook) functions. 5767 */ 5768int snd_config_search_definition(snd_config_t *config, 5769 const char *base, const char *name, 5770 snd_config_t **result) 5771{ 5772 snd_config_t *conf; 5773 char *key; 5774 const char *args = strchr(name, ':'); 5775 int err; 5776 if (args) { 5777 args++; 5778 key = alloca(args - name); 5779 memcpy(key, name, args - name - 1); 5780 key[args - name - 1] = '\0'; 5781 } else { 5782 key = (char *) name; 5783 } 5784 /* 5785 * if key contains dot (.), the implicit base is ignored 5786 * and the key starts from root given by the 'config' parameter 5787 */ 5788 snd_config_lock(); 5789 err = snd_config_search_alias_hooks(config, strchr(key, '.') ? NULL : base, key, &conf); 5790 if (err < 0) { 5791 snd_config_unlock(); 5792 return err; 5793 } 5794 err = snd_config_expand(conf, config, args, NULL, result); 5795 snd_config_unlock(); 5796 return err; 5797} 5798 5799#ifndef DOC_HIDDEN 5800void snd_config_set_hop(snd_config_t *conf, int hop) 5801{ 5802 conf->hop = hop; 5803} 5804 5805int snd_config_check_hop(snd_config_t *conf) 5806{ 5807 if (conf) { 5808 if (conf->hop >= SND_CONF_MAX_HOPS) { 5809 SYSERR("Too many definition levels (looped?)\n"); 5810 return -EINVAL; 5811 } 5812 return conf->hop; 5813 } 5814 return 0; 5815} 5816#endif 5817 5818#if 0 5819/* Not strictly needed, but useful to check for memory leaks */ 5820void _snd_config_end(void) __attribute__ ((destructor)); 5821 5822static void _snd_config_end(void) 5823{ 5824 int k; 5825 if (snd_config) 5826 snd_config_delete(snd_config); 5827 snd_config = 0; 5828 for (k = 0; k < files_info_count; ++k) 5829 free(files_info[k].name); 5830 free(files_info); 5831 files_info = NULL; 5832 files_info_count = 0; 5833} 5834#endif 5835 5836#ifndef DOC_HIDDEN 5837size_t page_size(void) 5838{ 5839 long s = sysconf(_SC_PAGE_SIZE); 5840 assert(s > 0); 5841 return s; 5842} 5843 5844size_t page_align(size_t size) 5845{ 5846 size_t r; 5847 long psz = page_size(); 5848 r = size % psz; 5849 if (r) 5850 return size + psz - r; 5851 return size; 5852} 5853 5854size_t page_ptr(size_t object_offset, size_t object_size, size_t *offset, size_t *mmap_offset) 5855{ 5856 size_t r; 5857 long psz = page_size(); 5858 assert(offset); 5859 assert(mmap_offset); 5860 *mmap_offset = object_offset; 5861 object_offset %= psz; 5862 *mmap_offset -= object_offset; 5863 object_size += object_offset; 5864 r = object_size % psz; 5865 if (r) 5866 r = object_size + psz - r; 5867 else 5868 r = object_size; 5869 *offset = object_offset; 5870 return r; 5871} 5872#endif /* DOC_HIDDEN */ 5873