#include <errno.h>
#include <argp.h>
#include <zck.h>
+#include <curl/curl.h>
#include "util_common.h"
static struct argp argp = {options, parse_opt, args_doc, doc};
-int main (int argc, char *argv[]) {
- zckCtx *zck_tgt = zck_create();
+int dl_range(CURL *curl, zckDL *dl, char *url, char *range, int is_chunk) {
+ if(dl == NULL || dl->priv == NULL) {
+ printf("Struct not defined\n");
+ return 0;
+ }
- if(zck_tgt == NULL)
- exit(1);
+ CURLcode res;
+
+ zck_dl_reset(dl);
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, zck_header_cb);
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, dl);
+ if(is_chunk)
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, zck_write_chunk_cb);
+ else
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, zck_write_zck_header_cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, dl);
+ curl_easy_setopt(curl, CURLOPT_RANGE, range);
+ res = curl_easy_perform(curl);
+
+ if(res != CURLE_OK) {
+ printf("Download failed: %s\n", curl_easy_strerror(res));
+ return False;
+ }
+ long code;
+ curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code);
+ if (code != 206 && code != 200) {
+ printf("HTTP Error: %li when download %s\n", code,
+ url);
+ return False;
+ }
+
+ return True;
+}
+
+int dl_byte_range(CURL *curl, zckDL *dl, char *url, int start, int end) {
+ char *range = zck_get_range(start, end);
+ return dl_range(curl, dl, url, range, 0);
+}
+
+int dl_bytes(CURL *curl, zckDL *dl, char *url, size_t bytes, size_t start, size_t *buffer_len, int log_level) {
+ if(start + bytes > *buffer_len) {
+ int fd = zck_get_fd(dl->zck);
+
+ if(lseek(fd, 0, SEEK_END) == -1) {
+ printf("Seek to end of temporary file failed: %s\n",
+ strerror(errno));
+ return 0;
+ }
+ if(*buffer_len >= start + bytes)
+ return 1;
+ if(!dl_byte_range(curl, dl, url, *buffer_len,
+ (start + bytes - *buffer_len) - 1)) {
+ printf("Error downloading bytes\n");
+ return 0;
+ }
+ if(log_level <= ZCK_LOG_DEBUG)
+ printf("Downloading %lu bytes at position %lu\n",
+ start+bytes-*buffer_len, *buffer_len);
+ *buffer_len += start + bytes - *buffer_len;
+ if(lseek(fd, start, SEEK_SET) == -1) {
+ printf("Seek to byte %lu of temporary file failed: %s\n", start,
+ strerror(errno));
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int dl_header(CURL *curl, zckDL *dl, char *url, int log_level) {
+ size_t buffer_len = 0;
+ size_t start = 0;
+
+ /* Download first two hundred bytes and read magic and hash type */
+ if(!dl_bytes(curl, dl, url, get_min_download_size(), start, &buffer_len, log_level))
+ return 0;
+ if(!zck_read_lead(dl->zck))
+ return 0;
+ start = zck_get_lead_length(dl->zck);
+ printf("Now we need %lu bytes\n", zck_get_header_length(dl->zck) - start);
+
+ if(!dl_bytes(curl, dl, url, zck_get_header_length(dl->zck) - start,
+ start, &buffer_len, log_level))
+ return 0;
+ if(!zck_read_header(dl->zck))
+ return 0;
+ return 1;
+}
- zck_dl_global_init();
+int main (int argc, char *argv[]) {
+ curl_global_init(CURL_GLOBAL_ALL);
struct arguments arguments = {0};
exit(1);
}
- zckDL *dl = zck_dl_init();
- if(dl == NULL)
- exit(1);
- dl->zck = zck_tgt;
-
char *outname_full = calloc(1, strlen(arguments.args[0])+1);
memcpy(outname_full, arguments.args[0], strlen(arguments.args[0]));
char *outname = basename(outname_full);
exit(1);
}
free(outname_full);
- dl->dst_fd = dst_fd;
+ zckCtx *zck_tgt = zck_init_adv_read(dst_fd);
+ if(zck_tgt == NULL)
+ exit(1);
- if(!zck_dl_get_header(zck_tgt, dl, arguments.args[0]))
+ CURL *curl_ctx = curl_easy_init();
+ if(!curl_ctx) {
+ printf("Unable to allocate %lu bytes for curl context\n",
+ sizeof(CURL));
exit(1);
+ }
- zck_range_close(&(dl->info));
- if(!zck_dl_copy_src_chunks(&(dl->info), zck_src, zck_tgt))
+ zckDL *dl = zck_dl_init(zck_tgt);
+ if(dl == NULL)
exit(1);
- int max_ranges = 256;
- if(!zck_range_calc_segments(&(dl->info), max_ranges))
+ dl->zck = zck_tgt;
+
+ if(!dl_header(curl_ctx, dl, arguments.args[0], arguments.log_level))
exit(1);
- lseek(dl->dst_fd, 0, SEEK_SET);
- if(!zck_dl_range(dl, arguments.args[0]))
+ if(!zck_copy_chunks(zck_src, zck_tgt))
exit(1);
printf("Downloaded %lu bytes\n",
(long unsigned)zck_dl_get_bytes_downloaded(dl));
int exit_val = 0;
- switch(zck_hash_check_data(dl->zck, dl->dst_fd)) {
+ switch(zck_validate_data_checksum(dl->zck)) {
case -1:
exit_val = 1;
break;
zck_dl_free(&dl);
zck_free(&zck_tgt);
zck_free(&zck_src);
- zck_dl_global_cleanup();
+ curl_easy_cleanup(curl_ctx);
+ curl_global_cleanup();
exit(exit_val);
}