1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#include "a.h"
typedef struct DEntry DEntry;
struct DEntry
{
CEntry ce;
HTTPHeader hdr;
char *tmpfile;
int fd;
};
static void
dfree(CEntry *ce)
{
DEntry *d;
d = (DEntry*)ce;
if(d->tmpfile){
remove(d->tmpfile);
free(d->tmpfile);
close(d->fd);
}
}
static Cache *downloadcache;
static char*
parseurl(char *url, char **path)
{
char *host, *p;
int len;
if(memcmp(url, "http://", 7) != 0)
return nil;
p = strchr(url+7, '/');
if(p == nil)
p = url+strlen(url);
len = p - (url+7);
host = emalloc(len+1);
memmove(host, url+7, len);
host[len] = 0;
if(*p == 0)
p = "/";
*path = p;
return host;
}
int
download(char *url, HTTPHeader *hdr)
{
DEntry *d;
char *host, *path;
char buf[] = "/var/tmp/smugfs.XXXXXX";
char *req;
int fd;
Fmt fmt;
if(downloadcache == nil)
downloadcache = newcache(sizeof(DEntry), 128, dfree);
host = parseurl(url, &path);
if(host == nil)
return -1;
d = (DEntry*)cachelookup(downloadcache, url, 1);
if(d->tmpfile){
free(host);
*hdr = d->hdr;
return dup(d->fd, -1);
}
d->fd = -1; // paranoia
if((fd = opentemp(buf, ORDWR|ORCLOSE)) < 0){
free(host);
return -1;
}
fmtstrinit(&fmt);
fmtprint(&fmt, "GET %s HTTP/1.0\r\n", path);
fmtprint(&fmt, "Host: %s\r\n", host);
fmtprint(&fmt, "User-Agent: " USER_AGENT "\r\n");
fmtprint(&fmt, "\r\n");
req = fmtstrflush(&fmt);
fprint(2, "Get %s\n", url);
if(httptofile(&http, host, req, hdr, fd) < 0){
free(host);
free(req);
return -1;
}
free(host);
free(req);
d->tmpfile = estrdup(buf);
d->fd = dup(fd, -1);
d->hdr = *hdr;
return fd;
}
void
downloadflush(char *substr)
{
if(downloadcache)
cacheflush(downloadcache, substr);
}
|