opkg_download.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /* vi: set noexpandtab sw=4 sts=4: */
  2. /* opkg_download.c - the opkg package management system
  3. Carl D. Worth
  4. Copyright (C) 2001 University of Southern California
  5. Copyright (C) 2008 OpenMoko Inc
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License as
  8. published by the Free Software Foundation; either version 2, or (at
  9. your option) any later version.
  10. This program is distributed in the hope that it will be useful, but
  11. WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. General Public License for more details.
  14. */
  15. #include <stdio.h>
  16. #include <unistd.h>
  17. #include <libgen.h>
  18. #include "opkg_download.h"
  19. #include "opkg_message.h"
  20. #include "sprintf_alloc.h"
  21. #include "xsystem.h"
  22. #include "file_util.h"
  23. #include "opkg_defines.h"
  24. #include "libbb/libbb.h"
  25. static int str_starts_with(const char *str, const char *prefix)
  26. {
  27. return (strncmp(str, prefix, strlen(prefix)) == 0);
  28. }
  29. int
  30. opkg_download(const char *src, const char *dest_file_name,
  31. const short hide_error)
  32. {
  33. int err = 0;
  34. char *src_basec = xstrdup(src);
  35. char *src_base = basename(src_basec);
  36. char *tmp_file_location;
  37. opkg_msg(NOTICE, "Downloading %s\n", src);
  38. if (str_starts_with(src, "file:")) {
  39. char *file_src = urldecode_path(src + 5);
  40. opkg_msg(INFO, "Copying %s to %s...", file_src, dest_file_name);
  41. err = file_copy(file_src, dest_file_name);
  42. opkg_msg(INFO, "Done.\n");
  43. free(src_basec);
  44. free(file_src);
  45. return err;
  46. }
  47. sprintf_alloc(&tmp_file_location, "%s/%s", conf->tmp_dir, src_base);
  48. free(src_basec);
  49. err = unlink(tmp_file_location);
  50. if (err && errno != ENOENT) {
  51. opkg_perror(ERROR, "Failed to unlink %s", tmp_file_location);
  52. free(tmp_file_location);
  53. return -1;
  54. }
  55. if (conf->http_proxy) {
  56. opkg_msg(DEBUG,
  57. "Setting environment variable: http_proxy = %s.\n",
  58. conf->http_proxy);
  59. setenv("http_proxy", conf->http_proxy, 1);
  60. }
  61. if (conf->ftp_proxy) {
  62. opkg_msg(DEBUG,
  63. "Setting environment variable: ftp_proxy = %s.\n",
  64. conf->ftp_proxy);
  65. setenv("ftp_proxy", conf->ftp_proxy, 1);
  66. }
  67. if (conf->no_proxy) {
  68. opkg_msg(DEBUG,
  69. "Setting environment variable: no_proxy = %s.\n",
  70. conf->no_proxy);
  71. setenv("no_proxy", conf->no_proxy, 1);
  72. }
  73. {
  74. int res;
  75. const char *argv[11];
  76. int i = 0;
  77. argv[i++] = "wget";
  78. argv[i++] = "-q";
  79. if (conf->no_check_certificate) {
  80. argv[i++] = "--no-check-certificate";
  81. }
  82. if (conf->http_timeout) {
  83. argv[i++] = "--timeout";
  84. argv[i++] = conf->http_timeout;
  85. }
  86. if (conf->http_proxy || conf->ftp_proxy) {
  87. argv[i++] = "-Y";
  88. argv[i++] = "on";
  89. }
  90. argv[i++] = "-O";
  91. argv[i++] = tmp_file_location;
  92. argv[i++] = src;
  93. argv[i++] = NULL;
  94. res = xsystem(argv);
  95. if (res) {
  96. opkg_msg(ERROR,
  97. "Failed to download %s, wget returned %d.\n",
  98. src, res);
  99. if (res == 4)
  100. opkg_msg(ERROR,
  101. "Check your network settings and connectivity.\n\n");
  102. free(tmp_file_location);
  103. return -1;
  104. }
  105. }
  106. err = file_move(tmp_file_location, dest_file_name);
  107. free(tmp_file_location);
  108. return err;
  109. }
  110. static int
  111. opkg_download_cache(const char *src, const char *dest_file_name)
  112. {
  113. char *cache_name = xstrdup(src);
  114. char *cache_location, *p;
  115. int err = 0;
  116. if (!conf->cache || str_starts_with(src, "file:")) {
  117. err = opkg_download(src, dest_file_name, 0);
  118. goto out1;
  119. }
  120. if (!file_is_dir(conf->cache)) {
  121. opkg_msg(ERROR, "%s is not a directory.\n", conf->cache);
  122. err = 1;
  123. goto out1;
  124. }
  125. for (p = cache_name; *p; p++)
  126. if (*p == '/')
  127. *p = ','; /* looks nicer than | or # */
  128. sprintf_alloc(&cache_location, "%s/%s", conf->cache, cache_name);
  129. if (file_exists(cache_location))
  130. opkg_msg(NOTICE, "Copying %s.\n", cache_location);
  131. else {
  132. /* cache file with funky name not found, try simple name */
  133. free(cache_name);
  134. char *filename = strrchr(dest_file_name, '/');
  135. if (filename)
  136. cache_name = xstrdup(filename + 1); // strip leading '/'
  137. else
  138. cache_name = xstrdup(dest_file_name);
  139. free(cache_location);
  140. sprintf_alloc(&cache_location, "%s/%s", conf->cache,
  141. cache_name);
  142. if (file_exists(cache_location))
  143. opkg_msg(NOTICE, "Copying %s.\n", cache_location);
  144. else {
  145. err = opkg_download(src, cache_location, 0);
  146. if (err) {
  147. (void)unlink(cache_location);
  148. goto out2;
  149. }
  150. }
  151. }
  152. err = file_copy(cache_location, dest_file_name);
  153. out2:
  154. free(cache_location);
  155. out1:
  156. free(cache_name);
  157. return err;
  158. }
  159. int opkg_download_pkg(pkg_t * pkg, const char *dir)
  160. {
  161. int err;
  162. char *url;
  163. char *local_filename;
  164. char *stripped_filename;
  165. char *urlencoded_path;
  166. char *filename;
  167. if (pkg->src == NULL) {
  168. opkg_msg(ERROR,
  169. "Package %s is not available from any configured src.\n",
  170. pkg->name);
  171. return -1;
  172. }
  173. filename = pkg_get_string(pkg, PKG_FILENAME);
  174. if (filename == NULL) {
  175. opkg_msg(ERROR,
  176. "Package %s does not have a valid filename field.\n",
  177. pkg->name);
  178. return -1;
  179. }
  180. urlencoded_path = urlencode_path(filename);
  181. sprintf_alloc(&url, "%s/%s", pkg->src->value, urlencoded_path);
  182. free(urlencoded_path);
  183. /* The filename might be something like
  184. "../../foo.opk". While this is correct, and exactly what we
  185. want to use to construct url above, here we actually need to
  186. use just the filename part, without any directory. */
  187. stripped_filename = strrchr(filename, '/');
  188. if (!stripped_filename)
  189. stripped_filename = filename;
  190. sprintf_alloc(&local_filename, "%s/%s", dir, stripped_filename);
  191. pkg_set_string(pkg, PKG_LOCAL_FILENAME, local_filename);
  192. err = opkg_download_cache(url, local_filename);
  193. free(url);
  194. return err;
  195. }
  196. /*
  197. * Downloads file from url, installs in package database, return package name.
  198. */
  199. int opkg_prepare_url_for_install(const char *url, char **namep)
  200. {
  201. int err = 0;
  202. pkg_t *pkg;
  203. abstract_pkg_t *ab_pkg;
  204. pkg = pkg_new();
  205. if (str_starts_with(url, "http://")
  206. || str_starts_with(url, "ftp://")) {
  207. char *tmp_file;
  208. char *file_basec = xstrdup(url);
  209. char *file_base = basename(file_basec);
  210. sprintf_alloc(&tmp_file, "%s/%s", conf->tmp_dir, file_base);
  211. err = opkg_download(url, tmp_file, 0);
  212. if (err)
  213. return err;
  214. err = pkg_init_from_file(pkg, tmp_file);
  215. if (err)
  216. return err;
  217. free(tmp_file);
  218. free(file_basec);
  219. } else if (strcmp(&url[strlen(url) - 4], OPKG_PKG_EXTENSION) == 0
  220. || strcmp(&url[strlen(url) - 4], IPKG_PKG_EXTENSION) == 0
  221. || strcmp(&url[strlen(url) - 4], DPKG_PKG_EXTENSION) == 0) {
  222. err = pkg_init_from_file(pkg, url);
  223. if (err)
  224. return err;
  225. opkg_msg(DEBUG2, "Package %s provided by hand (%s).\n",
  226. pkg->name, pkg_get_string(pkg, PKG_LOCAL_FILENAME));
  227. pkg->provided_by_hand = 1;
  228. } else {
  229. ab_pkg = ensure_abstract_pkg_by_name(url);
  230. if (!(ab_pkg->state_flag & SF_NEED_DETAIL)) {
  231. opkg_msg(DEBUG, "applying abpkg flag to %s\n", ab_pkg->name);
  232. ab_pkg->state_flag |= SF_NEED_DETAIL;
  233. }
  234. pkg_deinit(pkg);
  235. free(pkg);
  236. return 0;
  237. }
  238. pkg->dest = conf->default_dest;
  239. pkg->state_want = SW_INSTALL;
  240. pkg->state_flag |= SF_PREFER;
  241. hash_insert_pkg(pkg, 1);
  242. if (namep) {
  243. *namep = xstrdup(pkg->name);
  244. }
  245. return 0;
  246. }
  247. int opkg_verify_file(char *text_file, char *sig_file)
  248. {
  249. #if defined HAVE_USIGN
  250. const char *argv[] = { conf->verify_program, "verify", sig_file,
  251. text_file, NULL };
  252. return xsystem(argv) ? -1 : 0;
  253. #else
  254. /* mute `unused variable' warnings. */
  255. (void)sig_file;
  256. (void)text_file;
  257. (void)conf;
  258. return 0;
  259. #endif
  260. }