torture3: Fix a typo
[Samba.git] / source3 / locking / locking.c
blob221d6ee8d6e49c91a7d5dffa4dc392fa3d603110
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 uint32_t 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 for (i=0; i<d->num_leases; i++) {
569 /* Update the filename in leases_db. */
570 NTSTATUS status;
571 struct share_mode_lease *l;
573 l = &d->leases[i];
575 status = leases_db_rename(&l->client_guid,
576 &l->lease_key,
577 &id,
578 d->servicepath,
579 d->base_name,
580 d->stream_name);
581 if (!NT_STATUS_IS_OK(status)) {
582 /* Any error recovery possible here ? */
583 DEBUG(1,("Failed to rename lease key for "
584 "renamed file %s:%s. %s\n",
585 d->base_name,
586 d->stream_name,
587 nt_errstr(status)));
588 continue;
592 return True;
595 void get_file_infos(struct file_id id,
596 uint32_t name_hash,
597 bool *delete_on_close,
598 struct timespec *write_time)
600 struct share_mode_lock *lck;
602 if (delete_on_close) {
603 *delete_on_close = false;
606 if (write_time) {
607 ZERO_STRUCTP(write_time);
610 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
611 return;
614 if (delete_on_close) {
615 *delete_on_close = is_delete_on_close_set(lck, name_hash);
618 if (write_time) {
619 *write_time = get_share_mode_write_time(lck);
622 TALLOC_FREE(lck);
625 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
627 int num_props = 0;
629 if (e->stale) {
630 return false;
633 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
634 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
635 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
636 num_props += (e->op_type == LEASE_OPLOCK);
638 if ((num_props > 1) && serverid_exists(&e->pid)) {
639 smb_panic("Invalid share mode entry");
641 return (num_props != 0);
645 * See if we need to remove a lease being referred to by a
646 * share mode that is being marked stale or deleted.
649 static void remove_share_mode_lease(struct share_mode_data *d,
650 struct share_mode_entry *e)
652 struct GUID client_guid;
653 struct smb2_lease_key lease_key;
654 uint16_t op_type;
655 uint32_t lease_idx;
656 uint32_t i;
658 op_type = e->op_type;
659 e->op_type = NO_OPLOCK;
661 d->modified = true;
663 if (op_type != LEASE_OPLOCK) {
664 return;
668 * This used to reference a lease. If there's no other one referencing
669 * it, remove it.
672 lease_idx = e->lease_idx;
673 e->lease_idx = UINT32_MAX;
675 for (i=0; i<d->num_share_modes; i++) {
676 if (d->share_modes[i].stale) {
677 continue;
679 if (e == &d->share_modes[i]) {
680 /* Not ourselves. */
681 continue;
683 if (d->share_modes[i].lease_idx == lease_idx) {
684 break;
687 if (i < d->num_share_modes) {
689 * Found another one
691 return;
694 memcpy(&client_guid,
695 &d->leases[lease_idx].client_guid,
696 sizeof(client_guid));
697 lease_key = d->leases[lease_idx].lease_key;
699 d->num_leases -= 1;
700 d->leases[lease_idx] = d->leases[d->num_leases];
703 * We changed the lease array. Fix all references to it.
705 for (i=0; i<d->num_share_modes; i++) {
706 if (d->share_modes[i].lease_idx == d->num_leases) {
707 d->share_modes[i].lease_idx = lease_idx;
708 d->share_modes[i].lease = &d->leases[lease_idx];
713 NTSTATUS status;
715 status = leases_db_del(&client_guid,
716 &lease_key,
717 &e->id);
719 DEBUG(10, ("%s: leases_db_del returned %s\n", __func__,
720 nt_errstr(status)));
725 * In case d->share_modes[i] conflicts with something or otherwise is
726 * being used, we need to make sure the corresponding process still
727 * exists.
729 bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
731 struct share_mode_entry *e;
733 if (idx > d->num_share_modes) {
734 DEBUG(1, ("Asking for index %u, only %u around\n",
735 idx, (unsigned)d->num_share_modes));
736 return false;
738 e = &d->share_modes[idx];
739 if (e->stale) {
741 * Checked before
743 return true;
745 if (serverid_exists(&e->pid)) {
746 DEBUG(10, ("PID %s (index %u out of %u) still exists\n",
747 procid_str_static(&e->pid), idx,
748 (unsigned)d->num_share_modes));
749 return false;
751 DEBUG(10, ("PID %s (index %u out of %u) does not exist anymore\n",
752 procid_str_static(&e->pid), idx,
753 (unsigned)d->num_share_modes));
755 e->stale = true;
757 if (d->num_delete_tokens != 0) {
758 uint32_t i, num_stale;
761 * We cannot have any delete tokens
762 * if there are no valid share modes.
765 num_stale = 0;
767 for (i=0; i<d->num_share_modes; i++) {
768 if (d->share_modes[i].stale) {
769 num_stale += 1;
773 if (num_stale == d->num_share_modes) {
775 * No non-stale share mode found
777 TALLOC_FREE(d->delete_tokens);
778 d->num_delete_tokens = 0;
782 remove_share_mode_lease(d, e);
784 d->modified = true;
785 return true;
788 void remove_stale_share_mode_entries(struct share_mode_data *d)
790 uint32_t i;
792 i = 0;
793 while (i < d->num_share_modes) {
794 if (d->share_modes[i].stale) {
795 struct share_mode_entry *m = d->share_modes;
796 m[i] = m[d->num_share_modes-1];
797 d->num_share_modes -= 1;
798 } else {
799 i += 1;
804 bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
805 uid_t uid, uint64_t mid, uint16_t op_type,
806 uint32_t lease_idx)
808 struct share_mode_data *d = lck->data;
809 struct share_mode_entry *tmp, *e;
810 struct share_mode_lease *lease = NULL;
812 if (lease_idx == UINT32_MAX) {
813 lease = NULL;
814 } else if (lease_idx >= d->num_leases) {
815 return false;
816 } else {
817 lease = &d->leases[lease_idx];
820 tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry,
821 d->num_share_modes+1);
822 if (tmp == NULL) {
823 return false;
825 d->share_modes = tmp;
826 e = &d->share_modes[d->num_share_modes];
827 d->num_share_modes += 1;
828 d->modified = true;
830 ZERO_STRUCTP(e);
831 e->pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
832 e->share_access = fsp->share_access;
833 e->private_options = fsp->fh->private_options;
834 e->access_mask = fsp->access_mask;
835 e->op_mid = mid;
836 e->op_type = op_type;
837 e->lease_idx = lease_idx;
838 e->lease = lease;
839 e->time.tv_sec = fsp->open_time.tv_sec;
840 e->time.tv_usec = fsp->open_time.tv_usec;
841 e->id = fsp->file_id;
842 e->share_file_id = fsp->fh->gen_id;
843 e->uid = (uint32)uid;
844 e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
845 e->name_hash = fsp->name_hash;
847 return true;
850 static struct share_mode_entry *find_share_mode_entry(
851 struct share_mode_lock *lck, files_struct *fsp)
853 struct share_mode_data *d = lck->data;
854 struct server_id pid;
855 int i;
857 pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
859 for (i=0; i<d->num_share_modes; i++) {
860 struct share_mode_entry *e = &d->share_modes[i];
862 if (!is_valid_share_mode_entry(e)) {
863 continue;
865 if (!serverid_equal(&pid, &e->pid)) {
866 continue;
868 if (!file_id_equal(&fsp->file_id, &e->id)) {
869 continue;
871 if (fsp->fh->gen_id != e->share_file_id) {
872 continue;
874 return e;
876 return NULL;
879 /*******************************************************************
880 Del the share mode of a file for this process. Return the number of
881 entries left.
882 ********************************************************************/
884 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
886 struct share_mode_entry *e;
888 e = find_share_mode_entry(lck, fsp);
889 if (e == NULL) {
890 return False;
892 remove_share_mode_lease(lck->data, e);
893 *e = lck->data->share_modes[lck->data->num_share_modes-1];
894 lck->data->num_share_modes -= 1;
895 lck->data->modified = True;
896 return True;
899 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
900 struct files_struct *fsp)
902 struct share_mode_entry *e;
904 if (lck->data->num_share_modes != 1) {
905 return false;
908 if (fsp->op == NULL) {
909 return false;
911 if (!fsp->op->global->durable) {
912 return false;
915 e = find_share_mode_entry(lck, fsp);
916 if (e == NULL) {
917 return false;
920 DEBUG(10, ("Marking share mode entry disconnected for durable handle\n"));
922 server_id_set_disconnected(&e->pid);
925 * On reopen the caller needs to check that
926 * the client comes with the correct handle.
928 e->share_file_id = fsp->op->global->open_persistent_id;
930 lck->data->modified = true;
931 return true;
934 /*******************************************************************
935 Remove an oplock mid and mode entry from a share mode.
936 ********************************************************************/
938 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
940 struct share_mode_data *d = lck->data;
941 struct share_mode_entry *e;
943 e = find_share_mode_entry(lck, fsp);
944 if (e == NULL) {
945 return False;
948 remove_share_mode_lease(d, e);
949 d->modified = True;
950 return true;
953 /*******************************************************************
954 Downgrade a oplock type from exclusive to level II.
955 ********************************************************************/
957 bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
959 struct share_mode_entry *e;
961 e = find_share_mode_entry(lck, fsp);
962 if (e == NULL) {
963 return False;
966 e->op_type = LEVEL_II_OPLOCK;
967 lck->data->modified = True;
968 return True;
971 NTSTATUS downgrade_share_lease(struct smbd_server_connection *sconn,
972 struct share_mode_lock *lck,
973 const struct smb2_lease_key *key,
974 uint32_t new_lease_state,
975 struct share_mode_lease **_l)
977 struct share_mode_data *d = lck->data;
978 struct share_mode_lease *l;
979 uint32_t i;
981 *_l = NULL;
983 for (i=0; i<d->num_leases; i++) {
984 if (smb2_lease_equal(&sconn->client->connections->smb2.client.guid,
985 key,
986 &d->leases[i].client_guid,
987 &d->leases[i].lease_key)) {
988 break;
991 if (i == d->num_leases) {
992 DEBUG(10, ("lease not found\n"));
993 return NT_STATUS_INVALID_PARAMETER;
996 l = &d->leases[i];
998 if (!l->breaking) {
999 DEBUG(1, ("Attempt to break from %d to %d - but we're not in breaking state\n",
1000 (int)l->current_state, (int)new_lease_state));
1001 return NT_STATUS_UNSUCCESSFUL;
1005 * Can't upgrade anything: l->breaking_to_requested (and l->current_state)
1006 * must be a strict bitwise superset of new_lease_state
1008 if ((new_lease_state & l->breaking_to_requested) != new_lease_state) {
1009 DEBUG(1, ("Attempt to upgrade from %d to %d - expected %d\n",
1010 (int)l->current_state, (int)new_lease_state,
1011 (int)l->breaking_to_requested));
1012 return NT_STATUS_REQUEST_NOT_ACCEPTED;
1015 if (l->current_state != new_lease_state) {
1016 l->current_state = new_lease_state;
1017 d->modified = true;
1020 if ((new_lease_state & ~l->breaking_to_required) != 0) {
1021 DEBUG(5, ("lease state %d not fully broken from %d to %d\n",
1022 (int)new_lease_state,
1023 (int)l->current_state,
1024 (int)l->breaking_to_required));
1025 l->breaking_to_requested = l->breaking_to_required;
1026 if (l->current_state & (~SMB2_LEASE_READ)) {
1028 * Here we break in steps, as windows does
1029 * see the breaking3 and v2_breaking3 tests.
1031 l->breaking_to_requested |= SMB2_LEASE_READ;
1033 d->modified = true;
1034 *_l = l;
1035 return NT_STATUS_OPLOCK_BREAK_IN_PROGRESS;
1038 DEBUG(10, ("breaking from %d to %d - expected %d\n",
1039 (int)l->current_state, (int)new_lease_state,
1040 (int)l->breaking_to_requested));
1042 l->breaking_to_requested = 0;
1043 l->breaking_to_required = 0;
1044 l->breaking = false;
1046 d->modified = true;
1048 return NT_STATUS_OK;
1051 /****************************************************************************
1052 Adds a delete on close token.
1053 ****************************************************************************/
1055 static bool add_delete_on_close_token(struct share_mode_data *d,
1056 uint32_t name_hash,
1057 const struct security_token *nt_tok,
1058 const struct security_unix_token *tok)
1060 struct delete_token *tmp, *dtl;
1062 tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
1063 d->num_delete_tokens+1);
1064 if (tmp == NULL) {
1065 return false;
1067 d->delete_tokens = tmp;
1068 dtl = &d->delete_tokens[d->num_delete_tokens];
1070 dtl->name_hash = name_hash;
1071 dtl->delete_nt_token = dup_nt_token(d->delete_tokens, nt_tok);
1072 if (dtl->delete_nt_token == NULL) {
1073 return false;
1075 dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
1076 if (dtl->delete_token == NULL) {
1077 return false;
1079 d->num_delete_tokens += 1;
1080 d->modified = true;
1081 return true;
1084 /****************************************************************************
1085 Sets the delete on close flag over all share modes on this file.
1086 Modify the share mode entry for all files open
1087 on this device and inode to tell other smbds we have
1088 changed the delete on close flag. This will be noticed
1089 in the close code, the last closer will delete the file
1090 if flag is set.
1091 This makes a copy of any struct security_unix_token into the
1092 lck entry. This function is used when the lock is already granted.
1093 ****************************************************************************/
1095 void set_delete_on_close_lck(files_struct *fsp,
1096 struct share_mode_lock *lck,
1097 bool delete_on_close,
1098 const struct security_token *nt_tok,
1099 const struct security_unix_token *tok)
1101 struct share_mode_data *d = lck->data;
1102 int i;
1103 bool ret;
1105 if (delete_on_close) {
1106 SMB_ASSERT(nt_tok != NULL);
1107 SMB_ASSERT(tok != NULL);
1108 } else {
1109 SMB_ASSERT(nt_tok == NULL);
1110 SMB_ASSERT(tok == NULL);
1113 for (i=0; i<d->num_delete_tokens; i++) {
1114 struct delete_token *dt = &d->delete_tokens[i];
1115 if (dt->name_hash == fsp->name_hash) {
1116 d->modified = true;
1117 if (delete_on_close == false) {
1118 /* Delete this entry. */
1119 TALLOC_FREE(dt->delete_nt_token);
1120 TALLOC_FREE(dt->delete_token);
1121 *dt = d->delete_tokens[
1122 d->num_delete_tokens-1];
1123 d->num_delete_tokens -= 1;
1124 } else {
1125 /* Replace this token with the
1126 given tok. */
1127 TALLOC_FREE(dt->delete_nt_token);
1128 dt->delete_nt_token = dup_nt_token(dt, nt_tok);
1129 SMB_ASSERT(dt->delete_nt_token != NULL);
1130 TALLOC_FREE(dt->delete_token);
1131 dt->delete_token = copy_unix_token(dt, tok);
1132 SMB_ASSERT(dt->delete_token != NULL);
1134 return;
1138 if (!delete_on_close) {
1139 /* Nothing to delete - not found. */
1140 return;
1143 ret = add_delete_on_close_token(lck->data, fsp->name_hash, nt_tok, tok);
1144 SMB_ASSERT(ret);
1147 bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
1148 const struct security_token *nt_tok,
1149 const struct security_unix_token *tok)
1151 struct share_mode_lock *lck;
1153 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
1154 "%s, file %s\n",
1155 delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
1156 fsp_str_dbg(fsp)));
1158 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1159 if (lck == NULL) {
1160 return False;
1163 if (delete_on_close) {
1164 set_delete_on_close_lck(fsp, lck, true,
1165 nt_tok,
1166 tok);
1167 } else {
1168 set_delete_on_close_lck(fsp, lck, false,
1169 NULL,
1170 NULL);
1173 if (fsp->is_directory) {
1174 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
1175 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
1176 fsp->fsp_name->base_name);
1179 TALLOC_FREE(lck);
1181 fsp->delete_on_close = delete_on_close;
1183 return True;
1186 static struct delete_token *find_delete_on_close_token(
1187 struct share_mode_data *d, uint32_t name_hash)
1189 uint32_t i;
1191 DEBUG(10, ("find_delete_on_close_token: name_hash = 0x%x\n",
1192 (unsigned int)name_hash));
1194 for (i=0; i<d->num_delete_tokens; i++) {
1195 struct delete_token *dt = &d->delete_tokens[i];
1197 DEBUG(10, ("find__delete_on_close_token: dt->name_hash = 0x%x\n",
1198 (unsigned int)dt->name_hash ));
1199 if (dt->name_hash == name_hash) {
1200 return dt;
1203 return NULL;
1206 /****************************************************************************
1207 Return the NT token and UNIX token if there's a match. Return true if
1208 found, false if not.
1209 ****************************************************************************/
1211 bool get_delete_on_close_token(struct share_mode_lock *lck,
1212 uint32_t name_hash,
1213 const struct security_token **pp_nt_tok,
1214 const struct security_unix_token **pp_tok)
1216 struct delete_token *dt;
1218 dt = find_delete_on_close_token(lck->data, name_hash);
1219 if (dt == NULL) {
1220 return false;
1222 *pp_nt_tok = dt->delete_nt_token;
1223 *pp_tok = dt->delete_token;
1224 return true;
1227 bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
1229 return find_delete_on_close_token(lck->data, name_hash) != NULL;
1232 bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
1234 struct share_mode_lock *lck;
1236 DEBUG(5,("set_sticky_write_time: %s id=%s\n",
1237 timestring(talloc_tos(),
1238 convert_timespec_to_time_t(write_time)),
1239 file_id_string_tos(&fileid)));
1241 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1242 if (lck == NULL) {
1243 return False;
1246 if (timespec_compare(&lck->data->changed_write_time, &write_time) != 0) {
1247 lck->data->modified = True;
1248 lck->data->changed_write_time = write_time;
1251 TALLOC_FREE(lck);
1252 return True;
1255 bool set_write_time(struct file_id fileid, struct timespec write_time)
1257 struct share_mode_lock *lck;
1259 DEBUG(5,("set_write_time: %s id=%s\n",
1260 timestring(talloc_tos(),
1261 convert_timespec_to_time_t(write_time)),
1262 file_id_string_tos(&fileid)));
1264 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1265 if (lck == NULL) {
1266 return False;
1269 if (timespec_compare(&lck->data->old_write_time, &write_time) != 0) {
1270 lck->data->modified = True;
1271 lck->data->old_write_time = write_time;
1274 TALLOC_FREE(lck);
1275 return True;
1278 struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
1280 struct share_mode_data *d = lck->data;
1282 if (!null_timespec(d->changed_write_time)) {
1283 return d->changed_write_time;
1285 return d->old_write_time;