• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/opkg-lede/libopkg/opkg_download.c

  1 /* vi: set noexpandtab sw=4 sts=4: */
  2 /* opkg_download.c - the opkg package management system
  3 
  4    Carl D. Worth
  5 
  6    Copyright (C) 2001 University of Southern California
  7    Copyright (C) 2008 OpenMoko Inc
  8 
  9    This program is free software; you can redistribute it and/or
 10    modify it under the terms of the GNU General Public License as
 11    published by the Free Software Foundation; either version 2, or (at
 12    your option) any later version.
 13 
 14    This program is distributed in the hope that it will be useful, but
 15    WITHOUT ANY WARRANTY; without even the implied warranty of
 16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17    General Public License for more details.
 18 */
 19 
 20 #include <stdio.h>
 21 #include <unistd.h>
 22 #include <libgen.h>
 23 
 24 #include "opkg_download.h"
 25 #include "opkg_message.h"
 26 
 27 #include "sprintf_alloc.h"
 28 #include "xsystem.h"
 29 #include "file_util.h"
 30 #include "opkg_defines.h"
 31 #include "libbb/libbb.h"
 32 
 33 static int str_starts_with(const char *str, const char *prefix)
 34 {
 35         return (strncmp(str, prefix, strlen(prefix)) == 0);
 36 }
 37 
 38 int opkg_verify_integrity(pkg_t *pkg, const char *filename)
 39 {
 40         int err = 0;
 41         char *file_md5, *pkg_md5;
 42         char *file_sha256, *pkg_sha256;
 43         struct stat pkg_stat;
 44         long long int pkg_expected_size;
 45 
 46         /* Check file size */
 47         err = lstat(filename, &pkg_stat);
 48 
 49         if (err) {
 50                 opkg_msg(ERROR, "Failed to stat %s: %s\n",
 51                          filename, strerror(errno));
 52                 return err;
 53         }
 54 
 55         pkg_expected_size = pkg_get_int(pkg, PKG_SIZE);
 56 
 57         if (pkg_expected_size > 0 && pkg_stat.st_size != pkg_expected_size) {
 58                 opkg_msg(INFO,
 59                          "Package size mismatch: %s is %lld bytes, expecting %lld bytes\n",
 60                          pkg->name, (long long int)pkg_stat.st_size, pkg_expected_size);
 61                 err = -1;
 62                 goto out;
 63         }
 64 
 65         /* Check for md5 values */
 66         pkg_md5 = pkg_get_md5(pkg);
 67         if (pkg_md5) {
 68                 file_md5 = file_md5sum_alloc(filename);
 69                 if (file_md5 && strcmp(file_md5, pkg_md5)) {
 70                         opkg_msg(INFO, "Package %s md5sum mismatch.\n",
 71                                  pkg->name);
 72                         err = -1;
 73                         free(file_md5);
 74                         goto out;
 75                 }
 76                 if (file_md5)
 77                         free(file_md5);
 78         }
 79 
 80         /* Check for sha256 value */
 81         pkg_sha256 = pkg_get_sha256(pkg);
 82         if (pkg_sha256) {
 83                 file_sha256 = file_sha256sum_alloc(filename);
 84                 if (file_sha256 && strcmp(file_sha256, pkg_sha256)) {
 85                         opkg_msg(INFO, "Package %s sha256sum mismatch.\n",
 86                                  pkg->name);
 87                         err = -1;
 88                         free(file_sha256);
 89                         goto out;
 90                 }
 91                 if (file_sha256)
 92                         free(file_sha256);
 93         }
 94 
 95 out:
 96         return err;
 97 }
 98 
 99 int
