smbd: Simplify brl_locktest
[Samba.git] / source3 / locking / locking.c
blob0a994496d113077c936b3ff3f8dda1a4da53ce99
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"
50 #undef DBGC_CLASS
51 #define DBGC_CLASS DBGC_LOCKING
53 #define NO_LOCKING_COUNT (-1)
55 /****************************************************************************
56 Debugging aids :-).
57 ****************************************************************************/
59 const char *lock_type_name(enum brl_type lock_type)
61 switch (lock_type) {
62 case READ_LOCK:
63 return "READ";
64 case WRITE_LOCK:
65 return "WRITE";
66 case PENDING_READ_LOCK:
67 return "PENDING_READ";
68 case PENDING_WRITE_LOCK:
69 return "PENDING_WRITE";
70 default:
71 return "other";
75 const char *lock_flav_name(enum brl_flavour lock_flav)
77 return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
80 /****************************************************************************
81 Utility function called to see if a file region is locked.
82 Called in the read/write codepath.
83 ****************************************************************************/
85 void init_strict_lock_struct(files_struct *fsp,
86 uint64_t smblctx,
87 br_off start,
88 br_off size,
89 enum brl_type lock_type,
90 struct lock_struct *plock)
92 SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
94 plock->context.smblctx = smblctx;
95 plock->context.tid = fsp->conn->cnum;
96 plock->context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
97 plock->start = start;
98 plock->size = size;
99 plock->fnum = fsp->fnum;
100 plock->lock_type = lock_type;
101 plock->lock_flav = lp_posix_cifsu_locktype(fsp);
104 bool strict_lock_default(files_struct *fsp, struct lock_struct *plock)
106 struct byte_range_lock *br_lck;
107 int strict_locking = lp_strict_locking(fsp->conn->params);
108 bool ret = False;
110 if (plock->size == 0) {
111 return True;
114 if (!lp_locking(fsp->conn->params) || !strict_locking) {
115 return True;
118 if (strict_locking == Auto) {
119 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
120 (plock->lock_type == READ_LOCK ||
121 plock->lock_type == WRITE_LOCK)) {
122 DEBUG(10, ("is_locked: optimisation - exclusive oplock "
123 "on file %s\n", fsp_str_dbg(fsp)));
124 return true;
126 if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
127 (plock->lock_type == READ_LOCK)) {
128 DEBUG(10, ("is_locked: optimisation - level II oplock "
129 "on file %s\n", fsp_str_dbg(fsp)));
130 return true;
134 br_lck = brl_get_locks_readonly(fsp);
135 if (!br_lck) {
136 return true;
138 ret = brl_locktest(br_lck, plock);
140 DEBUG(10, ("strict_lock_default: flavour = %s brl start=%ju "
141 "len=%ju %s for fnum %ju file %s\n",
142 lock_flav_name(plock->lock_flav),
143 (uintmax_t)plock->start, (uintmax_t)plock->size,
144 ret ? "unlocked" : "locked",
145 (uintmax_t)plock->fnum, fsp_str_dbg(fsp)));
147 return ret;
150 void strict_unlock_default(files_struct *fsp, struct lock_struct *plock)
154 /****************************************************************************
155 Find out if a lock could be granted - return who is blocking us if we can't.
156 ****************************************************************************/
158 NTSTATUS query_lock(files_struct *fsp,
159 uint64_t *psmblctx,
160 uint64_t *pcount,
161 uint64_t *poffset,
162 enum brl_type *plock_type,
163 enum brl_flavour lock_flav)
165 struct byte_range_lock *br_lck = NULL;
167 if (!fsp->can_lock) {
168 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
171 if (!lp_locking(fsp->conn->params)) {
172 return NT_STATUS_OK;
175 br_lck = brl_get_locks_readonly(fsp);
176 if (!br_lck) {
177 return NT_STATUS_NO_MEMORY;
180 return brl_lockquery(br_lck,
181 psmblctx,
182 messaging_server_id(fsp->conn->sconn->msg_ctx),
183 poffset,
184 pcount,
185 plock_type,
186 lock_flav);
189 static void increment_current_lock_count(files_struct *fsp,
190 enum brl_flavour lock_flav)
192 if (lock_flav == WINDOWS_LOCK &&
193 fsp->current_lock_count != NO_LOCKING_COUNT) {
194 /* blocking ie. pending, locks also count here,
195 * as this is an efficiency counter to avoid checking
196 * the lock db. on close. JRA. */
198 fsp->current_lock_count++;
199 } else {
200 /* Notice that this has had a POSIX lock request.
201 * We can't count locks after this so forget them.
203 fsp->current_lock_count = NO_LOCKING_COUNT;
207 static void decrement_current_lock_count(files_struct *fsp,
208 enum brl_flavour lock_flav)
210 if (lock_flav == WINDOWS_LOCK &&
211 fsp->current_lock_count != NO_LOCKING_COUNT) {
212 SMB_ASSERT(fsp->current_lock_count > 0);
213 fsp->current_lock_count--;
217 /****************************************************************************
218 Utility function called by locking requests.
219 ****************************************************************************/
221 struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
222 files_struct *fsp,
223 uint64_t smblctx,
224 uint64_t count,
225 uint64_t offset,
226 enum brl_type lock_type,
227 enum brl_flavour lock_flav,
228 bool blocking_lock,
229 NTSTATUS *perr,
230 uint64_t *psmblctx)
232 struct byte_range_lock *br_lck = NULL;
234 /* silently return ok on print files as we don't do locking there */
235 if (fsp->print_file) {
236 *perr = NT_STATUS_OK;
237 return NULL;
240 if (!fsp->can_lock) {
241 *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
242 return NULL;
245 if (!lp_locking(fsp->conn->params)) {
246 *perr = NT_STATUS_OK;
247 return NULL;
250 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
252 DEBUG(10,("do_lock: lock flavour %s lock type %s start=%ju len=%ju "
253 "blocking_lock=%s requested for %s file %s\n",
254 lock_flav_name(lock_flav), lock_type_name(lock_type),
255 (uintmax_t)offset, (uintmax_t)count, blocking_lock ? "true" :
256 "false", fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
258 br_lck = brl_get_locks(talloc_tos(), fsp);
259 if (!br_lck) {
260 *perr = NT_STATUS_NO_MEMORY;
261 return NULL;
264 *perr = brl_lock(msg_ctx,
265 br_lck,
266 smblctx,
267 messaging_server_id(fsp->conn->sconn->msg_ctx),
268 offset,
269 count,
270 lock_type,
271 lock_flav,
272 blocking_lock,
273 psmblctx);
275 DEBUG(10, ("do_lock: returning status=%s\n", nt_errstr(*perr)));
277 increment_current_lock_count(fsp, lock_flav);
278 return br_lck;
281 /****************************************************************************
282 Utility function called by unlocking requests.
283 ****************************************************************************/
285 NTSTATUS do_unlock(struct messaging_context *msg_ctx,
286 files_struct *fsp,
287 uint64_t smblctx,
288 uint64_t count,
289 uint64_t offset,
290 enum brl_flavour lock_flav)
292 bool ok = False;
293 struct byte_range_lock *br_lck = NULL;
295 if (!fsp->can_lock) {
296 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
299 if (!lp_locking(fsp->conn->params)) {
300 return NT_STATUS_OK;
303 DEBUG(10, ("do_unlock: unlock start=%ju len=%ju requested for %s file "
304 "%s\n", (uintmax_t)offset, (uintmax_t)count,
305 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
307 br_lck = brl_get_locks(talloc_tos(), fsp);
308 if (!br_lck) {
309 return NT_STATUS_NO_MEMORY;
312 ok = brl_unlock(msg_ctx,
313 br_lck,
314 smblctx,
315 messaging_server_id(fsp->conn->sconn->msg_ctx),
316 offset,
317 count,
318 lock_flav);
320 TALLOC_FREE(br_lck);
322 if (!ok) {
323 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
324 return NT_STATUS_RANGE_NOT_LOCKED;
327 decrement_current_lock_count(fsp, lock_flav);
328 return NT_STATUS_OK;
331 /****************************************************************************
332 Cancel any pending blocked locks.
333 ****************************************************************************/
335 NTSTATUS do_lock_cancel(files_struct *fsp,
336 uint64 smblctx,
337 uint64_t count,
338 uint64_t offset,
339 enum brl_flavour lock_flav)
341 bool ok = False;
342 struct byte_range_lock *br_lck = NULL;
344 if (!fsp->can_lock) {
345 return fsp->is_directory ?
346 NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
349 if (!lp_locking(fsp->conn->params)) {
350 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
353 DEBUG(10, ("do_lock_cancel: cancel start=%ju len=%ju requested for "
354 "%s file %s\n", (uintmax_t)offset, (uintmax_t)count,
355 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
357 br_lck = brl_get_locks(talloc_tos(), fsp);
358 if (!br_lck) {
359 return NT_STATUS_NO_MEMORY;
362 ok = brl_lock_cancel(br_lck,
363 smblctx,
364 messaging_server_id(fsp->conn->sconn->msg_ctx),
365 offset,
366 count,
367 lock_flav);
369 TALLOC_FREE(br_lck);
371 if (!ok) {
372 DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
373 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
376 decrement_current_lock_count(fsp, lock_flav);
377 return NT_STATUS_OK;
380 /****************************************************************************
381 Remove any locks on this fd. Called from file_close().
382 ****************************************************************************/
384 void locking_close_file(struct messaging_context *msg_ctx,
385 files_struct *fsp,
386 enum file_close_type close_type)
388 struct byte_range_lock *br_lck;
390 if (!lp_locking(fsp->conn->params)) {
391 return;
394 /* If we have no outstanding locks or pending
395 * locks then we don't need to look in the lock db.
398 if (fsp->current_lock_count == 0) {
399 return;
402 br_lck = brl_get_locks(talloc_tos(),fsp);
404 if (br_lck) {
405 cancel_pending_lock_requests_by_fid(fsp, br_lck, close_type);
406 brl_close_fnum(msg_ctx, br_lck);
407 TALLOC_FREE(br_lck);
411 /*******************************************************************
412 Print out a share mode.
413 ********************************************************************/
415 char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
417 return talloc_asprintf(ctx, "share_mode_entry[%d]: "
418 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
419 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
420 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
421 num,
422 procid_str_static(&e->pid),
423 e->share_access, e->private_options,
424 e->access_mask, (unsigned long long)e->op_mid,
425 e->op_type, (unsigned long long)e->share_file_id,
426 (unsigned int)e->uid, (unsigned int)e->flags,
427 file_id_string_tos(&e->id),
428 (unsigned int)e->name_hash);
431 /*******************************************************************
432 Fetch a share mode where we know one MUST exist. This call reference
433 counts it internally to allow for nested lock fetches.
434 ********************************************************************/
436 struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
437 const struct file_id id)
439 return get_share_mode_lock(mem_ctx, id, NULL, NULL, NULL);
442 /*******************************************************************
443 Sets the service name and filename for rename.
444 At this point we emit "file renamed" messages to all
445 process id's that have this file open.
446 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
447 ********************************************************************/
449 bool rename_share_filename(struct messaging_context *msg_ctx,
450 struct share_mode_lock *lck,
451 struct file_id id,
452 const char *servicepath,
453 uint32_t orig_name_hash,
454 uint32_t new_name_hash,
455 const struct smb_filename *smb_fname_dst)
457 struct share_mode_data *d = lck->data;
458 size_t sp_len;
459 size_t bn_len;
460 size_t sn_len;
461 size_t msg_len;
462 char *frm = NULL;
463 int i;
464 bool strip_two_chars = false;
465 bool has_stream = smb_fname_dst->stream_name != NULL;
466 struct server_id self_pid = messaging_server_id(msg_ctx);
468 DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
469 servicepath, smb_fname_dst->base_name));
472 * rename_internal_fsp() and rename_internals() add './' to
473 * head of newname if newname does not contain a '/'.
475 if (smb_fname_dst->base_name[0] &&
476 smb_fname_dst->base_name[1] &&
477 smb_fname_dst->base_name[0] == '.' &&
478 smb_fname_dst->base_name[1] == '/') {
479 strip_two_chars = true;
482 d->servicepath = talloc_strdup(d, servicepath);
483 d->base_name = talloc_strdup(d, smb_fname_dst->base_name +
484 (strip_two_chars ? 2 : 0));
485 d->stream_name = talloc_strdup(d, smb_fname_dst->stream_name);
486 if (d->base_name == NULL ||
487 (has_stream && d->stream_name == NULL) ||
488 d->servicepath == NULL) {
489 DEBUG(0, ("rename_share_filename: talloc failed\n"));
490 return False;
492 d->modified = True;
494 sp_len = strlen(d->servicepath);
495 bn_len = strlen(d->base_name);
496 sn_len = has_stream ? strlen(d->stream_name) : 0;
498 msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + bn_len + 1 +
499 sn_len + 1;
501 /* Set up the name changed message. */
502 frm = talloc_array(d, char, msg_len);
503 if (!frm) {
504 return False;
507 push_file_id_24(frm, &id);
509 DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len ));
511 strlcpy(&frm[24],
512 d->servicepath ? d->servicepath : "",
513 sp_len+1);
514 strlcpy(&frm[24 + sp_len + 1],
515 d->base_name ? d->base_name : "",
516 bn_len+1);
517 strlcpy(&frm[24 + sp_len + 1 + bn_len + 1],
518 d->stream_name ? d->stream_name : "",
519 sn_len+1);
521 /* Send the messages. */
522 for (i=0; i<d->num_share_modes; i++) {
523 struct share_mode_entry *se = &d->share_modes[i];
524 if (!is_valid_share_mode_entry(se)) {
525 continue;
528 /* If this is a hardlink to the inode
529 with a different name, skip this. */
530 if (se->name_hash != orig_name_hash) {
531 continue;
534 se->name_hash = new_name_hash;
536 /* But not to ourselves... */
537 if (serverid_equal(&se->pid, &self_pid)) {
538 continue;
541 if (share_mode_stale_pid(d, i)) {
542 continue;
545 DEBUG(10,("rename_share_filename: sending rename message to "
546 "pid %s file_id %s sharepath %s base_name %s "
547 "stream_name %s\n",
548 procid_str_static(&se->pid),
549 file_id_string_tos(&id),
550 d->servicepath, d->base_name,
551 has_stream ? d->stream_name : ""));
553 messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME,
554 (uint8 *)frm, msg_len);
557 return True;
560 void get_file_infos(struct file_id id,
561 uint32_t name_hash,
562 bool *delete_on_close,
563 struct timespec *write_time)
565 struct share_mode_lock *lck;
567 if (delete_on_close) {
568 *delete_on_close = false;
571 if (write_time) {
572 ZERO_STRUCTP(write_time);
575 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
576 return;
579 if (delete_on_close) {
580 *delete_on_close = is_delete_on_close_set(lck, name_hash);
583 if (write_time) {
584 *write_time = get_share_mode_write_time(lck);
587 TALLOC_FREE(lck);
590 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
592 int num_props = 0;
594 if (e->stale) {
595 return false;
598 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
599 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
600 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
602 if ((num_props > 1) && serverid_exists(&e->pid)) {
603 smb_panic("Invalid share mode entry");
605 return (num_props != 0);
609 * In case d->share_modes[i] conflicts with something or otherwise is
610 * being used, we need to make sure the corresponding process still
611 * exists.
613 bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
615 struct share_mode_entry *e;
617 if (idx > d->num_share_modes) {
618 DEBUG(1, ("Asking for index %u, only %u around\n",
619 idx, (unsigned)d->num_share_modes));
620 return false;
622 e = &d->share_modes[idx];
623 if (e->stale) {
625 * Checked before
627 return true;
629 if (serverid_exists(&e->pid)) {
630 DEBUG(10, ("PID %s (index %u out of %u) still exists\n",
631 procid_str_static(&e->pid), idx,
632 (unsigned)d->num_share_modes));
633 return false;
635 DEBUG(10, ("PID %s (index %u out of %u) does not exist anymore\n",
636 procid_str_static(&e->pid), idx,
637 (unsigned)d->num_share_modes));
639 e->stale = true;
641 if (d->num_delete_tokens != 0) {
642 uint32_t i, num_stale;
645 * We cannot have any delete tokens
646 * if there are no valid share modes.
649 num_stale = 0;
651 for (i=0; i<d->num_share_modes; i++) {
652 if (d->share_modes[i].stale) {
653 num_stale += 1;
657 if (num_stale == d->num_share_modes) {
659 * No non-stale share mode found
661 TALLOC_FREE(d->delete_tokens);
662 d->num_delete_tokens = 0;
666 d->modified = true;
667 return true;
670 void remove_stale_share_mode_entries(struct share_mode_data *d)
672 uint32_t i;
674 i = 0;
675 while (i < d->num_share_modes) {
676 if (d->share_modes[i].stale) {
677 struct share_mode_entry *m = d->share_modes;
678 m[i] = m[d->num_share_modes-1];
679 d->num_share_modes -= 1;
680 } else {
681 i += 1;
686 bool set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
687 uid_t uid, uint64_t mid, uint16 op_type)
689 struct share_mode_data *d = lck->data;
690 struct share_mode_entry *tmp, *e;
692 tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry,
693 d->num_share_modes+1);
694 if (tmp == NULL) {
695 return false;
697 d->share_modes = tmp;
698 e = &d->share_modes[d->num_share_modes];
699 d->num_share_modes += 1;
700 d->modified = true;
702 ZERO_STRUCTP(e);
703 e->pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
704 e->share_access = fsp->share_access;
705 e->private_options = fsp->fh->private_options;
706 e->access_mask = fsp->access_mask;
707 e->op_mid = mid;
708 e->op_type = op_type;
709 e->time.tv_sec = fsp->open_time.tv_sec;
710 e->time.tv_usec = fsp->open_time.tv_usec;
711 e->id = fsp->file_id;
712 e->share_file_id = fsp->fh->gen_id;
713 e->uid = (uint32)uid;
714 e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
715 e->name_hash = fsp->name_hash;
717 return true;
720 static struct share_mode_entry *find_share_mode_entry(
721 struct share_mode_lock *lck, files_struct *fsp)
723 struct share_mode_data *d = lck->data;
724 struct server_id pid;
725 int i;
727 pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
729 for (i=0; i<d->num_share_modes; i++) {
730 struct share_mode_entry *e = &d->share_modes[i];
732 if (!is_valid_share_mode_entry(e)) {
733 continue;
735 if (!serverid_equal(&pid, &e->pid)) {
736 continue;
738 if (!file_id_equal(&fsp->file_id, &e->id)) {
739 continue;
741 if (fsp->fh->gen_id != e->share_file_id) {
742 continue;
744 return e;
746 return NULL;
749 /*******************************************************************
750 Del the share mode of a file for this process. Return the number of
751 entries left.
752 ********************************************************************/
754 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
756 struct share_mode_entry *e;
758 e = find_share_mode_entry(lck, fsp);
759 if (e == NULL) {
760 return False;
762 *e = lck->data->share_modes[lck->data->num_share_modes-1];
763 lck->data->num_share_modes -= 1;
764 lck->data->modified = True;
765 return True;
768 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
769 struct files_struct *fsp)
771 struct share_mode_entry *e;
773 if (lck->data->num_share_modes != 1) {
774 return false;
777 if (fsp->op == NULL) {
778 return false;
780 if (!fsp->op->global->durable) {
781 return false;
784 e = find_share_mode_entry(lck, fsp);
785 if (e == NULL) {
786 return false;
789 DEBUG(10, ("Marking share mode entry disconnected for durable handle\n"));
791 server_id_set_disconnected(&e->pid);
794 * On reopen the caller needs to check that
795 * the client comes with the correct handle.
797 e->share_file_id = fsp->op->global->open_persistent_id;
799 lck->data->modified = true;
800 return true;
803 /*******************************************************************
804 Remove an oplock mid and mode entry from a share mode.
805 ********************************************************************/
807 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
809 struct share_mode_entry *e;
811 e = find_share_mode_entry(lck, fsp);
812 if (e == NULL) {
813 return False;
816 e->op_type = NO_OPLOCK;
817 lck->data->modified = True;
818 return True;
821 /*******************************************************************
822 Downgrade a oplock type from exclusive to level II.
823 ********************************************************************/
825 bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
827 struct share_mode_entry *e;
829 e = find_share_mode_entry(lck, fsp);
830 if (e == NULL) {
831 return False;
834 e->op_type = LEVEL_II_OPLOCK;
835 lck->data->modified = True;
836 return True;
839 /****************************************************************************
840 Adds a delete on close token.
841 ****************************************************************************/
843 static bool add_delete_on_close_token(struct share_mode_data *d,
844 uint32_t name_hash,
845 const struct security_token *nt_tok,
846 const struct security_unix_token *tok)
848 struct delete_token *tmp, *dtl;
850 tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
851 d->num_delete_tokens+1);
852 if (tmp == NULL) {
853 return false;
855 d->delete_tokens = tmp;
856 dtl = &d->delete_tokens[d->num_delete_tokens];
858 dtl->name_hash = name_hash;
859 dtl->delete_nt_token = dup_nt_token(d->delete_tokens, nt_tok);
860 if (dtl->delete_nt_token == NULL) {
861 return false;
863 dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
864 if (dtl->delete_token == NULL) {
865 return false;
867 d->num_delete_tokens += 1;
868 d->modified = true;
869 return true;
872 /****************************************************************************
873 Sets the delete on close flag over all share modes on this file.
874 Modify the share mode entry for all files open
875 on this device and inode to tell other smbds we have
876 changed the delete on close flag. This will be noticed
877 in the close code, the last closer will delete the file
878 if flag is set.
879 This makes a copy of any struct security_unix_token into the
880 lck entry. This function is used when the lock is already granted.
881 ****************************************************************************/
883 void set_delete_on_close_lck(files_struct *fsp,
884 struct share_mode_lock *lck,
885 bool delete_on_close,
886 const struct security_token *nt_tok,
887 const struct security_unix_token *tok)
889 struct share_mode_data *d = lck->data;
890 int i;
891 bool ret;
893 if (delete_on_close) {
894 SMB_ASSERT(nt_tok != NULL);
895 SMB_ASSERT(tok != NULL);
896 } else {
897 SMB_ASSERT(nt_tok == NULL);
898 SMB_ASSERT(tok == NULL);
901 for (i=0; i<d->num_delete_tokens; i++) {
902 struct delete_token *dt = &d->delete_tokens[i];
903 if (dt->name_hash == fsp->name_hash) {
904 d->modified = true;
905 if (delete_on_close == false) {
906 /* Delete this entry. */
907 TALLOC_FREE(dt->delete_nt_token);
908 TALLOC_FREE(dt->delete_token);
909 *dt = d->delete_tokens[
910 d->num_delete_tokens-1];
911 d->num_delete_tokens -= 1;
912 } else {
913 /* Replace this token with the
914 given tok. */
915 TALLOC_FREE(dt->delete_nt_token);
916 dt->delete_nt_token = dup_nt_token(dt, nt_tok);
917 SMB_ASSERT(dt->delete_nt_token != NULL);
918 TALLOC_FREE(dt->delete_token);
919 dt->delete_token = copy_unix_token(dt, tok);
920 SMB_ASSERT(dt->delete_token != NULL);
922 return;
926 if (!delete_on_close) {
927 /* Nothing to delete - not found. */
928 return;
931 ret = add_delete_on_close_token(lck->data, fsp->name_hash, nt_tok, tok);
932 SMB_ASSERT(ret);
935 bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
936 const struct security_token *nt_tok,
937 const struct security_unix_token *tok)
939 struct share_mode_lock *lck;
941 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
942 "%s, file %s\n",
943 delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
944 fsp_str_dbg(fsp)));
946 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
947 if (lck == NULL) {
948 return False;
951 if (delete_on_close) {
952 set_delete_on_close_lck(fsp, lck, true,
953 nt_tok,
954 tok);
955 } else {
956 set_delete_on_close_lck(fsp, lck, false,
957 NULL,
958 NULL);
961 if (fsp->is_directory) {
962 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
963 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
964 fsp->fsp_name->base_name);
967 TALLOC_FREE(lck);
969 fsp->delete_on_close = delete_on_close;
971 return True;
974 static struct delete_token *find_delete_on_close_token(
975 struct share_mode_data *d, uint32_t name_hash)
977 uint32_t i;
979 DEBUG(10, ("find_delete_on_close_token: name_hash = 0x%x\n",
980 (unsigned int)name_hash));
982 for (i=0; i<d->num_delete_tokens; i++) {
983 struct delete_token *dt = &d->delete_tokens[i];
985 DEBUG(10, ("find__delete_on_close_token: dt->name_hash = 0x%x\n",
986 (unsigned int)dt->name_hash ));
987 if (dt->name_hash == name_hash) {
988 return dt;
991 return NULL;
994 /****************************************************************************
995 Return the NT token and UNIX token if there's a match. Return true if
996 found, false if not.
997 ****************************************************************************/
999 bool get_delete_on_close_token(struct share_mode_lock *lck,
1000 uint32_t name_hash,
1001 const struct security_token **pp_nt_tok,
1002 const struct security_unix_token **pp_tok)
1004 struct delete_token *dt;
1006 dt = find_delete_on_close_token(lck->data, name_hash);
1007 if (dt == NULL) {
1008 return false;
1010 *pp_nt_tok = dt->delete_nt_token;
1011 *pp_tok = dt->delete_token;
1012 return true;
1015 bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
1017 return find_delete_on_close_token(lck->data, name_hash) != NULL;
1020 bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
1022 struct share_mode_lock *lck;
1024 DEBUG(5,("set_sticky_write_time: %s id=%s\n",
1025 timestring(talloc_tos(),
1026 convert_timespec_to_time_t(write_time)),
1027 file_id_string_tos(&fileid)));
1029 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1030 if (lck == NULL) {
1031 return False;
1034 if (timespec_compare(&lck->data->changed_write_time, &write_time) != 0) {
1035 lck->data->modified = True;
1036 lck->data->changed_write_time = write_time;
1039 TALLOC_FREE(lck);
1040 return True;
1043 bool set_write_time(struct file_id fileid, struct timespec write_time)
1045 struct share_mode_lock *lck;
1047 DEBUG(5,("set_write_time: %s id=%s\n",
1048 timestring(talloc_tos(),
1049 convert_timespec_to_time_t(write_time)),
1050 file_id_string_tos(&fileid)));
1052 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1053 if (lck == NULL) {
1054 return False;
1057 if (timespec_compare(&lck->data->old_write_time, &write_time) != 0) {
1058 lck->data->modified = True;
1059 lck->data->old_write_time = write_time;
1062 TALLOC_FREE(lck);
1063 return True;
1066 struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
1068 struct share_mode_data *d = lck->data;
1070 if (!null_timespec(d->changed_write_time)) {
1071 return d->changed_write_time;
1073 return d->old_write_time;