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 "smbd/proto.h"
41 #include "system/filesys.h"
42 #include "lib/util/server_id.h"
43 #include "share_mode_lock.h"
44 #include "share_mode_lock_private.h"
45 #include "locking/proto.h"
46 #include "smbd/globals.h"
47 #include "dbwrap/dbwrap.h"
48 #include "dbwrap/dbwrap_open.h"
49 #include "../libcli/security/security.h"
53 #include "../librpc/gen_ndr/ndr_open_files.h"
54 #include "librpc/gen_ndr/ndr_file_id.h"
55 #include "librpc/gen_ndr/ndr_leases_db.h"
56 #include "locking/leases_db.h"
59 #define DBGC_CLASS DBGC_LOCKING
61 #define NO_LOCKING_COUNT (-1)
63 /****************************************************************************
65 ****************************************************************************/
67 const char *lock_type_name(enum brl_type lock_type
)
79 const char *lock_flav_name(enum brl_flavour lock_flav
)
81 return (lock_flav
== WINDOWS_LOCK
) ? "WINDOWS_LOCK" : "POSIX_LOCK";
84 /****************************************************************************
85 Utility function called to see if a file region is locked.
86 Called in the read/write codepath.
87 ****************************************************************************/
89 void init_strict_lock_struct(files_struct
*fsp
,
93 enum brl_type lock_type
,
94 enum brl_flavour lock_flav
,
95 struct lock_struct
*plock
)
97 SMB_ASSERT(lock_type
== READ_LOCK
|| lock_type
== WRITE_LOCK
);
99 *plock
= (struct lock_struct
) {
100 .context
.smblctx
= smblctx
,
101 .context
.tid
= fsp
->conn
->cnum
,
102 .context
.pid
= messaging_server_id(fsp
->conn
->sconn
->msg_ctx
),
106 .lock_type
= lock_type
,
107 .lock_flav
= lp_posix_cifsu_locktype(fsp
),
111 bool strict_lock_check_default(files_struct
*fsp
, struct lock_struct
*plock
)
113 struct byte_range_lock
*br_lck
;
114 int strict_locking
= lp_strict_locking(fsp
->conn
->params
);
117 if (plock
->size
== 0) {
121 if (!lp_locking(fsp
->conn
->params
) || !strict_locking
) {
125 if (strict_locking
== Auto
) {
126 uint32_t lease_type
= fsp_lease_type(fsp
);
128 if ((lease_type
& SMB2_LEASE_READ
) &&
129 (plock
->lock_type
== READ_LOCK
))
131 DBG_DEBUG("optimisation - read lease on file %s\n",
136 if ((lease_type
& SMB2_LEASE_WRITE
) &&
137 (plock
->lock_type
== WRITE_LOCK
))
139 DBG_DEBUG("optimisation - write lease on file %s\n",
145 br_lck
= brl_get_locks_readonly(fsp
);
149 ret
= brl_locktest(br_lck
, plock
);
153 * We got a lock conflict. Retry with rw locks to enable
154 * autocleanup. This is the slow path anyway.
156 br_lck
= brl_get_locks(talloc_tos(), fsp
);
157 if (br_lck
== NULL
) {
160 ret
= brl_locktest(br_lck
, plock
);
164 DBG_DEBUG("flavour = %s brl start=%" PRIu64
" "
165 "len=%" PRIu64
" %s for fnum %" PRIu64
" file %s\n",
166 lock_flav_name(plock
->lock_flav
),
169 ret
? "unlocked" : "locked",
176 /****************************************************************************
177 Find out if a lock could be granted - return who is blocking us if we can't.
178 ****************************************************************************/
180 NTSTATUS
query_lock(files_struct
*fsp
,
184 enum brl_type
*plock_type
,
185 enum brl_flavour lock_flav
)
187 struct byte_range_lock
*br_lck
= NULL
;
189 if (!fsp
->fsp_flags
.can_lock
) {
190 return fsp
->fsp_flags
.is_directory
?
191 NT_STATUS_INVALID_DEVICE_REQUEST
:
192 NT_STATUS_INVALID_HANDLE
;
195 if (!lp_locking(fsp
->conn
->params
)) {
199 br_lck
= brl_get_locks_readonly(fsp
);
201 return NT_STATUS_NO_MEMORY
;
204 return brl_lockquery(br_lck
,
206 messaging_server_id(fsp
->conn
->sconn
->msg_ctx
),
213 static void increment_current_lock_count(files_struct
*fsp
,
214 enum brl_flavour lock_flav
)
216 if (lock_flav
== WINDOWS_LOCK
&&
217 fsp
->current_lock_count
!= NO_LOCKING_COUNT
) {
218 /* blocking ie. pending, locks also count here,
219 * as this is an efficiency counter to avoid checking
220 * the lock db. on close. JRA. */
222 fsp
->current_lock_count
++;
224 /* Notice that this has had a POSIX lock request.
225 * We can't count locks after this so forget them.
227 fsp
->current_lock_count
= NO_LOCKING_COUNT
;
231 static void decrement_current_lock_count(files_struct
*fsp
,
232 enum brl_flavour lock_flav
)
234 if (lock_flav
== WINDOWS_LOCK
&&
235 fsp
->current_lock_count
!= NO_LOCKING_COUNT
) {
236 SMB_ASSERT(fsp
->current_lock_count
> 0);
237 fsp
->current_lock_count
--;
241 /****************************************************************************
242 Utility function called by locking requests.
243 ****************************************************************************/
245 struct do_lock_state
{
246 struct files_struct
*fsp
;
247 TALLOC_CTX
*req_mem_ctx
;
248 const struct GUID
*req_guid
;
252 enum brl_type lock_type
;
253 enum brl_flavour lock_flav
;
255 struct server_id blocker_pid
;
256 uint64_t blocker_smblctx
;
260 static void do_lock_fn(
261 struct share_mode_lock
*lck
,
264 struct do_lock_state
*state
= private_data
;
265 struct byte_range_lock
*br_lck
= NULL
;
267 br_lck
= brl_get_locks_for_locking(talloc_tos(),
271 if (br_lck
== NULL
) {
272 state
->status
= NT_STATUS_NO_MEMORY
;
276 state
->status
= brl_lock(
279 messaging_server_id(state
->fsp
->conn
->sconn
->msg_ctx
),
285 &state
->blocker_smblctx
);
290 NTSTATUS
do_lock(files_struct
*fsp
,
291 TALLOC_CTX
*req_mem_ctx
,
292 const struct GUID
*req_guid
,
296 enum brl_type lock_type
,
297 enum brl_flavour lock_flav
,
298 struct server_id
*pblocker_pid
,
301 struct do_lock_state state
= {
303 .req_mem_ctx
= req_mem_ctx
,
304 .req_guid
= req_guid
,
308 .lock_type
= lock_type
,
309 .lock_flav
= lock_flav
,
313 /* silently return ok on print files as we don't do locking there */
314 if (fsp
->print_file
) {
318 if (!fsp
->fsp_flags
.can_lock
) {
319 if (fsp
->fsp_flags
.is_directory
) {
320 return NT_STATUS_INVALID_DEVICE_REQUEST
;
322 return NT_STATUS_INVALID_HANDLE
;
325 if (!lp_locking(fsp
->conn
->params
)) {
329 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
331 DBG_DEBUG("lock flavour %s lock type %s start=%"PRIu64
" len=%"PRIu64
" "
332 "requested for %s file %s\n",
333 lock_flav_name(lock_flav
),
334 lock_type_name(lock_type
),
340 status
= share_mode_do_locked_vfs_allowed(fsp
->file_id
,
343 if (!NT_STATUS_IS_OK(status
)) {
344 DBG_DEBUG("share_mode_do_locked returned %s\n",
349 if (psmblctx
!= NULL
) {
350 *psmblctx
= state
.blocker_smblctx
;
352 if (pblocker_pid
!= NULL
) {
353 *pblocker_pid
= state
.blocker_pid
;
356 DBG_DEBUG("returning status=%s\n", nt_errstr(state
.status
));
358 increment_current_lock_count(fsp
, lock_flav
);
363 /****************************************************************************
364 Utility function called by unlocking requests.
365 ****************************************************************************/
367 NTSTATUS
do_unlock(files_struct
*fsp
,
371 enum brl_flavour lock_flav
)
374 struct byte_range_lock
*br_lck
= NULL
;
376 if (!fsp
->fsp_flags
.can_lock
) {
377 return fsp
->fsp_flags
.is_directory
?
378 NT_STATUS_INVALID_DEVICE_REQUEST
:
379 NT_STATUS_INVALID_HANDLE
;
382 if (!lp_locking(fsp
->conn
->params
)) {
386 DBG_DEBUG("unlock start=%"PRIu64
" len=%"PRIu64
" requested for %s file "
393 br_lck
= brl_get_locks(talloc_tos(), fsp
);
395 return NT_STATUS_NO_MEMORY
;
398 ok
= brl_unlock(br_lck
,
400 messaging_server_id(fsp
->conn
->sconn
->msg_ctx
),
408 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
409 return NT_STATUS_RANGE_NOT_LOCKED
;
412 decrement_current_lock_count(fsp
, lock_flav
);
416 /****************************************************************************
417 Remove any locks on this fd. Called from file_close().
418 ****************************************************************************/
420 void locking_close_file(files_struct
*fsp
,
421 enum file_close_type close_type
)
423 struct byte_range_lock
*br_lck
;
425 if (!lp_locking(fsp
->conn
->params
)) {
429 /* If we have no outstanding locks or pending
430 * locks then we don't need to look in the lock db.
433 if (fsp
->current_lock_count
== 0) {
437 br_lck
= brl_get_locks(talloc_tos(),fsp
);
441 * Unlocks must trigger dbwrap_watch watchers,
442 * normally in smbd_do_unlocking. Here it's done
443 * implicitly, we're closing the file and thus remove a
444 * share mode. This will wake the waiters.
446 brl_close_fnum(br_lck
);
451 /*******************************************************************
452 Print out a share mode.
453 ********************************************************************/
455 char *share_mode_str(TALLOC_CTX
*ctx
, int num
,
456 const struct file_id
*id
,
457 const struct share_mode_entry
*e
)
459 struct server_id_buf tmp
;
460 struct file_id_buf ftmp
;
462 return talloc_asprintf(ctx
, "share_mode_entry[%d]: "
463 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
464 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
465 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
467 server_id_str_buf(e
->pid
, &tmp
),
468 e
->share_access
, e
->private_options
,
469 e
->access_mask
, (unsigned long long)e
->op_mid
,
470 e
->op_type
, (unsigned long long)e
->share_file_id
,
471 (unsigned int)e
->uid
, (unsigned int)e
->flags
,
472 file_id_str_buf(*id
, &ftmp
),
473 (unsigned int)e
->name_hash
);
476 struct rename_share_filename_state
{
477 struct share_mode_data
*data
;
478 struct messaging_context
*msg_ctx
;
479 struct server_id self
;
480 uint32_t orig_name_hash
;
481 uint32_t new_name_hash
;
482 struct file_rename_message msg
;
485 static bool rename_lease_fn(struct share_mode_entry
*e
,
488 struct rename_share_filename_state
*state
= private_data
;
489 struct share_mode_data
*d
= state
->data
;
492 status
= leases_db_rename(&e
->client_guid
,
499 if (!NT_STATUS_IS_OK(status
)) {
500 /* Any error recovery possible here ? */
501 DBG_WARNING("Failed to rename lease key for "
502 "renamed file %s:%s. %s\n",
511 /*******************************************************************
512 Sets the service name and filename for rename.
513 At this point we emit "file renamed" messages to all
514 process id's that have this file open.
515 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
516 ********************************************************************/
518 static bool rename_share_filename_fn(
519 struct share_mode_entry
*e
,
523 struct rename_share_filename_state
*state
= private_data
;
525 enum ndr_err_code ndr_err
;
529 * If this is a hardlink to the inode with a different name,
532 if (e
->name_hash
!= state
->orig_name_hash
) {
535 e
->name_hash
= state
->new_name_hash
;
538 ok
= server_id_equal(&e
->pid
, &state
->self
);
543 state
->msg
.share_file_id
= e
->share_file_id
;
545 ndr_err
= ndr_push_struct_blob(
549 (ndr_push_flags_fn_t
)ndr_push_file_rename_message
);
550 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
551 DBG_DEBUG("ndr_push_file_rename_message failed: %s\n",
552 ndr_errstr(ndr_err
));
555 if (DEBUGLEVEL
>= 10) {
556 struct server_id_buf tmp
;
557 DBG_DEBUG("sending rename message to %s\n",
558 server_id_str_buf(e
->pid
, &tmp
));
559 NDR_PRINT_DEBUG(file_rename_message
, &state
->msg
);
562 messaging_send(state
->msg_ctx
, e
->pid
, MSG_SMB_FILE_RENAME
, &blob
);
564 TALLOC_FREE(blob
.data
);
569 bool rename_share_filename(struct messaging_context
*msg_ctx
,
570 struct share_mode_lock
*lck
,
572 const char *servicepath
,
573 uint32_t orig_name_hash
,
574 uint32_t new_name_hash
,
575 const struct smb_filename
*smb_fname_dst
)
577 struct rename_share_filename_state state
= {
579 .self
= messaging_server_id(msg_ctx
),
580 .orig_name_hash
= orig_name_hash
,
581 .new_name_hash
= new_name_hash
,
583 .msg
.servicepath
= servicepath
,
584 .msg
.base_name
= smb_fname_dst
->base_name
,
585 .msg
.stream_name
= smb_fname_dst
->stream_name
,
587 struct share_mode_data
*d
= NULL
;
591 DBG_DEBUG("servicepath %s newname %s\n",
593 smb_fname_dst
->base_name
);
595 status
= share_mode_lock_access_private_data(lck
, &d
);
596 if (!NT_STATUS_IS_OK(status
)) {
597 /* Any error recovery possible here ? */
598 DBG_ERR("share_mode_lock_access_private_data() failed for "
599 "servicepath %s newname %s - %s\n",
600 servicepath
, smb_fname_dst
->base_name
,
607 * rename_internal_fsp() and rename_internals() add './' to
608 * head of newname if newname does not contain a '/'.
611 if (strncmp(state
.msg
.base_name
, "./", 2) == 0) {
612 state
.msg
.base_name
+= 2;
615 d
->servicepath
= talloc_strdup(d
, state
.msg
.servicepath
);
616 d
->base_name
= talloc_strdup(d
, state
.msg
.base_name
);
617 d
->stream_name
= talloc_strdup(d
, state
.msg
.stream_name
);
618 if ((d
->servicepath
== NULL
) ||
619 (d
->base_name
== NULL
) ||
620 ((state
.msg
.stream_name
!= NULL
) && (d
->stream_name
== NULL
))) {
621 DBG_WARNING("talloc failed\n");
626 ok
= share_mode_forall_entries(
627 lck
, rename_share_filename_fn
, &state
);
629 DBG_WARNING("share_mode_forall_entries failed\n");
632 ok
= share_mode_forall_leases(lck
, rename_lease_fn
, &state
);
635 * Ignore error here. Not sure what to do..
637 DBG_WARNING("share_mode_forall_leases failed\n");
643 void get_file_infos(struct file_id id
,
645 bool *delete_on_close
,
646 struct timespec
*write_time
)
648 struct share_mode_lock
*lck
;
650 if (delete_on_close
) {
651 *delete_on_close
= false;
655 *write_time
= make_omit_timespec();
658 if (!(lck
= fetch_share_mode_unlocked(talloc_tos(), id
))) {
662 if (delete_on_close
) {
663 *delete_on_close
= is_delete_on_close_set(lck
, name_hash
);
667 *write_time
= get_share_mode_write_time(lck
);
673 bool is_valid_share_mode_entry(const struct share_mode_entry
*e
)
681 num_props
+= ((e
->op_type
== NO_OPLOCK
) ? 1 : 0);
682 num_props
+= (EXCLUSIVE_OPLOCK_TYPE(e
->op_type
) ? 1 : 0);
683 num_props
+= (LEVEL_II_OPLOCK_TYPE(e
->op_type
) ? 1 : 0);
684 num_props
+= (e
->op_type
== LEASE_OPLOCK
);
686 if ((num_props
> 1) && serverid_exists(&e
->pid
)) {
687 smb_panic("Invalid share mode entry");
689 return (num_props
!= 0);
692 struct find_lease_ref_state
{
693 const struct GUID
*client_guid
;
694 const struct smb2_lease_key
*lease_key
;
698 static bool find_lease_ref_fn(
699 struct share_mode_entry
*e
,
703 struct find_lease_ref_state
*state
= private_data
;
708 if (e
->op_type
!= LEASE_OPLOCK
) {
712 state
->found_same
= smb2_lease_equal(
718 * If we found a lease reference, look no further (i.e. return true)
720 return state
->found_same
;
723 NTSTATUS
remove_lease_if_stale(struct share_mode_lock
*lck
,
724 const struct GUID
*client_guid
,
725 const struct smb2_lease_key
*lease_key
)
727 struct find_lease_ref_state state
= {
728 .client_guid
= client_guid
, .lease_key
= lease_key
,
730 struct file_id id
= share_mode_lock_file_id(lck
);
734 ok
= share_mode_forall_entries(lck
, find_lease_ref_fn
, &state
);
736 DBG_ERR("share_mode_forall_entries failed\n");
737 return NT_STATUS_INTERNAL_ERROR
;
740 if (state
.found_same
) {
741 return NT_STATUS_RESOURCE_IN_USE
;
744 status
= leases_db_del(client_guid
, lease_key
, &id
);
745 if (!NT_STATUS_IS_OK(status
)) {
746 int level
= DBGLVL_DEBUG
;
748 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
751 DBG_PREFIX(level
, ("leases_db_del failed: %s\n",
757 bool share_entry_stale_pid(struct share_mode_entry
*e
)
759 struct server_id_buf buf
;
766 exists
= serverid_exists(&e
->pid
);
768 DBG_DEBUG("PID %s still exists\n",
769 server_id_str_buf(e
->pid
, &buf
));
773 DBG_DEBUG("PID %s does not exist anymore\n",
774 server_id_str_buf(e
->pid
, &buf
));
781 /****************************************************************************
782 Adds a delete on close token.
783 ****************************************************************************/
785 static bool add_delete_on_close_token(struct share_mode_data
*d
,
786 struct files_struct
*fsp
,
787 const struct security_token
*nt_tok
,
788 const struct security_unix_token
*tok
)
790 struct delete_token
*tmp
, *dtl
;
791 const struct smb2_lease
*lease
= NULL
;
793 tmp
= talloc_realloc(d
, d
->delete_tokens
, struct delete_token
,
794 d
->num_delete_tokens
+1);
798 d
->delete_tokens
= tmp
;
799 dtl
= &d
->delete_tokens
[d
->num_delete_tokens
];
801 dtl
->name_hash
= fsp
->name_hash
;
803 lease
= fsp_get_smb2_lease(fsp
);
805 dtl
->parent_lease_key
= lease
->parent_lease_key
;
808 dtl
->delete_nt_token
= security_token_duplicate(d
->delete_tokens
, nt_tok
);
809 if (dtl
->delete_nt_token
== NULL
) {
812 dtl
->delete_token
= copy_unix_token(d
->delete_tokens
, tok
);
813 if (dtl
->delete_token
== NULL
) {
816 d
->num_delete_tokens
+= 1;
821 void reset_delete_on_close_lck(files_struct
*fsp
,
822 struct share_mode_lock
*lck
)
824 struct share_mode_data
*d
= NULL
;
828 status
= share_mode_lock_access_private_data(lck
, &d
);
829 if (!NT_STATUS_IS_OK(status
)) {
830 /* Any error recovery possible here ? */
831 DBG_ERR("share_mode_lock_access_private_data() failed for "
832 "%s - %s\n", fsp_str_dbg(fsp
), nt_errstr(status
));
833 smb_panic(__location__
);
837 for (i
=0; i
<d
->num_delete_tokens
; i
++) {
838 struct delete_token
*dt
= &d
->delete_tokens
[i
];
840 if (dt
->name_hash
== fsp
->name_hash
) {
843 /* Delete this entry. */
844 TALLOC_FREE(dt
->delete_nt_token
);
845 TALLOC_FREE(dt
->delete_token
);
846 *dt
= d
->delete_tokens
[d
->num_delete_tokens
-1];
847 d
->num_delete_tokens
-= 1;
852 struct set_delete_on_close_state
{
853 struct messaging_context
*msg_ctx
;
857 static bool set_delete_on_close_fn(
858 struct share_mode_entry
*e
,
862 struct set_delete_on_close_state
*state
= private_data
;
865 status
= messaging_send(
868 MSG_SMB_NOTIFY_CANCEL_DELETED
,
871 if (!NT_STATUS_IS_OK(status
)) {
872 struct server_id_buf tmp
;
873 DBG_DEBUG("messaging_send to %s returned %s\n",
874 server_id_str_buf(e
->pid
, &tmp
),
881 /****************************************************************************
882 Sets the delete on close flag over all share modes on this file.
883 Modify the share mode entry for all files open
884 on this device and inode to tell other smbds we have
885 changed the delete on close flag. This will be noticed
886 in the close code, the last closer will delete the file
888 This makes a copy of any struct security_unix_token into the
889 lck entry. This function is used when the lock is already granted.
890 ****************************************************************************/
892 void set_delete_on_close_lck(files_struct
*fsp
,
893 struct share_mode_lock
*lck
,
894 const struct security_token
*nt_tok
,
895 const struct security_unix_token
*tok
)
897 struct share_mode_data
*d
= NULL
;
898 struct set_delete_on_close_state state
= {
899 .msg_ctx
= fsp
->conn
->sconn
->msg_ctx
903 enum ndr_err_code ndr_err
;
906 status
= share_mode_lock_access_private_data(lck
, &d
);
907 if (!NT_STATUS_IS_OK(status
)) {
908 /* Any error recovery possible here ? */
909 DBG_ERR("share_mode_lock_access_private_data() failed for "
910 "%s - %s\n", fsp_str_dbg(fsp
), nt_errstr(status
));
911 smb_panic(__location__
);
915 SMB_ASSERT(nt_tok
!= NULL
);
916 SMB_ASSERT(tok
!= NULL
);
918 for (i
=0; i
<d
->num_delete_tokens
; i
++) {
919 struct delete_token
*dt
= &d
->delete_tokens
[i
];
920 if (dt
->name_hash
== fsp
->name_hash
) {
921 const struct smb2_lease
*lease
= NULL
;
925 /* Replace this token with the given tok. */
926 ZERO_STRUCT(dt
->parent_lease_key
);
927 lease
= fsp_get_smb2_lease(fsp
);
929 dt
->parent_lease_key
= lease
->parent_lease_key
;
932 TALLOC_FREE(dt
->delete_nt_token
);
933 dt
->delete_nt_token
= security_token_duplicate(dt
, nt_tok
);
934 SMB_ASSERT(dt
->delete_nt_token
!= NULL
);
935 TALLOC_FREE(dt
->delete_token
);
936 dt
->delete_token
= copy_unix_token(dt
, tok
);
937 SMB_ASSERT(dt
->delete_token
!= NULL
);
943 ret
= add_delete_on_close_token(d
, fsp
, nt_tok
, tok
);
946 ndr_err
= ndr_push_struct_blob(
950 (ndr_push_flags_fn_t
)ndr_push_file_id
);
951 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
952 DBG_ERR("ndr_push_file_id failed: %s\n",
953 ndr_errstr(ndr_err
));
954 smb_panic(__location__
);
957 ret
= share_mode_forall_entries(
958 lck
, set_delete_on_close_fn
, &state
);
960 DBG_ERR("share_mode_forall_entries failed\n");
961 smb_panic(__location__
);
964 TALLOC_FREE(state
.blob
.data
);
967 struct set_delete_on_close_locked_state
{
968 struct files_struct
*fsp
;
969 bool delete_on_close
;
970 const struct security_token
*nt_tok
;
971 const struct security_unix_token
*tok
;
974 static void set_delete_on_close_locked(struct share_mode_lock
*lck
,
977 struct set_delete_on_close_locked_state
*state
=
978 (struct set_delete_on_close_locked_state
*)private_data
;
980 if (state
->delete_on_close
) {
981 set_delete_on_close_lck(state
->fsp
,
986 reset_delete_on_close_lck(state
->fsp
, lck
);
989 state
->fsp
->fsp_flags
.delete_on_close
= state
->delete_on_close
;
992 bool set_delete_on_close(files_struct
*fsp
, bool delete_on_close
,
993 const struct security_token
*nt_tok
,
994 const struct security_unix_token
*tok
)
996 struct set_delete_on_close_locked_state state
= {
998 .delete_on_close
= delete_on_close
,
1004 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
1006 delete_on_close
? "Adding" : "Removing", fsp_fnum_dbg(fsp
),
1009 if (fsp
->fsp_flags
.is_directory
) {
1010 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp
->fsp_name
));
1013 status
= share_mode_do_locked_vfs_denied(fsp
->file_id
,
1014 set_delete_on_close_locked
,
1016 if (!NT_STATUS_IS_OK(status
)) {
1023 static struct delete_token
*find_delete_on_close_token(
1024 struct share_mode_data
*d
, uint32_t name_hash
)
1028 DBG_DEBUG("name_hash = 0x%"PRIx32
"\n", name_hash
);
1030 for (i
=0; i
<d
->num_delete_tokens
; i
++) {
1031 struct delete_token
*dt
= &d
->delete_tokens
[i
];
1033 DBG_DEBUG("dt->name_hash = 0x%"PRIx32
"\n",
1035 if (dt
->name_hash
== name_hash
) {
1042 /****************************************************************************
1043 Return the NT token and UNIX token if there's a match. Return true if
1044 found, false if not.
1045 ****************************************************************************/
1047 bool get_delete_on_close_token(struct share_mode_lock
*lck
,
1049 const struct security_token
**pp_nt_tok
,
1050 const struct security_unix_token
**pp_tok
,
1051 struct smb2_lease_key
*parent_lease_key
)
1053 struct share_mode_data
*d
= NULL
;
1054 struct delete_token
*dt
;
1057 status
= share_mode_lock_access_private_data(lck
, &d
);
1058 if (!NT_STATUS_IS_OK(status
)) {
1059 struct file_id id
= share_mode_lock_file_id(lck
);
1060 struct file_id_buf id_buf
;
1061 /* Any error recovery possible here ? */
1062 DBG_ERR("share_mode_lock_access_private_data() failed for "
1063 "%s name_hash=%"PRIu32
" - %s\n",
1064 file_id_str_buf(id
, &id_buf
), name_hash
,
1069 dt
= find_delete_on_close_token(d
, name_hash
);
1073 *pp_nt_tok
= dt
->delete_nt_token
;
1074 *pp_tok
= dt
->delete_token
;
1075 *parent_lease_key
= dt
->parent_lease_key
;
1079 bool is_delete_on_close_set(struct share_mode_lock
*lck
, uint32_t name_hash
)
1081 struct share_mode_data
*d
= NULL
;
1084 status
= share_mode_lock_access_private_data(lck
, &d
);
1085 if (!NT_STATUS_IS_OK(status
)) {
1086 struct file_id id
= share_mode_lock_file_id(lck
);
1087 struct file_id_buf id_buf
;
1088 /* Any error recovery possible here ? */
1089 DBG_ERR("share_mode_lock_access_private_data() failed for "
1090 "%s name_hash=%"PRIu32
" - %s\n",
1091 file_id_str_buf(id
, &id_buf
), name_hash
,
1096 return find_delete_on_close_token(d
, name_hash
) != NULL
;
1099 struct set_sticky_write_time_state
{
1100 struct file_id fileid
;
1101 struct timespec write_time
;
1105 static void set_sticky_write_time_fn(struct share_mode_lock
*lck
,
1108 struct set_sticky_write_time_state
*state
= private_data
;
1109 struct share_mode_data
*d
= NULL
;
1110 struct file_id_buf ftmp
;
1111 struct timeval_buf tbuf
;
1114 status
= share_mode_lock_access_private_data(lck
, &d
);
1115 if (!NT_STATUS_IS_OK(status
)) {
1116 /* Any error recovery possible here ? */
1117 DBG_ERR("share_mode_lock_access_private_data() failed for "
1119 timespec_string_buf(&state
->write_time
, true, &tbuf
),
1120 file_id_str_buf(state
->fileid
, &ftmp
),
1125 share_mode_set_changed_write_time(lck
, state
->write_time
);
1130 bool set_sticky_write_time(struct file_id fileid
, struct timespec write_time
)
1132 struct set_sticky_write_time_state state
= {
1134 .write_time
= write_time
,
1136 struct file_id_buf ftmp
;
1137 struct timeval_buf tbuf
;
1140 status
= share_mode_do_locked_vfs_denied(fileid
,
1141 set_sticky_write_time_fn
,
1143 if (!NT_STATUS_IS_OK(status
)) {
1144 /* Any error recovery possible here ? */
1145 DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
1147 timespec_string_buf(&write_time
, true, &tbuf
),
1148 file_id_str_buf(fileid
, &ftmp
),
1156 struct set_write_time_state
{
1157 struct file_id fileid
;
1158 struct timespec write_time
;
1162 static void set_write_time_fn(struct share_mode_lock
*lck
,
1165 struct set_write_time_state
*state
= private_data
;
1166 struct share_mode_data
*d
= NULL
;
1167 struct file_id_buf idbuf
;
1168 struct timeval_buf tbuf
;
1171 status
= share_mode_lock_access_private_data(lck
, &d
);
1172 if (!NT_STATUS_IS_OK(status
)) {
1173 /* Any error recovery possible here ? */
1174 DBG_ERR("share_mode_lock_access_private_data() failed for "
1176 timespec_string_buf(&state
->write_time
, true, &tbuf
),
1177 file_id_str_buf(state
->fileid
, &idbuf
),
1182 share_mode_set_old_write_time(lck
, state
->write_time
);
1187 bool set_write_time(struct file_id fileid
, struct timespec write_time
)
1189 struct set_write_time_state state
= {
1191 .write_time
= write_time
,
1193 struct file_id_buf idbuf
;
1194 struct timeval_buf tbuf
;
1197 status
= share_mode_do_locked_vfs_denied(fileid
,
1200 if (!NT_STATUS_IS_OK(status
)) {
1201 DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
1203 timespec_string_buf(&write_time
, true, &tbuf
),
1204 file_id_str_buf(fileid
, &idbuf
),
1212 struct timespec
get_share_mode_write_time(struct share_mode_lock
*lck
)
1214 struct share_mode_data
*d
= NULL
;
1217 status
= share_mode_lock_access_private_data(lck
, &d
);
1218 if (!NT_STATUS_IS_OK(status
)) {
1219 struct file_id id
= share_mode_lock_file_id(lck
);
1220 struct file_id_buf id_buf
;
1221 struct timespec ts_zero
= {};
1222 /* Any error recovery possible here ? */
1223 DBG_ERR("share_mode_lock_access_private_data() failed for "
1225 file_id_str_buf(id
, &id_buf
),
1227 smb_panic(__location__
);
1231 if (!null_nttime(d
->changed_write_time
)) {
1232 return nt_time_to_full_timespec(d
->changed_write_time
);
1234 return nt_time_to_full_timespec(d
->old_write_time
);
1237 struct file_has_open_streams_state
{
1242 static bool file_has_open_streams_fn(
1243 struct share_mode_entry
*e
,
1247 struct file_has_open_streams_state
*state
= private_data
;
1249 if ((e
->private_options
&
1250 NTCREATEX_FLAG_STREAM_BASEOPEN
) == 0) {
1254 if (share_entry_stale_pid(e
)) {
1258 state
->found_one
= true;
1262 static void file_has_open_streams_locked(struct share_mode_lock
*lck
,
1265 struct file_has_open_streams_state
*state
= private_data
;
1267 state
->ok
= share_mode_forall_entries(lck
,
1268 file_has_open_streams_fn
,
1272 bool file_has_open_streams(files_struct
*fsp
)
1274 struct file_has_open_streams_state state
= { .found_one
= false };
1277 status
= share_mode_do_locked_vfs_denied(fsp
->file_id
,
1278 file_has_open_streams_locked
,
1280 if (!NT_STATUS_IS_OK(status
)) {
1281 DBG_DEBUG("share_mode_do_locked_vfs_denied() failed - %s\n",
1287 DBG_DEBUG("share_mode_forall_entries failed\n");
1291 return state
.found_one
;
1295 * Walk share mode entries, looking at every lease only once
1298 struct share_mode_forall_leases_state
{
1299 TALLOC_CTX
*mem_ctx
;
1300 struct leases_db_key
*leases
;
1301 bool (*fn
)(struct share_mode_entry
*e
,
1302 void *private_data
);
1307 static bool share_mode_forall_leases_fn(
1308 struct share_mode_entry
*e
,
1312 struct share_mode_forall_leases_state
*state
= private_data
;
1313 struct leases_db_key
*leases
= state
->leases
;
1314 size_t i
, num_leases
;
1317 if (e
->op_type
!= LEASE_OPLOCK
) {
1321 num_leases
= talloc_array_length(leases
);
1323 for (i
=0; i
<num_leases
; i
++) {
1324 struct leases_db_key
*l
= &leases
[i
];
1325 bool same
= smb2_lease_equal(
1335 leases
= talloc_realloc(
1338 struct leases_db_key
,
1340 if (leases
== NULL
) {
1341 state
->status
= NT_STATUS_NO_MEMORY
;
1344 leases
[num_leases
] = (struct leases_db_key
) {
1345 .client_guid
= e
->client_guid
,
1346 .lease_key
= e
->lease_key
,
1348 state
->leases
= leases
;
1350 stop
= state
->fn(e
, state
->private_data
);
1354 bool share_mode_forall_leases(
1355 struct share_mode_lock
*lck
,
1356 bool (*fn
)(struct share_mode_entry
*e
,
1357 void *private_data
),
1360 struct share_mode_forall_leases_state state
= {
1361 .mem_ctx
= talloc_tos(),
1363 .private_data
= private_data
1367 ok
= share_mode_forall_entries(
1368 lck
, share_mode_forall_leases_fn
, &state
);
1369 TALLOC_FREE(state
.leases
);
1371 DBG_ERR("share_mode_forall_entries failed\n");
1375 if (!NT_STATUS_IS_OK(state
.status
)) {
1376 DBG_ERR("share_mode_forall_leases_fn returned %s\n",
1377 nt_errstr(state
.status
));