Blob
1 #include "a.h"3 // This code is almost certainly wrong.5 typedef struct Icache Icache;6 struct Icache7 {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 else43 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 else67 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 else98 icache.tail = ic;99 return ic;100 }102 void103 icacheflush(char *substr)104 {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 }else117 l = &ic->next;118 }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 else126 icache.tail = ic;127 }128 }else129 icache.tail = nil;130 }132 int133 urlfetch(char *url, HTTPHeader hdr)134 {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);143 }145 if(memcmp(url, "http://", 7) != 0){146 werrstr("non-http url");147 return -1;148 }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;166 }167 free(host);168 icacheinsert(url, &hdr, buf, fd);169 return fd;170 }