Skip to content

Commit

Permalink
axel: Fix speed limiting, and use 64-bit sizes and offsets
Browse files Browse the repository at this point in the history
Reset delay_time only when it's too small for another subtraction,
the original code wrongly cleared it when the speed is within spec.

Variables used to overflow on 32-bit systems, use off_t instead, which
should be 64 bits on systems supporting that.

[[email protected]: Improved commit message]
Signed-off-by: Ismael Luceno <[email protected]>
  • Loading branch information
wtywtykk authored and ismaell committed Nov 21, 2020
1 parent c652bbb commit 9cedf8b
Show file tree
Hide file tree
Showing 13 changed files with 64 additions and 53 deletions.
28 changes: 14 additions & 14 deletions src/axel.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ axel_new(conf_t *conf, int count, const search_t *res)
if (axel->size != LLONG_MAX) {
char hsize[32];
axel_size_human(hsize, sizeof(hsize), axel->size);
axel_message(axel, _("File size: %s (%zu bytes)"),
axel_message(axel, _("File size: %s (%jd bytes)"),
hsize, axel->size);
} else {
axel_message(axel, _("File size: unavailable"));
Expand Down Expand Up @@ -339,7 +339,7 @@ axel_open(axel_t *axel)
}

axel_message(axel,
_("State file found: %zu bytes downloaded, %zu to go."),
_("State file found: %jd bytes downloaded, %jd to go."),
axel->bytes_done, axel->size - axel->bytes_done);

close(fd);
Expand Down Expand Up @@ -372,7 +372,7 @@ axel_open(axel_t *axel)
_("Crappy filesystem/OS.. Working around. :-("));
lseek(axel->outfd, 0, SEEK_SET);
memset(buffer, 0, axel->conf->buffer_size);
long long int j = axel->size;
off_t j = axel->size;
while (j > 0) {
ssize_t nwrite;

Expand Down Expand Up @@ -404,16 +404,16 @@ void
reactivate_connection(axel_t *axel, int thread)
{
/* TODO Make the minimum also depend on the connection speed */
long long int max_remaining = MIN_CHUNK_WORTH - 1;
off_t max_remaining = MIN_CHUNK_WORTH - 1;
int idx = -1;

if (axel->conn[thread].enabled ||
axel->conn[thread].currentbyte < axel->conn[thread].lastbyte)
return;

for (int j = 0; j < axel->conf->num_connections; j++) {
long long int remaining =
axel->conn[j].lastbyte - axel->conn[j].currentbyte;
off_t remaining =
axel->conn[j].lastbyte - axel->conn[j].currentbyte;
if (remaining > max_remaining) {
max_remaining = remaining;
idx = j;
Expand Down Expand Up @@ -489,11 +489,11 @@ axel_do(axel_t *axel)
{
fd_set fds[1];
int hifd, i;
long long int remaining, size;
off_t remaining, size;
struct timeval timeval[1];
url_t *url_ptr;
struct timespec delay = {.tv_sec = 0, .tv_nsec = 100000000};
unsigned int max_speed_ratio;
unsigned long long int max_speed_ratio;

/* Create statefile if necessary */
if (axel_gettime() > axel->next_state) {
Expand Down Expand Up @@ -675,7 +675,7 @@ axel_do(axel_t *axel)

/* Calculate current average speed and finish_time */
axel->bytes_per_second =
(int)((double)(axel->bytes_done - axel->start_byte) /
(off_t)((double)(axel->bytes_done - axel->start_byte) /
(axel_gettime() - axel->start_time));
if (axel->bytes_per_second != 0)
axel->finish_time =
Expand All @@ -698,10 +698,10 @@ axel_do(axel_t *axel)
} else if (axel->delay_time.tv_sec > 0) {
axel->delay_time.tv_sec--;
axel->delay_time.tv_nsec += 999000000;
} else {
axel->delay_time.tv_sec = 0;
axel->delay_time.tv_nsec = 0;
}
} else {
axel->delay_time.tv_sec = 0;
axel->delay_time.tv_nsec = 0;
}
if (axel_sleep(axel->delay_time) < 0) {
axel_message(axel,
Expand Down Expand Up @@ -882,12 +882,12 @@ static void
axel_divide(axel_t *axel)
{
/* Optimize the number of connections in case the file is small */
size_t maxconns = max(1u, axel->size / MIN_CHUNK_WORTH);
off_t maxconns = max(1u, axel->size / MIN_CHUNK_WORTH);
if (maxconns < axel->conf->num_connections)
axel->conf->num_connections = maxconns;

/* Calculate each segment's size */
size_t seg_len = axel->size / axel->conf->num_connections;
off_t seg_len = axel->size / axel->conf->num_connections;

if (!seg_len) {
printf(_("Too few bytes remaining, forcing a single connection\n"));
Expand Down
4 changes: 2 additions & 2 deletions src/axel.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ typedef struct {
char filename[MAX_STRING];
double start_time;
int next_state, finish_time;
size_t bytes_done, start_byte, size;
int bytes_per_second;
off_t bytes_done, start_byte, size;
long long int bytes_per_second;
struct timespec delay_time;
int outfd;
int ready;
Expand Down
13 changes: 12 additions & 1 deletion src/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,23 @@ conf_loadfile(conf_t *conf, const char *file)
KEY(search_amount)
KEY(search_top)
else
goto other_keys;
goto long_num_keys;

/* Save numeric option */
*((int *)dst) = atoi(value);
continue;

/* Long numeric options */
long_num_keys:
MATCH
KEY(max_speed)
else
goto other_keys;

/* Save numeric option */
*((unsigned long long *)dst) = strtoull(value, NULL, 10);
continue;

other_keys:
/* Option defunct but shouldn't be an error */
if (strcmp(key, "speed_type") == 0)
Expand Down
2 changes: 1 addition & 1 deletion src/conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ typedef struct {
int reconnect_delay;
int max_redirect;
int buffer_size;
int max_speed;
unsigned long long max_speed;
int verbose;
int alternate_output;
int insecure;
Expand Down
2 changes: 1 addition & 1 deletion src/conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ conn_setup(conn_t *conn)
conn->tcp = &conn->ftp->data_tcp;

if (conn->currentbyte) {
ftp_command(conn->ftp, "REST %lld", conn->currentbyte);
ftp_command(conn->ftp, "REST %jd", conn->currentbyte);
if (ftp_wait(conn->ftp) / 100 != 3 &&
conn->ftp->status / 100 != 2)
return 0;
Expand Down
6 changes: 3 additions & 3 deletions src/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ typedef struct {

ftp_t ftp[1];
http_t http[1];
long long int size; /* File size, not 'connection size'.. */
long long int currentbyte;
long long int lastbyte;
off_t size; /* File size, not 'connection size'.. */
off_t currentbyte;
off_t lastbyte;
tcp_t *tcp;
bool enabled;
bool supported;
Expand Down
10 changes: 5 additions & 5 deletions src/ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,17 @@ ftp_cwd(ftp_t *conn, char *cwd)
}

/* Get file size. Should work with all reasonable servers now */
long long int
off_t
ftp_size(ftp_t *conn, char *file, int maxredir, unsigned io_timeout)
{
long long int i, j, size = MAX_STRING;
off_t i, j, size = MAX_STRING;
char *reply, *s, fn[MAX_STRING];

/* Try the SIZE command first, if possible */
if (!strchr(file, '*') && !strchr(file, '?')) {
ftp_command(conn, "SIZE %s", file);
if (ftp_wait(conn) / 100 == 2) {
sscanf(conn->message, "%*i %lld", &i);
sscanf(conn->message, "%*i %jd", &i);
return i;
} else if (conn->status / 10 != 50) {
fprintf(stderr, _("File not found.\n"));
Expand Down Expand Up @@ -213,10 +213,10 @@ ftp_size(ftp_t *conn, char *file, int maxredir, unsigned io_timeout)
possible wildcards. */
else {
s = strstr(reply, "\n-");
i = sscanf(s, "%*s %*i %*s %*s %lld %*s %*i %*s %100s", &size,
i = sscanf(s, "%*s %*i %*s %*s %jd %*s %*i %*s %100s", &size,
fn);
if (i < 2) {
i = sscanf(s, "%*s %*i %lld %*i %*s %*i %*i %100s",
i = sscanf(s, "%*s %*i %jd %*i %*s %*i %*i %100s",
&size, fn);
if (i < 2) {
return -2;
Expand Down
2 changes: 1 addition & 1 deletion src/ftp.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,6 @@ __attribute__((format(printf, 2, 3)))
int ftp_command(ftp_t *conn, const char *format, ...);
int ftp_cwd(ftp_t *conn, char *cwd);
int ftp_data(ftp_t *conn, unsigned io_timeout);
long long int ftp_size(ftp_t *conn, char *file, int maxredir, unsigned io_timeout);
off_t ftp_size(ftp_t *conn, char *file, int maxredir, unsigned io_timeout);

#endif /* AXEL_FTP_H */
14 changes: 7 additions & 7 deletions src/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,10 @@ http_get(http_t *conn, char *lurl)
http_addheader(conn, "Accept: */*");
http_addheader(conn, "Accept-Encoding: identity");
if (conn->lastbyte && conn->firstbyte >= 0) {
http_addheader(conn, "Range: bytes=%lld-%lld",
http_addheader(conn, "Range: bytes=%jd-%jd",
conn->firstbyte, conn->lastbyte - 1);
} else if (conn->firstbyte >= 0) {
http_addheader(conn, "Range: bytes=%lld-",
http_addheader(conn, "Range: bytes=%jd-",
conn->firstbyte);
}
}
Expand Down Expand Up @@ -313,20 +313,20 @@ http_header(const http_t *conn, const char *header)
return NULL;
}

long long int
off_t
http_size(http_t *conn)
{
const char *i;
long long int j;
off_t j;

if ((i = http_header(conn, "Content-Length:")) == NULL)
return -2;

sscanf(i, "%lld", &j);
sscanf(i, "%jd", &j);
return j;
}

long long int
off_t
http_size_from_range(http_t *conn)
{
const char *i;
Expand All @@ -337,7 +337,7 @@ http_size_from_range(http_t *conn)
if (!i++)
return -2;

long long int j = strtoll(i, NULL, 10);
off_t j = strtoll(i, NULL, 10);
if (!j && *i != '0')
return -3;

Expand Down
8 changes: 4 additions & 4 deletions src/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ typedef struct {
int proto; /* FTP through HTTP proxies */
int proxy;
char proxy_auth[MAX_STRING];
long long int firstbyte;
long long int lastbyte;
off_t firstbyte;
off_t lastbyte;
int status;
tcp_t tcp;
char *local_if;
Expand All @@ -69,8 +69,8 @@ void http_addheader(http_t *conn, const char *format, ...);
int http_exec(http_t *conn);
const char *http_header(const http_t *conn, const char *header);
void http_filename(const http_t *conn, char *filename);
long long int http_size(http_t *conn);
long long int http_size_from_range(http_t *conn);
off_t http_size(http_t *conn);
off_t http_size_from_range(http_t *conn);
void http_encode(char *s, size_t len);
void http_decode(char *s);

Expand Down
2 changes: 1 addition & 1 deletion src/search.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ search_makelist(search_t *results, char *orig_url)
/* Sorting: */ "o=n&"
/* Filename: */ "q=%s&"
/* Num. of results: */ "m=%i&"
/* Size (min/max): */ "s1=%lld&s2=%lld",
/* Size (min/max): */ "s1=%jd&s2=%jd",
conn->file, results->conf->search_amount,
conn->size, conn->size);

Expand Down
2 changes: 1 addition & 1 deletion src/search.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
typedef struct {
char url[MAX_STRING];
double speed_start_time;
int speed, size;
off_t speed, size;
pthread_t speed_thread[1];
conf_t *conf;
} search_t;
Expand Down
24 changes: 12 additions & 12 deletions src/text.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@

static void stop(int signal);
static char *time_human(char *dst, size_t len, unsigned int value);
static void print_commas(long long int bytes_done);
static void print_commas(off_t bytes_done);
static void print_alternate_output(axel_t *axel);
static void print_progress(size_t cur, size_t prev, size_t total, double kbps);
static void print_progress(off_t cur, off_t prev, off_t total, double kbps);
static void print_help(void);
static void print_version(void);
static void print_version_info(void);
Expand Down Expand Up @@ -140,7 +140,7 @@ main(int argc, char *argv[])
sizeof(conf->add_header[0]));
break;
case 's':
if (!sscanf(optarg, "%i", &conf->max_speed)) {
if (!sscanf(optarg, "%llu", &conf->max_speed)) {
print_help();
goto free_conf;
}
Expand Down Expand Up @@ -291,7 +291,7 @@ main(int argc, char *argv[])
j = min(j, conf->search_top);
printf("%-60s %15s\n", "URL", _("Speed"));
for (i = 0; i < j; i++)
printf("%-70.70s %5i\n", search[i].url,
printf("%-70.70s %5jd\n", search[i].url,
search[i].speed);
printf("\n");
}
Expand Down Expand Up @@ -396,7 +396,7 @@ main(int argc, char *argv[])
signal(SIGTERM, stop);

while (!axel->ready && run) {
size_t prev;
off_t prev;

prev = axel->bytes_done;
axel_do(axel);
Expand Down Expand Up @@ -504,7 +504,7 @@ time_human(char *dst, size_t len, unsigned int value)
/* Part of the infamous wget-like interface. Just put it in a function
because I need it quite often.. */
void
print_commas(long long int bytes_done)
print_commas(off_t bytes_done)
{
int i, j;

Expand All @@ -525,21 +525,21 @@ print_commas(long long int bytes_done)
*/
static
void
print_progress(size_t cur, size_t prev, size_t total, double kbps)
print_progress(off_t cur, off_t prev, off_t total, double kbps)
{
prev /= 1024;
cur /= 1024;

bool print_speed = prev > 0;
for (size_t i = prev; i < cur; i++) {
for (off_t i = prev; i < cur; i++) {
if (i % 50 == 0) {
if (print_speed)
printf(" [%6.1fKB/s]", kbps);

if (total == LLONG_MAX)
printf("\n[ N/A] ");
else
printf("\n[%3zu%%] ",
printf("\n[%3jd%%] ",
min(100U, 102400 * i / total));
} else if (i % 10 == 0) {
putchar(' ');
Expand All @@ -562,7 +562,7 @@ alt_id(int n)

static void
print_alternate_output_progress(axel_t *axel, char *progress, int width,
long long int done, long long int total,
off_t done, off_t total,
double now)
{
if (!width)
Expand Down Expand Up @@ -591,8 +591,8 @@ print_alternate_output_progress(axel_t *axel, char *progress, int width,
static void
print_alternate_output(axel_t *axel)
{
long long int done = axel->bytes_done;
long long int total = axel->size;
off_t done = axel->bytes_done;
off_t total = axel->size;
double now = axel_gettime();
int width = get_term_width();
char *progress;
Expand Down

0 comments on commit 9cedf8b

Please sign in to comment.