100 opkg_download(const char *src, const char *dest_file_name,
101               const short hide_error)
102 {
103         int err = 0;
104 
105         char *src_basec = xstrdup(src);
106         char *src_base = basename(src_basec);
107         char *tmp_file_location;
108 
109         opkg_msg(NOTICE, "Downloading %s\n", src);
110 
111         if (str_starts_with(src, "file:")) {
112                 char *file_src = urldecode_path(src + 5);
113                 opkg_msg(INFO, "Copying %s to %s...", file_src, dest_file_name);
114                 err = file_copy(file_src, dest_file_name);
115                 opkg_msg(INFO, "Done.\n");
116                 free(src_basec);
117                 free(file_src);
118                 return err;
119         }
120 
121         sprintf_alloc(&tmp_file_location, "%s/%s", conf->tmp_dir, src_base);
122         free(src_basec);
123         err = unlink(tmp_file_location);
124         if (err && errno != ENOENT) {
125                 opkg_perror(ERROR, "Failed to unlink %s", tmp_file_location);
126                 free(tmp_file_location);
127                 return -1;
128         }
129 
130         if (conf->http_proxy) {
131                 opkg_msg(DEBUG,
132                          "Setting environment variable: http_proxy = %s.\n",
133                          conf->http_proxy);
134                 setenv("http_proxy", conf->http_proxy, 1);
135         }
136         if (conf->https_proxy) {
137                 opkg_msg(DEBUG,
138                          "Setting environment variable: https_proxy = %s.\n",
139                          conf->https_proxy);
140                 setenv("https_proxy", conf->https_proxy, 1);
141         }
142         if (conf->ftp_proxy) {
143                 opkg_msg(DEBUG,
144                          "Setting environment variable: ftp_proxy = %s.\n",
145                          conf->ftp_proxy);
146                 setenv("ftp_proxy", conf->ftp_proxy, 1);
147         }
148         if (conf->no_proxy) {
149                 opkg_msg(DEBUG,
150                          "Setting environment variable: no_proxy = %s.\n",
151                          conf->no_proxy);
152                 setenv("no_proxy", conf->no_proxy, 1);
153         }
154 
155         {
156                 int res;
157                 const char *argv[11];
158                 int i = 0;
159 
160                 argv[i++] = "wget";
161                 argv[i++] = "-q";
162                 if (conf->no_check_certificate) {
163                         argv[i++] = "--no-check-certificate";
164                 }
165                 if (conf->http_timeout) {
166                         argv[i++] = "--timeout";
167                         argv[i++] = conf->http_timeout;
168                 }
169                 if (conf->http_proxy || conf->https_proxy || conf->ftp_proxy) {
170                         argv[i++] = "-Y";
171                         argv[i++] = "on";
172                 }
173                 argv[i++] = "-O";
174                 argv[i++] = tmp_file_location;
175                 argv[i++] = src;
176                 argv[i++] = NULL;
177                 res = xsystem(argv);
178 
179                 if (res) {
180                         opkg_msg(ERROR,
181                                  "Failed to download %s, wget returned %d.\n",
182                                  src, res);
183                         if (res == 4)
184                                 opkg_msg(ERROR,
185                                          "Check your network settings and connectivity.\n\n");
186                         free(tmp_file_location);
187                         return -1;
188                 }
189         }
190 
191         err = file_move(tmp_file_location, dest_file_name);
192 
193         free(tmp_file_location);
194 
195         return err;
196 }
197 
198 static char* get_cache_filename(const char *dest_file_name)
199 {
200         char *cache_name;
201         char *filename = strrchr(dest_file_name, '/');
202         if (filename)
203                 cache_name = xstrdup(filename + 1);     // strip leading '/'
204         else
205                 cache_name = xstrdup(dest_file_name);
206         return cache_name;
207 }
208 
209 static int
210 opkg_download_cache(const char *src, const char *dest_file_name)
211 {
212         char *cache_name, *cache_location;
213         int err = 0;
214 
215         if (!conf->cache || str_starts_with(src, "file:")) {
216                 err = opkg_download(src, dest_file_name, 0);
217                 goto out1;
218         }
219 
220         if (!file_is_dir(conf->cache)) {
221                 opkg_msg(ERROR, "%s is not a directory.\n", conf->cache);
222                 err = 1;
223                 goto out1;
224         }
225 
226         cache_name = get_cache_filename(dest_file_name);
227         sprintf_alloc(&cache_location, "%s/%s", conf->cache, cache_name);
228         if (file_exists(cache_location))
229                 opkg_msg(NOTICE, "Copying %s.\n", cache_location);
230         else {
231                 err = opkg_download(src, cache_location, 0);
232                 if (err) {
233                         (void)unlink(cache_location);
234                         goto out2;
235                 }
236         }
237 
238         err = file_copy(cache_location, dest_file_name);
239 
240 out2:
241         free(cache_location);
242         free(cache_name);
243 out1:
244         return err;
245 }
246 
247 int opkg_download_pkg(pkg_t * pkg, const char *dir)
248 {
249         int err;
250         char *url;
251         char *local_filename;
252         char *stripped_filename;
253         char *urlencoded_path;
254         char *filename;
255         char *cache_name;
256         char *cache_location;
257 
258         if (pkg->src == NULL) {
259                 opkg_msg(ERROR,
260                          "Package %s is not available from any configured src.\n",
261                          pkg->name);
262                 return -1;
263         }
264 
265         filename = pkg_get_string(pkg, PKG_FILENAME);
266 
267         if (filename == NULL) {
268                 opkg_msg(ERROR,
269                          "Package %s does not have a valid filename field.\n",
270                          pkg->name);
271                 return -1;
272         }
273 
274         urlencoded_path = urlencode_path(filename);
275         sprintf_alloc(&url, "%s/%s", pkg->src->value, urlencoded_path);
276         free(urlencoded_path);
277 
278         /* The filename might be something like
279            "../../foo.opk". While this is correct, and exactly what we
280            want to use to construct url above, here we actually need to
281            use just the filename part, without any directory. */
282 
283         stripped_filename = strrchr(filename, '/');
284         if (!stripped_filename)
285                 stripped_filename = filename;
286 
287         sprintf_alloc(&local_filename, "%s/%s", dir, stripped_filename);
288         pkg_set_string(pkg, PKG_LOCAL_FILENAME, local_filename);
289 
290         /* Invalidate/remove cached package if it has an incorrect checksum. */
291         if (conf->cache) {
292                 cache_name = get_cache_filename(local_filename);
293                 sprintf_alloc(&cache_location, "%s/%s", conf->cache, cache_name);
294                 free(cache_name);
295                 if (file_exists(cache_location)) {
296                         err = opkg_verify_integrity(pkg, cache_location);
297                         if (err) {
298                                 opkg_msg(NOTICE,
299                                          "Removing %s from cache because it has incorrect checksum.\n",
300                                          pkg->name);
301                                 unlink(cache_location);
302                         }
303                 }
304                 free(cache_location);
305         }
306 
307         err = opkg_download_cache(url, local_filename);
308         free(url);
309 
310         return err;
311 }
312 
313 /*
314  * Downloads file from url, installs in package database, return package name.
315  */
316 int opkg_prepare_url_for_install(const char *url, char **namep)
317 {
318         int err = 0;
319         pkg_t *pkg;
320         abstract_pkg_t *ab_pkg;
321 
322         pkg = pkg_new();
323 
324         if (str_starts_with(url, "http://")
325             || str_starts_with(url, "ftp://")) {
326                 char *tmp_file;
327                 char *file_basec = xstrdup(url);
328                 char *file_base = basename(file_basec);
329 
330                 sprintf_alloc(&tmp_file, "%s/%s", conf->tmp_dir, file_base);
331                 err = opkg_download(url, tmp_file, 0);
332                 if (err)
333                         return err;
334 
335                 err = pkg_init_from_file(pkg, tmp_file);
336                 if (err)
337                         return err;
338 
339                 free(tmp_file);
340                 free(file_basec);
341 
342         } else if (strcmp(&url[strlen(url) - 4], OPKG_PKG_EXTENSION) == 0
343                    || strcmp(&url[strlen(url) - 4], IPKG_PKG_EXTENSION) == 0
344                    || strcmp(&url[strlen(url) - 4], DPKG_PKG_EXTENSION) == 0) {
345 
346                 err = pkg_init_from_file(pkg, url);
347                 if (err)
348                         return err;
349                 opkg_msg(DEBUG2, "Package %s provided by hand (%s).\n",
350                          pkg->name, pkg_get_string(pkg, PKG_LOCAL_FILENAME));
351                 pkg->provided_by_hand = 1;
352 
353         } else {
354                 ab_pkg = ensure_abstract_pkg_by_name(url);
355 
356                 if (!(ab_pkg->state_flag & SF_NEED_DETAIL)) {
357                         opkg_msg(DEBUG, "applying abpkg flag to %s\n", ab_pkg->name);
358                         ab_pkg->state_flag |= SF_NEED_DETAIL;
359                 }
360 
361                 pkg_deinit(pkg);
362                 free(pkg);
363                 return 0;
364         }
365 
366         pkg->dest = conf->default_dest;
367         pkg->state_want = SW_INSTALL;
368         pkg->state_flag |= SF_PREFER;
369         hash_insert_pkg(pkg, 1);
370 
371         if (namep) {
372                 *namep = xstrdup(pkg->name);
373         }
374         return 0;
375 }
376 
377 int opkg_verify_file(char *text_file, char *sig_file)
378 {
379 #if defined HAVE_USIGN
380         const char *argv[] = { conf->verify_program, "verify", sig_file,
381                                text_file, NULL };
382 
383         return xsystem(argv) ? -1 : 0;
384 #else
385         /* mute `unused variable' warnings. */
386         (void)sig_file;
387         (void)text_file;
388         (void)conf;
389         return 0;
390 #endif
391 }
392 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt