opkg_conf.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. /* opkg_conf.c - the opkg package management system
  2. Copyright (C) 2009 Ubiq Technologies <graham.gower@gmail.com>
  3. Carl D. Worth
  4. Copyright (C) 2001 University of Southern California
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2, or (at
  8. your option) any later version.
  9. This program is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. */
  14. #include "config.h"
  15. #include <stdio.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <fcntl.h>
  19. #include <glob.h>
  20. #include <unistd.h>
  21. #include "opkg_conf.h"
  22. #include "pkg_vec.h"
  23. #include "pkg.h"
  24. #include "xregex.h"
  25. #include "sprintf_alloc.h"
  26. #include "opkg_message.h"
  27. #include "file_util.h"
  28. #include "opkg_defines.h"
  29. #include "libbb/libbb.h"
  30. static int lock_fd;
  31. static char *lock_file = NULL;
  32. static opkg_conf_t _conf;
  33. opkg_conf_t *conf = &_conf;
  34. /*
  35. * Config file options
  36. */
  37. opkg_option_t options[] = {
  38. {"cache", OPKG_OPT_TYPE_STRING, &_conf.cache},
  39. {"force_defaults", OPKG_OPT_TYPE_BOOL, &_conf.force_defaults},
  40. {"force_maintainer", OPKG_OPT_TYPE_BOOL, &_conf.force_maintainer},
  41. {"force_depends", OPKG_OPT_TYPE_BOOL, &_conf.force_depends},
  42. {"force_overwrite", OPKG_OPT_TYPE_BOOL, &_conf.force_overwrite},
  43. {"force_downgrade", OPKG_OPT_TYPE_BOOL, &_conf.force_downgrade},
  44. {"force_reinstall", OPKG_OPT_TYPE_BOOL, &_conf.force_reinstall},
  45. {"force_space", OPKG_OPT_TYPE_BOOL, &_conf.force_space},
  46. {"force_postinstall", OPKG_OPT_TYPE_BOOL, &_conf.force_postinstall},
  47. {"force_checksum", OPKG_OPT_TYPE_BOOL, &_conf.force_checksum},
  48. {"check_signature", OPKG_OPT_TYPE_BOOL, &_conf.check_signature},
  49. {"ftp_proxy", OPKG_OPT_TYPE_STRING, &_conf.ftp_proxy},
  50. {"http_proxy", OPKG_OPT_TYPE_STRING, &_conf.http_proxy},
  51. {"no_proxy", OPKG_OPT_TYPE_STRING, &_conf.no_proxy},
  52. {"test", OPKG_OPT_TYPE_BOOL, &_conf.noaction},
  53. {"noaction", OPKG_OPT_TYPE_BOOL, &_conf.noaction},
  54. {"download_only", OPKG_OPT_TYPE_BOOL, &_conf.download_only},
  55. {"nodeps", OPKG_OPT_TYPE_BOOL, &_conf.nodeps},
  56. {"nocase", OPKG_OPT_TYPE_BOOL, &_conf.nocase},
  57. {"offline_root", OPKG_OPT_TYPE_STRING, &_conf.offline_root},
  58. {"overlay_root", OPKG_OPT_TYPE_STRING, &_conf.overlay_root},
  59. {"proxy_passwd", OPKG_OPT_TYPE_STRING, &_conf.proxy_passwd},
  60. {"proxy_user", OPKG_OPT_TYPE_STRING, &_conf.proxy_user},
  61. {"query-all", OPKG_OPT_TYPE_BOOL, &_conf.query_all},
  62. {"size", OPKG_OPT_TYPE_BOOL, &_conf.size},
  63. {"tmp_dir", OPKG_OPT_TYPE_STRING, &_conf.tmp_dir},
  64. {"verbosity", OPKG_OPT_TYPE_INT, &_conf.verbosity},
  65. #if defined(HAVE_OPENSSL)
  66. {"signature_ca_file", OPKG_OPT_TYPE_STRING, &_conf.signature_ca_file},
  67. {"signature_ca_path", OPKG_OPT_TYPE_STRING, &_conf.signature_ca_path},
  68. #endif
  69. #if defined(HAVE_PATHFINDER)
  70. {"check_x509_path", OPKG_OPT_TYPE_BOOL, &_conf.check_x509_path},
  71. #endif
  72. #if defined(HAVE_SSLCURL) && defined(HAVE_CURL)
  73. {"ssl_engine", OPKG_OPT_TYPE_STRING, &_conf.ssl_engine},
  74. {"ssl_cert", OPKG_OPT_TYPE_STRING, &_conf.ssl_cert},
  75. {"ssl_cert_type", OPKG_OPT_TYPE_STRING, &_conf.ssl_cert_type},
  76. {"ssl_key", OPKG_OPT_TYPE_STRING, &_conf.ssl_key},
  77. {"ssl_key_type", OPKG_OPT_TYPE_STRING, &_conf.ssl_key_type},
  78. {"ssl_key_passwd", OPKG_OPT_TYPE_STRING, &_conf.ssl_key_passwd},
  79. {"ssl_ca_file", OPKG_OPT_TYPE_STRING, &_conf.ssl_ca_file},
  80. {"ssl_ca_path", OPKG_OPT_TYPE_STRING, &_conf.ssl_ca_path},
  81. {"ssl_dont_verify_peer", OPKG_OPT_TYPE_BOOL,
  82. &_conf.ssl_dont_verify_peer},
  83. #endif
  84. {NULL, 0, NULL}
  85. };
  86. static int resolve_pkg_dest_list(void)
  87. {
  88. nv_pair_list_elt_t *iter;
  89. nv_pair_t *nv_pair;
  90. pkg_dest_t *dest;
  91. char *root_dir;
  92. for (iter = nv_pair_list_first(&conf->tmp_dest_list); iter;
  93. iter = nv_pair_list_next(&conf->tmp_dest_list, iter)) {
  94. nv_pair = (nv_pair_t *) iter->data;
  95. if (conf->offline_root) {
  96. sprintf_alloc(&root_dir, "%s%s", conf->offline_root,
  97. nv_pair->value);
  98. } else {
  99. root_dir = xstrdup(nv_pair->value);
  100. }
  101. dest =
  102. pkg_dest_list_append(&conf->pkg_dest_list, nv_pair->name,
  103. root_dir, conf->lists_dir);
  104. free(root_dir);
  105. if (conf->default_dest == NULL)
  106. conf->default_dest = dest;
  107. if (conf->dest_str && !strcmp(dest->name, conf->dest_str)) {
  108. conf->default_dest = dest;
  109. conf->restrict_to_default_dest = 1;
  110. }
  111. }
  112. if (conf->dest_str && !conf->restrict_to_default_dest) {
  113. opkg_msg(ERROR, "Unknown dest name: `%s'.\n", conf->dest_str);
  114. return -1;
  115. }
  116. return 0;
  117. }
  118. static int opkg_conf_set_option(const char *name, const char *value)
  119. {
  120. int i = 0;
  121. while (options[i].name) {
  122. if (strcmp(options[i].name, name) == 0) {
  123. switch (options[i].type) {
  124. case OPKG_OPT_TYPE_BOOL:
  125. if (*(int *)options[i].value) {
  126. opkg_msg(ERROR,
  127. "Duplicate boolean option %s, "
  128. "leaving this option on.\n",
  129. name);
  130. return 0;
  131. }
  132. *((int *const)options[i].value) = 1;
  133. return 0;
  134. case OPKG_OPT_TYPE_INT:
  135. if (value) {
  136. if (*(int *)options[i].value) {
  137. opkg_msg(ERROR,
  138. "Duplicate option %s, "
  139. "using first seen value \"%d\".\n",
  140. name,
  141. *((int *)options[i].
  142. value));
  143. return 0;
  144. }
  145. *((int *const)options[i].value) =
  146. atoi(value);
  147. return 0;
  148. } else {
  149. opkg_msg(ERROR,
  150. "Option %s needs an argument\n",
  151. name);
  152. return -1;
  153. }
  154. case OPKG_OPT_TYPE_STRING:
  155. if (value) {
  156. if (*(char **)options[i].value) {
  157. opkg_msg(ERROR,
  158. "Duplicate option %s, "
  159. "using first seen value \"%s\".\n",
  160. name,
  161. *((char **)options[i].
  162. value));
  163. return 0;
  164. }
  165. *((char **const)options[i].value) =
  166. xstrdup(value);
  167. return 0;
  168. } else {
  169. opkg_msg(ERROR,
  170. "Option %s needs an argument\n",
  171. name);
  172. return -1;
  173. }
  174. }
  175. }
  176. i++;
  177. }
  178. opkg_msg(ERROR, "Unrecognized option: %s=%s\n", name, value);
  179. return -1;
  180. }
  181. static int
  182. opkg_conf_parse_file(const char *filename,
  183. pkg_src_list_t * pkg_src_list,
  184. pkg_src_list_t * dist_src_list)
  185. {
  186. int line_num = 0;
  187. int err = 0;
  188. FILE *file;
  189. regex_t valid_line_re, comment_re;
  190. #define regmatch_size 14
  191. regmatch_t regmatch[regmatch_size];
  192. file = fopen(filename, "r");
  193. if (file == NULL) {
  194. opkg_perror(ERROR, "Failed to open %s", filename);
  195. err = -1;
  196. goto err0;
  197. }
  198. opkg_msg(INFO, "Loading conf file %s.\n", filename);
  199. err = xregcomp(&comment_re,
  200. "^[[:space:]]*(#.*|[[:space:]]*)$", REG_EXTENDED);
  201. if (err)
  202. goto err1;
  203. err = xregcomp(&valid_line_re,
  204. "^[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))"
  205. "[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))"
  206. "[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))"
  207. "([[:space:]]+([^[:space:]]+))?([[:space:]]+(.*))?[[:space:]]*$",
  208. REG_EXTENDED);
  209. if (err)
  210. goto err2;
  211. while (1) {
  212. char *line;
  213. char *type, *name, *value, *extra;
  214. line_num++;
  215. line = file_read_line_alloc(file);
  216. if (line == NULL)
  217. break;
  218. if (regexec(&comment_re, line, 0, 0, 0) == 0)
  219. goto NEXT_LINE;
  220. if (regexec(&valid_line_re, line, regmatch_size, regmatch, 0) ==
  221. REG_NOMATCH) {
  222. opkg_msg(ERROR, "%s:%d: Ignoring invalid line: `%s'\n",
  223. filename, line_num, line);
  224. goto NEXT_LINE;
  225. }
  226. /* This has to be so ugly to deal with optional quotation marks */
  227. if (regmatch[2].rm_so > 0) {
  228. type = xstrndup(line + regmatch[2].rm_so,
  229. regmatch[2].rm_eo - regmatch[2].rm_so);
  230. } else {
  231. type = xstrndup(line + regmatch[3].rm_so,
  232. regmatch[3].rm_eo - regmatch[3].rm_so);
  233. }
  234. if (regmatch[5].rm_so > 0) {
  235. name = xstrndup(line + regmatch[5].rm_so,
  236. regmatch[5].rm_eo - regmatch[5].rm_so);
  237. } else {
  238. name = xstrndup(line + regmatch[6].rm_so,
  239. regmatch[6].rm_eo - regmatch[6].rm_so);
  240. }
  241. if (regmatch[8].rm_so > 0) {
  242. value = xstrndup(line + regmatch[8].rm_so,
  243. regmatch[8].rm_eo - regmatch[8].rm_so);
  244. } else {
  245. value = xstrndup(line + regmatch[9].rm_so,
  246. regmatch[9].rm_eo - regmatch[9].rm_so);
  247. }
  248. extra = NULL;
  249. if (regmatch[11].rm_so > 0) {
  250. if (regmatch[13].rm_so > 0
  251. && regmatch[13].rm_so != regmatch[13].rm_eo)
  252. extra =
  253. xstrndup(line + regmatch[11].rm_so,
  254. regmatch[13].rm_eo -
  255. regmatch[11].rm_so);
  256. else
  257. extra = xstrndup(line + regmatch[11].rm_so,
  258. regmatch[11].rm_eo -
  259. regmatch[11].rm_so);
  260. }
  261. if (regmatch[13].rm_so != regmatch[13].rm_eo
  262. && strncmp(type, "dist", 4) != 0) {
  263. opkg_msg(ERROR,
  264. "%s:%d: Ignoring config line with trailing garbage: `%s'\n",
  265. filename, line_num, line);
  266. } else {
  267. /* We use the conf->tmp_dest_list below instead of
  268. conf->pkg_dest_list because we might encounter an
  269. offline_root option later and that would invalidate the
  270. directories we would have computed in
  271. pkg_dest_list_init. (We do a similar thing with
  272. tmp_src_nv_pair_list for sake of symmetry.) */
  273. if (strcmp(type, "option") == 0) {
  274. opkg_conf_set_option(name, value);
  275. } else if (strcmp(type, "dist") == 0) {
  276. if (!nv_pair_list_find
  277. ((nv_pair_list_t *) dist_src_list, name)) {
  278. pkg_src_list_append(dist_src_list, name,
  279. value, extra, 0);
  280. } else {
  281. opkg_msg(ERROR,
  282. "Duplicate dist declaration (%s %s). "
  283. "Skipping.\n", name, value);
  284. }
  285. } else if (strcmp(type, "dist/gz") == 0) {
  286. if (!nv_pair_list_find
  287. ((nv_pair_list_t *) dist_src_list, name)) {
  288. pkg_src_list_append(dist_src_list, name,
  289. value, extra, 1);
  290. } else {
  291. opkg_msg(ERROR,
  292. "Duplicate dist declaration (%s %s). "
  293. "Skipping.\n", name, value);
  294. }
  295. } else if (strcmp(type, "src") == 0) {
  296. if (!nv_pair_list_find
  297. ((nv_pair_list_t *) pkg_src_list, name)) {
  298. pkg_src_list_append(pkg_src_list, name,
  299. value, extra, 0);
  300. } else {
  301. opkg_msg(ERROR,
  302. "Duplicate src declaration (%s %s). "
  303. "Skipping.\n", name, value);
  304. }
  305. } else if (strcmp(type, "src/gz") == 0) {
  306. if (!nv_pair_list_find
  307. ((nv_pair_list_t *) pkg_src_list, name)) {
  308. pkg_src_list_append(pkg_src_list, name,
  309. value, extra, 1);
  310. } else {
  311. opkg_msg(ERROR,
  312. "Duplicate src declaration (%s %s). "
  313. "Skipping.\n", name, value);
  314. }
  315. } else if (strcmp(type, "dest") == 0) {
  316. nv_pair_list_append(&conf->tmp_dest_list, name,
  317. value);
  318. } else if (strcmp(type, "lists_dir") == 0) {
  319. conf->lists_dir = xstrdup(value);
  320. } else if (strcmp(type, "arch") == 0) {
  321. opkg_msg(INFO,
  322. "Supported arch %s priority (%s)\n",
  323. name, value);
  324. if (!value) {
  325. opkg_msg(NOTICE,
  326. "No priority given for architecture %s,"
  327. "defaulting to 10\n", name);
  328. value = xstrdup("10");
  329. }
  330. nv_pair_list_append(&conf->arch_list, name,
  331. value);
  332. } else {
  333. opkg_msg(ERROR,
  334. "%s:%d: Ignoring invalid line: `%s'\n",
  335. filename, line_num, line);
  336. }
  337. }
  338. free(type);
  339. free(name);
  340. free(value);
  341. if (extra)
  342. free(extra);
  343. NEXT_LINE:
  344. free(line);
  345. }
  346. regfree(&valid_line_re);
  347. err2:
  348. regfree(&comment_re);
  349. err1:
  350. if (fclose(file) == EOF) {
  351. opkg_perror(ERROR, "Couldn't close %s", filename);
  352. err = -1;
  353. }
  354. err0:
  355. return err;
  356. }
  357. int opkg_conf_write_status_files(void)
  358. {
  359. pkg_dest_list_elt_t *iter;
  360. pkg_dest_t *dest;
  361. pkg_vec_t *all;
  362. pkg_t *pkg;
  363. int i, ret = 0;
  364. if (conf->noaction)
  365. return 0;
  366. list_for_each_entry(iter, &conf->pkg_dest_list.head, node) {
  367. dest = (pkg_dest_t *) iter->data;
  368. dest->status_fp = fopen(dest->status_file_name, "w");
  369. if (dest->status_fp == NULL && errno != EROFS) {
  370. opkg_perror(ERROR, "Can't open status file %s",
  371. dest->status_file_name);
  372. ret = -1;
  373. }
  374. }
  375. all = pkg_vec_alloc();
  376. pkg_hash_fetch_available(all);
  377. for (i = 0; i < all->len; i++) {
  378. pkg = all->pkgs[i];
  379. /* We don't need most uninstalled packages in the status file */
  380. if (pkg->state_status == SS_NOT_INSTALLED
  381. && (pkg->state_want == SW_UNKNOWN
  382. || (pkg->state_want == SW_DEINSTALL
  383. && pkg->state_flag != SF_HOLD)
  384. || pkg->state_want == SW_PURGE)) {
  385. continue;
  386. }
  387. if (pkg->dest == NULL) {
  388. opkg_msg(ERROR,
  389. "Internal error: package %s has a NULL dest\n",
  390. pkg->name);
  391. continue;
  392. }
  393. if (pkg->dest->status_fp)
  394. pkg_print_status(pkg, pkg->dest->status_fp);
  395. }
  396. pkg_vec_free(all);
  397. list_for_each_entry(iter, &conf->pkg_dest_list.head, node) {
  398. dest = (pkg_dest_t *) iter->data;
  399. if (dest->status_fp && fclose(dest->status_fp) == EOF) {
  400. opkg_perror(ERROR, "Couldn't close %s",
  401. dest->status_file_name);
  402. ret = -1;
  403. }
  404. }
  405. return ret;
  406. }
  407. char *root_filename_alloc(char *filename)
  408. {
  409. char *root_filename;
  410. sprintf_alloc(&root_filename, "%s%s",
  411. (conf->offline_root ? conf->offline_root : ""), filename);
  412. return root_filename;
  413. }
  414. static int glob_errfunc(const char *epath, int eerrno)
  415. {
  416. if (eerrno == ENOENT)
  417. /* If leading dir does not exist, we get GLOB_NOMATCH. */
  418. return 0;
  419. opkg_msg(ERROR, "glob failed for %s: %s\n", epath, strerror(eerrno));
  420. return 0;
  421. }
  422. int opkg_conf_init(void)
  423. {
  424. pkg_src_list_init(&conf->pkg_src_list);
  425. pkg_src_list_init(&conf->dist_src_list);
  426. pkg_dest_list_init(&conf->pkg_dest_list);
  427. pkg_dest_list_init(&conf->tmp_dest_list);
  428. nv_pair_list_init(&conf->arch_list);
  429. return 0;
  430. }
  431. int opkg_conf_load(void)
  432. {
  433. int i, glob_ret;
  434. char *tmp, *tmp_dir_base, **tmp_val;
  435. glob_t globbuf;
  436. char *etc_opkg_conf_pattern;
  437. conf->restrict_to_default_dest = 0;
  438. conf->default_dest = NULL;
  439. #if defined(HAVE_PATHFINDER)
  440. conf->check_x509_path = 1;
  441. #endif
  442. if (!conf->offline_root)
  443. conf->offline_root = xstrdup(getenv("OFFLINE_ROOT"));
  444. if (conf->conf_file) {
  445. struct stat st;
  446. if (stat(conf->conf_file, &st) == -1) {
  447. opkg_perror(ERROR, "Couldn't stat %s", conf->conf_file);
  448. goto err0;
  449. }
  450. if (opkg_conf_parse_file(conf->conf_file,
  451. &conf->pkg_src_list,
  452. &conf->dist_src_list))
  453. goto err1;
  454. }
  455. if (conf->offline_root)
  456. sprintf_alloc(&etc_opkg_conf_pattern, "%s/etc/opkg/*.conf",
  457. conf->offline_root);
  458. else {
  459. const char *conf_file_dir = getenv("OPKG_CONF_DIR");
  460. if (conf_file_dir == NULL)
  461. conf_file_dir = OPKG_CONF_DEFAULT_CONF_FILE_DIR;
  462. sprintf_alloc(&etc_opkg_conf_pattern, "%s/*.conf",
  463. conf_file_dir);
  464. }
  465. memset(&globbuf, 0, sizeof(globbuf));
  466. glob_ret = glob(etc_opkg_conf_pattern, 0, glob_errfunc, &globbuf);
  467. if (glob_ret && glob_ret != GLOB_NOMATCH) {
  468. free(etc_opkg_conf_pattern);
  469. globfree(&globbuf);
  470. goto err1;
  471. }
  472. free(etc_opkg_conf_pattern);
  473. for (i = 0; i < globbuf.gl_pathc; i++) {
  474. if (globbuf.gl_pathv[i])
  475. if (conf->conf_file &&
  476. !strcmp(conf->conf_file, globbuf.gl_pathv[i]))
  477. continue;
  478. if (opkg_conf_parse_file(globbuf.gl_pathv[i],
  479. &conf->pkg_src_list,
  480. &conf->dist_src_list) < 0) {
  481. globfree(&globbuf);
  482. goto err1;
  483. }
  484. }
  485. globfree(&globbuf);
  486. if (conf->offline_root)
  487. sprintf_alloc(&lock_file, "%s/%s", conf->offline_root,
  488. OPKGLOCKFILE);
  489. else
  490. sprintf_alloc(&lock_file, "%s", OPKGLOCKFILE);
  491. lock_fd = creat(lock_file, S_IRUSR | S_IWUSR | S_IRGRP);
  492. if (lock_fd == -1) {
  493. opkg_perror(ERROR, "Could not create lock file %s", lock_file);
  494. goto err2;
  495. }
  496. if (lockf(lock_fd, F_TLOCK, (off_t) 0) == -1) {
  497. opkg_perror(ERROR, "Could not lock %s", lock_file);
  498. if (close(lock_fd) == -1)
  499. opkg_perror(ERROR, "Couldn't close descriptor %d (%s)",
  500. lock_fd, lock_file);
  501. lock_fd = -1;
  502. goto err2;
  503. }
  504. if (conf->tmp_dir)
  505. tmp_dir_base = conf->tmp_dir;
  506. else
  507. tmp_dir_base = getenv("TMPDIR");
  508. sprintf_alloc(&tmp, "%s/%s",
  509. tmp_dir_base ? tmp_dir_base :
  510. OPKG_CONF_DEFAULT_TMP_DIR_BASE, OPKG_CONF_TMP_DIR_SUFFIX);
  511. if (conf->tmp_dir)
  512. free(conf->tmp_dir);
  513. conf->tmp_dir = mkdtemp(tmp);
  514. if (conf->tmp_dir == NULL) {
  515. opkg_perror(ERROR, "Creating temp dir %s failed", tmp);
  516. goto err3;
  517. }
  518. pkg_hash_init();
  519. hash_table_init("file-hash", &conf->file_hash,
  520. OPKG_CONF_DEFAULT_HASH_LEN);
  521. hash_table_init("obs-file-hash", &conf->obs_file_hash,
  522. OPKG_CONF_DEFAULT_HASH_LEN / 16);
  523. if (conf->lists_dir == NULL)
  524. conf->lists_dir = xstrdup(OPKG_CONF_LISTS_DIR);
  525. if (conf->offline_root) {
  526. sprintf_alloc(&tmp, "%s/%s", conf->offline_root,
  527. conf->lists_dir);
  528. free(conf->lists_dir);
  529. conf->lists_dir = tmp;
  530. }
  531. /* if no architectures were defined, then default all, noarch, and host architecture */
  532. if (nv_pair_list_empty(&conf->arch_list)) {
  533. nv_pair_list_append(&conf->arch_list, "all", "1");
  534. nv_pair_list_append(&conf->arch_list, "noarch", "1");
  535. nv_pair_list_append(&conf->arch_list, HOST_CPU_STR, "10");
  536. }
  537. /* Even if there is no conf file, we'll need at least one dest. */
  538. if (nv_pair_list_empty(&conf->tmp_dest_list)) {
  539. nv_pair_list_append(&conf->tmp_dest_list,
  540. OPKG_CONF_DEFAULT_DEST_NAME,
  541. OPKG_CONF_DEFAULT_DEST_ROOT_DIR);
  542. }
  543. if (resolve_pkg_dest_list())
  544. goto err4;
  545. nv_pair_list_deinit(&conf->tmp_dest_list);
  546. return 0;
  547. err4:
  548. free(conf->lists_dir);
  549. pkg_hash_deinit();
  550. hash_table_deinit(&conf->file_hash);
  551. hash_table_deinit(&conf->obs_file_hash);
  552. if (rmdir(conf->tmp_dir) == -1)
  553. opkg_perror(ERROR, "Couldn't remove dir %s", conf->tmp_dir);
  554. err3:
  555. if (lockf(lock_fd, F_ULOCK, (off_t) 0) == -1)
  556. opkg_perror(ERROR, "Couldn't unlock %s", lock_file);
  557. if (close(lock_fd) == -1)
  558. opkg_perror(ERROR, "Couldn't close descriptor %d (%s)",
  559. lock_fd, lock_file);
  560. if (unlink(lock_file) == -1)
  561. opkg_perror(ERROR, "Couldn't unlink %s", lock_file);
  562. err2:
  563. if (lock_file) {
  564. free(lock_file);
  565. lock_file = NULL;
  566. }
  567. err1:
  568. pkg_src_list_deinit(&conf->pkg_src_list);
  569. pkg_src_list_deinit(&conf->dist_src_list);
  570. pkg_dest_list_deinit(&conf->pkg_dest_list);
  571. nv_pair_list_deinit(&conf->arch_list);
  572. for (i = 0; options[i].name; i++) {
  573. if (options[i].type == OPKG_OPT_TYPE_STRING) {
  574. tmp_val = (char **)options[i].value;
  575. if (*tmp_val) {
  576. free(*tmp_val);
  577. *tmp_val = NULL;
  578. }
  579. }
  580. }
  581. err0:
  582. nv_pair_list_deinit(&conf->tmp_dest_list);
  583. if (conf->dest_str)
  584. free(conf->dest_str);
  585. if (conf->conf_file)
  586. free(conf->conf_file);
  587. return -1;
  588. }
  589. void opkg_conf_deinit(void)
  590. {
  591. int i;
  592. char **tmp;
  593. if (conf->tmp_dir)
  594. rm_r(conf->tmp_dir);
  595. if (conf->lists_dir)
  596. free(conf->lists_dir);
  597. if (conf->dest_str)
  598. free(conf->dest_str);
  599. if (conf->conf_file)
  600. free(conf->conf_file);
  601. pkg_src_list_deinit(&conf->pkg_src_list);
  602. pkg_src_list_deinit(&conf->dist_src_list);
  603. pkg_dest_list_deinit(&conf->pkg_dest_list);
  604. nv_pair_list_deinit(&conf->arch_list);
  605. for (i = 0; options[i].name; i++) {
  606. if (options[i].type == OPKG_OPT_TYPE_STRING) {
  607. tmp = (char **)options[i].value;
  608. if (*tmp) {
  609. free(*tmp);
  610. *tmp = NULL;
  611. }
  612. }
  613. }
  614. if (conf->verbosity >= DEBUG) {
  615. hash_print_stats(&conf->pkg_hash);
  616. hash_print_stats(&conf->file_hash);
  617. hash_print_stats(&conf->obs_file_hash);
  618. }
  619. pkg_hash_deinit();
  620. hash_table_deinit(&conf->file_hash);
  621. hash_table_deinit(&conf->obs_file_hash);
  622. if (lock_fd != -1) {
  623. if (lockf(lock_fd, F_ULOCK, (off_t) 0) == -1)
  624. opkg_perror(ERROR, "Couldn't unlock %s", lock_file);
  625. if (close(lock_fd) == -1)
  626. opkg_perror(ERROR, "Couldn't close descriptor %d (%s)",
  627. lock_fd, lock_file);
  628. }
  629. if (lock_file) {
  630. if (unlink(lock_file) == -1)
  631. opkg_perror(ERROR, "Couldn't unlink %s", lock_file);
  632. free(lock_file);
  633. }
  634. }