Add -m switch
Disaply size of downloaded file in an human way
This commit is contained in:
parent
a5d01d4ddf
commit
c3c7945ddf
139
gget.c
139
gget.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2014 Grégory Soutadé
|
||||
Copyright 2014-2016 Grégory Soutadé
|
||||
|
||||
This file is part of gget.
|
||||
|
||||
|
@ -86,6 +86,7 @@ static int get_console_width()
|
|||
typedef struct {
|
||||
curl_off_t dltotal;
|
||||
curl_off_t dlnow;
|
||||
curl_off_t dllast;
|
||||
unsigned speed;
|
||||
} stats_t ;
|
||||
|
||||
|
@ -101,6 +102,7 @@ typedef struct {
|
|||
unsigned already_downloaded;
|
||||
unsigned start;
|
||||
unsigned end;
|
||||
unsigned max_chunk_size;
|
||||
curl_off_t max_speed;
|
||||
stats_t* stats;
|
||||
} transfert_t;
|
||||
|
@ -216,8 +218,8 @@ static int progress_cb(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl
|
|||
|
||||
curl_easy_getinfo(t->curl, CURLINFO_SPEED_DOWNLOAD, &speed_d);
|
||||
|
||||
t->stats[t->id].dltotal = dltotal + t->already_downloaded;
|
||||
t->stats[t->id].dlnow = dlnow + t->already_downloaded;
|
||||
t->stats[t->id].dlnow += (dlnow - t->stats[t->id].dllast);
|
||||
t->stats[t->id].dllast = dlnow;
|
||||
t->stats[t->id].speed = speed_d;
|
||||
|
||||
return 0;
|
||||
|
@ -226,14 +228,12 @@ static int progress_cb(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl
|
|||
void* do_transfert(transfert_t* t)
|
||||
{
|
||||
CURLcode res;
|
||||
char range[50];
|
||||
|
||||
snprintf(range, sizeof(range), "%u-%u", t->start, t->end);
|
||||
char range[64];
|
||||
unsigned start, end, chunk_size;
|
||||
|
||||
curl_easy_setopt(t->curl, CURLOPT_USERAGENT, t->user_agent);
|
||||
curl_easy_setopt(t->curl, CURLOPT_URL, t->url);
|
||||
curl_easy_setopt(t->curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(t->curl, CURLOPT_RANGE, range);
|
||||
|
||||
if (t->max_speed)
|
||||
curl_easy_setopt(t->curl, CURLOPT_MAX_RECV_SPEED_LARGE, t->max_speed);
|
||||
|
@ -248,12 +248,36 @@ void* do_transfert(transfert_t* t)
|
|||
curl_easy_setopt(t->curl, CURLOPT_XFERINFOFUNCTION, progress_cb);
|
||||
curl_easy_setopt(t->curl, CURLOPT_XFERINFODATA, t);
|
||||
|
||||
/* Perform the request, res will get the return code */
|
||||
res = curl_easy_perform(t->curl);
|
||||
/* Check for errors */
|
||||
if(res != CURLE_OK)
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
start = t->start;
|
||||
if (t->max_chunk_size && (t->end - t->start) > t->max_chunk_size)
|
||||
chunk_size = t->max_chunk_size;
|
||||
else
|
||||
chunk_size = t->end - t->start;
|
||||
end = start + chunk_size;
|
||||
|
||||
while (start < t->end)
|
||||
{
|
||||
snprintf(range, sizeof(range), "%u-%u", start, end);
|
||||
curl_easy_setopt(t->curl, CURLOPT_RANGE, range);
|
||||
|
||||
/* Perform the request, res will get the return code */
|
||||
res = curl_easy_perform(t->curl);
|
||||
/* Check for errors */
|
||||
if(res != CURLE_OK)
|
||||
{
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
break;
|
||||
}
|
||||
|
||||
start += chunk_size + 1;
|
||||
if (t->max_chunk_size && (t->end - start) > t->max_chunk_size)
|
||||
chunk_size = t->max_chunk_size;
|
||||
else
|
||||
chunk_size = t->end - start;
|
||||
end = start + chunk_size;
|
||||
t->stats[t->id].dllast = 0;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -262,7 +286,7 @@ static int configure_transfert(int id, transfert_t* t,
|
|||
char* url, char* filename,
|
||||
unsigned start, unsigned end,
|
||||
unsigned max_speed, char* user_agent,
|
||||
int* exists)
|
||||
unsigned max_chunk_size, int* exists)
|
||||
{
|
||||
// filename + . + number + \0
|
||||
unsigned filename_size = strlen(filename)+1+3+1;
|
||||
|
@ -284,6 +308,7 @@ static int configure_transfert(int id, transfert_t* t,
|
|||
t->end = end;
|
||||
t->max_speed = max_speed;
|
||||
t->user_agent = user_agent;
|
||||
t->max_chunk_size = max_chunk_size;
|
||||
|
||||
if (stat(t->tmp_filename, &s))
|
||||
{
|
||||
|
@ -371,6 +396,7 @@ static int get_file_info(char* url, char* user_agent,
|
|||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
|
||||
if (!quiet)
|
||||
curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
|
||||
|
||||
|
@ -452,13 +478,14 @@ static void find_free_file(char** filename)
|
|||
static void usage(char* program_name)
|
||||
{
|
||||
printf("%s: Parallel HTTP file download\n", program_name);
|
||||
printf("usage: %s [-n nb_threads] [-l speed_limit] [-o out_filename] [-u user_agent] [-q] [-h] url\n",
|
||||
printf("usage: %s [-n nb_threads] [-l speed_limit] [-o out_filename] [-u user_agent] [-m max_chunk_size[kKmMgG] ] [-q] [-h] url\n",
|
||||
program_name);
|
||||
printf("\t-n : Specify number of threads (default : %d)\n", DEFAULT_NB_THREADS);
|
||||
printf("\t-l : Download speed limit for all threads (not per thread)\n");
|
||||
printf("\t-o : Out filename, default is retrieved by GET request or '%s' if not found\n",
|
||||
DEFAULT_OUT_FILENAME);
|
||||
printf("\t-u : User agent, default is '%s'\n", DEFAULT_USER_AGENT);
|
||||
printf("\t-m : Max chunk size in bytes\n");
|
||||
printf("\t-q : Quiet mode\n");
|
||||
printf("\t-h : Display help\n");
|
||||
}
|
||||
|
@ -467,14 +494,15 @@ int main(int argc, char** argv)
|
|||
{
|
||||
pthread_t display_thread = 0;
|
||||
unsigned nb_threads = DEFAULT_NB_THREADS;
|
||||
char* user_agent = strdup(DEFAULT_USER_AGENT);
|
||||
char* user_agent = strdup(DEFAULT_USER_AGENT), *endptr;
|
||||
stats_t* stats = NULL;
|
||||
int ret = -1, i;
|
||||
stats_params_t stats_params;
|
||||
transfert_t* transferts = NULL;
|
||||
unsigned total_size, thread_size;
|
||||
unsigned start, end, max_speed = 0, quiet = 0;
|
||||
char* out_filename = NULL, *url = NULL;
|
||||
unsigned total_size, thread_size, multiplier=1;
|
||||
double displayed_size;
|
||||
unsigned start, end, max_speed = 0, quiet = 0, max_chunk_size = 0;
|
||||
char* out_filename = NULL, *url = NULL, c;
|
||||
char* suffix = "B";
|
||||
void* res;
|
||||
int opt;
|
||||
|
@ -484,7 +512,7 @@ int main(int argc, char** argv)
|
|||
int continuous_mode=0;
|
||||
int exists;
|
||||
|
||||
while ((opt = getopt(argc, argv, "hn:l:o:u:q")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "hn:l:o:u:qm:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
nb_threads = atoi(optarg);
|
||||
|
@ -499,6 +527,39 @@ int main(int argc, char** argv)
|
|||
case 'l':
|
||||
max_speed = atoi(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
if (strlen(optarg) > 1)
|
||||
{
|
||||
c = optarg[strlen(optarg)-1];
|
||||
if (c < '0' || c > '9')
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 'g':
|
||||
case 'G':
|
||||
multiplier *= 1024;
|
||||
case 'm':
|
||||
case 'M':
|
||||
multiplier *= 1024;
|
||||
case 'k':
|
||||
case 'K':
|
||||
multiplier *= 1024;
|
||||
optarg[strlen(optarg)-1] = 0;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
max_chunk_size = strtoul(optarg, &endptr, 0);
|
||||
if (*endptr)
|
||||
{
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
max_chunk_size *= multiplier;
|
||||
break;
|
||||
case 'o':
|
||||
out_filename = strdup(optarg);
|
||||
break;
|
||||
|
@ -539,7 +600,29 @@ int main(int argc, char** argv)
|
|||
goto end;
|
||||
}
|
||||
else
|
||||
printf("Save in '%s'\n\n", out_filename);
|
||||
{
|
||||
displayed_size = (double)total_size;
|
||||
suffix = "B";
|
||||
if (displayed_size > (1024))
|
||||
{
|
||||
displayed_size /= 1024.0;
|
||||
suffix = "kB";
|
||||
}
|
||||
|
||||
if (displayed_size > (1024))
|
||||
{
|
||||
displayed_size /= 1024.0;
|
||||
suffix = "MB";
|
||||
}
|
||||
|
||||
if (displayed_size > (1024))
|
||||
{
|
||||
displayed_size /= 1024.0;
|
||||
suffix = "GB";
|
||||
}
|
||||
|
||||
printf("Save in '%s' (%.2f%s)\n\n", out_filename, displayed_size, suffix);
|
||||
}
|
||||
|
||||
stats = malloc(sizeof(*stats)*nb_threads);
|
||||
memset(stats, 0, sizeof(*stats)*nb_threads);
|
||||
|
@ -561,10 +644,16 @@ int main(int argc, char** argv)
|
|||
end = total_size;
|
||||
|
||||
ret = configure_transfert(i, &transferts[i], url, out_filename,
|
||||
start, end, max_speed, user_agent, &exists);
|
||||
start, end, max_speed, user_agent,
|
||||
max_chunk_size, &exists);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
transferts[i].stats[i].dltotal = transferts[i].already_downloaded +
|
||||
(end - start);
|
||||
transferts[i].stats[i].dlnow = transferts[i].already_downloaded;
|
||||
transferts[i].stats[i].dllast = 0;
|
||||
|
||||
// First set continuous mode
|
||||
if (i == 0)
|
||||
{
|
||||
|
@ -583,7 +672,8 @@ int main(int argc, char** argv)
|
|||
|
||||
// Check for last temporary file
|
||||
configure_transfert(i, &transferts[i], url, out_filename,
|
||||
start, end, max_speed, user_agent, &exists);
|
||||
start, end, max_speed, user_agent, max_chunk_size,
|
||||
&exists);
|
||||
unlink(transferts[i].tmp_filename);
|
||||
|
||||
if (exists)
|
||||
|
@ -665,7 +755,8 @@ end:
|
|||
if (transferts)
|
||||
free(transferts);
|
||||
|
||||
printf("\n");
|
||||
if (!quiet)
|
||||
printf("\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user