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(
258 bool *modified_dependent
,
261 struct do_lock_state
*state
= private_data
;
262 struct byte_range_lock
*br_lck
= NULL
;
264 br_lck
= brl_get_locks_for_locking(talloc_tos(),
268 if (br_lck
== NULL
) {
269 state
->status
= NT_STATUS_NO_MEMORY
;
273 state
->status
= brl_lock(
276 messaging_server_id(state
->fsp
->conn
->sconn
->msg_ctx
),
282 &state
->blocker_smblctx
);
287 NTSTATUS
do_lock(files_struct
*fsp
,
288 TALLOC_CTX
*req_mem_ctx
,
289 const struct GUID
*req_guid
,
293 enum brl_type lock_type
,
294 enum brl_flavour lock_flav
,
295 struct server_id
*pblocker_pid
,
298 struct do_lock_state state
= {
300 .req_mem_ctx
= req_mem_ctx
,
301 .req_guid
= req_guid
,
305 .lock_type
= lock_type
,
306 .lock_flav
= lock_flav
,
310 /* silently return ok on print files as we don't do locking there */
311 if (fsp
->print_file
) {
315 if (!fsp
->fsp_flags
.can_lock
) {
316 if (fsp
->fsp_flags
.is_directory
) {
317 return NT_STATUS_INVALID_DEVICE_REQUEST
;
319 return NT_STATUS_INVALID_HANDLE
;
322 if (!lp_locking(fsp
->conn
->params
)) {
326 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
328 DBG_DEBUG("lock flavour %s lock type %s start=%"PRIu64
" len=%"PRIu64
" "
329 "requested for %s file %s\n",
330 lock_flav_name(lock_flav
),
331 lock_type_name(lock_type
),
337 status
= share_mode_do_locked(fsp
->file_id
, do_lock_fn
, &state
);
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 * implictly, 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_lock
*lck
;
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
->lck
->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
= {
575 .self
= messaging_server_id(msg_ctx
),
576 .orig_name_hash
= orig_name_hash
,
577 .new_name_hash
= new_name_hash
,
579 .msg
.servicepath
= servicepath
,
580 .msg
.base_name
= smb_fname_dst
->base_name
,
581 .msg
.stream_name
= smb_fname_dst
->stream_name
,
583 struct share_mode_data
*d
= lck
->data
;
586 DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
587 servicepath
, smb_fname_dst
->base_name
));
590 * rename_internal_fsp() and rename_internals() add './' to
591 * head of newname if newname does not contain a '/'.
594 if (strncmp(state
.msg
.base_name
, "./", 2) == 0) {
595 state
.msg
.base_name
+= 2;
598 d
->servicepath
= talloc_strdup(d
, state
.msg
.servicepath
);
599 d
->base_name
= talloc_strdup(d
, state
.msg
.base_name
);
600 d
->stream_name
= talloc_strdup(d
, state
.msg
.stream_name
);
601 if ((d
->servicepath
== NULL
) ||
602 (d
->base_name
== NULL
) ||
603 ((state
.msg
.stream_name
!= NULL
) && (d
->stream_name
== NULL
))) {
604 DBG_WARNING("talloc failed\n");
609 ok
= share_mode_forall_entries(
610 lck
, rename_share_filename_fn
, &state
);
612 DBG_WARNING("share_mode_forall_entries failed\n");
615 ok
= share_mode_forall_leases(lck
, rename_lease_fn
, &state
);
618 * Ignore error here. Not sure what to do..
620 DBG_WARNING("share_mode_forall_leases failed\n");
626 void get_file_infos(struct file_id id
,
628 bool *delete_on_close
,
629 struct timespec
*write_time
)
631 struct share_mode_lock
*lck
;
633 if (delete_on_close
) {
634 *delete_on_close
= false;
638 *write_time
= make_omit_timespec();
641 if (!(lck
= fetch_share_mode_unlocked(talloc_tos(), id
))) {
645 if (delete_on_close
) {
646 *delete_on_close
= is_delete_on_close_set(lck
, name_hash
);
650 *write_time
= get_share_mode_write_time(lck
);
656 bool is_valid_share_mode_entry(const struct share_mode_entry
*e
)
664 num_props
+= ((e
->op_type
== NO_OPLOCK
) ? 1 : 0);
665 num_props
+= (EXCLUSIVE_OPLOCK_TYPE(e
->op_type
) ? 1 : 0);
666 num_props
+= (LEVEL_II_OPLOCK_TYPE(e
->op_type
) ? 1 : 0);
667 num_props
+= (e
->op_type
== LEASE_OPLOCK
);
669 if ((num_props
> 1) && serverid_exists(&e
->pid
)) {
670 smb_panic("Invalid share mode entry");
672 return (num_props
!= 0);
675 struct find_lease_ref_state
{
676 const struct GUID
*client_guid
;
677 const struct smb2_lease_key
*lease_key
;
681 static bool find_lease_ref_fn(
682 struct share_mode_entry
*e
,
686 struct find_lease_ref_state
*state
= private_data
;
691 if (e
->op_type
!= LEASE_OPLOCK
) {
695 state
->found_same
= smb2_lease_equal(
701 * If we found a lease reference, look no further (i.e. return true)
703 return state
->found_same
;
706 NTSTATUS
remove_lease_if_stale(struct share_mode_lock
*lck
,
707 const struct GUID
*client_guid
,
708 const struct smb2_lease_key
*lease_key
)
710 struct find_lease_ref_state state
= {
711 .client_guid
= client_guid
, .lease_key
= lease_key
,
713 struct share_mode_data
*d
= lck
->data
;
717 ok
= share_mode_forall_entries(lck
, find_lease_ref_fn
, &state
);
719 return NT_STATUS_INTERNAL_ERROR
;
722 if (state
.found_same
) {
723 return NT_STATUS_RESOURCE_IN_USE
;
726 status
= leases_db_del(client_guid
, lease_key
, &d
->id
);
727 if (!NT_STATUS_IS_OK(status
)) {
728 int level
= DBGLVL_DEBUG
;
730 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
733 DBG_PREFIX(level
, ("leases_db_del failed: %s\n",
739 bool share_entry_stale_pid(struct share_mode_entry
*e
)
741 struct server_id_buf buf
;
748 exists
= serverid_exists(&e
->pid
);
750 DBG_DEBUG("PID %s still exists\n",
751 server_id_str_buf(e
->pid
, &buf
));
755 DBG_DEBUG("PID %s does not exist anymore\n",
756 server_id_str_buf(e
->pid
, &buf
));
763 /****************************************************************************
764 Adds a delete on close token.
765 ****************************************************************************/
767 static bool add_delete_on_close_token(struct share_mode_data
*d
,
769 const struct security_token
*nt_tok
,
770 const struct security_unix_token
*tok
)
772 struct delete_token
*tmp
, *dtl
;
774 tmp
= talloc_realloc(d
, d
->delete_tokens
, struct delete_token
,
775 d
->num_delete_tokens
+1);
779 d
->delete_tokens
= tmp
;
780 dtl
= &d
->delete_tokens
[d
->num_delete_tokens
];
782 dtl
->name_hash
= name_hash
;
783 dtl
->delete_nt_token
= dup_nt_token(d
->delete_tokens
, nt_tok
);
784 if (dtl
->delete_nt_token
== NULL
) {
787 dtl
->delete_token
= copy_unix_token(d
->delete_tokens
, tok
);
788 if (dtl
->delete_token
== NULL
) {
791 d
->num_delete_tokens
+= 1;
796 void reset_delete_on_close_lck(files_struct
*fsp
,
797 struct share_mode_lock
*lck
)
799 struct share_mode_data
*d
= lck
->data
;
802 for (i
=0; i
<d
->num_delete_tokens
; i
++) {
803 struct delete_token
*dt
= &d
->delete_tokens
[i
];
805 if (dt
->name_hash
== fsp
->name_hash
) {
808 /* Delete this entry. */
809 TALLOC_FREE(dt
->delete_nt_token
);
810 TALLOC_FREE(dt
->delete_token
);
811 *dt
= d
->delete_tokens
[d
->num_delete_tokens
-1];
812 d
->num_delete_tokens
-= 1;
817 struct set_delete_on_close_state
{
818 struct messaging_context
*msg_ctx
;
822 static bool set_delete_on_close_fn(
823 struct share_mode_entry
*e
,
827 struct set_delete_on_close_state
*state
= private_data
;
830 status
= messaging_send(
833 MSG_SMB_NOTIFY_CANCEL_DELETED
,
836 if (!NT_STATUS_IS_OK(status
)) {
837 struct server_id_buf tmp
;
838 DBG_DEBUG("messaging_send to %s returned %s\n",
839 server_id_str_buf(e
->pid
, &tmp
),
846 /****************************************************************************
847 Sets the delete on close flag over all share modes on this file.
848 Modify the share mode entry for all files open
849 on this device and inode to tell other smbds we have
850 changed the delete on close flag. This will be noticed
851 in the close code, the last closer will delete the file
853 This makes a copy of any struct security_unix_token into the
854 lck entry. This function is used when the lock is already granted.
855 ****************************************************************************/
857 void set_delete_on_close_lck(files_struct
*fsp
,
858 struct share_mode_lock
*lck
,
859 const struct security_token
*nt_tok
,
860 const struct security_unix_token
*tok
)
862 struct share_mode_data
*d
= lck
->data
;
863 struct set_delete_on_close_state state
= {
864 .msg_ctx
= fsp
->conn
->sconn
->msg_ctx
868 enum ndr_err_code ndr_err
;
870 SMB_ASSERT(nt_tok
!= NULL
);
871 SMB_ASSERT(tok
!= NULL
);
873 for (i
=0; i
<d
->num_delete_tokens
; i
++) {
874 struct delete_token
*dt
= &d
->delete_tokens
[i
];
875 if (dt
->name_hash
== fsp
->name_hash
) {
878 /* Replace this token with the given tok. */
879 TALLOC_FREE(dt
->delete_nt_token
);
880 dt
->delete_nt_token
= dup_nt_token(dt
, nt_tok
);
881 SMB_ASSERT(dt
->delete_nt_token
!= NULL
);
882 TALLOC_FREE(dt
->delete_token
);
883 dt
->delete_token
= copy_unix_token(dt
, tok
);
884 SMB_ASSERT(dt
->delete_token
!= NULL
);
890 ret
= add_delete_on_close_token(lck
->data
, fsp
->name_hash
, nt_tok
, tok
);
893 ndr_err
= ndr_push_struct_blob(
897 (ndr_push_flags_fn_t
)ndr_push_file_id
);
898 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
899 DEBUG(10, ("ndr_push_file_id failed: %s\n",
900 ndr_errstr(ndr_err
)));
903 ret
= share_mode_forall_entries(
904 lck
, set_delete_on_close_fn
, &state
);
906 DBG_DEBUG("share_mode_forall_entries failed\n");
909 TALLOC_FREE(state
.blob
.data
);
912 bool set_delete_on_close(files_struct
*fsp
, bool delete_on_close
,
913 const struct security_token
*nt_tok
,
914 const struct security_unix_token
*tok
)
916 struct share_mode_lock
*lck
;
918 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
920 delete_on_close
? "Adding" : "Removing", fsp_fnum_dbg(fsp
),
923 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
928 if (delete_on_close
) {
929 set_delete_on_close_lck(fsp
, lck
, nt_tok
, tok
);
931 reset_delete_on_close_lck(fsp
, lck
);
934 if (fsp
->fsp_flags
.is_directory
) {
935 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp
->fsp_name
));
936 send_stat_cache_delete_message(fsp
->conn
->sconn
->msg_ctx
,
937 fsp
->fsp_name
->base_name
);
942 fsp
->fsp_flags
.delete_on_close
= delete_on_close
;
947 static struct delete_token
*find_delete_on_close_token(
948 struct share_mode_data
*d
, uint32_t name_hash
)
952 DBG_DEBUG("name_hash = 0x%"PRIx32
"\n", name_hash
);
954 for (i
=0; i
<d
->num_delete_tokens
; i
++) {
955 struct delete_token
*dt
= &d
->delete_tokens
[i
];
957 DBG_DEBUG("dt->name_hash = 0x%"PRIx32
"\n",
959 if (dt
->name_hash
== name_hash
) {
966 /****************************************************************************
967 Return the NT token and UNIX token if there's a match. Return true if
969 ****************************************************************************/
971 bool get_delete_on_close_token(struct share_mode_lock
*lck
,
973 const struct security_token
**pp_nt_tok
,
974 const struct security_unix_token
**pp_tok
)
976 struct delete_token
*dt
;
978 dt
= find_delete_on_close_token(lck
->data
, name_hash
);
982 *pp_nt_tok
= dt
->delete_nt_token
;
983 *pp_tok
= dt
->delete_token
;
987 bool is_delete_on_close_set(struct share_mode_lock
*lck
, uint32_t name_hash
)
989 return find_delete_on_close_token(lck
->data
, name_hash
) != NULL
;
992 bool set_sticky_write_time(struct file_id fileid
, struct timespec write_time
)
994 struct share_mode_lock
*lck
;
995 struct file_id_buf ftmp
;
996 struct timeval_buf tbuf
;
997 NTTIME nt
= full_timespec_to_nt_time(&write_time
);
999 DBG_INFO("%s id=%s\n",
1000 timespec_string_buf(&write_time
, true, &tbuf
),
1001 file_id_str_buf(fileid
, &ftmp
));
1003 lck
= get_existing_share_mode_lock(talloc_tos(), fileid
);
1008 if (lck
->data
->changed_write_time
!= nt
) {
1009 lck
->data
->modified
= True
;
1010 lck
->data
->changed_write_time
= nt
;
1017 bool set_write_time(struct file_id fileid
, struct timespec write_time
)
1019 struct share_mode_lock
*lck
;
1020 struct file_id_buf idbuf
;
1021 struct timeval_buf tbuf
;
1022 NTTIME nt
= full_timespec_to_nt_time(&write_time
);
1024 DBG_INFO("%s id=%s\n",
1025 timespec_string_buf(&write_time
, true, &tbuf
),
1026 file_id_str_buf(fileid
, &idbuf
));
1028 lck
= get_existing_share_mode_lock(talloc_tos(), fileid
);
1033 if (lck
->data
->old_write_time
!= nt
) {
1034 lck
->data
->modified
= True
;
1035 lck
->data
->old_write_time
= nt
;
1042 struct timespec
get_share_mode_write_time(struct share_mode_lock
*lck
)
1044 struct share_mode_data
*d
= lck
->data
;
1046 if (!null_nttime(d
->changed_write_time
)) {
1047 return nt_time_to_full_timespec(d
->changed_write_time
);
1049 return nt_time_to_full_timespec(d
->old_write_time
);
1052 struct file_has_open_streams_state
{
1056 static bool file_has_open_streams_fn(
1057 struct share_mode_entry
*e
,
1061 struct file_has_open_streams_state
*state
= private_data
;
1063 if ((e
->private_options
&
1064 NTCREATEX_FLAG_STREAM_BASEOPEN
) == 0) {
1068 if (share_entry_stale_pid(e
)) {
1072 state
->found_one
= true;
1076 bool file_has_open_streams(files_struct
*fsp
)
1078 struct file_has_open_streams_state state
= { .found_one
= false };
1079 struct share_mode_lock
*lock
= NULL
;
1082 lock
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
1087 ok
= share_mode_forall_entries(
1088 lock
, file_has_open_streams_fn
, &state
);
1092 DBG_DEBUG("share_mode_forall_entries failed\n");
1095 return state
.found_one
;
1099 * Walk share mode entries, looking at every lease only once
1102 struct share_mode_forall_leases_state
{
1103 TALLOC_CTX
*mem_ctx
;
1104 struct leases_db_key
*leases
;
1105 bool (*fn
)(struct share_mode_entry
*e
,
1106 void *private_data
);
1111 static bool share_mode_forall_leases_fn(
1112 struct share_mode_entry
*e
,
1116 struct share_mode_forall_leases_state
*state
= private_data
;
1117 struct leases_db_key
*leases
= state
->leases
;
1118 size_t i
, num_leases
;
1121 if (e
->op_type
!= LEASE_OPLOCK
) {
1125 num_leases
= talloc_array_length(leases
);
1127 for (i
=0; i
<num_leases
; i
++) {
1128 struct leases_db_key
*l
= &leases
[i
];
1129 bool same
= smb2_lease_equal(
1139 leases
= talloc_realloc(
1142 struct leases_db_key
,
1144 if (leases
== NULL
) {
1145 state
->status
= NT_STATUS_NO_MEMORY
;
1148 leases
[num_leases
] = (struct leases_db_key
) {
1149 .client_guid
= e
->client_guid
,
1150 .lease_key
= e
->lease_key
,
1152 state
->leases
= leases
;
1154 stop
= state
->fn(e
, state
->private_data
);
1158 bool share_mode_forall_leases(
1159 struct share_mode_lock
*lck
,
1160 bool (*fn
)(struct share_mode_entry
*e
,
1161 void *private_data
),
1164 struct share_mode_forall_leases_state state
= {
1165 .mem_ctx
= talloc_tos(),
1167 .private_data
= private_data
1171 ok
= share_mode_forall_entries(
1172 lck
, share_mode_forall_leases_fn
, &state
);
1173 TALLOC_FREE(state
.leases
);
1175 DBG_DEBUG("share_mode_forall_entries failed\n");
1179 if (!NT_STATUS_IS_OK(state
.status
)) {
1180 DBG_DEBUG("share_mode_forall_leases_fn returned %s\n",
1181 nt_errstr(state
.status
));