bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "lib.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "array.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "bsearch-insert-pos.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "ioloop.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "str.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "strescape.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "file-dotlock.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "ostream.h"
15f43b172d2c626aa03c921979c49821a55c7e5eTimo Sirainen#include "mail-storage.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "acl-cache.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include "acl-backend-vfile.h"
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen#include <utime.h>
15f43b172d2c626aa03c921979c49821a55c7e5eTimo Sirainen#include <sys/stat.h>
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainenstatic struct dotlock_settings dotlock_set = {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen .timeout = 30,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen .stale_timeout = 120
cc287b822b175619a853686b738ba673e370117bTimo Sirainen};
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainenstatic int acl_backend_vfile_update_begin(struct acl_object_vfile *aclobj,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct dotlock **dotlock_r)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen{
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct acl_object *_aclobj = &aclobj->aclobj;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct mailbox_permissions perm;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen int fd;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (aclobj->local_path == NULL) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen i_error("Can't update acl object '%s': No local acl file path",
cc287b822b175619a853686b738ba673e370117bTimo Sirainen aclobj->aclobj.name);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return -1;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* first lock the ACL file */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen mailbox_list_get_permissions(_aclobj->backend->list,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen _aclobj->name, &perm);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen fd = file_dotlock_open_group(&dotlock_set, aclobj->local_path, 0,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen perm.file_create_mode,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen perm.file_create_gid,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen perm.file_create_gid_origin, dotlock_r);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (fd == -1) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen i_error("file_dotlock_open(%s) failed: %m", aclobj->local_path);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return -1;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* locked successfully, re-read the existing file to make sure we
cc287b822b175619a853686b738ba673e370117bTimo Sirainen don't lose any changes. */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen acl_cache_flush(_aclobj->backend->cache, _aclobj->name);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (_aclobj->backend->v.object_refresh_cache(_aclobj) < 0) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen file_dotlock_delete(dotlock_r);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return -1;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return fd;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen}
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainenstatic bool
086c52e4bcdc950e47ee331e1e07c9c10982a670Timo Sirainenvfile_object_modify_right(struct acl_object *aclobj, unsigned int idx,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen const struct acl_rights_update *update)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen{
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct acl_rights *right;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen bool c1, c2;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen right = array_idx_modifiable(&aclobj->rights, idx);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen c1 = acl_right_names_modify(aclobj->rights_pool, &right->rights,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->rights.rights, update->modify_mode);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen c2 = acl_right_names_modify(aclobj->rights_pool, &right->neg_rights,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->rights.neg_rights,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->neg_modify_mode);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (right->rights == NULL && right->neg_rights == NULL) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* this identifier no longer exists */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen array_delete(&aclobj->rights, idx, 1);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen c1 = TRUE;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return c1 || c2;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen}
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainenstatic bool
086c52e4bcdc950e47ee331e1e07c9c10982a670Timo Sirainenvfile_object_add_right(struct acl_object *aclobj, unsigned int idx,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen const struct acl_rights_update *update)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen{
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct acl_rights right;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen bool c1, c2;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (update->modify_mode == ACL_MODIFY_MODE_REMOVE &&
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->neg_modify_mode == ACL_MODIFY_MODE_REMOVE) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* nothing to do */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return FALSE;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&right);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen right.id_type = update->rights.id_type;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen right.identifier = p_strdup(aclobj->rights_pool,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->rights.identifier);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen c1 = acl_right_names_modify(aclobj->rights_pool, &right.rights,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->rights.rights, update->modify_mode);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen c2 = acl_right_names_modify(aclobj->rights_pool, &right.neg_rights,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->rights.neg_rights,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->neg_modify_mode);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (c1 || c2) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen array_insert(&aclobj->rights, idx, &right, 1);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return TRUE;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return FALSE;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen}
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainenstatic void
cc287b822b175619a853686b738ba673e370117bTimo Sirainenvfile_write_right(string_t *dest, const struct acl_rights *right,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen bool neg)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen{
cc287b822b175619a853686b738ba673e370117bTimo Sirainen const char *const *rights = neg ? right->neg_rights : right->rights;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (neg) str_append_c(dest,'-');
cc287b822b175619a853686b738ba673e370117bTimo Sirainen acl_rights_write_id(dest, right);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (strchr(str_c(dest), ' ') != NULL) T_BEGIN {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* need to escape it */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen const char *escaped = t_strdup(str_escape(str_c(dest)));
cc287b822b175619a853686b738ba673e370117bTimo Sirainen str_truncate(dest, 0);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen str_printfa(dest, "\"%s\"", escaped);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen } T_END;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen str_append_c(dest, ' ');
cc287b822b175619a853686b738ba673e370117bTimo Sirainen acl_right_names_write(dest, rights);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen str_append_c(dest, '\n');
cc287b822b175619a853686b738ba673e370117bTimo Sirainen}
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainenstatic int
086c52e4bcdc950e47ee331e1e07c9c10982a670Timo Sirainenacl_backend_vfile_update_write(struct acl_object *aclobj,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen int fd, const char *path)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen{
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct ostream *output;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen string_t *str;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen const struct acl_rights *rights;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen unsigned int i, count;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen int ret = 0;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen output = o_stream_create_fd_file(fd, 0, FALSE);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen o_stream_cork(output);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen str = str_new(default_pool, 256);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* rights are sorted with globals at the end, so we can stop at the
cc287b822b175619a853686b738ba673e370117bTimo Sirainen first global */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen rights = array_get(&aclobj->rights, &count);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen for (i = 0; i < count && !rights[i].global; i++) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (rights[i].rights != NULL) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen vfile_write_right(str, &rights[i], FALSE);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
cc287b822b175619a853686b738ba673e370117bTimo Sirainen str_truncate(str, 0);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (rights[i].neg_rights != NULL) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen vfile_write_right(str, &rights[i], TRUE);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
cc287b822b175619a853686b738ba673e370117bTimo Sirainen str_truncate(str, 0);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen str_free(&str);
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen if (o_stream_finish(output) < 0) {
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen i_error("write(%s) failed: %s", path,
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen o_stream_get_error(output));
cc287b822b175619a853686b738ba673e370117bTimo Sirainen ret = -1;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen o_stream_destroy(&output);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* we really don't want to lose ACL files' contents, so fsync() always
cc287b822b175619a853686b738ba673e370117bTimo Sirainen before renaming */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (fsync(fd) < 0) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen i_error("fsync(%s) failed: %m", path);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen ret = -1;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return ret;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen}
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainenstatic void acl_backend_vfile_update_cache(struct acl_object *_aclobj, int fd)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen{
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct acl_backend_vfile_validity *validity;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct stat st;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (fstat(fd, &st) < 0) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* we'll just recalculate or fail it later */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen acl_cache_flush(_aclobj->backend->cache, _aclobj->name);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen validity = acl_cache_get_validity(_aclobj->backend->cache,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen _aclobj->name);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen validity->local_validity.last_read_time = ioloop_time;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen validity->local_validity.last_mtime = st.st_mtime;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen validity->local_validity.last_size = st.st_size;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen}
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainenint acl_backend_vfile_object_update(struct acl_object *_aclobj,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen const struct acl_rights_update *update)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen{
086c52e4bcdc950e47ee331e1e07c9c10982a670Timo Sirainen struct acl_object_vfile *aclobj =
086c52e4bcdc950e47ee331e1e07c9c10982a670Timo Sirainen (struct acl_object_vfile *)_aclobj;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct acl_backend_vfile *backend =
cc287b822b175619a853686b738ba673e370117bTimo Sirainen (struct acl_backend_vfile *)_aclobj->backend;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct acl_backend_vfile_validity *validity;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct dotlock *dotlock;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen struct utimbuf ut;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen time_t orig_mtime;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen const char *path;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen unsigned int i;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen int fd;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen bool changed;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* global ACLs can't be updated here */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen i_assert(!update->rights.global);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen fd = acl_backend_vfile_update_begin(aclobj, &dotlock);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (fd == -1)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return -1;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
086c52e4bcdc950e47ee331e1e07c9c10982a670Timo Sirainen if (!array_bsearch_insert_pos(&_aclobj->rights, &update->rights,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen acl_rights_cmp, &i))
086c52e4bcdc950e47ee331e1e07c9c10982a670Timo Sirainen changed = vfile_object_add_right(_aclobj, i, update);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen else
086c52e4bcdc950e47ee331e1e07c9c10982a670Timo Sirainen changed = vfile_object_modify_right(_aclobj, i, update);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (!changed) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen file_dotlock_delete(&dotlock);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return 0;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen validity = acl_cache_get_validity(_aclobj->backend->cache,
cc287b822b175619a853686b738ba673e370117bTimo Sirainen _aclobj->name);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen orig_mtime = validity->local_validity.last_mtime;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* ACLs were really changed, write the new ones */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen path = file_dotlock_get_lock_path(dotlock);
086c52e4bcdc950e47ee331e1e07c9c10982a670Timo Sirainen if (acl_backend_vfile_update_write(_aclobj, fd, path) < 0) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen file_dotlock_delete(&dotlock);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen acl_cache_flush(_aclobj->backend->cache, _aclobj->name);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return -1;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (orig_mtime < update->last_change && update->last_change != 0) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* set mtime to last_change, if it's higher than the file's
cc287b822b175619a853686b738ba673e370117bTimo Sirainen original mtime. if original mtime is higher, then we're
cc287b822b175619a853686b738ba673e370117bTimo Sirainen merging some changes and it's better for the mtime to get
cc287b822b175619a853686b738ba673e370117bTimo Sirainen updated. */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen ut.actime = ioloop_time;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen ut.modtime = update->last_change;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (utime(path, &ut) < 0)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen i_error("utime(%s) failed: %m", path);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen acl_backend_vfile_update_cache(_aclobj, fd);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (file_dotlock_replace(&dotlock, 0) < 0) {
cc287b822b175619a853686b738ba673e370117bTimo Sirainen acl_cache_flush(_aclobj->backend->cache, _aclobj->name);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return -1;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen }
cc287b822b175619a853686b738ba673e370117bTimo Sirainen /* make sure dovecot-acl-list gets updated if we changed any
cc287b822b175619a853686b738ba673e370117bTimo Sirainen lookup rights. */
cc287b822b175619a853686b738ba673e370117bTimo Sirainen if (acl_rights_has_nonowner_lookup_changes(&update->rights) ||
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->modify_mode == ACL_MODIFY_MODE_REPLACE ||
cc287b822b175619a853686b738ba673e370117bTimo Sirainen update->modify_mode == ACL_MODIFY_MODE_CLEAR)
cc287b822b175619a853686b738ba673e370117bTimo Sirainen (void)acl_backend_vfile_acllist_rebuild(backend);
cc287b822b175619a853686b738ba673e370117bTimo Sirainen return 0;
cc287b822b175619a853686b738ba673e370117bTimo Sirainen}