Blob


1 #include "a.h"
3 // This code is almost certainly wrong.
5 typedef struct Icache Icache;
6 struct Icache
7 {
8 char *url;
9 HTTPHeader hdr;
10 char *tmpfile;
11 int fd;
12 Icache *next;
13 Icache *prev;
14 Icache *hash;
15 };
17 enum {
18 NHASH = 128,
19 MAXCACHE = 128,
20 };
21 static struct {
22 Icache *hash[NHASH];
23 Icache *head;
24 Icache *tail;
25 int n;
26 } icache;
28 static Icache*
29 icachefind(char *url)
30 {
31 int h;
32 Icache *ic;
34 h = hash(url) % NHASH;
35 for(ic=icache.hash[h]; ic; ic=ic->hash){
36 if(strcmp(ic->url, url) == 0){
37 /* move to front */
38 if(ic->prev) {
39 ic->prev->next = ic->next;
40 if(ic->next)
41 ic->next->prev = ic->prev;
42 else
43 icache.tail = ic->prev;
44 ic->prev = nil;
45 ic->next = icache.head;
46 icache.head->prev = ic;
47 icache.head = ic;
48 }
49 return ic;
50 }
51 }
52 return nil;
53 }
55 static Icache*
56 icacheinsert(char *url, HTTPHeader *hdr, char *file, int fd)
57 {
58 int h;
59 Icache *ic, **l;
61 if(icache.n == MAXCACHE){
62 ic = icache.tail;
63 icache.tail = ic->prev;
64 if(ic->prev)
65 ic->prev->next = nil;
66 else
67 icache.head = ic->prev;
68 h = hash(ic->url) % NHASH;
69 for(l=&icache.hash[h]; *l; l=&(*l)->hash){
70 if(*l == ic){
71 *l = ic->hash;
72 goto removed;
73 }
74 }
75 sysfatal("cannot find ic in cache");
76 removed:
77 free(ic->url);
78 close(ic->fd);
79 remove(ic->file);
80 free(ic->file);
81 }else{
82 ic = emalloc(sizeof *ic);
83 icache.n++;
84 }
86 ic->url = estrdup(url);
87 ic->fd = dup(fd, -1);
88 ic->file = estrdup(file);
89 ic->hdr = *hdr;
90 h = hash(url) % NHASH;
91 ic->hash = icache.hash[h];
92 icache.hash[h] = ic;
93 ic->prev = nil;
94 ic->next = icache.head;
95 if(ic->next)
96 ic->next->prev = ic;
97 else
98 icache.tail = ic;
99 return ic;
102 void
103 icacheflush(char *substr)
105 Icache **l, *ic;
107 for(l=&icache.head; (ic=*l); ) {
108 if(substr == nil || strstr(ic->url, substr)) {
109 icache.n--;
110 *l = ic->next;
111 free(ic->url);
112 close(ic->fd);
113 remove(ic->file);
114 free(ic->file);
115 free(ic);
116 }else
117 l = &ic->next;
120 if(icache.head) {
121 icache.head->prev = nil;
122 for(ic=icache.head; ic; ic=ic->next){
123 if(ic->next)
124 ic->next->prev = ic;
125 else
126 icache.tail = ic;
128 }else
129 icache.tail = nil;
132 int
133 urlfetch(char *url, HTTPHeader hdr)
135 Icache *ic;
136 char buf[50], *host, *path, *p;
137 int fd, len;
139 ic = icachefind(url);
140 if(ic != nil){
141 *hdr = ic->hdr;
142 return dup(ic->fd, -1);
145 if(memcmp(url, "http://", 7) != 0){
146 werrstr("non-http url");
147 return -1;
149 p = strchr(url+7, '/');
150 if(p == nil)
151 p = url+strlen(url);
152 len = p - (url+7);
153 host = emalloc(len+1);
154 memmove(host, url+7, len);
155 host[len] = 0;
156 if(*p == 0)
157 p = "/";
159 strcpy(buf, "/var/tmp/smugfs.XXXXXX");
160 fd = opentemp(buf, ORDWR|ORCLOSE);
161 if(fd < 0)
162 return -1;
163 if(httptofile(http, host, req, &hdr, fd) < 0){
164 free(host);
165 return -1;
167 free(host);
168 icacheinsert(url, &hdr, buf, fd);
169 return fd;