commit 202234cf970182207ccb8fc7ee8df87a58fe63eb
parent 521ff6a11d535f61d28bce03c8fe1862c4b0236e
Author: Joris Vink <joris@coders.se>
Date: Thu, 28 Jun 2018 23:00:42 +0200
filemap and fileref improvements.
- make sure we can serve updated files even if we have an old
fileref around.
- add filemap_index as a configuration option: allows one to specify
what file to serve if a directory was requested (eg: index.html)
Diffstat:
5 files changed, 89 insertions(+), 13 deletions(-)
diff --git a/conf/kore.conf.example b/conf/kore.conf.example
@@ -68,6 +68,11 @@ workers 4
# NOTE: This file location must be inside your chrooted environment.
#rand_file random.data
+# Filemap settings
+# filemap_index Name of the file to be used as the directory
+# index for a filemap.
+#filemap_index index.html
+
# HTTP specific settings.
# http_header_max Maximum size of HTTP headers (in bytes).
#
diff --git a/include/kore/kore.h b/include/kore/kore.h
@@ -109,15 +109,18 @@ extern int daemon(int, int);
struct http_request;
#endif
+#define KORE_FILEREF_SOFT_REMOVED 0x1000
+
struct kore_fileref {
+ int fd;
int cnt;
+ int flags;
off_t size;
char *path;
+ time_t mtime;
u_int64_t expiration;
#if !defined(KORE_USE_PLATFORM_SENDFILE)
void *base;
-#else
- int fd;
#endif
TAILQ_ENTRY(kore_fileref) list;
};
@@ -641,13 +644,16 @@ void kore_msg_send(u_int16_t, u_int8_t, const void *, u_int32_t);
int kore_msg_register(u_int8_t,
void (*cb)(struct kore_msg *, const void *));
+#if !defined(KORE_NO_HTTP)
void kore_filemap_init(void);
int kore_filemap_create(struct kore_domain *, const char *,
const char *);
+extern char *kore_filemap_index;
+#endif
void kore_fileref_init(void);
struct kore_fileref *kore_fileref_get(const char *);
-struct kore_fileref *kore_fileref_create(const char *, int, off_t);
+struct kore_fileref *kore_fileref_create(const char *, int, off_t, time_t);
void kore_fileref_release(struct kore_fileref *);
void kore_domain_init(void);
diff --git a/src/config.c b/src/config.c
@@ -82,6 +82,7 @@ static int configure_dynamic_handler(char *);
static int configure_accesslog(char *);
static int configure_http_header_max(char *);
static int configure_http_body_max(char *);
+static int configure_filemap_index(char *);
static int configure_http_media_type(char *);
static int configure_http_hsts_enable(char *);
static int configure_http_keepalive_time(char *);
@@ -150,6 +151,7 @@ static struct {
#endif
#if !defined(KORE_NO_HTTP)
{ "filemap", configure_filemap },
+ { "filemap_index", configure_filemap_index },
{ "static", configure_static_handler },
{ "dynamic", configure_dynamic_handler },
{ "accesslog", configure_accesslog },
@@ -660,6 +662,15 @@ configure_accesslog(char *path)
}
static int
+configure_filemap_index(char *index)
+{
+ kore_free(kore_filemap_index);
+ kore_filemap_index = kore_strdup(index);
+
+ return (KORE_RESULT_OK);
+}
+
+static int
configure_http_media_type(char *type)
{
int i;
diff --git a/src/filemap.c b/src/filemap.c
@@ -42,6 +42,8 @@ static void filemap_serve(struct http_request *, struct filemap_entry *);
static TAILQ_HEAD(, filemap_entry) maps;
+char *kore_filemap_index = NULL;
+
void
kore_filemap_init(void)
{
@@ -124,7 +126,7 @@ filemap_serve(struct http_request *req, struct filemap_entry *map)
{
struct stat st;
struct kore_fileref *ref;
- int len, fd;
+ int len, fd, index;
char fpath[MAXPATHLEN];
len = snprintf(fpath, sizeof(fpath), "%s/%s", map->ondisk,
@@ -144,6 +146,11 @@ filemap_serve(struct http_request *req, struct filemap_entry *map)
return;
}
+ index = 0;
+
+lookup:
+ printf("path: %s\n", fpath);
+
if ((ref = kore_fileref_get(fpath)) == NULL) {
if ((fd = open(fpath, O_RDONLY | O_NOFOLLOW)) == -1) {
switch (errno) {
@@ -176,13 +183,27 @@ filemap_serve(struct http_request *req, struct filemap_entry *map)
}
/* kore_fileref_create() takes ownership of the fd. */
- ref = kore_fileref_create(fpath, fd, st.st_size);
+ ref = kore_fileref_create(fpath, fd,
+ st.st_size, st.st_mtime);
if (ref == NULL) {
http_response(req,
HTTP_STATUS_INTERNAL_ERROR, NULL, 0);
} else {
fd = -1;
}
+ } else if (S_ISDIR(st.st_mode) && index == 0) {
+ len = snprintf(fpath, sizeof(fpath),
+ "%s/%s%s", map->ondisk,
+ req->path + map->root_len,
+ kore_filemap_index != NULL ?
+ kore_filemap_index : "index.html");
+ if (len == -1 || (size_t)len >= sizeof(fpath)) {
+ http_response(req,
+ HTTP_STATUS_INTERNAL_ERROR, NULL, 0);
+ return;
+ }
+ index++;
+ goto lookup;
} else {
http_response(req, HTTP_STATUS_NOT_FOUND, NULL, 0);
}
diff --git a/src/fileref.c b/src/fileref.c
@@ -28,6 +28,7 @@
/* cached filerefs expire after 30 seconds of inactivity. */
#define FILEREF_EXPIRATION (1000 * 30)
+static void fileref_soft_remove(struct kore_fileref *);
static void fileref_expiration_check(void *, u_int64_t);
static TAILQ_HEAD(, kore_fileref) refs;
@@ -42,7 +43,7 @@ kore_fileref_init(void)
}
struct kore_fileref *
-kore_fileref_create(const char *path, int fd, off_t size)
+kore_fileref_create(const char *path, int fd, off_t size, time_t mtime)
{
struct kore_fileref *ref;
@@ -52,7 +53,10 @@ kore_fileref_create(const char *path, int fd, off_t size)
ref = kore_pool_get(&ref_pool);
ref->cnt = 1;
+ ref->fd = fd;
+ ref->flags = 0;
ref->size = size;
+ ref->mtime = mtime;
ref->path = kore_strdup(path);
#if !defined(KORE_USE_PLATFORM_SENDFILE)
@@ -64,9 +68,6 @@ kore_fileref_create(const char *path, int fd, off_t size)
fatal("net_send_file: mmap failed: %s", errno_s);
if (madvise(ref->base, (size_t)size, MADV_SEQUENTIAL) == -1)
fatal("net_send_file: madvise: %s", errno_s);
- close(fd);
-#else
- ref->fd = fd;
#endif
#if defined(FILEREF_DEBUG)
@@ -85,10 +86,23 @@ kore_fileref_create(const char *path, int fd, off_t size)
struct kore_fileref *
kore_fileref_get(const char *path)
{
+ struct stat st;
struct kore_fileref *ref;
TAILQ_FOREACH(ref, &refs, list) {
if (!strcmp(ref->path, path)) {
+ if (stat(ref->path, &st) == -1) {
+ kore_log(LOG_ERR, "stat(%s): %s",
+ ref->path, errno_s);
+ fileref_soft_remove(ref);
+ return (NULL);
+ }
+
+ if (st.st_mtime != ref->mtime) {
+ fileref_soft_remove(ref);
+ return (NULL);
+ }
+
ref->cnt++;
#if defined(FILEREF_DEBUG)
kore_log(LOG_DEBUG, "ref:%p cnt:%d",
@@ -127,6 +141,23 @@ kore_fileref_release(struct kore_fileref *ref)
}
static void
+fileref_soft_remove(struct kore_fileref *ref)
+{
+ TAILQ_REMOVE(&refs, ref, list);
+ ref->flags |= KORE_FILEREF_SOFT_REMOVED;
+
+ if (ref->cnt == 0) {
+ close(ref->fd);
+ kore_free(ref->path);
+
+#if !defined(KORE_USE_PLATFORM_SENDFILE)
+ (void)munmap(ref->base, ref->size);
+#endif
+ kore_pool_put(&ref_pool, ref);
+ }
+}
+
+static void
fileref_expiration_check(void *arg, u_int64_t now)
{
struct kore_fileref *ref, *next;
@@ -143,12 +174,14 @@ fileref_expiration_check(void *arg, u_int64_t now)
#if defined(FILEREF_DEBUG)
kore_log(LOG_DEBUG, "ref:%p expired, removing", (void *)ref);
#endif
- TAILQ_REMOVE(&refs, ref, list);
- kore_free(ref->path);
-#if defined(KORE_USE_PLATFORM_SENDFILE)
+ if (!(ref->flags & KORE_FILEREF_SOFT_REMOVED))
+ TAILQ_REMOVE(&refs, ref, list);
+
close(ref->fd);
-#else
+ kore_free(ref->path);
+
+#if !defined(KORE_USE_PLATFORM_SENDFILE)
(void)munmap(ref->base, ref->size);
#endif
kore_pool_put(&ref_pool, ref);