PageRenderTime 33ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/external/e2fsprogs/e2fsck/profile_helpers.c

https://gitlab.com/brian0218/rk3066_r-box_android4.2.2_sdk
C | 309 lines | 202 code | 45 blank | 62 comment | 45 complexity | 7d2c427826da14e7b7328b00fe16b096 MD5 | raw file
  1. /*
  2. * profile_helpers.c -- Helper functions for the profile library
  3. *
  4. * These functions are not part of the "core" profile library, and do
  5. * not require access to the internal functions and data structures of
  6. * the profile library. They are mainly convenience functions for
  7. * programs that want to do something unusual such as obtaining the
  8. * list of sections or relations, or accessing multiple values from a
  9. * relation that is listed more than once. This functionality can all
  10. * be done using the profile_iterator abstraction, but it is less
  11. * convenient.
  12. *
  13. * Copyright (C) 2006 by Theodore Ts'o.
  14. *
  15. * %Begin-Header%
  16. * This file may be redistributed under the terms of the GNU Public
  17. * License.
  18. * %End-Header%
  19. */
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <errno.h>
  23. #include <et/com_err.h>
  24. #include "profile.h"
  25. #include "prof_err.h"
  26. /*
  27. * These functions --- init_list(), end_list(), and add_to_list() are
  28. * internal functions used to build up a null-terminated char ** list
  29. * of strings to be returned by functions like profile_get_values.
  30. *
  31. * The profile_string_list structure is used for internal booking
  32. * purposes to build up the list, which is returned in *ret_list by
  33. * the end_list() function.
  34. *
  35. * The publicly exported interface for freeing char** list is
  36. * profile_free_list().
  37. */
  38. struct profile_string_list {
  39. char **list;
  40. int num;
  41. int max;
  42. };
  43. /*
  44. * Initialize the string list abstraction.
  45. */
  46. static errcode_t init_list(struct profile_string_list *list)
  47. {
  48. list->num = 0;
  49. list->max = 10;
  50. list->list = malloc(list->max * sizeof(char *));
  51. if (list->list == 0)
  52. return ENOMEM;
  53. list->list[0] = 0;
  54. return 0;
  55. }
  56. /*
  57. * Free any memory left over in the string abstraction, returning the
  58. * built up list in *ret_list if it is non-null.
  59. */
  60. static void end_list(struct profile_string_list *list, char ***ret_list)
  61. {
  62. char **cp;
  63. if (list == 0)
  64. return;
  65. if (ret_list) {
  66. *ret_list = list->list;
  67. return;
  68. } else {
  69. for (cp = list->list; *cp; cp++)
  70. free(*cp);
  71. free(list->list);
  72. }
  73. list->num = list->max = 0;
  74. list->list = 0;
  75. }
  76. /*
  77. * Add a string to the list.
  78. */
  79. static errcode_t add_to_list(struct profile_string_list *list, char *str)
  80. {
  81. char **newlist;
  82. int newmax;
  83. if (list->num+1 >= list->max) {
  84. newmax = list->max + 10;
  85. newlist = realloc(list->list, newmax * sizeof(char *));
  86. if (newlist == 0)
  87. return ENOMEM;
  88. list->max = newmax;
  89. list->list = newlist;
  90. }
  91. list->list[list->num++] = str;
  92. list->list[list->num] = 0;
  93. return 0;
  94. }
  95. /*
  96. * Return TRUE if the string is already a member of the list.
  97. */
  98. static int is_list_member(struct profile_string_list *list, const char *str)
  99. {
  100. char **cpp;
  101. if (!list->list)
  102. return 0;
  103. for (cpp = list->list; *cpp; cpp++) {
  104. if (!strcmp(*cpp, str))
  105. return 1;
  106. }
  107. return 0;
  108. }
  109. /*
  110. * This function frees a null-terminated list as returned by
  111. * profile_get_values.
  112. */
  113. void profile_free_list(char **list)
  114. {
  115. char **cp;
  116. if (list == 0)
  117. return;
  118. for (cp = list; *cp; cp++)
  119. free(*cp);
  120. free(list);
  121. }
  122. errcode_t
  123. profile_get_values(profile_t profile, const char *const *names,
  124. char ***ret_values)
  125. {
  126. errcode_t retval;
  127. void *state;
  128. char *value;
  129. struct profile_string_list values;
  130. if ((retval = profile_iterator_create(profile, names,
  131. PROFILE_ITER_RELATIONS_ONLY,
  132. &state)))
  133. return retval;
  134. if ((retval = init_list(&values)))
  135. return retval;
  136. do {
  137. if ((retval = profile_iterator(&state, 0, &value)))
  138. goto cleanup;
  139. if (value)
  140. add_to_list(&values, value);
  141. } while (state);
  142. if (values.num == 0) {
  143. retval = PROF_NO_RELATION;
  144. goto cleanup;
  145. }
  146. end_list(&values, ret_values);
  147. return 0;
  148. cleanup:
  149. end_list(&values, 0);
  150. return retval;
  151. }
  152. /*
  153. * This function will return the list of the names of subections in the
  154. * under the specified section name.
  155. */
  156. errcode_t
  157. profile_get_subsection_names(profile_t profile, const char **names,
  158. char ***ret_names)
  159. {
  160. errcode_t retval;
  161. void *state;
  162. char *name;
  163. struct profile_string_list values;
  164. if ((retval = profile_iterator_create(profile, names,
  165. PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY,
  166. &state)))
  167. return retval;
  168. if ((retval = init_list(&values)))
  169. return retval;
  170. do {
  171. if ((retval = profile_iterator(&state, &name, 0)))
  172. goto cleanup;
  173. if (name)
  174. add_to_list(&values, name);
  175. } while (state);
  176. end_list(&values, ret_names);
  177. return 0;
  178. cleanup:
  179. end_list(&values, 0);
  180. return retval;
  181. }
  182. /*
  183. * This function will return the list of the names of relations in the
  184. * under the specified section name.
  185. */
  186. errcode_t
  187. profile_get_relation_names(profile_t profile, const char **names,
  188. char ***ret_names)
  189. {
  190. errcode_t retval;
  191. void *state;
  192. char *name;
  193. struct profile_string_list values;
  194. if ((retval = profile_iterator_create(profile, names,
  195. PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY,
  196. &state)))
  197. return retval;
  198. if ((retval = init_list(&values)))
  199. return retval;
  200. do {
  201. if ((retval = profile_iterator(&state, &name, 0)))
  202. goto cleanup;
  203. if (name) {
  204. if (is_list_member(&values, name))
  205. free(name);
  206. else
  207. add_to_list(&values, name);
  208. }
  209. } while (state);
  210. end_list(&values, ret_names);
  211. return 0;
  212. cleanup:
  213. end_list(&values, 0);
  214. return retval;
  215. }
  216. void
  217. profile_release_string(char *str)
  218. {
  219. free(str);
  220. }
  221. errcode_t
  222. profile_init_path(const char * filepath,
  223. profile_t *ret_profile)
  224. {
  225. int n_entries, i;
  226. unsigned int ent_len;
  227. const char *s, *t;
  228. char **filenames;
  229. errcode_t retval;
  230. /* count the distinct filename components */
  231. for(s = filepath, n_entries = 1; *s; s++) {
  232. if (*s == ':')
  233. n_entries++;
  234. }
  235. /* the array is NULL terminated */
  236. filenames = (char **) malloc((n_entries+1) * sizeof(char*));
  237. if (filenames == 0)
  238. return ENOMEM;
  239. /* measure, copy, and skip each one */
  240. for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
  241. ent_len = t-s;
  242. filenames[i] = (char*) malloc(ent_len + 1);
  243. if (filenames[i] == 0) {
  244. /* if malloc fails, free the ones that worked */
  245. while(--i >= 0) free(filenames[i]);
  246. free(filenames);
  247. return ENOMEM;
  248. }
  249. strncpy(filenames[i], s, ent_len);
  250. filenames[i][ent_len] = 0;
  251. if (*t == 0) {
  252. i++;
  253. break;
  254. }
  255. }
  256. /* cap the array */
  257. filenames[i] = 0;
  258. retval = profile_init((const char **) filenames,
  259. ret_profile);
  260. /* count back down and free the entries */
  261. while(--i >= 0) free(filenames[i]);
  262. free(filenames);
  263. return retval;
  264. }