s3:locking: ensure all share mode removal functions go through a common lease refcoun...
[Samba.git] / source3 / locking / locking.c
blobf96887e683239140954741f2d56666bb72cd3407
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 "system/filesys.h"
40 #include "locking/proto.h"
41 #include "smbd/globals.h"
42 #include "dbwrap/dbwrap.h"
43 #include "dbwrap/dbwrap_open.h"
44 #include "../libcli/security/security.h"
45 #include "serverid.h"
46 #include "messages.h"
47 #include "util_tdb.h"
48 #include "../librpc/gen_ndr/ndr_open_files.h"
49 #include "locking/leases_db.h"
51 #undef DBGC_CLASS
52 #define DBGC_CLASS DBGC_LOCKING
54 #define NO_LOCKING_COUNT (-1)
56 /****************************************************************************
57 Debugging aids :-).
58 ****************************************************************************/
60 const char *lock_type_name(enum brl_type lock_type)
62 switch (lock_type) {
63 case READ_LOCK:
64 return "READ";
65 case WRITE_LOCK:
66 return "WRITE";
67 case PENDING_READ_LOCK:
68 return "PENDING_READ";
69 case PENDING_WRITE_LOCK:
70 return "PENDING_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_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 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
121 (plock->lock_type == READ_LOCK ||
122 plock->lock_type == WRITE_LOCK)) {
123 DEBUG(10, ("is_locked: optimisation - exclusive oplock "
124 "on file %s\n", fsp_str_dbg(fsp)));
125 return true;
127 if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
128 (plock->lock_type == READ_LOCK)) {
129 DEBUG(10, ("is_locked: optimisation - level II oplock "
130 "on file %s\n", fsp_str_dbg(fsp)));
131 return true;
135 br_lck = brl_get_locks_readonly(fsp);
136 if (!br_lck) {
137 return true;
139 ret = brl_locktest(br_lck, plock);
141 if (!ret) {
143 * We got a lock conflict. Retry with rw locks to enable
144 * autocleanup. This is the slow path anyway.
146 br_lck = brl_get_locks(talloc_tos(), fsp);
147 ret = brl_locktest(br_lck, plock);
148 TALLOC_FREE(br_lck);
151 DEBUG(10, ("strict_lock_default: flavour = %s brl start=%ju "
152 "len=%ju %s for fnum %ju file %s\n",
153 lock_flav_name(plock->lock_flav),
154 (uintmax_t)plock->start, (uintmax_t)plock->size,
155 ret ? "unlocked" : "locked",
156 (uintmax_t)plock->fnum, fsp_str_dbg(fsp)));
158 return ret;
161 void strict_unlock_default(files_struct *fsp, struct lock_struct *plock)
165 /****************************************************************************
166 Find out if a lock could be granted - return who is blocking us if we can't.
167 ****************************************************************************/
169 NTSTATUS query_lock(files_struct *fsp,
170 uint64_t *psmblctx,
171 uint64_t *pcount,
172 uint64_t *poffset,
173 enum brl_type *plock_type,
174 enum brl_flavour lock_flav)
176 struct byte_range_lock *br_lck = NULL;
178 if (!fsp->can_lock) {
179 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
182 if (!lp_locking(fsp->conn->params)) {
183 return NT_STATUS_OK;
186 br_lck = brl_get_locks_readonly(fsp);
187 if (!br_lck) {
188 return NT_STATUS_NO_MEMORY;
191 return brl_lockquery(br_lck,
192 psmblctx,
193 messaging_server_id(fsp->conn->sconn->msg_ctx),
194 poffset,
195 pcount,
196 plock_type,
197 lock_flav);
200 static void increment_current_lock_count(files_struct *fsp,
201 enum brl_flavour lock_flav)
203 if (lock_flav == WINDOWS_LOCK &&
204 fsp->current_lock_count != NO_LOCKING_COUNT) {
205 /* blocking ie. pending, locks also count here,
206 * as this is an efficiency counter to avoid checking
207 * the lock db. on close. JRA. */
209 fsp->current_lock_count++;
210 } else {
211 /* Notice that this has had a POSIX lock request.
212 * We can't count locks after this so forget them.
214 fsp->current_lock_count = NO_LOCKING_COUNT;
218 static void decrement_current_lock_count(files_struct *fsp,
219 enum brl_flavour lock_flav)
221 if (lock_flav == WINDOWS_LOCK &&
222 fsp->current_lock_count != NO_LOCKING_COUNT) {
223 SMB_ASSERT(fsp->current_lock_count > 0);
224 fsp->current_lock_count--;
228 /****************************************************************************
229 Utility function called by locking requests.
230 ****************************************************************************/
232 struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
233 files_struct *fsp,
234 uint64_t smblctx,
235 uint64_t count,
236 uint64_t offset,
237 enum brl_type lock_type,
238 enum brl_flavour lock_flav,
239 bool blocking_lock,
240 NTSTATUS *perr,
241 uint64_t *psmblctx)
243 struct byte_range_lock *br_lck = NULL;
245 /* silently return ok on print files as we don't do locking there */
246 if (fsp->print_file) {
247 *perr = NT_STATUS_OK;
248 return NULL;
251 if (!fsp->can_lock) {
252 *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
253 return NULL;
256 if (!lp_locking(fsp->conn->params)) {
257 *perr = NT_STATUS_OK;
258 return NULL;
261 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
263 DEBUG(10,("do_lock: lock flavour %s lock type %s start=%ju len=%ju "
264 "blocking_lock=%s requested for %s file %s\n",
265 lock_flav_name(lock_flav), lock_type_name(lock_type),
266 (uintmax_t)offset, (uintmax_t)count, blocking_lock ? "true" :
267 "false", fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
269 br_lck = brl_get_locks(talloc_tos(), fsp);
270 if (!br_lck) {
271 *perr = NT_STATUS_NO_MEMORY;
272 return NULL;
275 *perr = brl_lock(msg_ctx,
276 br_lck,
277 smblctx,
278 messaging_server_id(fsp->conn->sconn->msg_ctx),
279 offset,
280 count,
281 lock_type,
282 lock_flav,
283 blocking_lock,
284 psmblctx);
286 DEBUG(10, ("do_lock: returning status=%s\n", nt_errstr(*perr)));
288 increment_current_lock_count(fsp, lock_flav);
289 return br_lck;
292 /****************************************************************************
293 Utility function called by unlocking requests.
294 ****************************************************************************/
296 NTSTATUS do_unlock(struct messaging_context *msg_ctx,
297 files_struct *fsp,
298 uint64_t smblctx,
299 uint64_t count,
300 uint64_t offset,
301 enum brl_flavour lock_flav)
303 bool ok = False;
304 struct byte_range_lock *br_lck = NULL;
306 if (!fsp->can_lock) {
307 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
310 if (!lp_locking(fsp->conn->params)) {
311 return NT_STATUS_OK;
314 DEBUG(10, ("do_unlock: unlock start=%ju len=%ju requested for %s file "
315 "%s\n", (uintmax_t)offset, (uintmax_t)count,
316 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
318 br_lck = brl_get_locks(talloc_tos(), fsp);
319 if (!br_lck) {
320 return NT_STATUS_NO_MEMORY;
323 ok = brl_unlock(msg_ctx,
324 br_lck,
325 smblctx,
326 messaging_server_id(fsp->conn->sconn->msg_ctx),
327 offset,
328 count,
329 lock_flav);
331 TALLOC_FREE(br_lck);
333 if (!ok) {
334 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
335 return NT_STATUS_RANGE_NOT_LOCKED;
338 decrement_current_lock_count(fsp, lock_flav);
339 return NT_STATUS_OK;
342 /****************************************************************************
343 Cancel any pending blocked locks.
344 ****************************************************************************/
346 NTSTATUS do_lock_cancel(files_struct *fsp,
347 uint64 smblctx,
348 uint64_t count,
349 uint64_t offset,
350 enum brl_flavour lock_flav)
352 bool ok = False;
353 struct byte_range_lock *br_lck = NULL;
355 if (!fsp->can_lock) {
356 return fsp->is_directory ?
357 NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
360 if (!lp_locking(fsp->conn->params)) {
361 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
364 DEBUG(10, ("do_lock_cancel: cancel start=%ju len=%ju requested for "
365 "%s file %s\n", (uintmax_t)offset, (uintmax_t)count,
366 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
368 br_lck = brl_get_locks(talloc_tos(), fsp);
369 if (!br_lck) {
370 return NT_STATUS_NO_MEMORY;
373 ok = brl_lock_cancel(br_lck,
374 smblctx,
375 messaging_server_id(fsp->conn->sconn->msg_ctx),
376 offset,
377 count,
378 lock_flav);
380 TALLOC_FREE(br_lck);
382 if (!ok) {
383 DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
384 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
387 decrement_current_lock_count(fsp, lock_flav);
388 return NT_STATUS_OK;
391 /****************************************************************************
392 Remove any locks on this fd. Called from file_close().
393 ****************************************************************************/
395 void locking_close_file(struct messaging_context *msg_ctx,
396 files_struct *fsp,
397 enum file_close_type close_type)
399 struct byte_range_lock *br_lck;
401 if (!lp_locking(fsp->conn->params)) {
402 return;
405 /* If we have no outstanding locks or pending
406 * locks then we don't need to look in the lock db.
409 if (fsp->current_lock_count == 0) {
410 return;
413 br_lck = brl_get_locks(talloc_tos(),fsp);
415 if (br_lck) {
416 cancel_pending_lock_requests_by_fid(fsp, br_lck, close_type);
417 brl_close_fnum(msg_ctx, br_lck);
418 TALLOC_FREE(br_lck);
422 /*******************************************************************
423 Print out a share mode.
424 ********************************************************************/
426 char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
428 return talloc_asprintf(ctx, "share_mode_entry[%d]: "
429 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
430 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
431 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
432 num,
433 procid_str_static(&e->pid),
434 e->share_access, e->private_options,
435 e->access_mask, (unsigned long long)e->op_mid,
436 e->op_type, (unsigned long long)e->share_file_id,
437 (unsigned int)e->uid, (unsigned int)e->flags,
438 file_id_string_tos(&e->id),
439 (unsigned int)e->name_hash);
442 /*******************************************************************
443 Fetch a share mode where we know one MUST exist. This call reference
444 counts it internally to allow for nested lock fetches.
445 ********************************************************************/
447 struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
448 const struct file_id id)
450 return get_share_mode_lock(mem_ctx, id, NULL, NULL, NULL);
453 /*******************************************************************
454 Sets the service name and filename for rename.
455 At this point we emit "file renamed" messages to all
456 process id's that have this file open.
457 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
458 ********************************************************************/
460 bool rename_share_filename(struct messaging_context *msg_ctx,
461 struct share_mode_lock *lck,
462 struct file_id id,
463 const char *servicepath,
464 uint32_t orig_name_hash,
465 uint32_t new_name_hash,
466 const struct smb_filename *smb_fname_dst)
468 struct share_mode_data *d = lck->data;
469 size_t sp_len;
470 size_t bn_len;
471 size_t sn_len;
472 size_t msg_len;
473 char *frm = NULL;
474 int i;
475 bool strip_two_chars = false;
476 bool has_stream = smb_fname_dst->stream_name != NULL;
477 struct server_id self_pid = messaging_server_id(msg_ctx);
479 DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
480 servicepath, smb_fname_dst->base_name));
483 * rename_internal_fsp() and rename_internals() add './' to
484 * head of newname if newname does not contain a '/'.
486 if (smb_fname_dst->base_name[0] &&
487 smb_fname_dst->base_name[1] &&
488 smb_fname_dst->base_name[0] == '.' &&
489 smb_fname_dst->base_name[1] == '/') {
490 strip_two_chars = true;
493 d->servicepath = talloc_strdup(d, servicepath);
494 d->base_name = talloc_strdup(d, smb_fname_dst->base_name +
495 (strip_two_chars ? 2 : 0));
496 d->stream_name = talloc_strdup(d, smb_fname_dst->stream_name);
497 if (d->base_name == NULL ||
498 (has_stream && d->stream_name == NULL) ||
499 d->servicepath == NULL) {
500 DEBUG(0, ("rename_share_filename: talloc failed\n"));
501 return False;
503 d->modified = True;
505 sp_len = strlen(d->servicepath);
506 bn_len = strlen(d->base_name);
507 sn_len = has_stream ? strlen(d->stream_name) : 0;
509 msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + bn_len + 1 +
510 sn_len + 1;
512 /* Set up the name changed message. */
513 frm = talloc_array(d, char, msg_len);
514 if (!frm) {
515 return False;
518 push_file_id_24(frm, &id);
520 DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len ));
522 strlcpy(&frm[24],
523 d->servicepath ? d->servicepath : "",
524 sp_len+1);
525 strlcpy(&frm[24 + sp_len + 1],
526 d->base_name ? d->base_name : "",
527 bn_len+1);
528 strlcpy(&frm[24 + sp_len + 1 + bn_len + 1],
529 d->stream_name ? d->stream_name : "",
530 sn_len+1);
532 /* Send the messages. */
533 for (i=0; i<d->num_share_modes; i++) {
534 struct share_mode_entry *se = &d->share_modes[i];
535 if (!is_valid_share_mode_entry(se)) {
536 continue;
539 /* If this is a hardlink to the inode
540 with a different name, skip this. */
541 if (se->name_hash != orig_name_hash) {
542 continue;
545 se->name_hash = new_name_hash;
547 /* But not to ourselves... */
548 if (serverid_equal(&se->pid, &self_pid)) {
549 continue;
552 if (share_mode_stale_pid(d, i)) {
553 continue;
556 DEBUG(10,("rename_share_filename: sending rename message to "
557 "pid %s file_id %s sharepath %s base_name %s "
558 "stream_name %s\n",
559 procid_str_static(&se->pid),
560 file_id_string_tos(&id),
561 d->servicepath, d->base_name,
562 has_stream ? d->stream_name : ""));
564 messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME,
565 (uint8 *)frm, msg_len);
568 return True;
571 void get_file_infos(struct file_id id,
572 uint32_t name_hash,
573 bool *delete_on_close,
574 struct timespec *write_time)
576 struct share_mode_lock *lck;
578 if (delete_on_close) {
579 *delete_on_close = false;
582 if (write_time) {
583 ZERO_STRUCTP(write_time);
586 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
587 return;
590 if (delete_on_close) {
591 *delete_on_close = is_delete_on_close_set(lck, name_hash);
594 if (write_time) {
595 *write_time = get_share_mode_write_time(lck);
598 TALLOC_FREE(lck);
601 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
603 int num_props = 0;
605 if (e->stale) {
606 return false;
609 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
610 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
611 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
612 num_props += (e->op_type == LEASE_OPLOCK);
614 if ((num_props > 1) && serverid_exists(&e->pid)) {
615 smb_panic("Invalid share mode entry");
617 return (num_props != 0);
621 * See if we need to remove a lease being referred to by a
622 * share mode that is being marked stale or deleted.
625 static void remove_share_mode_lease(struct share_mode_data *d,
626 struct share_mode_entry *e)
628 struct GUID client_guid;
629 struct smb2_lease_key lease_key;
630 uint16_t op_type;
631 uint32_t lease_idx;
632 uint32_t i;
634 op_type = e->op_type;
635 e->op_type = NO_OPLOCK;
637 d->modified = true;
639 if (op_type != LEASE_OPLOCK) {
640 return;
644 * This used to reference a lease. If there's no other one referencing
645 * it, remove it.
648 lease_idx = e->lease_idx;
649 e->lease_idx = UINT32_MAX;
651 for (i=0; i<d->num_share_modes; i++) {
652 if (d->share_modes[i].stale) {
653 continue;
655 if (e == &d->share_modes[i]) {
656 /* Not ourselves. */
657 continue;
659 if (d->share_modes[i].lease_idx == lease_idx) {
660 break;
663 if (i < d->num_share_modes) {
665 * Found another one
667 return;
670 memcpy(&client_guid,
671 &d->leases[lease_idx].client_guid,
672 sizeof(client_guid));
673 lease_key = d->leases[lease_idx].lease_key;
675 d->num_leases -= 1;
676 d->leases[lease_idx] = d->leases[d->num_leases];
679 * We changed the lease array. Fix all references to it.
681 for (i=0; i<d->num_share_modes; i++) {
682 if (d->share_modes[i].lease_idx == d->num_leases) {
683 d->share_modes[i].lease_idx = lease_idx;
684 d->share_modes[i].lease = &d->leases[lease_idx];
689 NTSTATUS status;
691 status = leases_db_del(&client_guid,
692 &lease_key,
693 &e->id);
695 DEBUG(10, ("%s: leases_db_del returned %s\n", __func__,
696 nt_errstr(status)));
701 * In case d->share_modes[i] conflicts with something or otherwise is
702 * being used, we need to make sure the corresponding process still
703 * exists.
705 bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
707 struct share_mode_entry *e;
709 if (idx > d->num_share_modes) {
710 DEBUG(1, ("Asking for index %u, only %u around\n",
711 idx, (unsigned)d->num_share_modes));
712 return false;
714 e = &d->share_modes[idx];
715 if (e->stale) {
717 * Checked before
719 return true;
721 if (serverid_exists(&e->pid)) {
722 DEBUG(10, ("PID %s (index %u out of %u) still exists\n",
723 procid_str_static(&e->pid), idx,
724 (unsigned)d->num_share_modes));
725 return false;
727 DEBUG(10, ("PID %s (index %u out of %u) does not exist anymore\n",
728 procid_str_static(&e->pid), idx,
729 (unsigned)d->num_share_modes));
731 e->stale = true;
733 if (d->num_delete_tokens != 0) {
734 uint32_t i, num_stale;
737 * We cannot have any delete tokens
738 * if there are no valid share modes.
741 num_stale = 0;
743 for (i=0; i<d->num_share_modes; i++) {
744 if (d->share_modes[i].stale) {
745 num_stale += 1;
749 if (num_stale == d->num_share_modes) {
751 * No non-stale share mode found
753 TALLOC_FREE(d->delete_tokens);
754 d->num_delete_tokens = 0;
758 remove_share_mode_lease(d, e);
760 d->modified = true;
761 return true;
764 void remove_stale_share_mode_entries(struct share_mode_data *d)
766 uint32_t i;
768 i = 0;
769 while (i < d->num_share_modes) {
770 if (d->share_modes[i].stale) {
771 struct share_mode_entry *m = d->share_modes;
772 m[i] = m[d->num_share_modes-1];
773 d->num_share_modes -= 1;
774 } else {
775 i += 1;
780 bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
781 uid_t uid, uint64_t mid, uint16_t op_type,
782 uint32_t lease_idx)
784 struct share_mode_data *d = lck->data;
785 struct share_mode_entry *tmp, *e;
786 struct share_mode_lease *lease = NULL;
788 if (lease_idx == UINT32_MAX) {
789 lease = NULL;
790 } else if (lease_idx >= d->num_leases) {
791 return false;
792 } else {
793 lease = &d->leases[lease_idx];
796 tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry,
797 d->num_share_modes+1);
798 if (tmp == NULL) {
799 return false;
801 d->share_modes = tmp;
802 e = &d->share_modes[d->num_share_modes];
803 d->num_share_modes += 1;
804 d->modified = true;
806 ZERO_STRUCTP(e);
807 e->pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
808 e->share_access = fsp->share_access;
809 e->private_options = fsp->fh->private_options;
810 e->access_mask = fsp->access_mask;
811 e->op_mid = mid;
812 e->op_type = op_type;
813 e->lease_idx = lease_idx;
814 e->lease = lease;
815 e->time.tv_sec = fsp->open_time.tv_sec;
816 e->time.tv_usec = fsp->open_time.tv_usec;
817 e->id = fsp->file_id;
818 e->share_file_id = fsp->fh->gen_id;
819 e->uid = (uint32)uid;
820 e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
821 e->name_hash = fsp->name_hash;
823 return true;
826 static struct share_mode_entry *find_share_mode_entry(
827 struct share_mode_lock *lck, files_struct *fsp)
829 struct share_mode_data *d = lck->data;
830 struct server_id pid;
831 int i;
833 pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
835 for (i=0; i<d->num_share_modes; i++) {
836 struct share_mode_entry *e = &d->share_modes[i];
838 if (!is_valid_share_mode_entry(e)) {
839 continue;
841 if (!serverid_equal(&pid, &e->pid)) {
842 continue;
844 if (!file_id_equal(&fsp->file_id, &e->id)) {
845 continue;
847 if (fsp->fh->gen_id != e->share_file_id) {
848 continue;
850 return e;
852 return NULL;
855 /*******************************************************************
856 Del the share mode of a file for this process. Return the number of
857 entries left.
858 ********************************************************************/
860 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
862 struct share_mode_entry *e;
864 e = find_share_mode_entry(lck, fsp);
865 if (e == NULL) {
866 return False;
868 remove_share_mode_lease(lck->data, e);
869 *e = lck->data->share_modes[lck->data->num_share_modes-1];
870 lck->data->num_share_modes -= 1;
871 lck->data->modified = True;
872 return True;
875 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
876 struct files_struct *fsp)
878 struct share_mode_entry *e;
880 if (lck->data->num_share_modes != 1) {
881 return false;
884 if (fsp->op == NULL) {
885 return false;
887 if (!fsp->op->global->durable) {
888 return false;
891 e = find_share_mode_entry(lck, fsp);
892 if (e == NULL) {
893 return false;
896 DEBUG(10, ("Marking share mode entry disconnected for durable handle\n"));
898 server_id_set_disconnected(&e->pid);
901 * On reopen the caller needs to check that
902 * the client comes with the correct handle.
904 e->share_file_id = fsp->op->global->open_persistent_id;
906 lck->data->modified = true;
907 return true;
910 /*******************************************************************
911 Remove an oplock mid and mode entry from a share mode.
912 ********************************************************************/
914 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
916 struct share_mode_data *d = lck->data;
917 struct share_mode_entry *e;
919 e = find_share_mode_entry(lck, fsp);
920 if (e == NULL) {
921 return False;
924 remove_share_mode_lease(d, e);
925 d->modified = True;
926 return true;
929 /*******************************************************************
930 Downgrade a oplock type from exclusive to level II.
931 ********************************************************************/
933 bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
935 struct share_mode_entry *e;
937 e = find_share_mode_entry(lck, fsp);
938 if (e == NULL) {
939 return False;
942 e->op_type = LEVEL_II_OPLOCK;
943 lck->data->modified = True;
944 return True;
947 /****************************************************************************
948 Adds a delete on close token.
949 ****************************************************************************/
951 static bool add_delete_on_close_token(struct share_mode_data *d,
952 uint32_t name_hash,
953 const struct security_token *nt_tok,
954 const struct security_unix_token *tok)
956 struct delete_token *tmp, *dtl;
958 tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
959 d->num_delete_tokens+1);
960 if (tmp == NULL) {
961 return false;
963 d->delete_tokens = tmp;
964 dtl = &d->delete_tokens[d->num_delete_tokens];
966 dtl->name_hash = name_hash;
967 dtl->delete_nt_token = dup_nt_token(d->delete_tokens, nt_tok);
968 if (dtl->delete_nt_token == NULL) {
969 return false;
971 dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
972 if (dtl->delete_token == NULL) {
973 return false;
975 d->num_delete_tokens += 1;
976 d->modified = true;
977 return true;
980 /****************************************************************************
981 Sets the delete on close flag over all share modes on this file.
982 Modify the share mode entry for all files open
983 on this device and inode to tell other smbds we have
984 changed the delete on close flag. This will be noticed
985 in the close code, the last closer will delete the file
986 if flag is set.
987 This makes a copy of any struct security_unix_token into the
988 lck entry. This function is used when the lock is already granted.
989 ****************************************************************************/
991 void set_delete_on_close_lck(files_struct *fsp,
992 struct share_mode_lock *lck,
993 bool delete_on_close,
994 const struct security_token *nt_tok,
995 const struct security_unix_token *tok)
997 struct share_mode_data *d = lck->data;
998 int i;
999 bool ret;
1001 if (delete_on_close) {
1002 SMB_ASSERT(nt_tok != NULL);
1003 SMB_ASSERT(tok != NULL);
1004 } else {
1005 SMB_ASSERT(nt_tok == NULL);
1006 SMB_ASSERT(tok == NULL);
1009 for (i=0; i<d->num_delete_tokens; i++) {
1010 struct delete_token *dt = &d->delete_tokens[i];
1011 if (dt->name_hash == fsp->name_hash) {
1012 d->modified = true;
1013 if (delete_on_close == false) {
1014 /* Delete this entry. */
1015 TALLOC_FREE(dt->delete_nt_token);
1016 TALLOC_FREE(dt->delete_token);
1017 *dt = d->delete_tokens[
1018 d->num_delete_tokens-1];
1019 d->num_delete_tokens -= 1;
1020 } else {
1021 /* Replace this token with the
1022 given tok. */
1023 TALLOC_FREE(dt->delete_nt_token);
1024 dt->delete_nt_token = dup_nt_token(dt, nt_tok);
1025 SMB_ASSERT(dt->delete_nt_token != NULL);
1026 TALLOC_FREE(dt->delete_token);
1027 dt->delete_token = copy_unix_token(dt, tok);
1028 SMB_ASSERT(dt->delete_token != NULL);
1030 return;
1034 if (!delete_on_close) {
1035 /* Nothing to delete - not found. */
1036 return;
1039 ret = add_delete_on_close_token(lck->data, fsp->name_hash, nt_tok, tok);
1040 SMB_ASSERT(ret);
1043 bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
1044 const struct security_token *nt_tok,
1045 const struct security_unix_token *tok)
1047 struct share_mode_lock *lck;
1049 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
1050 "%s, file %s\n",
1051 delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
1052 fsp_str_dbg(fsp)));
1054 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1055 if (lck == NULL) {
1056 return False;
1059 if (delete_on_close) {
1060 set_delete_on_close_lck(fsp, lck, true,
1061 nt_tok,
1062 tok);
1063 } else {
1064 set_delete_on_close_lck(fsp, lck, false,
1065 NULL,
1066 NULL);
1069 if (fsp->is_directory) {
1070 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
1071 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
1072 fsp->fsp_name->base_name);
1075 TALLOC_FREE(lck);
1077 fsp->delete_on_close = delete_on_close;
1079 return True;
1082 static struct delete_token *find_delete_on_close_token(
1083 struct share_mode_data *d, uint32_t name_hash)
1085 uint32_t i;
1087 DEBUG(10, ("find_delete_on_close_token: name_hash = 0x%x\n",
1088 (unsigned int)name_hash));
1090 for (i=0; i<d->num_delete_tokens; i++) {
1091 struct delete_token *dt = &d->delete_tokens[i];
1093 DEBUG(10, ("find__delete_on_close_token: dt->name_hash = 0x%x\n",
1094 (unsigned int)dt->name_hash ));
1095 if (dt->name_hash == name_hash) {
1096 return dt;
1099 return NULL;
1102 /****************************************************************************
1103 Return the NT token and UNIX token if there's a match. Return true if
1104 found, false if not.
1105 ****************************************************************************/
1107 bool get_delete_on_close_token(struct share_mode_lock *lck,
1108 uint32_t name_hash,
1109 const struct security_token **pp_nt_tok,
1110 const struct security_unix_token **pp_tok)
1112 struct delete_token *dt;
1114 dt = find_delete_on_close_token(lck->data, name_hash);
1115 if (dt == NULL) {
1116 return false;
1118 *pp_nt_tok = dt->delete_nt_token;
1119 *pp_tok = dt->delete_token;
1120 return true;
1123 bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
1125 return find_delete_on_close_token(lck->data, name_hash) != NULL;
1128 bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
1130 struct share_mode_lock *lck;
1132 DEBUG(5,("set_sticky_write_time: %s id=%s\n",
1133 timestring(talloc_tos(),
1134 convert_timespec_to_time_t(write_time)),
1135 file_id_string_tos(&fileid)));
1137 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1138 if (lck == NULL) {
1139 return False;
1142 if (timespec_compare(&lck->data->changed_write_time, &write_time) != 0) {
1143 lck->data->modified = True;
1144 lck->data->changed_write_time = write_time;
1147 TALLOC_FREE(lck);
1148 return True;
1151 bool set_write_time(struct file_id fileid, struct timespec write_time)
1153 struct share_mode_lock *lck;
1155 DEBUG(5,("set_write_time: %s id=%s\n",
1156 timestring(talloc_tos(),
1157 convert_timespec_to_time_t(write_time)),
1158 file_id_string_tos(&fileid)));
1160 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1161 if (lck == NULL) {
1162 return False;
1165 if (timespec_compare(&lck->data->old_write_time, &write_time) != 0) {
1166 lck->data->modified = True;
1167 lck->data->old_write_time = write_time;
1170 TALLOC_FREE(lck);
1171 return True;
1174 struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
1176 struct share_mode_data *d = lck->data;
1178 if (!null_timespec(d->changed_write_time)) {
1179 return d->changed_write_time;
1181 return d->old_write_time;