core/swupdate.c | 37 ++++++++++++-----
corelib/downloader.c | 95 ++++++++++++++++++++++++++++++++++++++++++--
include/download_interface.h | 31 +++++++++++++++
include/installer.h | 6 ---
4 files changed, 149 insertions(+), 20 deletions(-)
create mode 100644 include/download_interface.h
diff --git a/core/swupdate.c b/core/swupdate.c
index 4da15f5..ff03fa1 100644
--- a/core/swupdate.c
+++ b/core/swupdate.c
@@ -47,6 +47,7 @@
#endif
#include "lua_util.h"
#include "mongoose_interface.h"
+#include "download_interface.h"
#include "network_ipc.h"
#include "sslapi.h"
#include "suricatta/suricatta.h"
@@ -442,10 +443,8 @@ int main(int argc, char **argv)
int opt_w = 0;
int opt_c = 0;
char image_url[MAX_URL];
- int opt_d = 0;
unsigned long __attribute__ ((__unused__)) opt_t = DL_LOWSPEED_TIME;
int __attribute__ ((__unused__)) opt_r = 3;
- RECOVERY_STATUS result;
char main_options[256];
unsigned int public_key_mandatory = 0;
@@ -460,6 +459,13 @@ int main(int argc, char **argv)
int ac = 0;
#endif
+#ifdef CONFIG_DOWNLOAD
+ char dwloptions[1024];
+ char **dwlav = NULL;
+ int dwlac = 0;
+ int opt_d = 0;
+#endif
+
#ifdef CONFIG_MTD
memset(&flashdesc, 0, sizeof(flashdesc));
#endif
@@ -584,10 +590,13 @@ int main(int argc, char **argv)
usage(argv[0]);
exit(0);
break;
+#ifdef CONFIG_DOWNLOAD
case 'd':
- strncpy(image_url, optarg, sizeof(image_url));
+ (void)snprintf(dwloptions, sizeof(dwloptions), "%s %s", argv[0], optarg);
+ dwlav = splitargs(dwloptions, &dwlac);
opt_d = 1;
break;
+#endif
case 'r':
errno = 0;
opt_r = strtoul(optarg, NULL, 10);
@@ -688,6 +697,19 @@ int main(int argc, char **argv)
spawn_process(suricatta_uid, suricatta_gid, cfgfname,
argcount, argvalues, start_suricatta);
}
+
+#endif
+
+#ifdef CONFIG_DOWNLOAD
+ if (opt_d) {
+ uid_t dwl_uid;
+ gid_t dwl_gid;
+
+ read_settings_user_id(cfgfname, "download",
+ &dwl_uid, &dwl_gid);
+ spawn_process(dwl_uid, dwl_gid, cfgfname,
+ dwlac, dwlav, start_download);
+ }
#endif
}
@@ -751,14 +773,7 @@ int main(int argc, char **argv)
notify(SUCCESS, 0, 0);
}
- if (opt_d) {
- result = download_from_url(image_url, opt_r, opt_t);
- if (result == SUCCESS)
- exit(0);
- else
- exit(1);
- }
- if (opt_w || opt_s || opt_u)
+ if (opt_w || opt_s || opt_u || opt_d)
pthread_join(network_daemon, NULL);
}
diff --git a/corelib/downloader.c b/corelib/downloader.c
index 16df71b..e5efb31 100644
--- a/corelib/downloader.c
+++ b/corelib/downloader.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <errno.h>
#include <ctype.h>
+#include <getopt.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -35,9 +36,25 @@
#include "swupdate.h"
#include "installer.h"
#include "network_ipc.h"
+#include "parselib.h"
+#include "swupdate_status.h"
+#include "swupdate_settings.h"
+#include "download_interface.h"
+
+#define SETSTRING(p, v) do { \
+ if (p) \
+ free(p); \
+ p = strdup(v); \
+} while (0)
static int cnt = 0;
+struct dwl_options {
+ char *url;
+ int retries;
+ int timeout;
+};
+
/* notify download progress each second */
#define MINIMAL_PROGRESS_INTERVAL 1
@@ -46,6 +63,13 @@ struct dlprogress {
CURL *curl;
};
+static struct option long_options[] = {
+ {"url", required_argument, NULL, 'u'},
+ {"retry", required_argument, NULL, 'r'},
+ {"timeout", required_argument, NULL, 't'},
+ {NULL, 0, NULL, 0}};
+
+
/*
* Callback from the libcurl API to progress meter function
* This function gets called by libcurl instead of its internal equivalent.
@@ -166,19 +190,20 @@ static void set_option_common(CURL *curl_handle,
* It si not thought to work with local (file://)
* for that, the -i option is used.
*/
-RECOVERY_STATUS download_from_url(char *image_url, int retries,
+static RECOVERY_STATUS download_from_url(char *image_url, int retries,
unsigned long lowspeed_time)
{
CURL *curl_handle;
CURLcode res = CURLE_GOT_NOTHING;
int fd;
- int attempt = 3;
+ int attempt = 10;
int result;
double dummy;
unsigned long long dwlbytes = 0;
int i;
struct dlprogress progress;
+ TRACE("download from url started : %s", image_url);
if (!strlen(image_url)) {
ERROR("Image URL not provided... aborting download and update\n");
return FAILURE;
@@ -258,7 +283,6 @@ RECOVERY_STATUS download_from_url(char *image_url, int retries,
curl_global_cleanup();
if (res == CURLE_OK) {
- INFO("Success : %llu bytes", dwlbytes);
result = ipc_wait_for_complete(NULL);
} else {
INFO("Error : %s", curl_easy_strerror(res));
@@ -269,3 +293,68 @@ RECOVERY_STATUS download_from_url(char *image_url, int retries,
return result;
}
+
+static int download_settings(void *elem, void __attribute__ ((__unused__)) *data)
+{
+ struct dwl_options *opt = (struct dwl_options *)data;
+ char tmp[128];
+
+ GET_FIELD_STRING(LIBCFG_PARSER, elem, "url", tmp);
+ if (strlen(tmp)) {
+ SETSTRING(opt->url, tmp);
+ }
+
+ get_field(LIBCFG_PARSER, elem, "retry",
+ &opt->retries);
+ get_field(LIBCFG_PARSER, elem, "timeout",
+ &opt->timeout);
+
+ return 0;
+}
+
+int start_download(char *fname, int argc, char *argv[])
+{
+ struct dwl_options options;
+ int choice = 0;
+ RECOVERY_STATUS result;
+
+ memset(&options, 0, sizeof(options));
+ if (fname) {
+ read_module_settings(fname, "download", download_settings,
+ &options);
+ }
+
+
+ /* reset to optind=1 to parse download's argument vector */
+ optind = 1;
+ while ((choice = getopt_long(argc, argv, "t:u:r:",
+ long_options, NULL)) != -1) {
+ switch (choice) {
+ case 't':
+ options.timeout =
+ (unsigned char)strtoul(optarg, NULL, 10);
+ break;
+ case 'u':
+ SETSTRING(options.url, optarg);
+ break;
+ case 'r':
+ options.retries =
+ (unsigned char)strtoul(optarg, NULL, 10);
+ break;
+ case '?':
+ default:
+ return -EINVAL;
+ }
+ }
+
+ result = FAILURE;
+
+ while (1) {
+ if (result == FAILURE)
+ result = download_from_url(options.url, options.retries,
+ options.timeout);
+ sleep(60);
+ }
+
+ return 0;
+}
diff --git a/include/download_interface.h b/include/download_interface.h
new file mode 100644
index 0000000..dd8ef23
--- /dev/null
+++ b/include/download_interface.h
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2016
+ * Stefano Babic, DENX Software Engineering,
sba...@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+
+#ifndef _DWL_INTERFACE_H
+#define _DWL_INTERFACE_H
+
+/*
+ * This is used by swupdate to start the Downloader Process
+ */
+int start_download(char *cfgfname, int argc, char *argv[]);
+
+void download_print_help(void);
+
+#endif
diff --git a/include/installer.h b/include/installer.h
index 801e4ac..ec70d00 100644
--- a/include/installer.h
+++ b/include/installer.h
@@ -34,10 +34,4 @@ int run_prepost_scripts(struct swupdate_cfg *sw, script_fn type);
void cleanup_files(struct swupdate_cfg *software);
-#ifdef CONFIG_DOWNLOAD
-RECOVERY_STATUS download_from_url(char *image_url, int retries,
- unsigned long lowspeed_time);
-#else
-#define download_from_url(url, retries, lowspeed_time) (0)
-#endif
#endif
--
2.7.4