Browse Source

[mod_webdav] update stat_cache after file mod

update stat_cache entries after file modifications (PUT)
invalidate stat_cache entries after file movement (COPY MOVE DELETE)
personal/stbuehler/ci-build
Glenn Strauss 3 years ago
parent
commit
311f258ab3
  1. 51
      src/mod_webdav.c

51
src/mod_webdav.c

@ -2148,11 +2148,12 @@ webdav_if_match_or_unmodified_since (connection * const con, struct stat *st)
static void
webdav_response_etag (connection * const con, struct stat *st)
webdav_response_etag (server *srv, connection * const con, struct stat *st)
{
if (0 != con->etag_flags) {
buffer *etagb = con->physical.etag;
etag_create(etagb, st, con->etag_flags);
stat_cache_update_entry(srv,CONST_BUF_LEN(con->physical.path),st,etagb);
etag_mutate(etagb, etagb);
http_header_response_set(con, HTTP_HEADER_ETAG,
CONST_STR_LEN("ETag"),
@ -2184,10 +2185,12 @@ webdav_parse_Depth (connection * const con)
static int
webdav_unlinkat (const plugin_config * const pconf, const buffer * const uri,
const int dfd, const char * const d_name)
const int dfd, const char * const d_name, size_t len)
{
if (0 == unlinkat(dfd, d_name, 0))
if (0 == unlinkat(dfd, d_name, 0)) {
stat_cache_delete_entry(pconf->srv, d_name, len);
return webdav_prop_delete_uri(pconf, uri);
}
switch(errno) {
case EACCES: case EPERM: return 403; /* Forbidden */
@ -2201,8 +2204,10 @@ static int
webdav_delete_file (const plugin_config * const pconf,
const physical_st * const dst)
{
if (0 == unlink(dst->path->ptr))
if (0 == unlink(dst->path->ptr)) {
stat_cache_delete_entry(pconf->srv, CONST_BUF_LEN(dst->path));
return webdav_prop_delete_uri(pconf, dst->rel_path);
}
switch(errno) {
case EACCES: case EPERM: return 403; /* Forbidden */
@ -2265,7 +2270,8 @@ webdav_delete_dir (const plugin_config * const pconf,
multi_status |= webdav_delete_dir(pconf, dst, b, flags);
}
else {
int status = webdav_unlinkat(pconf, dst->rel_path, dfd, de->d_name);
int status =
webdav_unlinkat(pconf, dst->rel_path, dfd, de->d_name, len);
if (0 != status) {
webdav_xml_response_status(b, dst->rel_path, status);
multi_status = 1;
@ -2398,7 +2404,12 @@ webdav_copytmp_rename (const plugin_config * const pconf,
AT_FDCWD, dst->path->ptr,
overwrite ? 0 : RENAME_NOREPLACE))
#endif
{
/* unconditional stat cache deletion
* (not worth extra syscall/race to detect overwritten or not) */
stat_cache_delete_entry(pconf->srv, CONST_BUF_LEN(dst->path));
return 0;
}
else {
const int errnum = errno;
unlink(tmpb->ptr);
@ -2447,6 +2458,10 @@ webdav_copymove_file (const plugin_config * const pconf,
* though unlikely if locks are used since locks have not yet been
* released. */
if (overwrite) unlink(src->path->ptr);
/* unconditional stat cache deletion
* (not worth extra syscall/race to detect overwritten or not) */
stat_cache_delete_entry(pconf->srv, CONST_BUF_LEN(dst->path));
stat_cache_delete_entry(pconf->srv, CONST_BUF_LEN(src->path));
webdav_prop_move_uri(pconf, src->rel_path, dst->rel_path);
return 0;
}
@ -3976,6 +3991,8 @@ mod_webdav_delete (connection * const con, const plugin_config * const pconf)
}
buffer_free(ms);
/* invalidate stat cache of src if DELETE, whether or not successful */
stat_cache_delete_dir(pconf->srv, CONST_BUF_LEN(con->physical.path));
}
else if (con->physical.path->ptr[con->physical.path->used - 2] == '/')
http_status_set_error(con, 403);
@ -4120,7 +4137,7 @@ 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(con, &st);
if (0 == fstat(fd, &st)) webdav_response_etag(pconf->srv, con, &st);
}
close(fd);
http_status_set_fin(con, 201); /* Created */
@ -4236,6 +4253,7 @@ mod_webdav_put_prep (connection * const con, const plugin_config * const pconf)
#if (defined(__linux__) || defined(__CYGWIN__)) && defined(O_TMPFILE)
static int
mod_webdav_put_linkat_rename (connection * const con,
const plugin_config * const pconf,
const char * const pathtemp)
{
chunkqueue * const cq = con->request_content_queue;
@ -4269,7 +4287,8 @@ 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(con, &st);
if (0 == fstat(c->file.fd, &st))
webdav_response_etag(pconf->srv, con, &st);
}
chunkqueue_mark_written(cq, c->file.length);
@ -4284,7 +4303,9 @@ mod_webdav_put_linkat_rename (connection * const con,
__attribute_cold__
static handler_t
mod_webdav_put_deprecated_unsafe_partial_put_compat (connection * const con, const buffer * const h)
mod_webdav_put_deprecated_unsafe_partial_put_compat (connection * const con,
const plugin_config *pconf,
const buffer * const h)
{
/* historical code performed very limited range parse (repeated here) */
/* we only support <num>- ... */
@ -4333,7 +4354,7 @@ mod_webdav_put_deprecated_unsafe_partial_put_compat (connection * const con, con
if (!http_status_is_set(con)) {
http_status_set_fin(con, 204); /* No Content */
if (0 != con->etag_flags) webdav_response_etag(con, &st);
if (0 != con->etag_flags) webdav_response_etag(pconf->srv, con, &st);
}
return HANDLER_FINISHED;
@ -4366,7 +4387,8 @@ mod_webdav_put (connection * const con, const plugin_config * const pconf)
http_header_request_get(con, HTTP_HEADER_OTHER,
CONST_STR_LEN("Content-Range"));
if (NULL != h)
return mod_webdav_put_deprecated_unsafe_partial_put_compat(con, h);
return
mod_webdav_put_deprecated_unsafe_partial_put_compat(con,pconf,h);
}
/* construct temporary filename in same directory as target
@ -4415,7 +4437,7 @@ mod_webdav_put (connection * const con, const plugin_config * const pconf)
if (!mod_webdav_write_single_file_chunk(con, cq))
return HANDLER_FINISHED;
}
if (mod_webdav_put_linkat_rename(con, pathtemp))
if (mod_webdav_put_linkat_rename(con, pconf, pathtemp))
return HANDLER_FINISHED;
/* attempt traditional copy (below) if linkat() failed for any reason */
}
@ -4451,7 +4473,7 @@ mod_webdav_put (connection * const con, const plugin_config * const pconf)
? 204 /* No Content */
: 201); /* Created */
if (0 == rename(pathtemp, con->physical.path->ptr)) {
if (0 != con->etag_flags) webdav_response_etag(con, &st);
if (0 != con->etag_flags) webdav_response_etag(pconf->srv,con,&st);
}
else {
if (errno == EISDIR)
@ -4745,6 +4767,9 @@ mod_webdav_copymove_b (connection * const con, const plugin_config * const pconf
webdav_xml_doc_multistatus(con, pconf, ms); /* 207 Multi-status */
}
buffer_free(ms);
/* invalidate stat cache of src if MOVE, whether or not successful */
if (con->request.http_method == HTTP_METHOD_MOVE)
stat_cache_delete_dir(pconf->srv,CONST_BUF_LEN(con->physical.path));
return HANDLER_FINISHED;
}
else if (con->physical.path->ptr[con->physical.path->used - 2] == '/') {
@ -5307,7 +5332,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(con, &st);
webdav_response_etag(pconf->srv, con, &st);
http_status_set_fin(con, created ? 201 : 200); /* Created | OK */
}
else /*(database error obtaining lock)*/

Loading…
Cancel
Save