script/autobuild.py: add support git worktree
[Samba.git] / source3 / locking / locking.c
blob2d9569809e44f666feac52d6383d1c56d6576542
1 /*
2 Unix SMB/CIFS implementation.
3 Locking functions
4 Copyright (C) Andrew Tridgell 1992-2000
5 Copyright (C) Jeremy Allison 1992-2006
6 Copyright (C) Volker Lendecke 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 Revision History:
23 12 aug 96: Erik.Devriendt@te6.siemens.be
24 added support for shared memory implementation of share mode locking
26 May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27 locking to deal with multiple share modes per open file.
29 September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
30 support.
32 rewritten completely to use new tdb code. Tridge, Dec '99
34 Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
35 Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
38 #include "includes.h"
39 #include "lib/util/time_basic.h"
40 #include "system/filesys.h"
41 #include "lib/util/server_id.h"
42 #include "locking/proto.h"
43 #include "smbd/globals.h"
44 #include "dbwrap/dbwrap.h"
45 #include "dbwrap/dbwrap_open.h"
46 #include "../libcli/security/security.h"
47 #include "serverid.h"
48 #include "messages.h"
49 #include "util_tdb.h"
50 #include "../librpc/gen_ndr/ndr_open_files.h"
51 #include "librpc/gen_ndr/ndr_file_id.h"
52 #include "librpc/gen_ndr/ndr_leases_db.h"
53 #include "locking/leases_db.h"
55 #undef DBGC_CLASS
56 #define DBGC_CLASS DBGC_LOCKING
58 #define NO_LOCKING_COUNT (-1)
60 /****************************************************************************
61 Debugging aids :-).
62 ****************************************************************************/
64 const char *lock_type_name(enum brl_type lock_type)
66 switch (lock_type) {
67 case READ_LOCK:
68 return "READ";
69 case WRITE_LOCK:
70 return "WRITE";
71 default:
72 return "other";
76 const char *lock_flav_name(enum brl_flavour lock_flav)
78 return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
81 /****************************************************************************
82 Utility function called to see if a file region is locked.
83 Called in the read/write codepath.
84 ****************************************************************************/
86 void init_strict_lock_struct(files_struct *fsp,
87 uint64_t smblctx,
88 br_off start,
89 br_off size,
90 enum brl_type lock_type,
91 struct lock_struct *plock)
93 SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
95 plock->context.smblctx = smblctx;
96 plock->context.tid = fsp->conn->cnum;
97 plock->context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
98 plock->start = start;
99 plock->size = size;
100 plock->fnum = fsp->fnum;
101 plock->lock_type = lock_type;
102 plock->lock_flav = lp_posix_cifsu_locktype(fsp);
105 bool strict_lock_check_default(files_struct *fsp, struct lock_struct *plock)
107 struct byte_range_lock *br_lck;
108 int strict_locking = lp_strict_locking(fsp->conn->params);
109 bool ret = False;
111 if (plock->size == 0) {
112 return True;
115 if (!lp_locking(fsp->conn->params) || !strict_locking) {
116 return True;
119 if (strict_locking == Auto) {
120 uint32_t lease_type = fsp_lease_type(fsp);
122 if ((lease_type & SMB2_LEASE_READ) &&
123 (plock->lock_type == READ_LOCK))
125 DBG_DEBUG("optimisation - read lease on file %s\n",
126 fsp_str_dbg(fsp));
127 return true;
130 if ((lease_type & SMB2_LEASE_WRITE) &&
131 (plock->lock_type == WRITE_LOCK))
133 DBG_DEBUG("optimisation - write lease on file %s\n",
134 fsp_str_dbg(fsp));
135 return true;
139 br_lck = brl_get_locks_readonly(fsp);
140 if (!br_lck) {
141 return true;
143 ret = brl_locktest(br_lck, plock);
145 if (!ret) {
147 * We got a lock conflict. Retry with rw locks to enable
148 * autocleanup. This is the slow path anyway.
150 br_lck = brl_get_locks(talloc_tos(), fsp);
151 if (br_lck == NULL) {
152 return true;
154 ret = brl_locktest(br_lck, plock);
155 TALLOC_FREE(br_lck);
158 DEBUG(10, ("strict_lock_default: flavour = %s brl start=%ju "
159 "len=%ju %s for fnum %ju file %s\n",
160 lock_flav_name(plock->lock_flav),
161 (uintmax_t)plock->start, (uintmax_t)plock->size,
162 ret ? "unlocked" : "locked",
163 (uintmax_t)plock->fnum, fsp_str_dbg(fsp)));
165 return ret;
168 /****************************************************************************
169 Find out if a lock could be granted - return who is blocking us if we can't.
170 ****************************************************************************/
172 NTSTATUS query_lock(files_struct *fsp,
173 uint64_t *psmblctx,
174 uint64_t *pcount,
175 uint64_t *poffset,
176 enum brl_type *plock_type,
177 enum brl_flavour lock_flav)
179 struct byte_range_lock *br_lck = NULL;
181 if (!fsp->can_lock) {
182 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
185 if (!lp_locking(fsp->conn->params)) {
186 return NT_STATUS_OK;
189 br_lck = brl_get_locks_readonly(fsp);
190 if (!br_lck) {
191 return NT_STATUS_NO_MEMORY;
194 return brl_lockquery(br_lck,
195 psmblctx,
196 messaging_server_id(fsp->conn->sconn->msg_ctx),
197 poffset,
198 pcount,
199 plock_type,
200 lock_flav);
203 static void increment_current_lock_count(files_struct *fsp,
204 enum brl_flavour lock_flav)
206 if (lock_flav == WINDOWS_LOCK &&
207 fsp->current_lock_count != NO_LOCKING_COUNT) {
208 /* blocking ie. pending, locks also count here,
209 * as this is an efficiency counter to avoid checking
210 * the lock db. on close. JRA. */
212 fsp->current_lock_count++;
213 } else {
214 /* Notice that this has had a POSIX lock request.
215 * We can't count locks after this so forget them.
217 fsp->current_lock_count = NO_LOCKING_COUNT;
221 static void decrement_current_lock_count(files_struct *fsp,
222 enum brl_flavour lock_flav)
224 if (lock_flav == WINDOWS_LOCK &&
225 fsp->current_lock_count != NO_LOCKING_COUNT) {
226 SMB_ASSERT(fsp->current_lock_count > 0);
227 fsp->current_lock_count--;
231 /****************************************************************************
232 Utility function called by locking requests.
233 ****************************************************************************/
235 struct do_lock_state {
236 struct files_struct *fsp;
237 TALLOC_CTX *req_mem_ctx;
238 const struct GUID *req_guid;
239 uint64_t smblctx;
240 uint64_t count;
241 uint64_t offset;
242 enum brl_type lock_type;
243 enum brl_flavour lock_flav;
245 struct server_id blocker_pid;
246 uint64_t blocker_smblctx;
247 NTSTATUS status;
250 static void do_lock_fn(
251 TDB_DATA value,
252 bool *modified_dependent,
253 void *private_data)
255 struct do_lock_state *state = private_data;
256 struct byte_range_lock *br_lck = NULL;
258 br_lck = brl_get_locks_for_locking(talloc_tos(),
259 state->fsp,
260 state->req_mem_ctx,
261 state->req_guid);
262 if (br_lck == NULL) {
263 state->status = NT_STATUS_NO_MEMORY;
264 return;
267 state->status = brl_lock(
268 br_lck,
269 state->smblctx,
270 messaging_server_id(state->fsp->conn->sconn->msg_ctx),
271 state->offset,
272 state->count,
273 state->lock_type,
274 state->lock_flav,
275 &state->blocker_pid,
276 &state->blocker_smblctx);
278 TALLOC_FREE(br_lck);
281 NTSTATUS do_lock(files_struct *fsp,
282 TALLOC_CTX *req_mem_ctx,
283 const struct GUID *req_guid,
284 uint64_t smblctx,
285 uint64_t count,
286 uint64_t offset,
287 enum brl_type lock_type,
288 enum brl_flavour lock_flav,
289 struct server_id *pblocker_pid,
290 uint64_t *psmblctx)
292 struct do_lock_state state = {
293 .fsp = fsp,
294 .req_mem_ctx = req_mem_ctx,
295 .req_guid = req_guid,
296 .smblctx = smblctx,
297 .count = count,
298 .offset = offset,
299 .lock_type = lock_type,
300 .lock_flav = lock_flav,
302 NTSTATUS status;
304 /* silently return ok on print files as we don't do locking there */
305 if (fsp->print_file) {
306 return NT_STATUS_OK;
309 if (!fsp->can_lock) {
310 if (fsp->is_directory) {
311 return NT_STATUS_INVALID_DEVICE_REQUEST;
313 return NT_STATUS_INVALID_HANDLE;
316 if (!lp_locking(fsp->conn->params)) {
317 return NT_STATUS_OK;
320 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
322 DBG_DEBUG("lock flavour %s lock type %s start=%"PRIu64" len=%"PRIu64" "
323 "requested for %s file %s\n",
324 lock_flav_name(lock_flav),
325 lock_type_name(lock_type),
326 offset,
327 count,
328 fsp_fnum_dbg(fsp),
329 fsp_str_dbg(fsp));
331 status = share_mode_do_locked(fsp->file_id, do_lock_fn, &state);
332 if (!NT_STATUS_IS_OK(status)) {
333 DBG_DEBUG("share_mode_do_locked returned %s\n",
334 nt_errstr(status));
335 return status;
338 if (psmblctx != NULL) {
339 *psmblctx = state.blocker_smblctx;
341 if (pblocker_pid != NULL) {
342 *pblocker_pid = state.blocker_pid;
345 DBG_DEBUG("returning status=%s\n", nt_errstr(state.status));
347 increment_current_lock_count(fsp, lock_flav);
349 return state.status;
352 /****************************************************************************
353 Utility function called by unlocking requests.
354 ****************************************************************************/
356 NTSTATUS do_unlock(files_struct *fsp,
357 uint64_t smblctx,
358 uint64_t count,
359 uint64_t offset,
360 enum brl_flavour lock_flav)
362 bool ok = False;
363 struct byte_range_lock *br_lck = NULL;
365 if (!fsp->can_lock) {
366 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
369 if (!lp_locking(fsp->conn->params)) {
370 return NT_STATUS_OK;
373 DBG_DEBUG("unlock start=%"PRIu64" len=%"PRIu64" requested for %s file "
374 "%s\n",
375 offset,
376 count,
377 fsp_fnum_dbg(fsp),
378 fsp_str_dbg(fsp));
380 br_lck = brl_get_locks(talloc_tos(), fsp);
381 if (!br_lck) {
382 return NT_STATUS_NO_MEMORY;
385 ok = brl_unlock(br_lck,
386 smblctx,
387 messaging_server_id(fsp->conn->sconn->msg_ctx),
388 offset,
389 count,
390 lock_flav);
392 TALLOC_FREE(br_lck);
394 if (!ok) {
395 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
396 return NT_STATUS_RANGE_NOT_LOCKED;
399 decrement_current_lock_count(fsp, lock_flav);
400 return NT_STATUS_OK;
403 /****************************************************************************
404 Remove any locks on this fd. Called from file_close().
405 ****************************************************************************/
407 void locking_close_file(files_struct *fsp,
408 enum file_close_type close_type)
410 struct byte_range_lock *br_lck;
412 if (!lp_locking(fsp->conn->params)) {
413 return;
416 /* If we have no outstanding locks or pending
417 * locks then we don't need to look in the lock db.
420 if (fsp->current_lock_count == 0) {
421 return;
424 br_lck = brl_get_locks(talloc_tos(),fsp);
426 if (br_lck) {
428 * Unlocks must trigger dbwrap_watch watchers,
429 * normally in smbd_do_unlocking. Here it's done
430 * implictly, we're closing the file and thus remove a
431 * share mode. This will wake the waiters.
433 brl_close_fnum(br_lck);
434 TALLOC_FREE(br_lck);
438 /*******************************************************************
439 Print out a share mode.
440 ********************************************************************/
442 char *share_mode_str(TALLOC_CTX *ctx, int num,
443 const struct file_id *id,
444 const struct share_mode_entry *e)
446 struct server_id_buf tmp;
447 struct file_id_buf ftmp;
449 return talloc_asprintf(ctx, "share_mode_entry[%d]: "
450 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
451 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
452 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
453 num,
454 server_id_str_buf(e->pid, &tmp),
455 e->share_access, e->private_options,
456 e->access_mask, (unsigned long long)e->op_mid,
457 e->op_type, (unsigned long long)e->share_file_id,
458 (unsigned int)e->uid, (unsigned int)e->flags,
459 file_id_str_buf(*id, &ftmp),
460 (unsigned int)e->name_hash);
463 /*******************************************************************
464 Fetch a share mode where we know one MUST exist. This call reference
465 counts it internally to allow for nested lock fetches.
466 ********************************************************************/
468 struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
469 const struct file_id id)
471 return get_share_mode_lock(mem_ctx, id, NULL, NULL, NULL);
474 struct rename_share_filename_state {
475 struct share_mode_lock *lck;
476 struct messaging_context *msg_ctx;
477 struct server_id self;
478 uint32_t orig_name_hash;
479 uint32_t new_name_hash;
480 struct file_rename_message msg;
483 static bool rename_lease_fn(struct share_mode_entry *e,
484 void *private_data)
486 struct rename_share_filename_state *state = private_data;
487 struct share_mode_data *d = state->lck->data;
488 NTSTATUS status;
490 status = leases_db_rename(&e->client_guid,
491 &e->lease_key,
492 &d->id,
493 d->servicepath,
494 d->base_name,
495 d->stream_name);
497 if (!NT_STATUS_IS_OK(status)) {
498 /* Any error recovery possible here ? */
499 DBG_WARNING("Failed to rename lease key for "
500 "renamed file %s:%s. %s\n",
501 d->base_name,
502 d->stream_name,
503 nt_errstr(status));
506 return false;
509 /*******************************************************************
510 Sets the service name and filename for rename.
511 At this point we emit "file renamed" messages to all
512 process id's that have this file open.
513 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
514 ********************************************************************/
516 static bool rename_share_filename_fn(
517 struct share_mode_entry *e,
518 bool *modified,
519 void *private_data)
521 struct rename_share_filename_state *state = private_data;
522 DATA_BLOB blob;
523 enum ndr_err_code ndr_err;
524 bool ok;
527 * If this is a hardlink to the inode with a different name,
528 * skip this.
530 if (e->name_hash != state->orig_name_hash) {
531 return false;
533 e->name_hash = state->new_name_hash;
534 *modified = true;
536 ok = server_id_equal(&e->pid, &state->self);
537 if (ok) {
538 return false;
541 state->msg.share_file_id = e->share_file_id;
543 ndr_err = ndr_push_struct_blob(
544 &blob,
545 talloc_tos(),
546 &state->msg,
547 (ndr_push_flags_fn_t)ndr_push_file_rename_message);
548 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
549 DBG_DEBUG("ndr_push_file_rename_message failed: %s\n",
550 ndr_errstr(ndr_err));
551 return false;
553 if (DEBUGLEVEL >= 10) {
554 struct server_id_buf tmp;
555 DBG_DEBUG("sending rename message to %s\n",
556 server_id_str_buf(e->pid, &tmp));
557 NDR_PRINT_DEBUG(file_rename_message, &state->msg);
560 messaging_send(state->msg_ctx, e->pid, MSG_SMB_FILE_RENAME, &blob);
562 TALLOC_FREE(blob.data);
564 return false;
567 bool rename_share_filename(struct messaging_context *msg_ctx,
568 struct share_mode_lock *lck,
569 struct file_id id,
570 const char *servicepath,
571 uint32_t orig_name_hash,
572 uint32_t new_name_hash,
573 const struct smb_filename *smb_fname_dst)
575 struct rename_share_filename_state state = {
576 .lck = lck,
577 .msg_ctx = msg_ctx,
578 .self = messaging_server_id(msg_ctx),
579 .orig_name_hash = orig_name_hash,
580 .new_name_hash = new_name_hash,
581 .msg.id = id,
582 .msg.servicepath = servicepath,
583 .msg.base_name = smb_fname_dst->base_name,
584 .msg.stream_name = smb_fname_dst->stream_name,
586 struct share_mode_data *d = lck->data;
587 bool ok;
589 DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
590 servicepath, smb_fname_dst->base_name));
593 * rename_internal_fsp() and rename_internals() add './' to
594 * head of newname if newname does not contain a '/'.
597 if (strncmp(state.msg.base_name, "./", 2) == 0) {
598 state.msg.base_name += 2;
601 d->servicepath = talloc_strdup(d, state.msg.servicepath);
602 d->base_name = talloc_strdup(d, state.msg.base_name);
603 d->stream_name = talloc_strdup(d, state.msg.stream_name);
604 if ((d->servicepath == NULL) ||
605 (d->base_name == NULL) ||
606 ((state.msg.stream_name != NULL) && (d->stream_name == NULL))) {
607 DBG_WARNING("talloc failed\n");
608 return false;
610 d->modified = True;
612 ok = share_mode_forall_entries(
613 lck, rename_share_filename_fn, &state);
614 if (!ok) {
615 DBG_WARNING("share_mode_forall_entries failed\n");
618 ok = share_mode_forall_leases(lck, rename_lease_fn, &state);
619 if (!ok) {
621 * Ignore error here. Not sure what to do..
623 DBG_WARNING("share_mode_forall_leases failed\n");
626 return True;
629 void get_file_infos(struct file_id id,
630 uint32_t name_hash,
631 bool *delete_on_close,
632 struct timespec *write_time)
634 struct share_mode_lock *lck;
636 if (delete_on_close) {
637 *delete_on_close = false;
640 if (write_time) {
641 *write_time = make_omit_timespec();
644 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
645 return;
648 if (delete_on_close) {
649 *delete_on_close = is_delete_on_close_set(lck, name_hash);
652 if (write_time) {
653 *write_time = get_share_mode_write_time(lck);
656 TALLOC_FREE(lck);
659 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
661 int num_props = 0;
663 if (e->stale) {
664 return false;
667 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
668 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
669 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
670 num_props += (e->op_type == LEASE_OPLOCK);
672 if ((num_props > 1) && serverid_exists(&e->pid)) {
673 smb_panic("Invalid share mode entry");
675 return (num_props != 0);
678 struct find_lease_ref_state {
679 const struct GUID *client_guid;
680 const struct smb2_lease_key *lease_key;
681 bool found_same;
684 static bool find_lease_ref_fn(
685 struct share_mode_entry *e,
686 bool *modified,
687 void *private_data)
689 struct find_lease_ref_state *state = private_data;
691 if (e->stale) {
692 return false;
694 if (e->op_type != LEASE_OPLOCK) {
695 return false;
698 state->found_same = smb2_lease_equal(
699 &e->client_guid,
700 &e->lease_key,
701 state->client_guid,
702 state->lease_key);
704 * If we found a lease reference, look no further (i.e. return true)
706 return state->found_same;
709 NTSTATUS remove_lease_if_stale(struct share_mode_lock *lck,
710 const struct GUID *client_guid,
711 const struct smb2_lease_key *lease_key)
713 struct find_lease_ref_state state = {
714 .client_guid = client_guid, .lease_key = lease_key,
716 struct share_mode_data *d = lck->data;
717 NTSTATUS status;
718 bool ok;
720 ok = share_mode_forall_entries(lck, find_lease_ref_fn, &state);
721 if (!ok) {
722 return NT_STATUS_INTERNAL_ERROR;
725 if (state.found_same) {
726 return NT_STATUS_RESOURCE_IN_USE;
729 status = leases_db_del(client_guid, lease_key, &d->id);
730 if (!NT_STATUS_IS_OK(status)) {
731 int level = DBGLVL_DEBUG;
733 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
734 level = DBGLVL_ERR;
736 DBG_PREFIX(level, ("leases_db_del failed: %s\n",
737 nt_errstr(status)));
739 return status;
742 bool share_entry_stale_pid(struct share_mode_entry *e)
744 struct server_id_buf buf;
745 bool exists;
747 if (e->stale) {
748 return true;
751 exists = serverid_exists(&e->pid);
752 if (exists) {
753 DBG_DEBUG("PID %s still exists\n",
754 server_id_str_buf(e->pid, &buf));
755 return false;
758 DBG_DEBUG("PID %s does not exist anymore\n",
759 server_id_str_buf(e->pid, &buf));
761 e->stale = true;
763 return true;
766 /****************************************************************************
767 Adds a delete on close token.
768 ****************************************************************************/
770 static bool add_delete_on_close_token(struct share_mode_data *d,
771 uint32_t name_hash,
772 const struct security_token *nt_tok,
773 const struct security_unix_token *tok)
775 struct delete_token *tmp, *dtl;
777 tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
778 d->num_delete_tokens+1);
779 if (tmp == NULL) {
780 return false;
782 d->delete_tokens = tmp;
783 dtl = &d->delete_tokens[d->num_delete_tokens];
785 dtl->name_hash = name_hash;
786 dtl->delete_nt_token = dup_nt_token(d->delete_tokens, nt_tok);
787 if (dtl->delete_nt_token == NULL) {
788 return false;
790 dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
791 if (dtl->delete_token == NULL) {
792 return false;
794 d->num_delete_tokens += 1;
795 d->modified = true;
796 return true;
799 void reset_delete_on_close_lck(files_struct *fsp,
800 struct share_mode_lock *lck)
802 struct share_mode_data *d = lck->data;
803 uint32_t i;
805 for (i=0; i<d->num_delete_tokens; i++) {
806 struct delete_token *dt = &d->delete_tokens[i];
808 if (dt->name_hash == fsp->name_hash) {
809 d->modified = true;
811 /* Delete this entry. */
812 TALLOC_FREE(dt->delete_nt_token);
813 TALLOC_FREE(dt->delete_token);
814 *dt = d->delete_tokens[d->num_delete_tokens-1];
815 d->num_delete_tokens -= 1;
820 struct set_delete_on_close_state {
821 struct messaging_context *msg_ctx;
822 DATA_BLOB blob;
825 static bool set_delete_on_close_fn(
826 struct share_mode_entry *e,
827 bool *modified,
828 void *private_data)
830 struct set_delete_on_close_state *state = private_data;
831 NTSTATUS status;
833 status = messaging_send(
834 state->msg_ctx,
835 e->pid,
836 MSG_SMB_NOTIFY_CANCEL_DELETED,
837 &state->blob);
839 if (!NT_STATUS_IS_OK(status)) {
840 struct server_id_buf tmp;
841 DBG_DEBUG("messaging_send to %s returned %s\n",
842 server_id_str_buf(e->pid, &tmp),
843 nt_errstr(status));
846 return false;
849 /****************************************************************************
850 Sets the delete on close flag over all share modes on this file.
851 Modify the share mode entry for all files open
852 on this device and inode to tell other smbds we have
853 changed the delete on close flag. This will be noticed
854 in the close code, the last closer will delete the file
855 if flag is set.
856 This makes a copy of any struct security_unix_token into the
857 lck entry. This function is used when the lock is already granted.
858 ****************************************************************************/
860 void set_delete_on_close_lck(files_struct *fsp,
861 struct share_mode_lock *lck,
862 const struct security_token *nt_tok,
863 const struct security_unix_token *tok)
865 struct share_mode_data *d = lck->data;
866 struct set_delete_on_close_state state = {
867 .msg_ctx = fsp->conn->sconn->msg_ctx
869 uint32_t i;
870 bool ret;
871 enum ndr_err_code ndr_err;
873 SMB_ASSERT(nt_tok != NULL);
874 SMB_ASSERT(tok != NULL);
876 for (i=0; i<d->num_delete_tokens; i++) {
877 struct delete_token *dt = &d->delete_tokens[i];
878 if (dt->name_hash == fsp->name_hash) {
879 d->modified = true;
881 /* Replace this token with the given tok. */
882 TALLOC_FREE(dt->delete_nt_token);
883 dt->delete_nt_token = dup_nt_token(dt, nt_tok);
884 SMB_ASSERT(dt->delete_nt_token != NULL);
885 TALLOC_FREE(dt->delete_token);
886 dt->delete_token = copy_unix_token(dt, tok);
887 SMB_ASSERT(dt->delete_token != NULL);
889 return;
893 ret = add_delete_on_close_token(lck->data, fsp->name_hash, nt_tok, tok);
894 SMB_ASSERT(ret);
896 ndr_err = ndr_push_struct_blob(
897 &state.blob,
898 talloc_tos(),
899 &fsp->file_id,
900 (ndr_push_flags_fn_t)ndr_push_file_id);
901 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
902 DEBUG(10, ("ndr_push_file_id failed: %s\n",
903 ndr_errstr(ndr_err)));
906 ret = share_mode_forall_entries(
907 lck, set_delete_on_close_fn, &state);
908 if (!ret) {
909 DBG_DEBUG("share_mode_forall_entries failed\n");
912 TALLOC_FREE(state.blob.data);
915 bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
916 const struct security_token *nt_tok,
917 const struct security_unix_token *tok)
919 struct share_mode_lock *lck;
921 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
922 "%s, file %s\n",
923 delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
924 fsp_str_dbg(fsp)));
926 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
927 if (lck == NULL) {
928 return False;
931 if (delete_on_close) {
932 set_delete_on_close_lck(fsp, lck, nt_tok, tok);
933 } else {
934 reset_delete_on_close_lck(fsp, lck);
937 if (fsp->is_directory) {
938 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
939 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
940 fsp->fsp_name->base_name);
943 TALLOC_FREE(lck);
945 fsp->delete_on_close = delete_on_close;
947 return True;
950 static struct delete_token *find_delete_on_close_token(
951 struct share_mode_data *d, uint32_t name_hash)
953 uint32_t i;
955 DBG_DEBUG("name_hash = 0x%"PRIx32"\n", name_hash);
957 for (i=0; i<d->num_delete_tokens; i++) {
958 struct delete_token *dt = &d->delete_tokens[i];
960 DBG_DEBUG("dt->name_hash = 0x%"PRIx32"\n",
961 dt->name_hash);
962 if (dt->name_hash == name_hash) {
963 return dt;
966 return NULL;
969 /****************************************************************************
970 Return the NT token and UNIX token if there's a match. Return true if
971 found, false if not.
972 ****************************************************************************/
974 bool get_delete_on_close_token(struct share_mode_lock *lck,
975 uint32_t name_hash,
976 const struct security_token **pp_nt_tok,
977 const struct security_unix_token **pp_tok)
979 struct delete_token *dt;
981 dt = find_delete_on_close_token(lck->data, name_hash);
982 if (dt == NULL) {
983 return false;
985 *pp_nt_tok = dt->delete_nt_token;
986 *pp_tok = dt->delete_token;
987 return true;
990 bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
992 return find_delete_on_close_token(lck->data, name_hash) != NULL;
995 bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
997 struct share_mode_lock *lck;
998 struct file_id_buf ftmp;
999 struct timeval_buf tbuf;
1000 NTTIME nt = full_timespec_to_nt_time(&write_time);
1002 DBG_INFO("%s id=%s\n",
1003 timespec_string_buf(&write_time, true, &tbuf),
1004 file_id_str_buf(fileid, &ftmp));
1006 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1007 if (lck == NULL) {
1008 return False;
1011 if (lck->data->changed_write_time != nt) {
1012 lck->data->modified = True;
1013 lck->data->changed_write_time = nt;
1016 TALLOC_FREE(lck);
1017 return True;
1020 bool set_write_time(struct file_id fileid, struct timespec write_time)
1022 struct share_mode_lock *lck;
1023 struct file_id_buf idbuf;
1024 struct timeval_buf tbuf;
1025 NTTIME nt = full_timespec_to_nt_time(&write_time);
1027 DBG_INFO("%s id=%s\n",
1028 timespec_string_buf(&write_time, true, &tbuf),
1029 file_id_str_buf(fileid, &idbuf));
1031 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1032 if (lck == NULL) {
1033 return False;
1036 if (lck->data->old_write_time != nt) {
1037 lck->data->modified = True;
1038 lck->data->old_write_time = nt;
1041 TALLOC_FREE(lck);
1042 return True;
1045 struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
1047 struct share_mode_data *d = lck->data;
1049 if (!null_nttime(d->changed_write_time)) {
1050 return nt_time_to_full_timespec(d->changed_write_time);
1052 return nt_time_to_full_timespec(d->old_write_time);
1055 struct file_has_open_streams_state {
1056 bool found_one;
1059 static bool file_has_open_streams_fn(
1060 struct share_mode_entry *e,
1061 bool *modified,
1062 void *private_data)
1064 struct file_has_open_streams_state *state = private_data;
1066 if ((e->private_options &
1067 NTCREATEX_OPTIONS_PRIVATE_STREAM_BASEOPEN) == 0) {
1068 return false;
1071 if (share_entry_stale_pid(e)) {
1072 return false;
1075 state->found_one = true;
1076 return true;
1079 bool file_has_open_streams(files_struct *fsp)
1081 struct file_has_open_streams_state state = { .found_one = false };
1082 struct share_mode_lock *lock = NULL;
1083 bool ok;
1085 lock = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1086 if (lock == NULL) {
1087 return false;
1090 ok = share_mode_forall_entries(
1091 lock, file_has_open_streams_fn, &state);
1092 TALLOC_FREE(lock);
1094 if (!ok) {
1095 DBG_DEBUG("share_mode_forall_entries failed\n");
1096 return false;
1098 return state.found_one;
1102 * Walk share mode entries, looking at every lease only once
1105 struct share_mode_forall_leases_state {
1106 TALLOC_CTX *mem_ctx;
1107 struct leases_db_key *leases;
1108 bool (*fn)(struct share_mode_entry *e,
1109 void *private_data);
1110 void *private_data;
1111 NTSTATUS status;
1114 static bool share_mode_forall_leases_fn(
1115 struct share_mode_entry *e,
1116 bool *modified,
1117 void *private_data)
1119 struct share_mode_forall_leases_state *state = private_data;
1120 struct leases_db_key *leases = state->leases;
1121 size_t i, num_leases;
1122 bool stop;
1124 if (e->op_type != LEASE_OPLOCK) {
1125 return false;
1128 num_leases = talloc_array_length(leases);
1130 for (i=0; i<num_leases; i++) {
1131 struct leases_db_key *l = &leases[i];
1132 bool same = smb2_lease_equal(
1133 &e->client_guid,
1134 &e->lease_key,
1135 &l->client_guid,
1136 &l->lease_key);
1137 if (same) {
1138 return false;
1142 leases = talloc_realloc(
1143 state->mem_ctx,
1144 leases,
1145 struct leases_db_key,
1146 num_leases+1);
1147 if (leases == NULL) {
1148 state->status = NT_STATUS_NO_MEMORY;
1149 return true;
1151 leases[num_leases] = (struct leases_db_key) {
1152 .client_guid = e->client_guid,
1153 .lease_key = e->lease_key,
1155 state->leases = leases;
1157 stop = state->fn(e, state->private_data);
1158 return stop;
1161 bool share_mode_forall_leases(
1162 struct share_mode_lock *lck,
1163 bool (*fn)(struct share_mode_entry *e,
1164 void *private_data),
1165 void *private_data)
1167 struct share_mode_forall_leases_state state = {
1168 .mem_ctx = talloc_tos(),
1169 .fn = fn,
1170 .private_data = private_data
1172 bool ok;
1174 ok = share_mode_forall_entries(
1175 lck, share_mode_forall_leases_fn, &state);
1176 TALLOC_FREE(state.leases);
1177 if (!ok) {
1178 DBG_DEBUG("share_mode_forall_entries failed\n");
1179 return false;
1182 if (!NT_STATUS_IS_OK(state.status)) {
1183 DBG_DEBUG("share_mode_forall_leases_fn returned %s\n",
1184 nt_errstr(state.status));
1185 return false;
1188 return true;