summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2019-05-09 21:09:52 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2019-05-09 21:09:52 -0400
commit146ea6bad0c04a582652d603bd954f10c4a8b83d (patch)
tree683eda1a374b94427be3c581a128b8d8c1007e0b
parentdd3d20c3d056fca1ce7b3019b9f99bf51c09a1e4 (diff)
downloadlighttpd1.4-146ea6bad0c04a582652d603bd954f10c4a8b83d.tar.gz
lighttpd1.4-146ea6bad0c04a582652d603bd954f10c4a8b83d.zip
[mod_webdav] invalidate parent dir in stat_cache
invalidate directory in stat_cache when a new file or dir is created within that directory
-rw-r--r--src/mod_webdav.c46
-rw-r--r--src/stat_cache.c7
-rw-r--r--src/stat_cache.h1
3 files changed, 42 insertions, 12 deletions
diff --git a/src/mod_webdav.c b/src/mod_webdav.c
index adbb6956..5ac16ca0 100644
--- a/src/mod_webdav.c
+++ b/src/mod_webdav.c
@@ -2146,8 +2146,10 @@ webdav_if_match_or_unmodified_since (connection * const con, struct stat *st)
static void
-webdav_response_etag (server *srv, connection * const con, struct stat *st)
+webdav_response_etag (const plugin_config * const pconf,
+ connection * const con, struct stat *st)
{
+ server *srv = pconf->srv;
if (0 != con->etag_flags) {
buffer *etagb = con->physical.etag;
etag_create(etagb, st, con->etag_flags);
@@ -2157,6 +2159,23 @@ webdav_response_etag (server *srv, connection * const con, struct stat *st)
CONST_STR_LEN("ETag"),
CONST_BUF_LEN(etagb));
}
+ else {
+ stat_cache_update_entry(srv,CONST_BUF_LEN(con->physical.path),st,NULL);
+ }
+}
+
+
+static void
+webdav_parent_modified (const plugin_config * const pconf, const buffer *path)
+{
+ size_t dirlen = buffer_string_length(path);
+ const char *fn = path->ptr;
+ /*force_assert(0 != dirlen);*/
+ /*force_assert(fn[0] == '/');*/
+ if (fn[dirlen-1] == '/') --dirlen;
+ if (0 != dirlen) while (fn[--dirlen] != '/') ;
+ if (0 == dirlen) dirlen = 1; /* root dir ("/") */
+ stat_cache_invalidate_entry(pconf->srv, fn, dirlen);
}
@@ -2502,8 +2521,10 @@ webdav_mkdir (const plugin_config * const pconf,
const physical_st * const dst,
const int overwrite)
{
- if (0 == mkdir(dst->path->ptr, WEBDAV_DIR_MODE))
+ if (0 == mkdir(dst->path->ptr, WEBDAV_DIR_MODE)) {
+ webdav_parent_modified(pconf, dst->path);
return 0;
+ }
switch (errno) {
case EEXIST:
@@ -2549,6 +2570,7 @@ webdav_mkdir (const plugin_config * const pconf,
if (0 != status)
return status;
+ webdav_parent_modified(pconf, dst->path);
return (0 == mkdir(dst->path->ptr, WEBDAV_DIR_MODE))
? 0
: 409; /* Conflict */
@@ -4147,9 +4169,10 @@ mod_webdav_put_0 (connection * const con, const plugin_config * const pconf)
if (0 != con->etag_flags) {
/*(skip sending etag if fstat() error; not expected)*/
struct stat st;
- if (0 == fstat(fd, &st)) webdav_response_etag(pconf->srv, con, &st);
+ if (0 == fstat(fd, &st)) webdav_response_etag(pconf, con, &st);
}
close(fd);
+ webdav_parent_modified(pconf, con->physical.path);
http_status_set_fin(con, 201); /* Created */
return HANDLER_FINISHED;
}
@@ -4285,6 +4308,8 @@ mod_webdav_put_linkat_rename (connection * const con,
http_status_set_fin(con, 0 == lstat(con->physical.path->ptr, &st)
? 204 /* No Content */
: 201); /* Created */
+ if (201 == http_status_get(con))
+ webdav_parent_modified(pconf, con->physical.path);
if (0 != rename(pathtemp, con->physical.path->ptr))
#endif
{
@@ -4298,7 +4323,7 @@ mod_webdav_put_linkat_rename (connection * const con,
if (0 != con->etag_flags && http_status_get(con) < 300) { /*(201, 204)*/
/*(skip sending etag if fstat() error; not expected)*/
if (0 == fstat(c->file.fd, &st))
- webdav_response_etag(pconf->srv, con, &st);
+ webdav_response_etag(pconf, con, &st);
}
chunkqueue_mark_written(cq, c->file.length);
@@ -4364,7 +4389,7 @@ mod_webdav_put_deprecated_unsafe_partial_put_compat (connection * const con,
if (!http_status_is_set(con)) {
http_status_set_fin(con, 204); /* No Content */
- if (0 != con->etag_flags) webdav_response_etag(pconf->srv, con, &st);
+ if (0 != con->etag_flags) webdav_response_etag(pconf, con, &st);
}
return HANDLER_FINISHED;
@@ -4482,8 +4507,10 @@ mod_webdav_put (connection * const con, const plugin_config * const pconf)
http_status_set_fin(con, 0 == lstat(con->physical.path->ptr, &ste)
? 204 /* No Content */
: 201); /* Created */
+ if (201 == http_status_get(con))
+ webdav_parent_modified(pconf, con->physical.path);
if (0 == rename(pathtemp, con->physical.path->ptr)) {
- if (0 != con->etag_flags) webdav_response_etag(pconf->srv,con,&st);
+ if (0 != con->etag_flags) webdav_response_etag(pconf, con, &st);
}
else {
if (errno == EISDIR)
@@ -4836,8 +4863,10 @@ mod_webdav_copymove_b (connection * const con, const plugin_config * const pconf
if (0 == lstat(dst_path->ptr, &st) && S_ISDIR(st.st_mode)) {
*slash = '/';
/* new entity will be created */
- if (!http_status_is_set(con))
+ if (!http_status_is_set(con)) {
+ webdav_parent_modified(pconf, dst_path);
http_status_set_fin(con, 201); /* Created */
+ }
break;
}
}
@@ -5306,6 +5335,7 @@ mod_webdav_lock (connection * const con, const plugin_config * const pconf)
if (0 != fstat(fd, &st)) con->etag_flags = 0;
close(fd);
created = 1;
+ webdav_parent_modified(pconf, con->physical.path);
}
else if (errno != EEXIST) {
http_status_set_error(con, 403); /* Forbidden */
@@ -5364,7 +5394,7 @@ mod_webdav_lock (connection * const con, const plugin_config * const pconf)
lockstr, sizeof(lockstr)-1);
webdav_xml_doc_lock_acquired(con, pconf, &lockdata);
if (0 != con->etag_flags && !S_ISDIR(st.st_mode))
- webdav_response_etag(pconf->srv, con, &st);
+ webdav_response_etag(pconf, con, &st);
http_status_set_fin(con, created ? 201 : 200); /* Created | OK */
}
else /*(database error obtaining lock)*/
diff --git a/src/stat_cache.c b/src/stat_cache.c
index cc84ec24..eeef8d29 100644
--- a/src/stat_cache.c
+++ b/src/stat_cache.c
@@ -240,7 +240,6 @@ static void fam_dir_invalidate_tree(splay_tree *t, const char *name, size_t len)
/* declarations */
static void stat_cache_delete_tree(server *srv, const char *name, size_t len);
-static void stat_cache_invalidate_entry(server *srv, const char *name, size_t len);
static void stat_cache_invalidate_dir_tree(server *srv, const char *name, size_t len);
static void stat_cache_handle_fdevent_in(server *srv, stat_cache_fam *scf)
@@ -751,9 +750,7 @@ void stat_cache_delete_entry(server *srv, const char *name, size_t len)
}
}
-#ifdef HAVE_FAM_H
-
-static void stat_cache_invalidate_entry(server *srv, const char *name, size_t len)
+void stat_cache_invalidate_entry(server *srv, const char *name, size_t len)
{
splay_tree **sptree = &srv->stat_cache->files;
stat_cache_entry *sce = stat_cache_sptree_find(sptree, name, len);
@@ -768,6 +765,8 @@ static void stat_cache_invalidate_entry(server *srv, const char *name, size_t le
}
}
+#ifdef HAVE_FAM_H
+
static void stat_cache_invalidate_dir_tree_walk(splay_tree *t,
const char *name, size_t len)
{
diff --git a/src/stat_cache.h b/src/stat_cache.h
index f0c532b9..8ff9016b 100644
--- a/src/stat_cache.h
+++ b/src/stat_cache.h
@@ -42,6 +42,7 @@ const buffer * stat_cache_etag_get(stat_cache_entry *sce, etag_flags_t flags);
void stat_cache_update_entry(server *srv, const char *name, size_t len, struct stat *st, buffer *etagb);
void stat_cache_delete_entry(server *srv, const char *name, size_t len);
void stat_cache_delete_dir(server *srv, const char *name, size_t len);
+void stat_cache_invalidate_entry(server *srv, const char *name, size_t len);
handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **sce);
int stat_cache_path_contains_symlink(server *srv, buffer *name);
int stat_cache_open_rdonly_fstat (buffer *name, struct stat *st, int symlinks);