# HG changeset patch # User Olaf Wintermann # Date 1513610672 -3600 # Node ID 5da2cf15eb44a5e01cefa5282915ddabb38f173d # Parent 067ea2315a8a9891da6c67b45e0a8855b86f1070 adds primitive progress indicator diff -r 067ea2315a8a -r 5da2cf15eb44 dav/main.c --- a/dav/main.c Mon Dec 18 11:56:11 2017 +0100 +++ b/dav/main.c Mon Dec 18 16:24:32 2017 +0100 @@ -374,6 +374,35 @@ return sn; } +int update_progress(DavResource *res, int64_t total, int64_t now, Progress *p) { + int ret = 0; + if(res != p->last_resource) { + p->cur += p->last_res_total - p->last_res_cur; + ret = 1; + } else { + p->cur += now - p->last_res_cur; + } + + p->last_resource = res; + p->last_res_cur = now; + p->last_res_total = total; + + return ret; +} + +void download_progress(DavResource *res, int64_t total, int64_t now, void *data) { + Progress *p = data; + int newres = update_progress(res, total, now, p); + + time_t newts = time(NULL); + if(newres || (p->ts != newts)) { + fprintf(p->out, "[%s]: %" PRId64 "k/%" PRId64 "k total: %" PRId64 "M/%" PRId64 "M\n", res->name, now/1024, total/1024, p->cur/(1024*1024), p->total/(1024*1024)); + fflush(p->out); + } + p->ts = newts; +} + + #define LIST_QUERY_ORDER_BY_NAME "select `idav:crypto-name`,`idav:crypto-key`,D:lockdiscovery,apache:executable from %s with depth = %d where lastmodified > %t order by iscollection desc, name" #define LIST_QUERY_ORDER_BY_DATE "select `idav:crypto-name`,`idav:crypto-key`,D:lockdiscovery,apache:executable from %s with depth = %d where lastmodified > %t order by iscollection desc, lastmodified desc" @@ -656,6 +685,21 @@ return -1; } + char *progressfile = cmd_getoption(a, "progressfile"); + Progress pdata; + memset(&pdata, 0, sizeof(Progress)); + if(progressfile) { + if(!strcmp(progressfile, "-")) { + pdata.out = stdout; + pdata.isstdout = 1; + } else { + pdata.out = fopen(progressfile, "w"); + } + if(pdata.out) { + dav_session_set_progresscallback(sn, download_progress, NULL, &pdata); + } + } + char *update = cmd_getoption(a, "update"); time_t t = -1; if(update) { @@ -764,6 +808,8 @@ } // download resources + pdata.total = totalsize; + int ret; getfunc get; TarOutputStream *tout = NULL; @@ -798,6 +844,9 @@ ucx_list_free(reslist); free(path); + if(pdata.out && !pdata.isstdout) { + fclose(pdata.out); + } return ret; } diff -r 067ea2315a8a -r 5da2cf15eb44 dav/main.h --- a/dav/main.h Mon Dec 18 11:56:11 2017 +0100 +++ b/dav/main.h Mon Dec 18 16:24:32 2017 +0100 @@ -29,6 +29,7 @@ #ifndef MAIN_H #define MAIN_H +#include #include #include "optparser.h" #include @@ -45,12 +46,26 @@ char *path; } GetResource; +typedef struct { + FILE *out; + int isstdout; + int64_t total; + int64_t cur; + int64_t last_res_cur; + int64_t last_res_total; + DavResource *last_resource; + time_t ts; +} Progress; + typedef int(*getfunc)(Repository *, GetResource *, CmdArgs *, void *); void print_usage(char *cmd); char* password_input(char *prompt); int request_auth(Repository *repo, DavSession *sn, CmdArgs *args); +int update_progress(DavResource *res, int64_t total, int64_t now, Progress *p); +void download_progress(DavResource *res, int64_t total, int64_t now, void *data); + int cmd_list(CmdArgs *args); void ls_print_list_elm(DavResource *res, char *parent, CmdArgs *args); void ls_print_elm(DavResource *res, char *parent, CmdArgs *args); diff -r 067ea2315a8a -r 5da2cf15eb44 dav/optparser.c --- a/dav/optparser.c Mon Dec 18 11:56:11 2017 +0100 +++ b/dav/optparser.c Mon Dec 18 16:24:32 2017 +0100 @@ -210,6 +210,20 @@ } break; } + case 'F': { + if(!option) { + option = "progressfile"; + optchar = 'F'; + } else { + fprintf( + stderr, + "Missing argument for option -%c\n", + optchar); + cmd_args_free(a); + return NULL; + } + break; + } } } } else if(option) { diff -r 067ea2315a8a -r 5da2cf15eb44 libidav/resource.c --- a/libidav/resource.c Mon Dec 18 11:56:11 2017 +0100 +++ b/libidav/resource.c Mon Dec 18 16:24:32 2017 +0100 @@ -765,9 +765,21 @@ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_fnc); curl_easy_setopt(handle, CURLOPT_WRITEDATA, stream); + if(sn->get_progress) { + curl_easy_setopt(handle, CURLOPT_XFERINFOFUNCTION, dav_session_get_progress); + curl_easy_setopt(handle, CURLOPT_XFERINFODATA, res); + curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 0L); + } + long status = 0; CURLcode ret = dav_session_curl_perform(sn, &status); + if(sn->get_progress) { + curl_easy_setopt(handle, CURLOPT_XFERINFOFUNCTION, NULL); + curl_easy_setopt(handle, CURLOPT_XFERINFODATA, NULL); + curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 1L); + } + char *hash = NULL; if(dec) { aes_decrypter_shutdown(dec); // get final bytes diff -r 067ea2315a8a -r 5da2cf15eb44 libidav/session.c --- a/libidav/session.c Mon Dec 18 11:56:11 2017 +0100 +++ b/libidav/session.c Mon Dec 18 16:24:32 2017 +0100 @@ -47,6 +47,7 @@ return NULL; } DavSession *sn = malloc(sizeof(DavSession)); + memset(sn, 0, sizeof(DavSession)); sn->mp = ucx_mempool_new(DAV_SESSION_MEMPOOL_SIZE); sn->pathcache = ucx_map_new_a(sn->mp->allocator, DAV_PATH_CACHE_SIZE); sn->key = NULL; @@ -145,6 +146,12 @@ sn->authprompt_userdata = userdata; } +void dav_session_set_progresscallback(DavSession *sn, dav_progress_func get, dav_progress_func put, void *userdata) { + sn->get_progress = get; + sn->put_progress = put; + sn->progress_userdata = userdata; +} + CURLcode dav_session_curl_perform(DavSession *sn, long *status) { return dav_session_curl_perform_buf(sn, NULL, NULL, status); } @@ -171,6 +178,24 @@ return ret; } +int dav_session_get_progress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { + DavResource *res = clientp; + DavSession *sn = res->session; + if(sn->get_progress) { + sn->get_progress(res, (int64_t)dltotal, (int64_t)dlnow, sn->progress_userdata); + } + return 0; +} + +int dav_session_put_progress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { + DavResource *res = clientp; + DavSession *sn = res->session; + if(sn->put_progress) { + sn->put_progress(res, (int64_t)ultotal, (int64_t)ulnow, sn->progress_userdata); + } + return 0; +} + void dav_session_set_error(DavSession *sn, CURLcode c, int status) { if(status > 0) { switch(status) { diff -r 067ea2315a8a -r 5da2cf15eb44 libidav/session.h --- a/libidav/session.h Mon Dec 18 11:56:11 2017 +0100 +++ b/libidav/session.h Mon Dec 18 16:24:32 2017 +0100 @@ -82,6 +82,9 @@ CURLcode dav_session_curl_perform(DavSession *sn, long *status); CURLcode dav_session_curl_perform_buf(DavSession *sn, UcxBuffer *request, UcxBuffer *response, long *status); +int dav_session_get_progress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); +int dav_session_put_progress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); + void dav_session_set_error(DavSession *sn, CURLcode c, int status); void dav_session_set_errstr(DavSession *sn, const char *str); diff -r 067ea2315a8a -r 5da2cf15eb44 libidav/webdav.h --- a/libidav/webdav.h Mon Dec 18 11:56:11 2017 +0100 +++ b/libidav/webdav.h Mon Dec 18 16:24:32 2017 +0100 @@ -64,6 +64,7 @@ typedef size_t(*dav_write_func)(const void*, size_t, size_t, void*); typedef int(*dav_auth_func)(DavSession *, void *); +typedef void(*dav_progress_func)(DavResource *, int64_t, int64_t, void *); enum DavError { DAV_OK = 0, @@ -145,6 +146,10 @@ int(*auth_prompt)(DavSession *sn, void *userdata); void *authprompt_userdata; + + void(*get_progress)(DavResource *res, int64_t total, int64_t now, void *userdata); + void(*put_progress)(DavResource *res, int64_t total, int64_t now, void *userdata); + void *progress_userdata; }; struct DavContext { @@ -224,6 +229,7 @@ void dav_session_enable_encryption(DavSession *sn, DavKey *key, int flags); void dav_session_set_authcallback(DavSession *sn, dav_auth_func func, void *userdata); +void dav_session_set_progresscallback(DavSession *sn, dav_progress_func get, dav_progress_func put, void *userdata); void dav_session_destroy(DavSession *sn);