Add -m switch

Disaply size of downloaded file in an human way
This commit is contained in:
Grégory Soutadé 2016-08-12 18:10:03 +02:00
parent a5d01d4ddf
commit c3c7945ddf
1 changed files with 116 additions and 25 deletions

141
gget.c
View File

@ -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,13 +248,37 @@ 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;
}