Do If-Modified-Since caching.
[statserve.git] / fssrc.c
... / ...
CommitLineData
1#include <stdlib.h>
2#include <stdio.h>
3#include <unistd.h>
4#include <errno.h>
5#include <string.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <ashd/utils.h>
9#include <ashd/mtio.h>
10#include <ashd/log.h>
11
12#include "statserve.h"
13
14struct fssrc {
15 char *path;
16};
17
18static struct fileinfo fsserve(struct source *src, char *nm)
19{
20 struct fssrc *d = src->pdata;
21 struct stat sb;
22 char *p;
23 struct charbuf rb;
24 int fd, ret;
25
26 if((nm[0] == '.') || strchr(nm, '/'))
27 return((struct fileinfo){});
28 p = sprintf2("%s/%s", d->path, nm);
29 if(stat(p, &sb)) {
30 if(errno != ENOENT)
31 flog(LOG_WARNING, "fssrc: %s: %s", p, strerror(errno));
32 free(p);
33 return((struct fileinfo){});
34 }
35 if(!S_ISREG(sb.st_mode)) {
36 free(p);
37 return((struct fileinfo){});
38 }
39 if((fd = open(p, O_RDONLY)) < 0) {
40 flog(LOG_WARNING, "fssrc: %s: %s", p, strerror(errno));
41 free(p);
42 return((struct fileinfo){});
43 }
44 bufinit(rb);
45 sizebuf(rb, sb.st_size);
46 while(1) {
47 sizebuf(rb, 4096);
48 if((ret = read(fd, rb.b + rb.d, rb.s - rb.d)) < 0) {
49 flog(LOG_ERR, "fssrc: %s: %s", p, strerror(errno));
50 free(p);
51 buffree(rb);
52 close(fd);
53 return((struct fileinfo){});
54 }
55 if(ret == 0)
56 break;
57 rb.d += ret;
58 }
59 close(fd);
60 return((struct fileinfo){.mtime = sb.st_mtime, .sz = rb.d, .data = rb.b, .ctype = "image/png"});
61}
62
63struct source *mkfssrc(char *path)
64{
65 struct source *src;
66 struct fssrc *d;
67
68 omalloc(src);
69 src->serve = fsserve;
70 src->pdata = omalloc(d);
71 d->path = sstrdup(path);
72 return(src);
73}