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