Archived
1
0
Fork 0

http.c: skip memory storage when download files

don't need to store the http data in memory when downloading files, write to disk directly.
This commit is contained in:
Henrik Hautakoski 2011-09-01 19:38:56 +02:00
parent 3aea2adbc6
commit c1a7c9671d

68
http.c
View file

@ -48,29 +48,18 @@ static char* strnstrr(const char *str, const char *needle, size_t size) {
return NULL; return NULL;
} }
static char* url_filename(const char *url) { static const char* url_filename(const char *url) {
const char *start = url; const char *start = url;
char *name = NULL;
size_t size;
for(; *url; url++) { for(; *url; url++) {
if (*url != '/') if (*url != '/')
continue; continue;
if (*(url+1)) { if (*(url+1) == 0)
start = url+1;
} else {
url--;
break; break;
} start = url + 1;
} }
size = url - start; return start;
if (size) {
name = malloc(size + 1);
memcpy(name, start, size + 1);
name[size+1] = '\0';
}
return name;
} }
#define HDR_CONDISP "Content-Disposition:" #define HDR_CONDISP "Content-Disposition:"
@ -164,21 +153,25 @@ error:
int http_download_file(const char *url, const char *dir) { int http_download_file(const char *url, const char *dir) {
int fd, err; int err;
char *filename = NULL; CURL *handle = NULL;
char path[4096];
CURL *handle;
CURLcode res; CURLcode res;
struct http_data *data = malloc(sizeof(struct http_data)); FILE *fd;
char tmpfile[4096], *filename = NULL;
data->block = NULL; /* Construct an filename from url. */
data->len = 0; snprintf(tmpfile, sizeof(tmpfile), "%s/%s", dir, url_filename(url));
fd = fopen(tmpfile, "w");
if (!fd)
goto error;
handle = setup_connection(url); handle = setup_connection(url);
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, fwrite);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, data); curl_easy_setopt(handle, CURLOPT_WRITEDATA, fd);
/* try look for the real filename in the http header */
curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, hdr_fname_cb); curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, hdr_fname_cb);
curl_easy_setopt(handle, CURLOPT_HEADERDATA, &filename); curl_easy_setopt(handle, CURLOPT_HEADERDATA, &filename);
@ -189,22 +182,19 @@ int http_download_file(const char *url, const char *dir) {
goto error; goto error;
} }
if (!filename) { if (filename) {
filename = url_filename(url); /* found the real file in http header.
move the old file. */
char realfile[4096];
snprintf(realfile, sizeof(realfile), "%s/%s", dir, filename);
if (rename(tmpfile, realfile) < 0)
goto error;
free(filename);
} else {
fclose(fd);
} }
/* now, write to file */
snprintf(path, sizeof(path), "%s/%s", dir, filename);
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd < 0)
goto error;
write(fd, data->block, data->len);
close(fd);
free(filename);
http_free(data);
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
return 0; return 0;
@ -212,7 +202,7 @@ error:
err = errno; err = errno;
if (filename) if (filename)
free(filename); free(filename);
http_free(data); fclose(fd);
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
errno = err; errno = err;
return -1; return -1;