conffile.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* Copyright (c) 2001 Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. #include "common/compat.h"
  7. #include "common/confline.h"
  8. #include "common/conffile.h"
  9. #include "lib/log/torlog.h"
  10. #include "common/util.h"
  11. #include "lib/container/smartlist.h"
  12. static smartlist_t *config_get_file_list(const char *path,
  13. smartlist_t *opened_files);
  14. static int config_get_included_config(const char *path, int recursion_level,
  15. int extended, config_line_t **config,
  16. config_line_t **config_last,
  17. smartlist_t *opened_lst);
  18. static int config_process_include(const char *path, int recursion_level,
  19. int extended, config_line_t **list,
  20. config_line_t **list_last,
  21. smartlist_t *opened_lst);
  22. /** Helper: parse the config string and strdup into key/value
  23. * strings. Set *result to the list, or NULL if parsing the string
  24. * failed. Set *has_include to 1 if <b>result</b> has values from
  25. * %included files. <b>opened_lst</b> will have a list of opened files if
  26. * provided. Return 0 on success, -1 on failure. Warn and ignore any
  27. * misformatted lines.
  28. *
  29. * If <b>extended</b> is set, then treat keys beginning with / and with + as
  30. * indicating "clear" and "append" respectively. */
  31. int
  32. config_get_lines_include(const char *string, config_line_t **result,
  33. int extended, int *has_include,
  34. smartlist_t *opened_lst)
  35. {
  36. return config_get_lines_aux(string, result, extended, 1, has_include,
  37. opened_lst, 1, NULL, config_process_include);
  38. }
  39. /** Adds a list of configuration files present on <b>path</b> to
  40. * <b>file_list</b>. <b>path</b> can be a file or a directory. If it is a file,
  41. * only that file will be added to <b>file_list</b>. If it is a directory,
  42. * all paths for files on that directory root (no recursion) except for files
  43. * whose name starts with a dot will be added to <b>file_list</b>.
  44. * <b>opened_files</b> will have a list of files opened by this function
  45. * if provided. Return 0 on success, -1 on failure. Ignores empty files.
  46. */
  47. static smartlist_t *
  48. config_get_file_list(const char *path, smartlist_t *opened_files)
  49. {
  50. smartlist_t *file_list = smartlist_new();
  51. if (opened_files) {
  52. smartlist_add_strdup(opened_files, path);
  53. }
  54. file_status_t file_type = file_status(path);
  55. if (file_type == FN_FILE) {
  56. smartlist_add_strdup(file_list, path);
  57. return file_list;
  58. } else if (file_type == FN_DIR) {
  59. smartlist_t *all_files = tor_listdir(path);
  60. if (!all_files) {
  61. smartlist_free(file_list);
  62. return NULL;
  63. }
  64. smartlist_sort_strings(all_files);
  65. SMARTLIST_FOREACH_BEGIN(all_files, char *, f) {
  66. if (f[0] == '.') {
  67. tor_free(f);
  68. continue;
  69. }
  70. char *fullname;
  71. tor_asprintf(&fullname, "%s"PATH_SEPARATOR"%s", path, f);
  72. tor_free(f);
  73. if (opened_files) {
  74. smartlist_add_strdup(opened_files, fullname);
  75. }
  76. if (file_status(fullname) != FN_FILE) {
  77. tor_free(fullname);
  78. continue;
  79. }
  80. smartlist_add(file_list, fullname);
  81. } SMARTLIST_FOREACH_END(f);
  82. smartlist_free(all_files);
  83. return file_list;
  84. } else if (file_type == FN_EMPTY) {
  85. return file_list;
  86. } else {
  87. smartlist_free(file_list);
  88. return NULL;
  89. }
  90. }
  91. /** Creates a list of config lines present on included <b>path</b>.
  92. * Set <b>config</b> to the list and <b>config_last</b> to the last element of
  93. * <b>config</b>. <b>opened_lst</b> will have a list of opened files if
  94. * provided. Return 0 on success, -1 on failure. */
  95. static int
  96. config_get_included_config(const char *path, int recursion_level, int extended,
  97. config_line_t **config, config_line_t **config_last,
  98. smartlist_t *opened_lst)
  99. {
  100. char *included_conf = read_file_to_str(path, 0, NULL);
  101. if (!included_conf) {
  102. return -1;
  103. }
  104. if (config_get_lines_aux(included_conf, config, extended, 1, NULL,
  105. opened_lst, recursion_level+1, config_last,
  106. config_process_include) < 0) {
  107. tor_free(included_conf);
  108. return -1;
  109. }
  110. tor_free(included_conf);
  111. return 0;
  112. }
  113. /** Process an %include <b>path</b> in a config file. Set <b>list</b> to the
  114. * list of configuration settings obtained and <b>list_last</b> to the last
  115. * element of the same list. <b>opened_lst</b> will have a list of opened
  116. * files if provided. Return 0 on success, -1 on failure. */
  117. static int
  118. config_process_include(const char *path, int recursion_level, int extended,
  119. config_line_t **list, config_line_t **list_last,
  120. smartlist_t *opened_lst)
  121. {
  122. config_line_t *ret_list = NULL;
  123. config_line_t **next = &ret_list;
  124. smartlist_t *config_files = config_get_file_list(path, opened_lst);
  125. if (!config_files) {
  126. return -1;
  127. }
  128. int rv = -1;
  129. SMARTLIST_FOREACH_BEGIN(config_files, const char *, config_file) {
  130. config_line_t *included_config = NULL;
  131. if (config_get_included_config(config_file, recursion_level, extended,
  132. &included_config, list_last,
  133. opened_lst) < 0) {
  134. goto done;
  135. }
  136. *next = included_config;
  137. if (*list_last)
  138. next = &(*list_last)->next;
  139. } SMARTLIST_FOREACH_END(config_file);
  140. *list = ret_list;
  141. rv = 0;
  142. done:
  143. SMARTLIST_FOREACH(config_files, char *, f, tor_free(f));
  144. smartlist_free(config_files);
  145. return rv;
  146. }