/lib/libkrb5/util/profile/prof_init.c

https://github.com/rhuitl/uClinux · C · 402 lines · 321 code · 57 blank · 24 comment · 77 complexity · a4e3ae7d0751600be124e2c8971f9971 MD5 · raw file

  1. /*
  2. * prof_init.c --- routines that manipulate the user-visible profile_t
  3. * object.
  4. */
  5. #include "prof_int.h"
  6. #include <stdio.h>
  7. #include <string.h>
  8. #ifdef HAVE_STDLIB_H
  9. #include <stdlib.h>
  10. #endif
  11. #include <errno.h>
  12. #ifdef HAVE_STDINT_H
  13. # include <stdint.h>
  14. #endif
  15. #ifdef HAVE_INTTYPES_H
  16. # include <inttypes.h>
  17. #endif
  18. typedef int32_t prof_int32;
  19. errcode_t KRB5_CALLCONV
  20. profile_init(const_profile_filespec_t *files, profile_t *ret_profile)
  21. {
  22. const_profile_filespec_t *fs;
  23. profile_t profile;
  24. prf_file_t new_file, last = 0;
  25. errcode_t retval = 0;
  26. profile = malloc(sizeof(struct _profile_t));
  27. if (!profile)
  28. return ENOMEM;
  29. memset(profile, 0, sizeof(struct _profile_t));
  30. profile->magic = PROF_MAGIC_PROFILE;
  31. /*
  32. * If the filenames list is not specified or empty, return an empty
  33. * profile.
  34. */
  35. if ( files && !PROFILE_LAST_FILESPEC(*files) ) {
  36. for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) {
  37. retval = profile_open_file(*fs, &new_file);
  38. /* if this file is missing, skip to the next */
  39. if (retval == ENOENT || retval == EACCES || retval == EPERM) {
  40. continue;
  41. }
  42. if (retval) {
  43. profile_release(profile);
  44. return retval;
  45. }
  46. if (last)
  47. last->next = new_file;
  48. else
  49. profile->first_file = new_file;
  50. last = new_file;
  51. }
  52. /*
  53. * If last is still null after the loop, then all the files were
  54. * missing, so return the appropriate error.
  55. */
  56. if (!last) {
  57. profile_release(profile);
  58. return ENOENT;
  59. }
  60. }
  61. *ret_profile = profile;
  62. return 0;
  63. }
  64. #define COUNT_LINKED_LIST(COUNT, PTYPE, START, FIELD) \
  65. { \
  66. size_t cll_counter = 0; \
  67. PTYPE cll_ptr = (START); \
  68. while (cll_ptr != NULL) { \
  69. cll_counter++; \
  70. cll_ptr = cll_ptr->FIELD; \
  71. } \
  72. (COUNT) = cll_counter; \
  73. }
  74. errcode_t KRB5_CALLCONV
  75. profile_copy(profile_t old_profile, profile_t *new_profile)
  76. {
  77. size_t size, i;
  78. const_profile_filespec_t *files;
  79. prf_file_t file;
  80. errcode_t err;
  81. /* The fields we care about are read-only after creation, so
  82. no locking is needed. */
  83. COUNT_LINKED_LIST (size, prf_file_t, old_profile->first_file, next);
  84. files = malloc ((size+1) * sizeof(*files));
  85. if (files == NULL)
  86. return ENOMEM;
  87. for (i = 0, file = old_profile->first_file; i < size; i++, file = file->next)
  88. files[i] = file->data->filespec;
  89. files[size] = NULL;
  90. err = profile_init (files, new_profile);
  91. free (files);
  92. return err;
  93. }
  94. errcode_t KRB5_CALLCONV
  95. profile_init_path(const_profile_filespec_list_t filepath,
  96. profile_t *ret_profile)
  97. {
  98. unsigned int n_entries;
  99. int i;
  100. unsigned int ent_len;
  101. const char *s, *t;
  102. profile_filespec_t *filenames;
  103. errcode_t retval;
  104. /* count the distinct filename components */
  105. for(s = filepath, n_entries = 1; *s; s++) {
  106. if (*s == ':')
  107. n_entries++;
  108. }
  109. /* the array is NULL terminated */
  110. filenames = (profile_filespec_t*) malloc((n_entries+1) * sizeof(char*));
  111. if (filenames == 0)
  112. return ENOMEM;
  113. /* measure, copy, and skip each one */
  114. for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) {
  115. ent_len = (unsigned int) (t-s);
  116. filenames[i] = (char*) malloc(ent_len + 1);
  117. if (filenames[i] == 0) {
  118. /* if malloc fails, free the ones that worked */
  119. while(--i >= 0) free(filenames[i]);
  120. free(filenames);
  121. return ENOMEM;
  122. }
  123. strncpy(filenames[i], s, ent_len);
  124. filenames[i][ent_len] = 0;
  125. if (*t == 0) {
  126. i++;
  127. break;
  128. }
  129. }
  130. /* cap the array */
  131. filenames[i] = 0;
  132. retval = profile_init((const_profile_filespec_t *) filenames,
  133. ret_profile);
  134. /* count back down and free the entries */
  135. while(--i >= 0) free(filenames[i]);
  136. free(filenames);
  137. return retval;
  138. }
  139. errcode_t KRB5_CALLCONV
  140. profile_is_writable(profile_t profile, int *writable)
  141. {
  142. if (!profile || profile->magic != PROF_MAGIC_PROFILE)
  143. return PROF_MAGIC_PROFILE;
  144. if (!writable)
  145. return EINVAL;
  146. if (profile->first_file)
  147. *writable = profile_file_is_writable(profile->first_file);
  148. return 0;
  149. }
  150. errcode_t KRB5_CALLCONV
  151. profile_is_modified(profile_t profile, int *modified)
  152. {
  153. if (!profile || profile->magic != PROF_MAGIC_PROFILE)
  154. return PROF_MAGIC_PROFILE;
  155. if (!modified)
  156. return EINVAL;
  157. if (profile->first_file)
  158. *modified = (profile->first_file->data->flags & PROFILE_FILE_DIRTY);
  159. return 0;
  160. }
  161. errcode_t KRB5_CALLCONV
  162. profile_flush(profile_t profile)
  163. {
  164. if (!profile || profile->magic != PROF_MAGIC_PROFILE)
  165. return PROF_MAGIC_PROFILE;
  166. if (profile->first_file)
  167. return profile_flush_file(profile->first_file);
  168. return 0;
  169. }
  170. errcode_t KRB5_CALLCONV
  171. profile_flush_to_file(profile_t profile, const_profile_filespec_t outfile)
  172. {
  173. if (!profile || profile->magic != PROF_MAGIC_PROFILE)
  174. return PROF_MAGIC_PROFILE;
  175. if (profile->first_file)
  176. return profile_flush_file_to_file(profile->first_file,
  177. outfile);
  178. return 0;
  179. }
  180. errcode_t KRB5_CALLCONV
  181. profile_flush_to_buffer(profile_t profile, char **buf)
  182. {
  183. return profile_flush_file_data_to_buffer(profile->first_file->data, buf);
  184. }
  185. void KRB5_CALLCONV
  186. profile_free_buffer(profile_t profile, char *buf)
  187. {
  188. free(buf);
  189. }
  190. void KRB5_CALLCONV
  191. profile_abandon(profile_t profile)
  192. {
  193. prf_file_t p, next;
  194. if (!profile || profile->magic != PROF_MAGIC_PROFILE)
  195. return;
  196. for (p = profile->first_file; p; p = next) {
  197. next = p->next;
  198. profile_free_file(p);
  199. }
  200. profile->magic = 0;
  201. free(profile);
  202. }
  203. void KRB5_CALLCONV
  204. profile_release(profile_t profile)
  205. {
  206. prf_file_t p, next;
  207. if (!profile || profile->magic != PROF_MAGIC_PROFILE)
  208. return;
  209. for (p = profile->first_file; p; p = next) {
  210. next = p->next;
  211. profile_close_file(p);
  212. }
  213. profile->magic = 0;
  214. free(profile);
  215. }
  216. /*
  217. * Here begins the profile serialization functions.
  218. */
  219. errcode_t profile_ser_size(const char *unused, profile_t profile,
  220. size_t *sizep)
  221. {
  222. size_t required;
  223. prf_file_t pfp;
  224. required = 3*sizeof(prof_int32);
  225. for (pfp = profile->first_file; pfp; pfp = pfp->next) {
  226. required += sizeof(prof_int32);
  227. required += strlen(pfp->data->filespec);
  228. }
  229. *sizep += required;
  230. return 0;
  231. }
  232. static void pack_int32(prof_int32 oval, unsigned char **bufpp, size_t *remainp)
  233. {
  234. store_32_be(oval, *bufpp);
  235. *bufpp += sizeof(prof_int32);
  236. *remainp -= sizeof(prof_int32);
  237. }
  238. errcode_t profile_ser_externalize(const char *unused, profile_t profile,
  239. unsigned char **bufpp, size_t *remainp)
  240. {
  241. errcode_t retval;
  242. size_t required;
  243. unsigned char *bp;
  244. size_t remain;
  245. prf_file_t pfp;
  246. prof_int32 fcount, slen;
  247. required = 0;
  248. bp = *bufpp;
  249. remain = *remainp;
  250. retval = EINVAL;
  251. if (profile) {
  252. retval = ENOMEM;
  253. (void) profile_ser_size(unused, profile, &required);
  254. if (required <= remain) {
  255. fcount = 0;
  256. for (pfp = profile->first_file; pfp; pfp = pfp->next)
  257. fcount++;
  258. pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
  259. pack_int32(fcount, &bp, &remain);
  260. for (pfp = profile->first_file; pfp; pfp = pfp->next) {
  261. slen = (prof_int32) strlen(pfp->data->filespec);
  262. pack_int32(slen, &bp, &remain);
  263. if (slen) {
  264. memcpy(bp, pfp->data->filespec, (size_t) slen);
  265. bp += slen;
  266. remain -= (size_t) slen;
  267. }
  268. }
  269. pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
  270. retval = 0;
  271. *bufpp = bp;
  272. *remainp = remain;
  273. }
  274. }
  275. return(retval);
  276. }
  277. static int unpack_int32(prof_int32 *intp, unsigned char **bufpp,
  278. size_t *remainp)
  279. {
  280. if (*remainp >= sizeof(prof_int32)) {
  281. *intp = load_32_be(*bufpp);
  282. *bufpp += sizeof(prof_int32);
  283. *remainp -= sizeof(prof_int32);
  284. return 0;
  285. }
  286. else
  287. return 1;
  288. }
  289. errcode_t profile_ser_internalize(const char *unused, profile_t *profilep,
  290. unsigned char **bufpp, size_t *remainp)
  291. {
  292. errcode_t retval;
  293. unsigned char *bp;
  294. size_t remain;
  295. int i;
  296. prof_int32 fcount, tmp;
  297. profile_filespec_t *flist = 0;
  298. bp = *bufpp;
  299. remain = *remainp;
  300. fcount = 0;
  301. if (remain >= 12)
  302. (void) unpack_int32(&tmp, &bp, &remain);
  303. else
  304. tmp = 0;
  305. if (tmp != PROF_MAGIC_PROFILE) {
  306. retval = EINVAL;
  307. goto cleanup;
  308. }
  309. (void) unpack_int32(&fcount, &bp, &remain);
  310. retval = ENOMEM;
  311. flist = (profile_filespec_t *) malloc(sizeof(profile_filespec_t) * (size_t) (fcount + 1));
  312. if (!flist)
  313. goto cleanup;
  314. memset(flist, 0, sizeof(char *) * (size_t) (fcount+1));
  315. for (i=0; i<fcount; i++) {
  316. if (!unpack_int32(&tmp, &bp, &remain)) {
  317. flist[i] = (char *) malloc((size_t) (tmp+1));
  318. if (!flist[i])
  319. goto cleanup;
  320. memcpy(flist[i], bp, (size_t) tmp);
  321. flist[i][tmp] = '\0';
  322. bp += tmp;
  323. remain -= (size_t) tmp;
  324. }
  325. }
  326. if (unpack_int32(&tmp, &bp, &remain) ||
  327. (tmp != PROF_MAGIC_PROFILE)) {
  328. retval = EINVAL;
  329. goto cleanup;
  330. }
  331. if ((retval = profile_init((const_profile_filespec_t *) flist,
  332. profilep)))
  333. goto cleanup;
  334. *bufpp = bp;
  335. *remainp = remain;
  336. cleanup:
  337. if (flist) {
  338. for (i=0; i<fcount; i++) {
  339. if (flist[i])
  340. free(flist[i]);
  341. }
  342. free(flist);
  343. }
  344. return(retval);
  345. }