|  | /*************************************************************************** | 
|  | *                                  _   _ ____  _ | 
|  | *  Project                     ___| | | |  _ \| | | 
|  | *                             / __| | | | |_) | | | 
|  | *                            | (__| |_| |  _ <| |___ | 
|  | *                             \___|\___/|_| \_\_____| | 
|  | * | 
|  | * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. | 
|  | * | 
|  | * This software is licensed as described in the file COPYING, which | 
|  | * you should have received as part of this distribution. The terms | 
|  | * are also available at https://curl.haxx.se/docs/copyright.html. | 
|  | * | 
|  | * You may opt to use, copy, modify, merge, publish, distribute and/or sell | 
|  | * copies of the Software, and permit persons to whom the Software is | 
|  | * furnished to do so, under the terms of the COPYING file. | 
|  | * | 
|  | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | 
|  | * KIND, either express or implied. | 
|  | * | 
|  | ***************************************************************************/ | 
|  | /* <DESC> | 
|  | * Use the progress callbacks, old and/or new one depending on available | 
|  | * libcurl version. | 
|  | * </DESC> | 
|  | */ | 
|  | #include <stdio.h> | 
|  | #include <curl/curl.h> | 
|  |  | 
|  | #define STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES         6000 | 
|  | #define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL     3 | 
|  |  | 
|  | struct myprogress { | 
|  | double lastruntime; | 
|  | CURL *curl; | 
|  | }; | 
|  |  | 
|  | /* this is how the CURLOPT_XFERINFOFUNCTION callback works */ | 
|  | static int xferinfo(void *p, | 
|  | curl_off_t dltotal, curl_off_t dlnow, | 
|  | curl_off_t ultotal, curl_off_t ulnow) | 
|  | { | 
|  | struct myprogress *myp = (struct myprogress *)p; | 
|  | CURL *curl = myp->curl; | 
|  | double curtime = 0; | 
|  |  | 
|  | curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime); | 
|  |  | 
|  | /* under certain circumstances it may be desirable for certain functionality | 
|  | to only run every N seconds, in order to do this the transaction time can | 
|  | be used */ | 
|  | if((curtime - myp->lastruntime) >= MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL) { | 
|  | myp->lastruntime = curtime; | 
|  | fprintf(stderr, "TOTAL TIME: %f \r\n", curtime); | 
|  | } | 
|  |  | 
|  | fprintf(stderr, "UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T | 
|  | "  DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T | 
|  | "\r\n", | 
|  | ulnow, ultotal, dlnow, dltotal); | 
|  |  | 
|  | if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES) | 
|  | return 1; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* for libcurl older than 7.32.0 (CURLOPT_PROGRESSFUNCTION) */ | 
|  | static int older_progress(void *p, | 
|  | double dltotal, double dlnow, | 
|  | double ultotal, double ulnow) | 
|  | { | 
|  | return xferinfo(p, | 
|  | (curl_off_t)dltotal, | 
|  | (curl_off_t)dlnow, | 
|  | (curl_off_t)ultotal, | 
|  | (curl_off_t)ulnow); | 
|  | } | 
|  |  | 
|  |  | 
|  | int main(void) | 
|  | { | 
|  | CURL *curl; | 
|  | CURLcode res = CURLE_OK; | 
|  | struct myprogress prog; | 
|  |  | 
|  | curl = curl_easy_init(); | 
|  | if(curl) { | 
|  | prog.lastruntime = 0; | 
|  | prog.curl = curl; | 
|  |  | 
|  | curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/"); | 
|  |  | 
|  | curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, older_progress); | 
|  | /* pass the struct pointer into the progress function */ | 
|  | curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog); | 
|  |  | 
|  | #if LIBCURL_VERSION_NUM >= 0x072000 | 
|  | /* xferinfo was introduced in 7.32.0, no earlier libcurl versions will | 
|  | compile as they won't have the symbols around. | 
|  |  | 
|  | If built with a newer libcurl, but running with an older libcurl: | 
|  | curl_easy_setopt() will fail in run-time trying to set the new | 
|  | callback, making the older callback get used. | 
|  |  | 
|  | New libcurls will prefer the new callback and instead use that one even | 
|  | if both callbacks are set. */ | 
|  |  | 
|  | curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); | 
|  | /* pass the struct pointer into the xferinfo function, note that this is | 
|  | an alias to CURLOPT_PROGRESSDATA */ | 
|  | curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog); | 
|  | #endif | 
|  |  | 
|  | curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); | 
|  | res = curl_easy_perform(curl); | 
|  |  | 
|  | if(res != CURLE_OK) | 
|  | fprintf(stderr, "%s\n", curl_easy_strerror(res)); | 
|  |  | 
|  | /* always cleanup */ | 
|  | curl_easy_cleanup(curl); | 
|  | } | 
|  | return (int)res; | 
|  | } |