smbd: Simplify strict_lock_default with early returns
[Samba.git] / source3 / locking / locking.c
blob1c0659ac043d00e81aa513dad0ee19904f769515
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,
139 plock->context.smblctx,
140 plock->context.pid,
141 plock->start,
142 plock->size,
143 plock->lock_type,
144 plock->lock_flav);
146 DEBUG(10, ("strict_lock_default: flavour = %s brl start=%ju "
147 "len=%ju %s for fnum %ju file %s\n",
148 lock_flav_name(plock->lock_flav),
149 (uintmax_t)plock->start, (uintmax_t)plock->size,
150 ret ? "unlocked" : "locked",
151 (uintmax_t)plock->fnum, fsp_str_dbg(fsp)));
153 return ret;
156 void strict_unlock_default(files_struct *fsp, struct lock_struct *plock)
160 /****************************************************************************
161 Find out if a lock could be granted - return who is blocking us if we can't.
162 ****************************************************************************/
164 NTSTATUS query_lock(files_struct *fsp,
165 uint64_t *psmblctx,
166 uint64_t *pcount,
167 uint64_t *poffset,
168 enum brl_type *plock_type,
169 enum brl_flavour lock_flav)
171 struct byte_range_lock *br_lck = NULL;
173 if (!fsp->can_lock) {
174 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
177 if (!lp_locking(fsp->conn->params)) {
178 return NT_STATUS_OK;
181 br_lck = brl_get_locks_readonly(fsp);
182 if (!br_lck) {
183 return NT_STATUS_NO_MEMORY;
186 return brl_lockquery(br_lck,
187 psmblctx,
188 messaging_server_id(fsp->conn->sconn->msg_ctx),
189 poffset,
190 pcount,
191 plock_type,
192 lock_flav);
195 static void increment_current_lock_count(files_struct *fsp,
196 enum brl_flavour lock_flav)
198 if (lock_flav == WINDOWS_LOCK &&
199 fsp->current_lock_count != NO_LOCKING_COUNT) {
200 /* blocking ie. pending, locks also count here,
201 * as this is an efficiency counter to avoid checking
202 * the lock db. on close. JRA. */
204 fsp->current_lock_count++;
205 } else {
206 /* Notice that this has had a POSIX lock request.
207 * We can't count locks after this so forget them.
209 fsp->current_lock_count = NO_LOCKING_COUNT;
213 static void decrement_current_lock_count(files_struct *fsp,
214 enum brl_flavour lock_flav)
216 if (lock_flav == WINDOWS_LOCK &&
217 fsp->current_lock_count != NO_LOCKING_COUNT) {
218 SMB_ASSERT(fsp->current_lock_count > 0);
219 fsp->current_lock_count--;
223 /****************************************************************************
224 Utility function called by locking requests.
225 ****************************************************************************/
227 struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
228 files_struct *fsp,
229 uint64_t smblctx,
230 uint64_t count,
231 uint64_t offset,
232 enum brl_type lock_type,
233 enum brl_flavour lock_flav,
234 bool blocking_lock,
235 NTSTATUS *perr,
236 uint64_t *psmblctx)
238 struct byte_range_lock *br_lck = NULL;
240 /* silently return ok on print files as we don't do locking there */
241 if (fsp->print_file) {
242 *perr = NT_STATUS_OK;
243 return NULL;
246 if (!fsp->can_lock) {
247 *perr = fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
248 return NULL;
251 if (!lp_locking(fsp->conn->params)) {
252 *perr = NT_STATUS_OK;
253 return NULL;
256 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
258 DEBUG(10,("do_lock: lock flavour %s lock type %s start=%ju len=%ju "
259 "blocking_lock=%s requested for %s file %s\n",
260 lock_flav_name(lock_flav), lock_type_name(lock_type),
261 (uintmax_t)offset, (uintmax_t)count, blocking_lock ? "true" :
262 "false", fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
264 br_lck = brl_get_locks(talloc_tos(), fsp);
265 if (!br_lck) {
266 *perr = NT_STATUS_NO_MEMORY;
267 return NULL;
270 *perr = brl_lock(msg_ctx,
271 br_lck,
272 smblctx,
273 messaging_server_id(fsp->conn->sconn->msg_ctx),
274 offset,
275 count,
276 lock_type,
277 lock_flav,
278 blocking_lock,
279 psmblctx);
281 DEBUG(10, ("do_lock: returning status=%s\n", nt_errstr(*perr)));
283 increment_current_lock_count(fsp, lock_flav);
284 return br_lck;
287 /****************************************************************************
288 Utility function called by unlocking requests.
289 ****************************************************************************/
291 NTSTATUS do_unlock(struct messaging_context *msg_ctx,
292 files_struct *fsp,
293 uint64_t smblctx,
294 uint64_t count,
295 uint64_t offset,
296 enum brl_flavour lock_flav)
298 bool ok = False;
299 struct byte_range_lock *br_lck = NULL;
301 if (!fsp->can_lock) {
302 return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
305 if (!lp_locking(fsp->conn->params)) {
306 return NT_STATUS_OK;
309 DEBUG(10, ("do_unlock: unlock start=%ju len=%ju requested for %s file "
310 "%s\n", (uintmax_t)offset, (uintmax_t)count,
311 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
313 br_lck = brl_get_locks(talloc_tos(), fsp);
314 if (!br_lck) {
315 return NT_STATUS_NO_MEMORY;
318 ok = brl_unlock(msg_ctx,
319 br_lck,
320 smblctx,
321 messaging_server_id(fsp->conn->sconn->msg_ctx),
322 offset,
323 count,
324 lock_flav);
326 TALLOC_FREE(br_lck);
328 if (!ok) {
329 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
330 return NT_STATUS_RANGE_NOT_LOCKED;
333 decrement_current_lock_count(fsp, lock_flav);
334 return NT_STATUS_OK;
337 /****************************************************************************
338 Cancel any pending blocked locks.
339 ****************************************************************************/
341 NTSTATUS do_lock_cancel(files_struct *fsp,
342 uint64 smblctx,
343 uint64_t count,
344 uint64_t offset,
345 enum brl_flavour lock_flav)
347 bool ok = False;
348 struct byte_range_lock *br_lck = NULL;
350 if (!fsp->can_lock) {
351 return fsp->is_directory ?
352 NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
355 if (!lp_locking(fsp->conn->params)) {
356 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
359 DEBUG(10, ("do_lock_cancel: cancel start=%ju len=%ju requested for "
360 "%s file %s\n", (uintmax_t)offset, (uintmax_t)count,
361 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
363 br_lck = brl_get_locks(talloc_tos(), fsp);
364 if (!br_lck) {
365 return NT_STATUS_NO_MEMORY;
368 ok = brl_lock_cancel(br_lck,
369 smblctx,
370 messaging_server_id(fsp->conn->sconn->msg_ctx),
371 offset,
372 count,
373 lock_flav);
375 TALLOC_FREE(br_lck);
377 if (!ok) {
378 DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
379 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
382 decrement_current_lock_count(fsp, lock_flav);
383 return NT_STATUS_OK;
386 /****************************************************************************
387 Remove any locks on this fd. Called from file_close().
388 ****************************************************************************/
390 void locking_close_file(struct messaging_context *msg_ctx,
391 files_struct *fsp,
392 enum file_close_type close_type)
394 struct byte_range_lock *br_lck;
396 if (!lp_locking(fsp->conn->params)) {
397 return;
400 /* If we have no outstanding locks or pending
401 * locks then we don't need to look in the lock db.
404 if (fsp->current_lock_count == 0) {
405 return;
408 br_lck = brl_get_locks(talloc_tos(),fsp);
410 if (br_lck) {
411 cancel_pending_lock_requests_by_fid(fsp, br_lck, close_type);
412 brl_close_fnum(msg_ctx, br_lck);
413 TALLOC_FREE(br_lck);
417 /*******************************************************************
418 Print out a share mode.
419 ********************************************************************/
421 char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
423 return talloc_asprintf(ctx, "share_mode_entry[%d]: "
424 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
425 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
426 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
427 num,
428 procid_str_static(&e->pid),
429 e->share_access, e->private_options,
430 e->access_mask, (unsigned long long)e->op_mid,
431 e->op_type, (unsigned long long)e->share_file_id,
432 (unsigned int)e->uid, (unsigned int)e->flags,
433 file_id_string_tos(&e->id),
434 (unsigned int)e->name_hash);
437 /*******************************************************************
438 Fetch a share mode where we know one MUST exist. This call reference
439 counts it internally to allow for nested lock fetches.
440 ********************************************************************/
442 struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
443 const struct file_id id)
445 return get_share_mode_lock(mem_ctx, id, NULL, NULL, NULL);
448 /*******************************************************************
449 Sets the service name and filename for rename.
450 At this point we emit "file renamed" messages to all
451 process id's that have this file open.
452 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
453 ********************************************************************/
455 bool rename_share_filename(struct messaging_context *msg_ctx,
456 struct share_mode_lock *lck,
457 struct file_id id,
458 const char *servicepath,
459 uint32_t orig_name_hash,
460 uint32_t new_name_hash,
461 const struct smb_filename *smb_fname_dst)
463 struct share_mode_data *d = lck->data;
464 size_t sp_len;
465 size_t bn_len;
466 size_t sn_len;
467 size_t msg_len;
468 char *frm = NULL;
469 int i;
470 bool strip_two_chars = false;
471 bool has_stream = smb_fname_dst->stream_name != NULL;
472 struct server_id self_pid = messaging_server_id(msg_ctx);
474 DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
475 servicepath, smb_fname_dst->base_name));
478 * rename_internal_fsp() and rename_internals() add './' to
479 * head of newname if newname does not contain a '/'.
481 if (smb_fname_dst->base_name[0] &&
482 smb_fname_dst->base_name[1] &&
483 smb_fname_dst->base_name[0] == '.' &&
484 smb_fname_dst->base_name[1] == '/') {
485 strip_two_chars = true;
488 d->servicepath = talloc_strdup(d, servicepath);
489 d->base_name = talloc_strdup(d, smb_fname_dst->base_name +
490 (strip_two_chars ? 2 : 0));
491 d->stream_name = talloc_strdup(d, smb_fname_dst->stream_name);
492 if (d->base_name == NULL ||
493 (has_stream && d->stream_name == NULL) ||
494 d->servicepath == NULL) {
495 DEBUG(0, ("rename_share_filename: talloc failed\n"));
496 return False;
498 d->modified = True;
500 sp_len = strlen(d->servicepath);
501 bn_len = strlen(d->base_name);
502 sn_len = has_stream ? strlen(d->stream_name) : 0;
504 msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + bn_len + 1 +
505 sn_len + 1;
507 /* Set up the name changed message. */
508 frm = talloc_array(d, char, msg_len);
509 if (!frm) {
510 return False;
513 push_file_id_24(frm, &id);
515 DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len ));
517 strlcpy(&frm[24],
518 d->servicepath ? d->servicepath : "",
519 sp_len+1);
520 strlcpy(&frm[24 + sp_len + 1],
521 d->base_name ? d->base_name : "",
522 bn_len+1);
523 strlcpy(&frm[24 + sp_len + 1 + bn_len + 1],
524 d->stream_name ? d->stream_name : "",
525 sn_len+1);
527 /* Send the messages. */
528 for (i=0; i<d->num_share_modes; i++) {
529 struct share_mode_entry *se = &d->share_modes[i];
530 if (!is_valid_share_mode_entry(se)) {
531 continue;
534 /* If this is a hardlink to the inode
535 with a different name, skip this. */
536 if (se->name_hash != orig_name_hash) {
537 continue;
540 se->name_hash = new_name_hash;
542 /* But not to ourselves... */
543 if (serverid_equal(&se->pid, &self_pid)) {
544 continue;
547 if (share_mode_stale_pid(d, i)) {
548 continue;
551 DEBUG(10,("rename_share_filename: sending rename message to "
552 "pid %s file_id %s sharepath %s base_name %s "
553 "stream_name %s\n",
554 procid_str_static(&se->pid),
555 file_id_string_tos(&id),
556 d->servicepath, d->base_name,
557 has_stream ? d->stream_name : ""));
559 messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME,
560 (uint8 *)frm, msg_len);
563 return True;
566 void get_file_infos(struct file_id id,
567 uint32_t name_hash,
568 bool *delete_on_close,
569 struct timespec *write_time)
571 struct share_mode_lock *lck;
573 if (delete_on_close) {
574 *delete_on_close = false;
577 if (write_time) {
578 ZERO_STRUCTP(write_time);
581 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
582 return;
585 if (delete_on_close) {
586 *delete_on_close = is_delete_on_close_set(lck, name_hash);
589 if (write_time) {
590 *write_time = get_share_mode_write_time(lck);
593 TALLOC_FREE(lck);
596 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
598 int num_props = 0;
600 if (e->stale) {
601 return false;
604 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
605 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
606 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
608 if ((num_props > 1) && serverid_exists(&e->pid)) {
609 smb_panic("Invalid share mode entry");
611 return (num_props != 0);
615 * In case d->share_modes[i] conflicts with something or otherwise is
616 * being used, we need to make sure the corresponding process still
617 * exists.
619 bool share_mode_stale_pid(struct share_mode_data *d, uint32_t idx)
621 struct share_mode_entry *e;
623 if (idx > d->num_share_modes) {
624 DEBUG(1, ("Asking for index %u, only %u around\n",
625 idx, (unsigned)d->num_share_modes));
626 return false;
628 e = &d->share_modes[idx];
629 if (e->stale) {
631 * Checked before
633 return true;
635 if (serverid_exists(&e->pid)) {
636 DEBUG(10, ("PID %s (index %u out of %u) still exists\n",
637 procid_str_static(&e->pid), idx,
638 (unsigned)d->num_share_modes));
639 return false;
641 DEBUG(10, ("PID %s (index %u out of %u) does not exist anymore\n",
642 procid_str_static(&e->pid), idx,
643 (unsigned)d->num_share_modes));
645 e->stale = true;
647 if (d->num_delete_tokens != 0) {
648 uint32_t i, num_stale;
651 * We cannot have any delete tokens
652 * if there are no valid share modes.
655 num_stale = 0;
657 for (i=0; i<d->num_share_modes; i++) {
658 if (d->share_modes[i].stale) {
659 num_stale += 1;
663 if (num_stale == d->num_share_modes) {
665 * No non-stale share mode found
667 TALLOC_FREE(d->delete_tokens);
668 d->num_delete_tokens = 0;
672 d->modified = true;
673 return true;
676 void remove_stale_share_mode_entries(struct share_mode_data *d)
678 uint32_t i;
680 i = 0;
681 while (i < d->num_share_modes) {
682 if (d->share_modes[i].stale) {
683 struct share_mode_entry *m = d->share_modes;
684 m[i] = m[d->num_share_modes-1];
685 d->num_share_modes -= 1;
686 } else {
687 i += 1;
692 bool set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
693 uid_t uid, uint64_t mid, uint16 op_type)
695 struct share_mode_data *d = lck->data;
696 struct share_mode_entry *tmp, *e;
698 tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry,
699 d->num_share_modes+1);
700 if (tmp == NULL) {
701 return false;
703 d->share_modes = tmp;
704 e = &d->share_modes[d->num_share_modes];
705 d->num_share_modes += 1;
706 d->modified = true;
708 ZERO_STRUCTP(e);
709 e->pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
710 e->share_access = fsp->share_access;
711 e->private_options = fsp->fh->private_options;
712 e->access_mask = fsp->access_mask;
713 e->op_mid = mid;
714 e->op_type = op_type;
715 e->time.tv_sec = fsp->open_time.tv_sec;
716 e->time.tv_usec = fsp->open_time.tv_usec;
717 e->id = fsp->file_id;
718 e->share_file_id = fsp->fh->gen_id;
719 e->uid = (uint32)uid;
720 e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
721 e->name_hash = fsp->name_hash;
723 return true;
726 static struct share_mode_entry *find_share_mode_entry(
727 struct share_mode_lock *lck, files_struct *fsp)
729 struct share_mode_data *d = lck->data;
730 struct server_id pid;
731 int i;
733 pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
735 for (i=0; i<d->num_share_modes; i++) {
736 struct share_mode_entry *e = &d->share_modes[i];
738 if (!is_valid_share_mode_entry(e)) {
739 continue;
741 if (!serverid_equal(&pid, &e->pid)) {
742 continue;
744 if (!file_id_equal(&fsp->file_id, &e->id)) {
745 continue;
747 if (fsp->fh->gen_id != e->share_file_id) {
748 continue;
750 return e;
752 return NULL;
755 /*******************************************************************
756 Del the share mode of a file for this process. Return the number of
757 entries left.
758 ********************************************************************/
760 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
762 struct share_mode_entry *e;
764 e = find_share_mode_entry(lck, fsp);
765 if (e == NULL) {
766 return False;
768 *e = lck->data->share_modes[lck->data->num_share_modes-1];
769 lck->data->num_share_modes -= 1;
770 lck->data->modified = True;
771 return True;
774 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
775 struct files_struct *fsp)
777 struct share_mode_entry *e;
779 if (lck->data->num_share_modes != 1) {
780 return false;
783 if (fsp->op == NULL) {
784 return false;
786 if (!fsp->op->global->durable) {
787 return false;
790 e = find_share_mode_entry(lck, fsp);
791 if (e == NULL) {
792 return false;
795 DEBUG(10, ("Marking share mode entry disconnected for durable handle\n"));
797 server_id_set_disconnected(&e->pid);
800 * On reopen the caller needs to check that
801 * the client comes with the correct handle.
803 e->share_file_id = fsp->op->global->open_persistent_id;
805 lck->data->modified = true;
806 return true;
809 /*******************************************************************
810 Remove an oplock mid and mode entry from a share mode.
811 ********************************************************************/
813 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
815 struct share_mode_entry *e;
817 e = find_share_mode_entry(lck, fsp);
818 if (e == NULL) {
819 return False;
822 e->op_type = NO_OPLOCK;
823 lck->data->modified = True;
824 return True;
827 /*******************************************************************
828 Downgrade a oplock type from exclusive to level II.
829 ********************************************************************/
831 bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
833 struct share_mode_entry *e;
835 e = find_share_mode_entry(lck, fsp);
836 if (e == NULL) {
837 return False;
840 e->op_type = LEVEL_II_OPLOCK;
841 lck->data->modified = True;
842 return True;
845 /****************************************************************************
846 Adds a delete on close token.
847 ****************************************************************************/
849 static bool add_delete_on_close_token(struct share_mode_data *d,
850 uint32_t name_hash,
851 const struct security_token *nt_tok,
852 const struct security_unix_token *tok)
854 struct delete_token *tmp, *dtl;
856 tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
857 d->num_delete_tokens+1);
858 if (tmp == NULL) {
859 return false;
861 d->delete_tokens = tmp;
862 dtl = &d->delete_tokens[d->num_delete_tokens];
864 dtl->name_hash = name_hash;
865 dtl->delete_nt_token = dup_nt_token(d->delete_tokens, nt_tok);
866 if (dtl->delete_nt_token == NULL) {
867 return false;
869 dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
870 if (dtl->delete_token == NULL) {
871 return false;
873 d->num_delete_tokens += 1;
874 d->modified = true;
875 return true;
878 /****************************************************************************
879 Sets the delete on close flag over all share modes on this file.
880 Modify the share mode entry for all files open
881 on this device and inode to tell other smbds we have
882 changed the delete on close flag. This will be noticed
883 in the close code, the last closer will delete the file
884 if flag is set.
885 This makes a copy of any struct security_unix_token into the
886 lck entry. This function is used when the lock is already granted.
887 ****************************************************************************/
889 void set_delete_on_close_lck(files_struct *fsp,
890 struct share_mode_lock *lck,
891 bool delete_on_close,
892 const struct security_token *nt_tok,
893 const struct security_unix_token *tok)
895 struct share_mode_data *d = lck->data;
896 int i;
897 bool ret;
899 if (delete_on_close) {
900 SMB_ASSERT(nt_tok != NULL);
901 SMB_ASSERT(tok != NULL);
902 } else {
903 SMB_ASSERT(nt_tok == NULL);
904 SMB_ASSERT(tok == NULL);
907 for (i=0; i<d->num_delete_tokens; i++) {
908 struct delete_token *dt = &d->delete_tokens[i];
909 if (dt->name_hash == fsp->name_hash) {
910 d->modified = true;
911 if (delete_on_close == false) {
912 /* Delete this entry. */
913 TALLOC_FREE(dt->delete_nt_token);
914 TALLOC_FREE(dt->delete_token);
915 *dt = d->delete_tokens[
916 d->num_delete_tokens-1];
917 d->num_delete_tokens -= 1;
918 } else {
919 /* Replace this token with the
920 given tok. */
921 TALLOC_FREE(dt->delete_nt_token);
922 dt->delete_nt_token = dup_nt_token(dt, nt_tok);
923 SMB_ASSERT(dt->delete_nt_token != NULL);
924 TALLOC_FREE(dt->delete_token);
925 dt->delete_token = copy_unix_token(dt, tok);
926 SMB_ASSERT(dt->delete_token != NULL);
928 return;
932 if (!delete_on_close) {
933 /* Nothing to delete - not found. */
934 return;
937 ret = add_delete_on_close_token(lck->data, fsp->name_hash, nt_tok, tok);
938 SMB_ASSERT(ret);
941 bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
942 const struct security_token *nt_tok,
943 const struct security_unix_token *tok)
945 struct share_mode_lock *lck;
947 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
948 "%s, file %s\n",
949 delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
950 fsp_str_dbg(fsp)));
952 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
953 if (lck == NULL) {
954 return False;
957 if (delete_on_close) {
958 set_delete_on_close_lck(fsp, lck, true,
959 nt_tok,
960 tok);
961 } else {
962 set_delete_on_close_lck(fsp, lck, false,
963 NULL,
964 NULL);
967 if (fsp->is_directory) {
968 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
969 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
970 fsp->fsp_name->base_name);
973 TALLOC_FREE(lck);
975 fsp->delete_on_close = delete_on_close;
977 return True;
980 static struct delete_token *find_delete_on_close_token(
981 struct share_mode_data *d, uint32_t name_hash)
983 uint32_t i;
985 DEBUG(10, ("find_delete_on_close_token: name_hash = 0x%x\n",
986 (unsigned int)name_hash));
988 for (i=0; i<d->num_delete_tokens; i++) {
989 struct delete_token *dt = &d->delete_tokens[i];
991 DEBUG(10, ("find__delete_on_close_token: dt->name_hash = 0x%x\n",
992 (unsigned int)dt->name_hash ));
993 if (dt->name_hash == name_hash) {
994 return dt;
997 return NULL;
1000 /****************************************************************************
1001 Return the NT token and UNIX token if there's a match. Return true if
1002 found, false if not.
1003 ****************************************************************************/
1005 bool get_delete_on_close_token(struct share_mode_lock *lck,
1006 uint32_t name_hash,
1007 const struct security_token **pp_nt_tok,
1008 const struct security_unix_token **pp_tok)
1010 struct delete_token *dt;
1012 dt = find_delete_on_close_token(lck->data, name_hash);
1013 if (dt == NULL) {
1014 return false;
1016 *pp_nt_tok = dt->delete_nt_token;
1017 *pp_tok = dt->delete_token;
1018 return true;
1021 bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
1023 return find_delete_on_close_token(lck->data, name_hash) != NULL;
1026 bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
1028 struct share_mode_lock *lck;
1030 DEBUG(5,("set_sticky_write_time: %s id=%s\n",
1031 timestring(talloc_tos(),
1032 convert_timespec_to_time_t(write_time)),
1033 file_id_string_tos(&fileid)));
1035 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1036 if (lck == NULL) {
1037 return False;
1040 if (timespec_compare(&lck->data->changed_write_time, &write_time) != 0) {
1041 lck->data->modified = True;
1042 lck->data->changed_write_time = write_time;
1045 TALLOC_FREE(lck);
1046 return True;
1049 bool set_write_time(struct file_id fileid, struct timespec write_time)
1051 struct share_mode_lock *lck;
1053 DEBUG(5,("set_write_time: %s id=%s\n",
1054 timestring(talloc_tos(),
1055 convert_timespec_to_time_t(write_time)),
1056 file_id_string_tos(&fileid)));
1058 lck = get_existing_share_mode_lock(talloc_tos(), fileid);
1059 if (lck == NULL) {
1060 return False;
1063 if (timespec_compare(&lck->data->old_write_time, &write_time) != 0) {
1064 lck->data->modified = True;
1065 lck->data->old_write_time = write_time;
1068 TALLOC_FREE(lck);
1069 return True;
1072 struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
1074 struct share_mode_data *d = lck->data;
1076 if (!null_timespec(d->changed_write_time)) {
1077 return d->changed_write_time;
1079 return d->old_write_time;