2 Unix SMB/CIFS implementation.
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/>.
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
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.
39 #include "lib/util/time_basic.h"
40 #include "system/filesys.h"
41 #include "lib/util/server_id.h"
42 #include "share_mode_lock.h"
43 #include "share_mode_lock_private.h"
44 #include "locking/proto.h"
45 #include "smbd/globals.h"
46 #include "dbwrap/dbwrap.h"
47 #include "dbwrap/dbwrap_open.h"
48 #include "../libcli/security/security.h"
52 #include "../librpc/gen_ndr/ndr_open_files.h"
53 #include "librpc/gen_ndr/ndr_file_id.h"
54 #include "librpc/gen_ndr/ndr_leases_db.h"
55 #include "locking/leases_db.h"
58 #define DBGC_CLASS DBGC_LOCKING
60 #define NO_LOCKING_COUNT (-1)
62 /****************************************************************************
64 ****************************************************************************/
66 const char *lock_type_name(enum brl_type lock_type)
78 const char *lock_flav_name(enum brl_flavour lock_flav)
80 return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
83 /****************************************************************************
84 Utility function called to see if a file region is locked.
85 Called in the read/write codepath.
86 ****************************************************************************/
88 void init_strict_lock_struct(files_struct *fsp,
92 enum brl_type lock_type,
93 enum brl_flavour lock_flav,
94 struct lock_struct *plock)
96 SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
98 plock->context.smblctx = smblctx;
99 plock->context.tid = fsp->conn->cnum;
100 plock->context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
101 plock->start = start;
103 plock->fnum = fsp->fnum;
104 plock->lock_type = lock_type;
105 plock->lock_flav = lp_posix_cifsu_locktype(fsp);
108 bool strict_lock_check_default(files_struct *fsp, struct lock_struct *plock)
110 struct byte_range_lock *br_lck;
111 int strict_locking = lp_strict_locking(fsp->conn->params);
114 if (plock->size == 0) {
118 if (!lp_locking(fsp->conn->params) || !strict_locking) {
122 if (strict_locking == Auto) {
123 uint32_t lease_type = fsp_lease_type(fsp);
125 if ((lease_type & SMB2_LEASE_READ) &&
126 (plock->lock_type == READ_LOCK))
128 DBG_DEBUG("optimisation - read lease on file %s\n",
133 if ((lease_type & SMB2_LEASE_WRITE) &&
134 (plock->lock_type == WRITE_LOCK))
136 DBG_DEBUG("optimisation - write lease on file %s\n",
142 br_lck = brl_get_locks_readonly(fsp);
146 ret = brl_locktest(br_lck, plock);
150 * We got a lock conflict. Retry with rw locks to enable
151 * autocleanup. This is the slow path anyway.
153 br_lck = brl_get_locks(talloc_tos(), fsp);
154 if (br_lck == NULL) {
157 ret = brl_locktest(br_lck, plock);
161 DEBUG(10, ("strict_lock_default: flavour = %s brl start=%ju "
162 "len=%ju %s for fnum %ju file %s\n",
163 lock_flav_name(plock->lock_flav),
164 (uintmax_t)plock->start, (uintmax_t)plock->size,
165 ret ? "unlocked" : "locked",
166 (uintmax_t)plock->fnum, fsp_str_dbg(fsp)));
171 /****************************************************************************
172 Find out if a lock could be granted - return who is blocking us if we can't.
173 ****************************************************************************/
175 NTSTATUS query_lock(files_struct *fsp,
179 enum brl_type *plock_type,
180 enum brl_flavour lock_flav)
182 struct byte_range_lock *br_lck = NULL;
184 if (!fsp->fsp_flags.can_lock) {
185 return fsp->fsp_flags.is_directory ?
186 NT_STATUS_INVALID_DEVICE_REQUEST :
187 NT_STATUS_INVALID_HANDLE;
190 if (!lp_locking(fsp->conn->params)) {
194 br_lck = brl_get_locks_readonly(fsp);
196 return NT_STATUS_NO_MEMORY;
199 return brl_lockquery(br_lck,
201 messaging_server_id(fsp->conn->sconn->msg_ctx),
208 static void increment_current_lock_count(files_struct *fsp,
209 enum brl_flavour lock_flav)
211 if (lock_flav == WINDOWS_LOCK &&
212 fsp->current_lock_count != NO_LOCKING_COUNT) {
213 /* blocking ie. pending, locks also count here,
214 * as this is an efficiency counter to avoid checking
215 * the lock db. on close. JRA. */
217 fsp->current_lock_count++;
219 /* Notice that this has had a POSIX lock request.
220 * We can't count locks after this so forget them.
222 fsp->current_lock_count = NO_LOCKING_COUNT;
226 static void decrement_current_lock_count(files_struct *fsp,
227 enum brl_flavour lock_flav)
229 if (lock_flav == WINDOWS_LOCK &&
230 fsp->current_lock_count != NO_LOCKING_COUNT) {
231 SMB_ASSERT(fsp->current_lock_count > 0);
232 fsp->current_lock_count--;
236 /****************************************************************************
237 Utility function called by locking requests.
238 ****************************************************************************/
240 struct do_lock_state {
241 struct files_struct *fsp;
242 TALLOC_CTX *req_mem_ctx;
243 const struct GUID *req_guid;
247 enum brl_type lock_type;
248 enum brl_flavour lock_flav;
250 struct server_id blocker_pid;
251 uint64_t blocker_smblctx;
255 static void do_lock_fn(
256 struct share_mode_lock *lck,
259 struct do_lock_state *state = private_data;
260 struct byte_range_lock *br_lck = NULL;
262 br_lck = brl_get_locks_for_locking(talloc_tos(),
266 if (br_lck == NULL) {
267 state->status = NT_STATUS_NO_MEMORY;
271 state->status = brl_lock(
274 messaging_server_id(state->fsp->conn->sconn->msg_ctx),
280 &state->blocker_smblctx);
285 NTSTATUS do_lock(files_struct *fsp,
286 TALLOC_CTX *req_mem_ctx,
287 const struct GUID *req_guid,
291 enum brl_type lock_type,
292 enum brl_flavour lock_flav,
293 struct server_id *pblocker_pid,
296 struct do_lock_state state = {
298 .req_mem_ctx = req_mem_ctx,
299 .req_guid = req_guid,
303 .lock_type = lock_type,
304 .lock_flav = lock_flav,
308 /* silently return ok on print files as we don't do locking there */
309 if (fsp->print_file) {
313 if (!fsp->fsp_flags.can_lock) {
314 if (fsp->fsp_flags.is_directory) {
315 return NT_STATUS_INVALID_DEVICE_REQUEST;
317 return NT_STATUS_INVALID_HANDLE;
320 if (!lp_locking(fsp->conn->params)) {
324 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
326 DBG_DEBUG("lock flavour %s lock type %s start=%"PRIu64" len=%"PRIu64" "
327 "requested for %s file %s\n",
328 lock_flav_name(lock_flav),
329 lock_type_name(lock_type),
335 status = share_mode_do_locked_vfs_allowed(fsp->file_id,
338 if (!NT_STATUS_IS_OK(status)) {
339 DBG_DEBUG("share_mode_do_locked returned %s\n",
344 if (psmblctx != NULL) {
345 *psmblctx = state.blocker_smblctx;
347 if (pblocker_pid != NULL) {
348 *pblocker_pid = state.blocker_pid;
351 DBG_DEBUG("returning status=%s\n", nt_errstr(state.status));
353 increment_current_lock_count(fsp, lock_flav);
358 /****************************************************************************
359 Utility function called by unlocking requests.
360 ****************************************************************************/
362 NTSTATUS do_unlock(files_struct *fsp,
366 enum brl_flavour lock_flav)
369 struct byte_range_lock *br_lck = NULL;
371 if (!fsp->fsp_flags.can_lock) {
372 return fsp->fsp_flags.is_directory ?
373 NT_STATUS_INVALID_DEVICE_REQUEST :
374 NT_STATUS_INVALID_HANDLE;
377 if (!lp_locking(fsp->conn->params)) {
381 DBG_DEBUG("unlock start=%"PRIu64" len=%"PRIu64" requested for %s file "
388 br_lck = brl_get_locks(talloc_tos(), fsp);
390 return NT_STATUS_NO_MEMORY;
393 ok = brl_unlock(br_lck,
395 messaging_server_id(fsp->conn->sconn->msg_ctx),
403 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
404 return NT_STATUS_RANGE_NOT_LOCKED;
407 decrement_current_lock_count(fsp, lock_flav);
411 /****************************************************************************
412 Remove any locks on this fd. Called from file_close().
413 ****************************************************************************/
415 void locking_close_file(files_struct *fsp,
416 enum file_close_type close_type)
418 struct byte_range_lock *br_lck;
420 if (!lp_locking(fsp->conn->params)) {
424 /* If we have no outstanding locks or pending
425 * locks then we don't need to look in the lock db.
428 if (fsp->current_lock_count == 0) {
432 br_lck = brl_get_locks(talloc_tos(),fsp);
436 * Unlocks must trigger dbwrap_watch watchers,
437 * normally in smbd_do_unlocking. Here it's done
438 * implicitly, we're closing the file and thus remove a
439 * share mode. This will wake the waiters.
441 brl_close_fnum(br_lck);
446 /*******************************************************************
447 Print out a share mode.
448 ********************************************************************/
450 char *share_mode_str(TALLOC_CTX *ctx, int num,
451 const struct file_id *id,
452 const struct share_mode_entry *e)
454 struct server_id_buf tmp;
455 struct file_id_buf ftmp;
457 return talloc_asprintf(ctx, "share_mode_entry[%d]: "
458 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
459 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
460 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
462 server_id_str_buf(e->pid, &tmp),
463 e->share_access, e->private_options,
464 e->access_mask, (unsigned long long)e->op_mid,
465 e->op_type, (unsigned long long)e->share_file_id,
466 (unsigned int)e->uid, (unsigned int)e->flags,
467 file_id_str_buf(*id, &ftmp),
468 (unsigned int)e->name_hash);
471 struct rename_share_filename_state {
472 struct share_mode_data *data;
473 struct messaging_context *msg_ctx;
474 struct server_id self;
475 uint32_t orig_name_hash;
476 uint32_t new_name_hash;
477 struct file_rename_message msg;
480 static bool rename_lease_fn(struct share_mode_entry *e,
483 struct rename_share_filename_state *state = private_data;
484 struct share_mode_data *d = state->data;
487 status = leases_db_rename(&e->client_guid,
494 if (!NT_STATUS_IS_OK(status)) {
495 /* Any error recovery possible here ? */
496 DBG_WARNING("Failed to rename lease key for "
497 "renamed file %s:%s. %s\n",
506 /*******************************************************************
507 Sets the service name and filename for rename.
508 At this point we emit "file renamed" messages to all
509 process id's that have this file open.
510 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
511 ********************************************************************/
513 static bool rename_share_filename_fn(
514 struct share_mode_entry *e,
518 struct rename_share_filename_state *state = private_data;
520 enum ndr_err_code ndr_err;
524 * If this is a hardlink to the inode with a different name,
527 if (e->name_hash != state->orig_name_hash) {
530 e->name_hash = state->new_name_hash;
533 ok = server_id_equal(&e->pid, &state->self);
538 state->msg.share_file_id = e->share_file_id;
540 ndr_err = ndr_push_struct_blob(
544 (ndr_push_flags_fn_t)ndr_push_file_rename_message);
545 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
546 DBG_DEBUG("ndr_push_file_rename_message failed: %s\n",
547 ndr_errstr(ndr_err));
550 if (DEBUGLEVEL >= 10) {
551 struct server_id_buf tmp;
552 DBG_DEBUG("sending rename message to %s\n",
553 server_id_str_buf(e->pid, &tmp));
554 NDR_PRINT_DEBUG(file_rename_message, &state->msg);
557 messaging_send(state->msg_ctx, e->pid, MSG_SMB_FILE_RENAME, &blob);
559 TALLOC_FREE(blob.data);
564 bool rename_share_filename(struct messaging_context *msg_ctx,
565 struct share_mode_lock *lck,
567 const char *servicepath,
568 uint32_t orig_name_hash,
569 uint32_t new_name_hash,
570 const struct smb_filename *smb_fname_dst)
572 struct rename_share_filename_state state = {
574 .self = messaging_server_id(msg_ctx),
575 .orig_name_hash = orig_name_hash,
576 .new_name_hash = new_name_hash,
578 .msg.servicepath = servicepath,
579 .msg.base_name = smb_fname_dst->base_name,
580 .msg.stream_name = smb_fname_dst->stream_name,
582 struct share_mode_data *d = NULL;
586 DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
587 servicepath, smb_fname_dst->base_name));
589 status = share_mode_lock_access_private_data(lck, &d);
590 if (!NT_STATUS_IS_OK(status)) {
591 /* Any error recovery possible here ? */
592 DBG_ERR("share_mode_lock_access_private_data() failed for "
593 "servicepath %s newname %s - %s\n",
594 servicepath, smb_fname_dst->base_name,
601 * rename_internal_fsp() and rename_internals() add './' to
602 * head of newname if newname does not contain a '/'.
605 if (strncmp(state.msg.base_name, "./", 2) == 0) {
606 state.msg.base_name += 2;
609 d->servicepath = talloc_strdup(d, state.msg.servicepath);
610 d->base_name = talloc_strdup(d, state.msg.base_name);
611 d->stream_name = talloc_strdup(d, state.msg.stream_name);
612 if ((d->servicepath == NULL) ||
613 (d->base_name == NULL) ||
614 ((state.msg.stream_name != NULL) && (d->stream_name == NULL))) {
615 DBG_WARNING("talloc failed\n");
620 ok = share_mode_forall_entries(
621 lck, rename_share_filename_fn, &state);
623 DBG_WARNING("share_mode_forall_entries failed\n");
626 ok = share_mode_forall_leases(lck, rename_lease_fn, &state);
629 * Ignore error here. Not sure what to do..
631 DBG_WARNING("share_mode_forall_leases failed\n");
637 void get_file_infos(struct file_id id,
639 bool *delete_on_close,
640 struct timespec *write_time)
642 struct share_mode_lock *lck;
644 if (delete_on_close) {
645 *delete_on_close = false;
649 *write_time = make_omit_timespec();
652 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
656 if (delete_on_close) {
657 *delete_on_close = is_delete_on_close_set(lck, name_hash);
661 *write_time = get_share_mode_write_time(lck);
667 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
675 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
676 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
677 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
678 num_props += (e->op_type == LEASE_OPLOCK);
680 if ((num_props > 1) && serverid_exists(&e->pid)) {
681 smb_panic("Invalid share mode entry");
683 return (num_props != 0);
686 struct find_lease_ref_state {
687 const struct GUID *client_guid;
688 const struct smb2_lease_key *lease_key;
692 static bool find_lease_ref_fn(
693 struct share_mode_entry *e,
697 struct find_lease_ref_state *state = private_data;
702 if (e->op_type != LEASE_OPLOCK) {
706 state->found_same = smb2_lease_equal(
712 * If we found a lease reference, look no further (i.e. return true)
714 return state->found_same;
717 NTSTATUS remove_lease_if_stale(struct share_mode_lock *lck,
718 const struct GUID *client_guid,
719 const struct smb2_lease_key *lease_key)
721 struct find_lease_ref_state state = {
722 .client_guid = client_guid, .lease_key = lease_key,
724 struct file_id id = share_mode_lock_file_id(lck);
728 ok = share_mode_forall_entries(lck, find_lease_ref_fn, &state);
730 DBG_ERR("share_mode_forall_entries failed\n");
731 return NT_STATUS_INTERNAL_ERROR;
734 if (state.found_same) {
735 return NT_STATUS_RESOURCE_IN_USE;
738 status = leases_db_del(client_guid, lease_key, &id);
739 if (!NT_STATUS_IS_OK(status)) {
740 int level = DBGLVL_DEBUG;
742 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
745 DBG_PREFIX(level, ("leases_db_del failed: %s\n",
751 bool share_entry_stale_pid(struct share_mode_entry *e)
753 struct server_id_buf buf;
760 exists = serverid_exists(&e->pid);
762 DBG_DEBUG("PID %s still exists\n",
763 server_id_str_buf(e->pid, &buf));
767 DBG_DEBUG("PID %s does not exist anymore\n",
768 server_id_str_buf(e->pid, &buf));
775 /****************************************************************************
776 Adds a delete on close token.
777 ****************************************************************************/
779 static bool add_delete_on_close_token(struct share_mode_data *d,
781 const struct security_token *nt_tok,
782 const struct security_unix_token *tok)
784 struct delete_token *tmp, *dtl;
786 tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
787 d->num_delete_tokens+1);
791 d->delete_tokens = tmp;
792 dtl = &d->delete_tokens[d->num_delete_tokens];
794 dtl->name_hash = name_hash;
795 dtl->delete_nt_token = security_token_duplicate(d->delete_tokens, nt_tok);
796 if (dtl->delete_nt_token == NULL) {
799 dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
800 if (dtl->delete_token == NULL) {
803 d->num_delete_tokens += 1;
808 void reset_delete_on_close_lck(files_struct *fsp,
809 struct share_mode_lock *lck)
811 struct share_mode_data *d = NULL;
815 status = share_mode_lock_access_private_data(lck, &d);
816 if (!NT_STATUS_IS_OK(status)) {
817 /* Any error recovery possible here ? */
818 DBG_ERR("share_mode_lock_access_private_data() failed for "
819 "%s - %s\n", fsp_str_dbg(fsp), nt_errstr(status));
820 smb_panic(__location__);
824 for (i=0; i<d->num_delete_tokens; i++) {
825 struct delete_token *dt = &d->delete_tokens[i];
827 if (dt->name_hash == fsp->name_hash) {
830 /* Delete this entry. */
831 TALLOC_FREE(dt->delete_nt_token);
832 TALLOC_FREE(dt->delete_token);
833 *dt = d->delete_tokens[d->num_delete_tokens-1];
834 d->num_delete_tokens -= 1;
839 struct set_delete_on_close_state {
840 struct messaging_context *msg_ctx;
844 static bool set_delete_on_close_fn(
845 struct share_mode_entry *e,
849 struct set_delete_on_close_state *state = private_data;
852 status = messaging_send(
855 MSG_SMB_NOTIFY_CANCEL_DELETED,
858 if (!NT_STATUS_IS_OK(status)) {
859 struct server_id_buf tmp;
860 DBG_DEBUG("messaging_send to %s returned %s\n",
861 server_id_str_buf(e->pid, &tmp),
868 /****************************************************************************
869 Sets the delete on close flag over all share modes on this file.
870 Modify the share mode entry for all files open
871 on this device and inode to tell other smbds we have
872 changed the delete on close flag. This will be noticed
873 in the close code, the last closer will delete the file
875 This makes a copy of any struct security_unix_token into the
876 lck entry. This function is used when the lock is already granted.
877 ****************************************************************************/
879 void set_delete_on_close_lck(files_struct *fsp,
880 struct share_mode_lock *lck,
881 const struct security_token *nt_tok,
882 const struct security_unix_token *tok)
884 struct share_mode_data *d = NULL;
885 struct set_delete_on_close_state state = {
886 .msg_ctx = fsp->conn->sconn->msg_ctx
890 enum ndr_err_code ndr_err;
893 status = share_mode_lock_access_private_data(lck, &d);
894 if (!NT_STATUS_IS_OK(status)) {
895 /* Any error recovery possible here ? */
896 DBG_ERR("share_mode_lock_access_private_data() failed for "
897 "%s - %s\n", fsp_str_dbg(fsp), nt_errstr(status));
898 smb_panic(__location__);
902 SMB_ASSERT(nt_tok != NULL);
903 SMB_ASSERT(tok != NULL);
905 for (i=0; i<d->num_delete_tokens; i++) {
906 struct delete_token *dt = &d->delete_tokens[i];
907 if (dt->name_hash == fsp->name_hash) {
910 /* Replace this token with the given tok. */
911 TALLOC_FREE(dt->delete_nt_token);
912 dt->delete_nt_token = security_token_duplicate(dt, nt_tok);
913 SMB_ASSERT(dt->delete_nt_token != NULL);
914 TALLOC_FREE(dt->delete_token);
915 dt->delete_token = copy_unix_token(dt, tok);
916 SMB_ASSERT(dt->delete_token != NULL);
922 ret = add_delete_on_close_token(d, fsp->name_hash, nt_tok, tok);
925 ndr_err = ndr_push_struct_blob(
929 (ndr_push_flags_fn_t)ndr_push_file_id);
930 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
931 DBG_ERR("ndr_push_file_id failed: %s\n",
932 ndr_errstr(ndr_err));
933 smb_panic(__location__);
936 ret = share_mode_forall_entries(
937 lck, set_delete_on_close_fn, &state);
939 DBG_ERR("share_mode_forall_entries failed\n");
940 smb_panic(__location__);
943 TALLOC_FREE(state.blob.data);
946 struct set_delete_on_close_locked_state {
947 struct files_struct *fsp;
948 bool delete_on_close;
949 const struct security_token *nt_tok;
950 const struct security_unix_token *tok;
953 static void set_delete_on_close_locked(struct share_mode_lock *lck,
956 struct set_delete_on_close_locked_state *state =
957 (struct set_delete_on_close_locked_state *)private_data;
959 if (state->delete_on_close) {
960 set_delete_on_close_lck(state->fsp,
965 reset_delete_on_close_lck(state->fsp, lck);
968 state->fsp->fsp_flags.delete_on_close = state->delete_on_close;
971 bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
972 const struct security_token *nt_tok,
973 const struct security_unix_token *tok)
975 struct set_delete_on_close_locked_state state = {
977 .delete_on_close = delete_on_close,
983 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
985 delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
988 if (fsp->fsp_flags.is_directory) {
989 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
992 status = share_mode_do_locked_vfs_denied(fsp->file_id,
993 set_delete_on_close_locked,
995 if (!NT_STATUS_IS_OK(status)) {
1002 static struct delete_token *find_delete_on_close_token(
1003 struct share_mode_data *d, uint32_t name_hash)
1007 DBG_DEBUG("name_hash = 0x%"PRIx32"\n", name_hash);
1009 for (i=0; i<d->num_delete_tokens; i++) {
1010 struct delete_token *dt = &d->delete_tokens[i];
1012 DBG_DEBUG("dt->name_hash = 0x%"PRIx32"\n",
1014 if (dt->name_hash == name_hash) {
1021 /****************************************************************************
1022 Return the NT token and UNIX token if there's a match. Return true if
1023 found, false if not.
1024 ****************************************************************************/
1026 bool get_delete_on_close_token(struct share_mode_lock *lck,
1028 const struct security_token **pp_nt_tok,
1029 const struct security_unix_token **pp_tok)
1031 struct share_mode_data *d = NULL;
1032 struct delete_token *dt;
1035 status = share_mode_lock_access_private_data(lck, &d);
1036 if (!NT_STATUS_IS_OK(status)) {
1037 struct file_id id = share_mode_lock_file_id(lck);
1038 struct file_id_buf id_buf;
1039 /* Any error recovery possible here ? */
1040 DBG_ERR("share_mode_lock_access_private_data() failed for "
1041 "%s name_hash=%"PRIu32" - %s\n",
1042 file_id_str_buf(id, &id_buf), name_hash,
1047 dt = find_delete_on_close_token(d, name_hash);
1051 *pp_nt_tok = dt->delete_nt_token;
1052 *pp_tok = dt->delete_token;
1056 bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
1058 struct share_mode_data *d = NULL;
1061 status = share_mode_lock_access_private_data(lck, &d);
1062 if (!NT_STATUS_IS_OK(status)) {
1063 struct file_id id = share_mode_lock_file_id(lck);
1064 struct file_id_buf id_buf;
1065 /* Any error recovery possible here ? */
1066 DBG_ERR("share_mode_lock_access_private_data() failed for "
1067 "%s name_hash=%"PRIu32" - %s\n",
1068 file_id_str_buf(id, &id_buf), name_hash,
1073 return find_delete_on_close_token(d, name_hash) != NULL;
1076 struct set_sticky_write_time_state {
1077 struct file_id fileid;
1078 struct timespec write_time;
1082 static void set_sticky_write_time_fn(struct share_mode_lock *lck,
1085 struct set_sticky_write_time_state *state = private_data;
1086 struct share_mode_data *d = NULL;
1087 struct file_id_buf ftmp;
1088 struct timeval_buf tbuf;
1091 status = share_mode_lock_access_private_data(lck, &d);
1092 if (!NT_STATUS_IS_OK(status)) {
1093 /* Any error recovery possible here ? */
1094 DBG_ERR("share_mode_lock_access_private_data() failed for "
1096 timespec_string_buf(&state->write_time, true, &tbuf),
1097 file_id_str_buf(state->fileid, &ftmp),
1102 share_mode_set_changed_write_time(lck, state->write_time);
1107 bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
1109 struct set_sticky_write_time_state state = {
1111 .write_time = write_time,
1113 struct file_id_buf ftmp;
1114 struct timeval_buf tbuf;
1117 status = share_mode_do_locked_vfs_denied(fileid,
1118 set_sticky_write_time_fn,
1120 if (!NT_STATUS_IS_OK(status)) {
1121 /* Any error recovery possible here ? */
1122 DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
1124 timespec_string_buf(&write_time, true, &tbuf),
1125 file_id_str_buf(fileid, &ftmp),
1133 struct set_write_time_state {
1134 struct file_id fileid;
1135 struct timespec write_time;
1139 static void set_write_time_fn(struct share_mode_lock *lck,
1142 struct set_write_time_state *state = private_data;
1143 struct share_mode_data *d = NULL;
1144 struct file_id_buf idbuf;
1145 struct timeval_buf tbuf;
1148 status = share_mode_lock_access_private_data(lck, &d);
1149 if (!NT_STATUS_IS_OK(status)) {
1150 /* Any error recovery possible here ? */
1151 DBG_ERR("share_mode_lock_access_private_data() failed for "
1153 timespec_string_buf(&state->write_time, true, &tbuf),
1154 file_id_str_buf(state->fileid, &idbuf),
1159 share_mode_set_old_write_time(lck, state->write_time);
1164 bool set_write_time(struct file_id fileid, struct timespec write_time)
1166 struct set_write_time_state state = {
1168 .write_time = write_time,
1170 struct file_id_buf idbuf;
1171 struct timeval_buf tbuf;
1174 status = share_mode_do_locked_vfs_denied(fileid,
1177 if (!NT_STATUS_IS_OK(status)) {
1178 DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
1180 timespec_string_buf(&write_time, true, &tbuf),
1181 file_id_str_buf(fileid, &idbuf),
1189 struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
1191 struct share_mode_data *d = NULL;
1194 status = share_mode_lock_access_private_data(lck, &d);
1195 if (!NT_STATUS_IS_OK(status)) {
1196 struct file_id id = share_mode_lock_file_id(lck);
1197 struct file_id_buf id_buf;
1198 struct timespec ts_zero = {};
1199 /* Any error recovery possible here ? */
1200 DBG_ERR("share_mode_lock_access_private_data() failed for "
1202 file_id_str_buf(id, &id_buf),
1204 smb_panic(__location__);
1208 if (!null_nttime(d->changed_write_time)) {
1209 return nt_time_to_full_timespec(d->changed_write_time);
1211 return nt_time_to_full_timespec(d->old_write_time);
1214 struct file_has_open_streams_state {
1219 static bool file_has_open_streams_fn(
1220 struct share_mode_entry *e,
1224 struct file_has_open_streams_state *state = private_data;
1226 if ((e->private_options &
1227 NTCREATEX_FLAG_STREAM_BASEOPEN) == 0) {
1231 if (share_entry_stale_pid(e)) {
1235 state->found_one = true;
1239 static void file_has_open_streams_locked(struct share_mode_lock *lck,
1242 struct file_has_open_streams_state *state = private_data;
1244 state->ok = share_mode_forall_entries(lck,
1245 file_has_open_streams_fn,
1249 bool file_has_open_streams(files_struct *fsp)
1251 struct file_has_open_streams_state state = { .found_one = false };
1254 status = share_mode_do_locked_vfs_denied(fsp->file_id,
1255 file_has_open_streams_locked,
1257 if (!NT_STATUS_IS_OK(status)) {
1258 DBG_DEBUG("share_mode_do_locked_vfs_denied() failed - %s\n",
1264 DBG_DEBUG("share_mode_forall_entries failed\n");
1268 return state.found_one;
1272 * Walk share mode entries, looking at every lease only once
1275 struct share_mode_forall_leases_state {
1276 TALLOC_CTX *mem_ctx;
1277 struct leases_db_key *leases;
1278 bool (*fn)(struct share_mode_entry *e,
1279 void *private_data);
1284 static bool share_mode_forall_leases_fn(
1285 struct share_mode_entry *e,
1289 struct share_mode_forall_leases_state *state = private_data;
1290 struct leases_db_key *leases = state->leases;
1291 size_t i, num_leases;
1294 if (e->op_type != LEASE_OPLOCK) {
1298 num_leases = talloc_array_length(leases);
1300 for (i=0; i<num_leases; i++) {
1301 struct leases_db_key *l = &leases[i];
1302 bool same = smb2_lease_equal(
1312 leases = talloc_realloc(
1315 struct leases_db_key,
1317 if (leases == NULL) {
1318 state->status = NT_STATUS_NO_MEMORY;
1321 leases[num_leases] = (struct leases_db_key) {
1322 .client_guid = e->client_guid,
1323 .lease_key = e->lease_key,
1325 state->leases = leases;
1327 stop = state->fn(e, state->private_data);
1331 bool share_mode_forall_leases(
1332 struct share_mode_lock *lck,
1333 bool (*fn)(struct share_mode_entry *e,
1334 void *private_data),
1337 struct share_mode_forall_leases_state state = {
1338 .mem_ctx = talloc_tos(),
1340 .private_data = private_data
1344 ok = share_mode_forall_entries(
1345 lck, share_mode_forall_leases_fn, &state);
1346 TALLOC_FREE(state.leases);
1348 DBG_ERR("share_mode_forall_entries failed\n");
1352 if (!NT_STATUS_IS_OK(state.status)) {
1353 DBG_ERR("share_mode_forall_leases_fn returned %s\n",
1354 nt_errstr(state.status));