aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/smugfs/icache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/smugfs/icache.c')
-rw-r--r--src/cmd/smugfs/icache.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/cmd/smugfs/icache.c b/src/cmd/smugfs/icache.c
new file mode 100644
index 00000000..750f232c
--- /dev/null
+++ b/src/cmd/smugfs/icache.c
@@ -0,0 +1,171 @@
+#include "a.h"
+
+// This code is almost certainly wrong.
+
+typedef struct Icache Icache;
+struct Icache
+{
+ char *url;
+ HTTPHeader hdr;
+ char *tmpfile;
+ int fd;
+ Icache *next;
+ Icache *prev;
+ Icache *hash;
+};
+
+enum {
+ NHASH = 128,
+ MAXCACHE = 128,
+};
+static struct {
+ Icache *hash[NHASH];
+ Icache *head;
+ Icache *tail;
+ int n;
+} icache;
+
+static Icache*
+icachefind(char *url)
+{
+ int h;
+ Icache *ic;
+
+ h = hash(url) % NHASH;
+ for(ic=icache.hash[h]; ic; ic=ic->hash){
+ if(strcmp(ic->url, url) == 0){
+ /* move to front */
+ if(ic->prev) {
+ ic->prev->next = ic->next;
+ if(ic->next)
+ ic->next->prev = ic->prev;
+ else
+ icache.tail = ic->prev;
+ ic->prev = nil;
+ ic->next = icache.head;
+ icache.head->prev = ic;
+ icache.head = ic;
+ }
+ return ic;
+ }
+ }
+ return nil;
+}
+
+static Icache*
+icacheinsert(char *url, HTTPHeader *hdr, char *file, int fd)
+{
+ int h;
+ Icache *ic, **l;
+
+ if(icache.n == MAXCACHE){
+ ic = icache.tail;
+ icache.tail = ic->prev;
+ if(ic->prev)
+ ic->prev->next = nil;
+ else
+ icache.head = ic->prev;
+ h = hash(ic->url) % NHASH;
+ for(l=&icache.hash[h]; *l; l=&(*l)->hash){
+ if(*l == ic){
+ *l = ic->hash;
+ goto removed;
+ }
+ }
+ sysfatal("cannot find ic in cache");
+ removed:
+ free(ic->url);
+ close(ic->fd);
+ remove(ic->file);
+ free(ic->file);
+ }else{
+ ic = emalloc(sizeof *ic);
+ icache.n++;
+ }
+
+ ic->url = estrdup(url);
+ ic->fd = dup(fd, -1);
+ ic->file = estrdup(file);
+ ic->hdr = *hdr;
+ h = hash(url) % NHASH;
+ ic->hash = icache.hash[h];
+ icache.hash[h] = ic;
+ ic->prev = nil;
+ ic->next = icache.head;
+ if(ic->next)
+ ic->next->prev = ic;
+ else
+ icache.tail = ic;
+ return ic;
+}
+
+void
+icacheflush(char *substr)
+{
+ Icache **l, *ic;
+
+ for(l=&icache.head; (ic=*l); ) {
+ if(substr == nil || strstr(ic->url, substr)) {
+ icache.n--;
+ *l = ic->next;
+ free(ic->url);
+ close(ic->fd);
+ remove(ic->file);
+ free(ic->file);
+ free(ic);
+ }else
+ l = &ic->next;
+ }
+
+ if(icache.head) {
+ icache.head->prev = nil;
+ for(ic=icache.head; ic; ic=ic->next){
+ if(ic->next)
+ ic->next->prev = ic;
+ else
+ icache.tail = ic;
+ }
+ }else
+ icache.tail = nil;
+}
+
+int
+urlfetch(char *url, HTTPHeader hdr)
+{
+ Icache *ic;
+ char buf[50], *host, *path, *p;
+ int fd, len;
+
+ ic = icachefind(url);
+ if(ic != nil){
+ *hdr = ic->hdr;
+ return dup(ic->fd, -1);
+ }
+
+ if(memcmp(url, "http://", 7) != 0){
+ werrstr("non-http url");
+ return -1;
+ }
+ 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 = "/";
+
+ strcpy(buf, "/var/tmp/smugfs.XXXXXX");
+ fd = opentemp(buf, ORDWR|ORCLOSE);
+ if(fd < 0)
+ return -1;
+ if(httptofile(http, host, req, &hdr, fd) < 0){
+ free(host);
+ return -1;
+ }
+ free(host);
+ icacheinsert(url, &hdr, buf, fd);
+ return fd;
+}
+