conffile.c 5.8 KB

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