opkg.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. /* opkg.c - the opkg package management system
  2. Thomas Wood <thomas@openedhand.com>
  3. Copyright (C) 2008 OpenMoko Inc
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License as
  6. published by the Free Software Foundation; either version 2, or (at
  7. your option) any later version.
  8. This program is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. */
  13. #include <stdio.h>
  14. #include <unistd.h>
  15. #include <fnmatch.h>
  16. #include "opkg.h"
  17. #include "opkg_conf.h"
  18. #include "opkg_install.h"
  19. #include "opkg_configure.h"
  20. #include "opkg_download.h"
  21. #include "opkg_remove.h"
  22. #include "opkg_upgrade.h"
  23. #include "sprintf_alloc.h"
  24. #include "file_util.h"
  25. #include <libbb/libbb.h>
  26. #define opkg_assert(expr) if (!(expr)) { \
  27. printf ("opkg: file %s: line %d (%s): Assertation '%s' failed",\
  28. __FILE__, __LINE__, __PRETTY_FUNCTION__, # expr); abort (); }
  29. #define progress(d, p) d.percentage = p; if (progress_callback) progress_callback (&d, user_data);
  30. /** Private Functions ***/
  31. static int opkg_configure_packages(char *pkg_name)
  32. {
  33. pkg_vec_t *all;
  34. int i;
  35. pkg_t *pkg;
  36. int r, err = 0;
  37. all = pkg_vec_alloc();
  38. pkg_hash_fetch_available(all);
  39. for (i = 0; i < all->len; i++) {
  40. pkg = all->pkgs[i];
  41. if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
  42. continue;
  43. if (pkg->state_status == SS_UNPACKED) {
  44. r = opkg_configure(pkg);
  45. if (r == 0) {
  46. pkg->state_status = SS_INSTALLED;
  47. pkg->parent->state_status = SS_INSTALLED;
  48. pkg->state_flag &= ~SF_PREFER;
  49. } else {
  50. if (!err)
  51. err = r;
  52. }
  53. }
  54. }
  55. pkg_vec_free(all);
  56. return err;
  57. }
  58. static struct opkg_conf saved_conf;
  59. /*** Public API ***/
  60. int opkg_new()
  61. {
  62. saved_conf = *conf;
  63. if (opkg_conf_init())
  64. goto err0;
  65. if (opkg_conf_load())
  66. goto err0;
  67. if (pkg_hash_load_feeds(0, NULL, NULL))
  68. goto err1;
  69. if (pkg_hash_load_status_files(NULL, NULL))
  70. goto err1;
  71. return 0;
  72. err1:
  73. pkg_hash_deinit();
  74. err0:
  75. opkg_conf_deinit();
  76. return -1;
  77. }
  78. void opkg_free(void)
  79. {
  80. opkg_conf_deinit();
  81. }
  82. int opkg_re_read_config_files(void)
  83. {
  84. opkg_free();
  85. *conf = saved_conf;
  86. return opkg_new();
  87. }
  88. void opkg_get_option(char *option, void **value)
  89. {
  90. int i = 0;
  91. extern opkg_option_t options[];
  92. /* look up the option
  93. * TODO: this would be much better as a hash table
  94. */
  95. while (options[i].name) {
  96. if (strcmp(options[i].name, option) != 0) {
  97. i++;
  98. continue;
  99. }
  100. }
  101. /* get the option */
  102. switch (options[i].type) {
  103. case OPKG_OPT_TYPE_BOOL:
  104. *((int *)value) = *((int *)options[i].value);
  105. return;
  106. case OPKG_OPT_TYPE_INT:
  107. *((int *)value) = *((int *)options[i].value);
  108. return;
  109. case OPKG_OPT_TYPE_STRING:
  110. *((char **)value) = xstrdup(options[i].value);
  111. return;
  112. }
  113. }
  114. void opkg_set_option(char *option, void *value)
  115. {
  116. int i = 0, found = 0;
  117. extern opkg_option_t options[];
  118. opkg_assert(option != NULL);
  119. opkg_assert(value != NULL);
  120. /* look up the option
  121. * TODO: this would be much better as a hash table
  122. */
  123. while (options[i].name) {
  124. if (strcmp(options[i].name, option) == 0) {
  125. found = 1;
  126. break;
  127. }
  128. i++;
  129. }
  130. if (!found) {
  131. opkg_msg(ERROR, "Invalid option: %s\n", option);
  132. return;
  133. }
  134. /* set the option */
  135. switch (options[i].type) {
  136. case OPKG_OPT_TYPE_BOOL:
  137. if (*((int *)value) == 0)
  138. *((int *)options[i].value) = 0;
  139. else
  140. *((int *)options[i].value) = 1;
  141. return;
  142. case OPKG_OPT_TYPE_INT:
  143. *((int *)options[i].value) = *((int *)value);
  144. return;
  145. case OPKG_OPT_TYPE_STRING:
  146. *((char **)options[i].value) = xstrdup(value);
  147. return;
  148. }
  149. }
  150. /**
  151. * @brief libopkg API: Install package
  152. * @param package_name The name of package in which is going to install
  153. * @param progress_callback The callback function that report the status to caller.
  154. */
  155. int
  156. opkg_install_package(const char *package_name,
  157. opkg_progress_callback_t progress_callback,
  158. void *user_data)
  159. {
  160. int err;
  161. char *stripped_filename, *local_filename;
  162. opkg_progress_data_t pdata;
  163. pkg_t *old, *new;
  164. pkg_vec_t *deps, *all;
  165. int i;
  166. char **unresolved = NULL;
  167. const char *filename;
  168. opkg_assert(package_name != NULL);
  169. /* ... */
  170. pkg_info_preinstall_check();
  171. /* check to ensure package is not already installed */
  172. old = pkg_hash_fetch_installed_by_name(package_name);
  173. if (old) {
  174. opkg_msg(ERROR, "Package %s is already installed\n",
  175. package_name);
  176. return -1;
  177. }
  178. new = pkg_hash_fetch_best_installation_candidate_by_name(package_name);
  179. if (!new) {
  180. opkg_msg(ERROR, "Couldn't find package %s\n", package_name);
  181. return -1;
  182. }
  183. new->state_flag |= SF_USER;
  184. pdata.action = -1;
  185. pdata.pkg = new;
  186. progress(pdata, 0);
  187. /* find dependancies and download them */
  188. deps = pkg_vec_alloc();
  189. /* this function does not return the original package, so we insert it later */
  190. pkg_hash_fetch_unsatisfied_dependencies(new, deps, &unresolved, 0);
  191. if (unresolved) {
  192. char **tmp = unresolved;
  193. opkg_msg(ERROR, "Couldn't satisfy the following dependencies"
  194. " for %s:\n", package_name);
  195. while (*tmp) {
  196. opkg_msg(ERROR, "\t%s", *tmp);
  197. free(*tmp);
  198. tmp++;
  199. }
  200. free(unresolved);
  201. pkg_vec_free(deps);
  202. opkg_message(ERROR, "\n");
  203. return -1;
  204. }
  205. /* insert the package we are installing so that we download it */
  206. pkg_vec_insert(deps, new);
  207. /* download package and dependencies */
  208. for (i = 0; i < deps->len; i++) {
  209. pkg_t *pkg;
  210. char *url, *urlencoded_path;
  211. pkg = deps->pkgs[i];
  212. if (pkg_get_string(pkg, PKG_LOCAL_FILENAME))
  213. continue;
  214. pdata.pkg = pkg;
  215. pdata.action = OPKG_DOWNLOAD;
  216. if (pkg->src == NULL) {
  217. opkg_msg(ERROR, "Package %s not available from any "
  218. "configured src\n", package_name);
  219. return -1;
  220. }
  221. filename = pkg_get_string(pkg, PKG_FILENAME);
  222. urlencoded_path = urlencode_path(filename);
  223. sprintf_alloc(&url, "%s/%s", pkg->src->value, urlencoded_path);
  224. free(urlencoded_path);
  225. /* Get the filename part, without any directory */
  226. stripped_filename = strrchr(filename, '/');
  227. if (!stripped_filename)
  228. stripped_filename = (char *)filename;
  229. sprintf_alloc(&local_filename, "%s/%s", conf->tmp_dir,
  230. stripped_filename);
  231. pkg_set_string(pkg, PKG_LOCAL_FILENAME, local_filename);
  232. err = opkg_download(url, local_filename, 0);
  233. free(url);
  234. if (err) {
  235. pkg_vec_free(deps);
  236. return -1;
  237. }
  238. }
  239. pkg_vec_free(deps);
  240. /* clear depenacy checked marks, left by pkg_hash_fetch_unsatisfied_dependencies */
  241. all = pkg_vec_alloc();
  242. pkg_hash_fetch_available(all);
  243. for (i = 0; i < all->len; i++) {
  244. all->pkgs[i]->parent->dependencies_checked = 0;
  245. }
  246. pkg_vec_free(all);
  247. /* 75% of "install" progress is for downloading */
  248. pdata.pkg = new;
  249. pdata.action = OPKG_INSTALL;
  250. progress(pdata, 75);
  251. /* unpack the package */
  252. err = opkg_install_pkg(new, 0);
  253. if (err) {
  254. return -1;
  255. }
  256. progress(pdata, 75);
  257. /* run configure scripts, etc. */
  258. err = opkg_configure_packages(NULL);
  259. if (err) {
  260. return -1;
  261. }
  262. /* write out status files and file lists */
  263. opkg_conf_write_status_files();
  264. pkg_write_changed_filelists();
  265. progress(pdata, 100);
  266. return 0;
  267. }
  268. int
  269. opkg_remove_package(const char *package_name,
  270. opkg_progress_callback_t progress_callback, void *user_data)
  271. {
  272. int err;
  273. pkg_t *pkg = NULL;
  274. pkg_t *pkg_to_remove;
  275. opkg_progress_data_t pdata;
  276. opkg_assert(package_name != NULL);
  277. pkg_info_preinstall_check();
  278. pkg = pkg_hash_fetch_installed_by_name(package_name);
  279. if (pkg == NULL || pkg->state_status == SS_NOT_INSTALLED) {
  280. opkg_msg(ERROR, "Package %s not installed\n", package_name);
  281. return -1;
  282. }
  283. pdata.action = OPKG_REMOVE;
  284. pdata.pkg = pkg;
  285. progress(pdata, 0);
  286. if (conf->restrict_to_default_dest) {
  287. pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(pkg->name,
  288. conf->
  289. default_dest);
  290. } else {
  291. pkg_to_remove = pkg_hash_fetch_installed_by_name(pkg->name);
  292. }
  293. progress(pdata, 75);
  294. err = opkg_remove_pkg(pkg_to_remove, 0);
  295. /* write out status files and file lists */
  296. opkg_conf_write_status_files();
  297. pkg_write_changed_filelists();
  298. progress(pdata, 100);
  299. return (err) ? -1 : 0;
  300. }
  301. int
  302. opkg_upgrade_package(const char *package_name,
  303. opkg_progress_callback_t progress_callback,
  304. void *user_data)
  305. {
  306. int err;
  307. pkg_t *pkg;
  308. opkg_progress_data_t pdata;
  309. opkg_assert(package_name != NULL);
  310. pkg_info_preinstall_check();
  311. if (conf->restrict_to_default_dest) {
  312. pkg = pkg_hash_fetch_installed_by_name_dest(package_name,
  313. conf->default_dest);
  314. } else {
  315. pkg = pkg_hash_fetch_installed_by_name(package_name);
  316. }
  317. if (!pkg) {
  318. opkg_msg(ERROR, "Package %s not installed\n", package_name);
  319. return -1;
  320. }
  321. pdata.action = OPKG_INSTALL;
  322. pdata.pkg = pkg;
  323. progress(pdata, 0);
  324. err = opkg_upgrade_pkg(pkg);
  325. if (err) {
  326. return -1;
  327. }
  328. progress(pdata, 75);
  329. err = opkg_configure_packages(NULL);
  330. if (err) {
  331. return -1;
  332. }
  333. /* write out status files and file lists */
  334. opkg_conf_write_status_files();
  335. pkg_write_changed_filelists();
  336. progress(pdata, 100);
  337. return 0;
  338. }
  339. int
  340. opkg_upgrade_all(opkg_progress_callback_t progress_callback, void *user_data)
  341. {
  342. pkg_vec_t *installed;
  343. int err = 0;
  344. int i;
  345. pkg_t *pkg;
  346. opkg_progress_data_t pdata;
  347. pdata.action = OPKG_INSTALL;
  348. pdata.pkg = NULL;
  349. progress(pdata, 0);
  350. installed = pkg_vec_alloc();
  351. pkg_info_preinstall_check();
  352. pkg_hash_fetch_all_installed(installed);
  353. for (i = 0; i < installed->len; i++) {
  354. pkg = installed->pkgs[i];
  355. pdata.pkg = pkg;
  356. progress(pdata, 99 * i / installed->len);
  357. err += opkg_upgrade_pkg(pkg);
  358. }
  359. pkg_vec_free(installed);
  360. if (err)
  361. return 1;
  362. err = opkg_configure_packages(NULL);
  363. if (err)
  364. return 1;
  365. /* write out status files and file lists */
  366. opkg_conf_write_status_files();
  367. pkg_write_changed_filelists();
  368. pdata.pkg = NULL;
  369. progress(pdata, 100);
  370. return 0;
  371. }
  372. int
  373. opkg_update_package_lists(opkg_progress_callback_t progress_callback,
  374. void *user_data)
  375. {
  376. char *tmp;
  377. int err, result = 0;
  378. char *lists_dir;
  379. pkg_src_list_elt_t *iter;
  380. pkg_src_t *src;
  381. int sources_list_count, sources_done;
  382. opkg_progress_data_t pdata;
  383. pdata.action = OPKG_DOWNLOAD;
  384. pdata.pkg = NULL;
  385. progress(pdata, 0);
  386. sprintf_alloc(&lists_dir, "%s", (conf->restrict_to_default_dest)
  387. ? conf->default_dest->lists_dir : conf->lists_dir);
  388. if (!file_is_dir(lists_dir)) {
  389. if (file_exists(lists_dir)) {
  390. opkg_msg(ERROR, "%s is not a directory\n", lists_dir);
  391. free(lists_dir);
  392. return 1;
  393. }
  394. err = file_mkdir_hier(lists_dir, 0755);
  395. if (err) {
  396. opkg_msg(ERROR, "Couldn't create lists_dir %s\n",
  397. lists_dir);
  398. free(lists_dir);
  399. return 1;
  400. }
  401. }
  402. sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
  403. if (mkdtemp(tmp) == NULL) {
  404. opkg_perror(ERROR, "Coundn't create temporary directory %s",
  405. tmp);
  406. free(lists_dir);
  407. free(tmp);
  408. return 1;
  409. }
  410. /* count the number of sources so we can give some progress updates */
  411. sources_list_count = 0;
  412. sources_done = 0;
  413. list_for_each_entry(iter, &conf->pkg_src_list.head, node) {
  414. sources_list_count++;
  415. }
  416. list_for_each_entry(iter, &conf->pkg_src_list.head, node) {
  417. char *url, *list_file_name = NULL;
  418. src = (pkg_src_t *) iter->data;
  419. sprintf_alloc(&url, "%s/%s", src->value,
  420. src->gzip ? "Packages.gz" : "Packages");
  421. sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
  422. if (opkg_download(url, list_file_name, 0)) {
  423. opkg_msg(ERROR, "Couldn't retrieve %s\n", url);
  424. result = -1;
  425. }
  426. free(url);
  427. #if defined(HAVE_USIGN)
  428. if (conf->check_signature) {
  429. char *sig_file_name;
  430. /* download detached signitures to verify the package lists */
  431. /* get the url for the sig file */
  432. sprintf_alloc(&url, "%s/%s", src->value,
  433. "Packages.sig");
  434. /* create filename for signature */
  435. sprintf_alloc(&sig_file_name, "%s/%s.sig", lists_dir,
  436. src->name);
  437. /* make sure there is no existing signature file */
  438. unlink(sig_file_name);
  439. err = opkg_download(url, sig_file_name, 0);
  440. if (err) {
  441. opkg_msg(ERROR, "Couldn't retrieve %s\n", url);
  442. } else {
  443. int err;
  444. err = opkg_verify_file(list_file_name,
  445. sig_file_name);
  446. if (err == 0) {
  447. opkg_msg(INFO, "Signature check "
  448. "passed for %s",
  449. list_file_name);
  450. } else {
  451. opkg_msg(ERROR, "Signature check "
  452. "failed for %s",
  453. list_file_name);
  454. }
  455. }
  456. free(sig_file_name);
  457. free(url);
  458. }
  459. #else
  460. opkg_msg(INFO, "Signature check skipped for %s as GPG support"
  461. " has not been enabled in this build\n",
  462. list_file_name);
  463. #endif
  464. free(list_file_name);
  465. sources_done++;
  466. progress(pdata, 100 * sources_done / sources_list_count);
  467. }
  468. rmdir(tmp);
  469. free(tmp);
  470. free(lists_dir);
  471. /* Now re-read the package lists to update package hash tables. */
  472. opkg_re_read_config_files();
  473. return result;
  474. }
  475. static int pkg_compare_names_and_version(const void *a0, const void *b0)
  476. {
  477. const pkg_t *a = *(const pkg_t **)a0;
  478. const pkg_t *b = *(const pkg_t **)b0;
  479. int ret;
  480. ret = strcmp(a->name, b->name);
  481. if (ret == 0)
  482. ret = pkg_compare_versions(a, b);
  483. return ret;
  484. }
  485. int opkg_list_packages(opkg_package_callback_t callback, void *user_data)
  486. {
  487. pkg_vec_t *all;
  488. int i;
  489. opkg_assert(callback);
  490. all = pkg_vec_alloc();
  491. pkg_hash_fetch_available(all);
  492. pkg_vec_sort(all, pkg_compare_names_and_version);
  493. for (i = 0; i < all->len; i++) {
  494. pkg_t *pkg;
  495. pkg = all->pkgs[i];
  496. callback(pkg, user_data);
  497. }
  498. pkg_vec_free(all);
  499. return 0;
  500. }
  501. int
  502. opkg_list_upgradable_packages(opkg_package_callback_t callback, void *user_data)
  503. {
  504. struct active_list *head;
  505. struct active_list *node;
  506. pkg_t *old = NULL, *new = NULL;
  507. opkg_assert(callback);
  508. /* ensure all data is valid */
  509. pkg_info_preinstall_check();
  510. head = prepare_upgrade_list();
  511. for (node = active_list_next(head, head); node;
  512. node = active_list_next(head, node)) {
  513. old = node->pkg;
  514. new =
  515. pkg_hash_fetch_best_installation_candidate_by_name(old->
  516. name);
  517. if (new == NULL)
  518. continue;
  519. callback(new, user_data);
  520. }
  521. active_list_head_delete(head);
  522. return 0;
  523. }
  524. pkg_t *opkg_find_package(const char *name, const char *ver, const char *arch,
  525. const char *repo)
  526. {
  527. int pkg_found = 0;
  528. pkg_t *pkg = NULL;
  529. pkg_vec_t *all;
  530. int i;
  531. #define sstrcmp(x,y) (x && y) ? strcmp (x, y) : 0
  532. all = pkg_vec_alloc();
  533. pkg_hash_fetch_available(all);
  534. for (i = 0; i < all->len; i++) {
  535. char *pkgv;
  536. pkg = all->pkgs[i];
  537. /* check name */
  538. if (sstrcmp(pkg->name, name))
  539. continue;
  540. /* check version */
  541. pkgv = pkg_version_str_alloc(pkg);
  542. if (sstrcmp(pkgv, ver)) {
  543. free(pkgv);
  544. continue;
  545. }
  546. free(pkgv);
  547. /* check architecture */
  548. if (arch) {
  549. if (sstrcmp(pkg_get_architecture(pkg), arch))
  550. continue;
  551. }
  552. /* check repository */
  553. if (repo) {
  554. if (sstrcmp(pkg->src->name, repo))
  555. continue;
  556. }
  557. /* match found */
  558. pkg_found = 1;
  559. break;
  560. }
  561. pkg_vec_free(all);
  562. return pkg_found ? pkg : NULL;
  563. }
  564. /**
  565. * @brief Check the accessibility of repositories.
  566. * @return return how many repositories cannot access. 0 means all okay.
  567. */
  568. int opkg_repository_accessibility_check(void)
  569. {
  570. pkg_src_list_elt_t *iter;
  571. str_list_elt_t *iter1;
  572. str_list_t *src;
  573. int repositories = 0;
  574. int ret = 0;
  575. char *repo_ptr;
  576. char *stmp;
  577. char *host, *end;
  578. src = str_list_alloc();
  579. list_for_each_entry(iter, &conf->pkg_src_list.head, node) {
  580. host = strstr(((pkg_src_t *) iter->data)->value, "://") + 3;
  581. end = index(host, '/');
  582. if (strstr(((pkg_src_t *) iter->data)->value, "://") && end)
  583. stmp = xstrndup(((pkg_src_t *) iter->data)->value,
  584. end -
  585. ((pkg_src_t *) iter->data)->value);
  586. else
  587. stmp = xstrdup(((pkg_src_t *) iter->data)->value);
  588. for (iter1 = str_list_first(src); iter1;
  589. iter1 = str_list_next(src, iter1)) {
  590. if (strstr(iter1->data, stmp))
  591. break;
  592. }
  593. if (iter1)
  594. continue;
  595. sprintf_alloc(&repo_ptr, "%s/index.html", stmp);
  596. free(stmp);
  597. str_list_append(src, repo_ptr);
  598. free(repo_ptr);
  599. repositories++;
  600. }
  601. while (repositories > 0) {
  602. iter1 = str_list_pop(src);
  603. repositories--;
  604. if (opkg_download(iter1->data, "/dev/null", 0))
  605. ret++;
  606. str_list_elt_deinit(iter1);
  607. }
  608. free(src);
  609. return ret;
  610. }