smbd: Make reopen_from_fsp() public
[samba4-gss.git] / source3 / locking / locking.c
blobdd963e4fbaadd00d30fbda6175c1a615b1047720
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 "lib/util/time_basic.h"
40 #include "smbd/proto.h"
41 #include "system/filesys.h"
42 #include "lib/util/server_id.h"
43 #include "share_mode_lock.h"
44 #include "share_mode_lock_private.h"
45 #include "locking/proto.h"
46 #include "smbd/globals.h"
47 #include "dbwrap/dbwrap.h"
48 #include "dbwrap/dbwrap_open.h"
49 #include "../libcli/security/security.h"
50 #include "serverid.h"
51 #include "messages.h"
52 #include "util_tdb.h"
53 #include "../librpc/gen_ndr/ndr_open_files.h"
54 #include "librpc/gen_ndr/ndr_file_id.h"
55 #include "librpc/gen_ndr/ndr_leases_db.h"
56 #include "locking/leases_db.h"
58 #undef DBGC_CLASS
59 #define DBGC_CLASS DBGC_LOCKING
61 #define NO_LOCKING_COUNT (-1)
63 /****************************************************************************
64 Debugging aids :-).
65 ****************************************************************************/
67 const char *lock_type_name(enum brl_type lock_type)
69 switch (lock_type) {
70 case READ_LOCK:
71 return "READ";
72 case WRITE_LOCK:
73 return "WRITE";
74 default:
75 return "other";
79 const char *lock_flav_name(enum brl_flavour lock_flav)
81 return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
84 /****************************************************************************
85 Utility function called to see if a file region is locked.
86 Called in the read/write codepath.
87 ****************************************************************************/
89 void init_strict_lock_struct(files_struct *fsp,
90 uint64_t smblctx,
91 br_off start,
92 br_off size,
93 enum brl_type lock_type,
94 enum brl_flavour lock_flav,
95 struct lock_struct *plock)
97 SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
99 *plock = (struct lock_struct) {
100 .context.smblctx = smblctx,
101 .context.tid = fsp->conn->cnum,
102 .context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx),
103 .start = start,
104 .size = size,
105 .fnum = fsp->fnum,
106 .lock_type = lock_type,
107 .lock_flav = lp_posix_cifsu_locktype(fsp),
111 bool strict_lock_check_default(files_struct *fsp, struct lock_struct *plock)
113 struct byte_range_lock *br_lck;
114 int strict_locking = lp_strict_locking(fsp->conn->params);
115 bool ret = False;
117 if (plock->size == 0) {
118 return True;
121 if (!lp_locking(fsp->conn->params) || !strict_locking) {
122 return True;
125 if (strict_locking == Auto) {
126 uint32_t lease_type = fsp_lease_type(fsp);
128 if ((lease_type & SMB2_LEASE_READ) &&
129 (plock->lock_type == READ_LOCK))
131 DBG_DEBUG("optimisation - read lease on file %s\n",
132 fsp_str_dbg(fsp));
133 return true;
136 if ((lease_type & SMB2_LEASE_WRITE) &&
137 (plock->lock_type == WRITE_LOCK))
139 DBG_DEBUG("optimisation - write lease on file %s\n",
140 fsp_str_dbg(fsp));
141 return true;
145 br_lck = brl_get_locks_readonly(fsp);
146 if (!br_lck) {
147 return true;
149 ret = brl_locktest(br_lck, plock);
151 if (!ret) {
153 * We got a lock conflict. Retry with rw locks to enable
154 * autocleanup. This is the slow path anyway.
156 br_lck = brl_get_locks(talloc_tos(), fsp);
157 if (br_lck == NULL) {
158 return true;
160 ret = brl_locktest(br_lck, plock);
161 TALLOC_FREE(br_lck);
164 DBG_DEBUG("flavour = %s brl start=%" PRIu64 " "
165 "len=%" PRIu64 " %s for fnum %" PRIu64 " file %s\n",
166 lock_flav_name(plock->lock_flav),
167 plock->start,
168 plock->size,
169 ret ? "unlocked" : "locked",
170 plock->fnum,
171 fsp_str_dbg(fsp));
173 return ret;
176 /****************************************************************************
177 Find out if a lock could be granted - return who is blocking us if we can't.
178 ****************************************************************************/
180 NTSTATUS query_lock(files_struct *fsp,
181 uint64_t *psmblctx,
182 uint64_t *pcount,
183 uint64_t *poffset,
184 enum brl_type *plock_type,
185 enum brl_flavour lock_flav)
187 struct byte_range_lock *br_lck = NULL;
189 if (!fsp->fsp_flags.can_lock) {
190 return fsp->fsp_flags.is_directory ?
191 NT_STATUS_INVALID_DEVICE_REQUEST :
192 NT_STATUS_INVALID_HANDLE;
195 if (!lp_locking(fsp->conn->params)) {
196 return NT_STATUS_OK;
199 br_lck = brl_get_locks_readonly(fsp);
200 if (!br_lck) {
201 return NT_STATUS_NO_MEMORY;
204 return brl_lockquery(br_lck,
205 psmblctx,
206 messaging_server_id(fsp->conn->sconn->msg_ctx),
207 poffset,
208 pcount,
209 plock_type,
210 lock_flav);
213 static void increment_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 /* blocking ie. pending, locks also count here,
219 * as this is an efficiency counter to avoid checking
220 * the lock db. on close. JRA. */
222 fsp->current_lock_count++;
223 } else {
224 /* Notice that this has had a POSIX lock request.
225 * We can't count locks after this so forget them.
227 fsp->current_lock_count = NO_LOCKING_COUNT;
231 static void decrement_current_lock_count(files_struct *fsp,
232 enum brl_flavour lock_flav)
234 if (lock_flav == WINDOWS_LOCK &&
235 fsp->current_lock_count != NO_LOCKING_COUNT) {
236 SMB_ASSERT(fsp->current_lock_count > 0);
237 fsp->current_lock_count--;
241 /****************************************************************************
242 Utility function called by locking requests.
243 ****************************************************************************/
245 struct do_lock_state {
246 struct files_struct *fsp;
247 TALLOC_CTX *req_mem_ctx;
248 const struct GUID *req_guid;
249 uint64_t smblctx;
250 uint64_t count;
251 uint64_t offset;
252 enum brl_type lock_type;
253 enum brl_flavour lock_flav;
255 struct server_id blocker_pid;
256 uint64_t blocker_smblctx;
257 NTSTATUS status;
260 static void do_lock_fn(
261 struct share_mode_lock *lck,
262 void *private_data)
264 struct do_lock_state *state = private_data;
265 struct byte_range_lock *br_lck = NULL;
267 br_lck = brl_get_locks_for_locking(talloc_tos(),
268 state->fsp,
269 state->req_mem_ctx,
270 state->req_guid);
271 if (br_lck == NULL) {
272 state->status = NT_STATUS_NO_MEMORY;
273 return;
276 state->status = brl_lock(
277 br_lck,
278 state->smblctx,
279 messaging_server_id(state->fsp->conn->sconn->msg_ctx),
280 state->offset,
281 state->count,
282 state->lock_type,
283 state->lock_flav,
284 &state->blocker_pid,
285 &state->blocker_smblctx);
287 TALLOC_FREE(br_lck);
290 NTSTATUS do_lock(files_struct *fsp,
291 TALLOC_CTX *req_mem_ctx,
292 const struct GUID *req_guid,
293 uint64_t smblctx,
294 uint64_t count,
295 uint64_t offset,
296 enum brl_type lock_type,
297 enum brl_flavour lock_flav,
298 struct server_id *pblocker_pid,
299 uint64_t *psmblctx)
301 struct do_lock_state state = {
302 .fsp = fsp,
303 .req_mem_ctx = req_mem_ctx,
304 .req_guid = req_guid,
305 .smblctx = smblctx,
306 .count = count,
307 .offset = offset,
308 .lock_type = lock_type,
309 .lock_flav = lock_flav,
311 NTSTATUS status;
313 /* silently return ok on print files as we don't do locking there */
314 if (fsp->print_file) {
315 return NT_STATUS_OK;
318 if (!fsp->fsp_flags.can_lock) {
319 if (fsp->fsp_flags.is_directory) {
320 return NT_STATUS_INVALID_DEVICE_REQUEST;
322 return NT_STATUS_INVALID_HANDLE;
325 if (!lp_locking(fsp->conn->params)) {
326 return NT_STATUS_OK;
329 /* NOTE! 0 byte long ranges ARE allowed and should be stored */
331 DBG_DEBUG("lock flavour %s lock type %s start=%"PRIu64" len=%"PRIu64" "
332 "requested for %s file %s\n",
333 lock_flav_name(lock_flav),
334 lock_type_name(lock_type),
335 offset,
336 count,
337 fsp_fnum_dbg(fsp),
338 fsp_str_dbg(fsp));
340 status = share_mode_do_locked_vfs_allowed(fsp->file_id,
341 do_lock_fn,
342 &state);
343 if (!NT_STATUS_IS_OK(status)) {
344 DBG_DEBUG("share_mode_do_locked returned %s\n",
345 nt_errstr(status));
346 return status;
349 if (psmblctx != NULL) {
350 *psmblctx = state.blocker_smblctx;
352 if (pblocker_pid != NULL) {
353 *pblocker_pid = state.blocker_pid;
356 DBG_DEBUG("returning status=%s\n", nt_errstr(state.status));
358 increment_current_lock_count(fsp, lock_flav);
360 return state.status;
363 /****************************************************************************
364 Utility function called by unlocking requests.
365 ****************************************************************************/
367 NTSTATUS do_unlock(files_struct *fsp,
368 uint64_t smblctx,
369 uint64_t count,
370 uint64_t offset,
371 enum brl_flavour lock_flav)
373 bool ok = False;
374 struct byte_range_lock *br_lck = NULL;
376 if (!fsp->fsp_flags.can_lock) {
377 return fsp->fsp_flags.is_directory ?
378 NT_STATUS_INVALID_DEVICE_REQUEST :
379 NT_STATUS_INVALID_HANDLE;
382 if (!lp_locking(fsp->conn->params)) {
383 return NT_STATUS_OK;
386 DBG_DEBUG("unlock start=%"PRIu64" len=%"PRIu64" requested for %s file "
387 "%s\n",
388 offset,
389 count,
390 fsp_fnum_dbg(fsp),
391 fsp_str_dbg(fsp));
393 br_lck = brl_get_locks(talloc_tos(), fsp);
394 if (!br_lck) {
395 return NT_STATUS_NO_MEMORY;
398 ok = brl_unlock(br_lck,
399 smblctx,
400 messaging_server_id(fsp->conn->sconn->msg_ctx),
401 offset,
402 count,
403 lock_flav);
405 TALLOC_FREE(br_lck);
407 if (!ok) {
408 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
409 return NT_STATUS_RANGE_NOT_LOCKED;
412 decrement_current_lock_count(fsp, lock_flav);
413 return NT_STATUS_OK;
416 /****************************************************************************
417 Remove any locks on this fd. Called from file_close().
418 ****************************************************************************/
420 void locking_close_file(files_struct *fsp,
421 enum file_close_type close_type)
423 struct byte_range_lock *br_lck;
425 if (!lp_locking(fsp->conn->params)) {
426 return;
429 /* If we have no outstanding locks or pending
430 * locks then we don't need to look in the lock db.
433 if (fsp->current_lock_count == 0) {
434 return;
437 br_lck = brl_get_locks(talloc_tos(),fsp);
439 if (br_lck) {
441 * Unlocks must trigger dbwrap_watch watchers,
442 * normally in smbd_do_unlocking. Here it's done
443 * implicitly, we're closing the file and thus remove a
444 * share mode. This will wake the waiters.
446 brl_close_fnum(br_lck);
447 TALLOC_FREE(br_lck);
451 /*******************************************************************
452 Print out a share mode.
453 ********************************************************************/
455 char *share_mode_str(TALLOC_CTX *ctx, int num,
456 const struct file_id *id,
457 const struct share_mode_entry *e)
459 struct server_id_buf tmp;
460 struct file_id_buf ftmp;
462 return talloc_asprintf(ctx, "share_mode_entry[%d]: "
463 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
464 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
465 "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
466 num,
467 server_id_str_buf(e->pid, &tmp),
468 e->share_access, e->private_options,
469 e->access_mask, (unsigned long long)e->op_mid,
470 e->op_type, (unsigned long long)e->share_file_id,
471 (unsigned int)e->uid, (unsigned int)e->flags,
472 file_id_str_buf(*id, &ftmp),
473 (unsigned int)e->name_hash);
476 struct rename_share_filename_state {
477 struct share_mode_data *data;
478 struct messaging_context *msg_ctx;
479 struct server_id self;
480 uint32_t orig_name_hash;
481 uint32_t new_name_hash;
482 struct file_rename_message msg;
485 static bool rename_lease_fn(struct share_mode_entry *e,
486 void *private_data)
488 struct rename_share_filename_state *state = private_data;
489 struct share_mode_data *d = state->data;
490 NTSTATUS status;
492 status = leases_db_rename(&e->client_guid,
493 &e->lease_key,
494 &d->id,
495 d->servicepath,
496 d->base_name,
497 d->stream_name);
499 if (!NT_STATUS_IS_OK(status)) {
500 /* Any error recovery possible here ? */
501 DBG_WARNING("Failed to rename lease key for "
502 "renamed file %s:%s. %s\n",
503 d->base_name,
504 d->stream_name,
505 nt_errstr(status));
508 return false;
511 /*******************************************************************
512 Sets the service name and filename for rename.
513 At this point we emit "file renamed" messages to all
514 process id's that have this file open.
515 Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
516 ********************************************************************/
518 static bool rename_share_filename_fn(
519 struct share_mode_entry *e,
520 bool *modified,
521 void *private_data)
523 struct rename_share_filename_state *state = private_data;
524 DATA_BLOB blob;
525 enum ndr_err_code ndr_err;
526 bool ok;
529 * If this is a hardlink to the inode with a different name,
530 * skip this.
532 if (e->name_hash != state->orig_name_hash) {
533 return false;
535 e->name_hash = state->new_name_hash;
536 *modified = true;
538 ok = server_id_equal(&e->pid, &state->self);
539 if (ok) {
540 return false;
543 state->msg.share_file_id = e->share_file_id;
545 ndr_err = ndr_push_struct_blob(
546 &blob,
547 talloc_tos(),
548 &state->msg,
549 (ndr_push_flags_fn_t)ndr_push_file_rename_message);
550 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
551 DBG_DEBUG("ndr_push_file_rename_message failed: %s\n",
552 ndr_errstr(ndr_err));
553 return false;
555 if (DEBUGLEVEL >= 10) {
556 struct server_id_buf tmp;
557 DBG_DEBUG("sending rename message to %s\n",
558 server_id_str_buf(e->pid, &tmp));
559 NDR_PRINT_DEBUG(file_rename_message, &state->msg);
562 messaging_send(state->msg_ctx, e->pid, MSG_SMB_FILE_RENAME, &blob);
564 TALLOC_FREE(blob.data);
566 return false;
569 bool rename_share_filename(struct messaging_context *msg_ctx,
570 struct share_mode_lock *lck,
571 struct file_id id,
572 const char *servicepath,
573 uint32_t orig_name_hash,
574 uint32_t new_name_hash,
575 const struct smb_filename *smb_fname_dst)
577 struct rename_share_filename_state state = {
578 .msg_ctx = msg_ctx,
579 .self = messaging_server_id(msg_ctx),
580 .orig_name_hash = orig_name_hash,
581 .new_name_hash = new_name_hash,
582 .msg.id = id,
583 .msg.servicepath = servicepath,
584 .msg.base_name = smb_fname_dst->base_name,
585 .msg.stream_name = smb_fname_dst->stream_name,
587 struct share_mode_data *d = NULL;
588 NTSTATUS status;
589 bool ok;
591 DBG_DEBUG("servicepath %s newname %s\n",
592 servicepath,
593 smb_fname_dst->base_name);
595 status = share_mode_lock_access_private_data(lck, &d);
596 if (!NT_STATUS_IS_OK(status)) {
597 /* Any error recovery possible here ? */
598 DBG_ERR("share_mode_lock_access_private_data() failed for "
599 "servicepath %s newname %s - %s\n",
600 servicepath, smb_fname_dst->base_name,
601 nt_errstr(status));
602 return false;
604 state.data = d;
607 * rename_internal_fsp() and rename_internals() add './' to
608 * head of newname if newname does not contain a '/'.
611 if (strncmp(state.msg.base_name, "./", 2) == 0) {
612 state.msg.base_name += 2;
615 d->servicepath = talloc_strdup(d, state.msg.servicepath);
616 d->base_name = talloc_strdup(d, state.msg.base_name);
617 d->stream_name = talloc_strdup(d, state.msg.stream_name);
618 if ((d->servicepath == NULL) ||
619 (d->base_name == NULL) ||
620 ((state.msg.stream_name != NULL) && (d->stream_name == NULL))) {
621 DBG_WARNING("talloc failed\n");
622 return false;
624 d->modified = True;
626 ok = share_mode_forall_entries(
627 lck, rename_share_filename_fn, &state);
628 if (!ok) {
629 DBG_WARNING("share_mode_forall_entries failed\n");
632 ok = share_mode_forall_leases(lck, rename_lease_fn, &state);
633 if (!ok) {
635 * Ignore error here. Not sure what to do..
637 DBG_WARNING("share_mode_forall_leases failed\n");
640 return True;
643 void get_file_infos(struct file_id id,
644 uint32_t name_hash,
645 bool *delete_on_close,
646 struct timespec *write_time)
648 struct share_mode_lock *lck;
650 if (delete_on_close) {
651 *delete_on_close = false;
654 if (write_time) {
655 *write_time = make_omit_timespec();
658 if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
659 return;
662 if (delete_on_close) {
663 *delete_on_close = is_delete_on_close_set(lck, name_hash);
666 if (write_time) {
667 *write_time = get_share_mode_write_time(lck);
670 TALLOC_FREE(lck);
673 bool is_valid_share_mode_entry(const struct share_mode_entry *e)
675 int num_props = 0;
677 if (e->stale) {
678 return false;
681 num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
682 num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
683 num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
684 num_props += (e->op_type == LEASE_OPLOCK);
686 if ((num_props > 1) && serverid_exists(&e->pid)) {
687 smb_panic("Invalid share mode entry");
689 return (num_props != 0);
692 struct find_lease_ref_state {
693 const struct GUID *client_guid;
694 const struct smb2_lease_key *lease_key;
695 bool found_same;
698 static bool find_lease_ref_fn(
699 struct share_mode_entry *e,
700 bool *modified,
701 void *private_data)
703 struct find_lease_ref_state *state = private_data;
705 if (e->stale) {
706 return false;
708 if (e->op_type != LEASE_OPLOCK) {
709 return false;
712 state->found_same = smb2_lease_equal(
713 &e->client_guid,
714 &e->lease_key,
715 state->client_guid,
716 state->lease_key);
718 * If we found a lease reference, look no further (i.e. return true)
720 return state->found_same;
723 NTSTATUS remove_lease_if_stale(struct share_mode_lock *lck,
724 const struct GUID *client_guid,
725 const struct smb2_lease_key *lease_key)
727 struct find_lease_ref_state state = {
728 .client_guid = client_guid, .lease_key = lease_key,
730 struct file_id id = share_mode_lock_file_id(lck);
731 NTSTATUS status;
732 bool ok;
734 ok = share_mode_forall_entries(lck, find_lease_ref_fn, &state);
735 if (!ok) {
736 DBG_ERR("share_mode_forall_entries failed\n");
737 return NT_STATUS_INTERNAL_ERROR;
740 if (state.found_same) {
741 return NT_STATUS_RESOURCE_IN_USE;
744 status = leases_db_del(client_guid, lease_key, &id);
745 if (!NT_STATUS_IS_OK(status)) {
746 int level = DBGLVL_DEBUG;
748 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
749 level = DBGLVL_ERR;
751 DBG_PREFIX(level, ("leases_db_del failed: %s\n",
752 nt_errstr(status)));
754 return status;
757 bool share_entry_stale_pid(struct share_mode_entry *e)
759 struct server_id_buf buf;
760 bool exists;
762 if (e->stale) {
763 return true;
766 exists = serverid_exists(&e->pid);
767 if (exists) {
768 DBG_DEBUG("PID %s still exists\n",
769 server_id_str_buf(e->pid, &buf));
770 return false;
773 DBG_DEBUG("PID %s does not exist anymore\n",
774 server_id_str_buf(e->pid, &buf));
776 e->stale = true;
778 return true;
781 /****************************************************************************
782 Adds a delete on close token.
783 ****************************************************************************/
785 static bool add_delete_on_close_token(struct share_mode_data *d,
786 struct files_struct *fsp,
787 const struct security_token *nt_tok,
788 const struct security_unix_token *tok)
790 struct delete_token *tmp, *dtl;
791 const struct smb2_lease *lease = NULL;
793 tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
794 d->num_delete_tokens+1);
795 if (tmp == NULL) {
796 return false;
798 d->delete_tokens = tmp;
799 dtl = &d->delete_tokens[d->num_delete_tokens];
801 dtl->name_hash = fsp->name_hash;
803 lease = fsp_get_smb2_lease(fsp);
804 if (lease != NULL) {
805 dtl->parent_lease_key = lease->parent_lease_key;
808 dtl->delete_nt_token = security_token_duplicate(d->delete_tokens, nt_tok);
809 if (dtl->delete_nt_token == NULL) {
810 return false;
812 dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
813 if (dtl->delete_token == NULL) {
814 return false;
816 d->num_delete_tokens += 1;
817 d->modified = true;
818 return true;
821 void reset_delete_on_close_lck(files_struct *fsp,
822 struct share_mode_lock *lck)
824 struct share_mode_data *d = NULL;
825 NTSTATUS status;
826 uint32_t i;
828 status = share_mode_lock_access_private_data(lck, &d);
829 if (!NT_STATUS_IS_OK(status)) {
830 /* Any error recovery possible here ? */
831 DBG_ERR("share_mode_lock_access_private_data() failed for "
832 "%s - %s\n", fsp_str_dbg(fsp), nt_errstr(status));
833 smb_panic(__location__);
834 return;
837 for (i=0; i<d->num_delete_tokens; i++) {
838 struct delete_token *dt = &d->delete_tokens[i];
840 if (dt->name_hash == fsp->name_hash) {
841 d->modified = true;
843 /* Delete this entry. */
844 TALLOC_FREE(dt->delete_nt_token);
845 TALLOC_FREE(dt->delete_token);
846 *dt = d->delete_tokens[d->num_delete_tokens-1];
847 d->num_delete_tokens -= 1;
852 struct set_delete_on_close_state {
853 struct messaging_context *msg_ctx;
854 DATA_BLOB blob;
857 static bool set_delete_on_close_fn(
858 struct share_mode_entry *e,
859 bool *modified,
860 void *private_data)
862 struct set_delete_on_close_state *state = private_data;
863 NTSTATUS status;
865 status = messaging_send(
866 state->msg_ctx,
867 e->pid,
868 MSG_SMB_NOTIFY_CANCEL_DELETED,
869 &state->blob);
871 if (!NT_STATUS_IS_OK(status)) {
872 struct server_id_buf tmp;
873 DBG_DEBUG("messaging_send to %s returned %s\n",
874 server_id_str_buf(e->pid, &tmp),
875 nt_errstr(status));
878 return false;
881 /****************************************************************************
882 Sets the delete on close flag over all share modes on this file.
883 Modify the share mode entry for all files open
884 on this device and inode to tell other smbds we have
885 changed the delete on close flag. This will be noticed
886 in the close code, the last closer will delete the file
887 if flag is set.
888 This makes a copy of any struct security_unix_token into the
889 lck entry. This function is used when the lock is already granted.
890 ****************************************************************************/
892 void set_delete_on_close_lck(files_struct *fsp,
893 struct share_mode_lock *lck,
894 const struct security_token *nt_tok,
895 const struct security_unix_token *tok)
897 struct share_mode_data *d = NULL;
898 struct set_delete_on_close_state state = {
899 .msg_ctx = fsp->conn->sconn->msg_ctx
901 uint32_t i;
902 bool ret;
903 enum ndr_err_code ndr_err;
904 NTSTATUS status;
906 status = share_mode_lock_access_private_data(lck, &d);
907 if (!NT_STATUS_IS_OK(status)) {
908 /* Any error recovery possible here ? */
909 DBG_ERR("share_mode_lock_access_private_data() failed for "
910 "%s - %s\n", fsp_str_dbg(fsp), nt_errstr(status));
911 smb_panic(__location__);
912 return;
915 SMB_ASSERT(nt_tok != NULL);
916 SMB_ASSERT(tok != NULL);
918 for (i=0; i<d->num_delete_tokens; i++) {
919 struct delete_token *dt = &d->delete_tokens[i];
920 if (dt->name_hash == fsp->name_hash) {
921 const struct smb2_lease *lease = NULL;
923 d->modified = true;
925 /* Replace this token with the given tok. */
926 ZERO_STRUCT(dt->parent_lease_key);
927 lease = fsp_get_smb2_lease(fsp);
928 if (lease != NULL) {
929 dt->parent_lease_key = lease->parent_lease_key;
932 TALLOC_FREE(dt->delete_nt_token);
933 dt->delete_nt_token = security_token_duplicate(dt, nt_tok);
934 SMB_ASSERT(dt->delete_nt_token != NULL);
935 TALLOC_FREE(dt->delete_token);
936 dt->delete_token = copy_unix_token(dt, tok);
937 SMB_ASSERT(dt->delete_token != NULL);
939 return;
943 ret = add_delete_on_close_token(d, fsp, nt_tok, tok);
944 SMB_ASSERT(ret);
946 ndr_err = ndr_push_struct_blob(
947 &state.blob,
948 talloc_tos(),
949 &fsp->file_id,
950 (ndr_push_flags_fn_t)ndr_push_file_id);
951 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
952 DBG_ERR("ndr_push_file_id failed: %s\n",
953 ndr_errstr(ndr_err));
954 smb_panic(__location__);
957 ret = share_mode_forall_entries(
958 lck, set_delete_on_close_fn, &state);
959 if (!ret) {
960 DBG_ERR("share_mode_forall_entries failed\n");
961 smb_panic(__location__);
964 TALLOC_FREE(state.blob.data);
967 struct set_delete_on_close_locked_state {
968 struct files_struct *fsp;
969 bool delete_on_close;
970 const struct security_token *nt_tok;
971 const struct security_unix_token *tok;
974 static void set_delete_on_close_locked(struct share_mode_lock *lck,
975 void *private_data)
977 struct set_delete_on_close_locked_state *state =
978 (struct set_delete_on_close_locked_state *)private_data;
980 if (state->delete_on_close) {
981 set_delete_on_close_lck(state->fsp,
982 lck,
983 state->nt_tok,
984 state->tok);
985 } else {
986 reset_delete_on_close_lck(state->fsp, lck);
989 state->fsp->fsp_flags.delete_on_close = state->delete_on_close;
992 bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
993 const struct security_token *nt_tok,
994 const struct security_unix_token *tok)
996 struct set_delete_on_close_locked_state state = {
997 .fsp = fsp,
998 .delete_on_close = delete_on_close,
999 .nt_tok = nt_tok,
1000 .tok = tok,
1002 NTSTATUS status;
1004 DEBUG(10,("set_delete_on_close: %s delete on close flag for "
1005 "%s, file %s\n",
1006 delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
1007 fsp_str_dbg(fsp)));
1009 if (fsp->fsp_flags.is_directory) {
1010 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
1013 status = share_mode_do_locked_vfs_denied(fsp->file_id,
1014 set_delete_on_close_locked,
1015 &state);
1016 if (!NT_STATUS_IS_OK(status)) {
1017 return false;
1020 return True;
1023 static struct delete_token *find_delete_on_close_token(
1024 struct share_mode_data *d, uint32_t name_hash)
1026 uint32_t i;
1028 DBG_DEBUG("name_hash = 0x%"PRIx32"\n", name_hash);
1030 for (i=0; i<d->num_delete_tokens; i++) {
1031 struct delete_token *dt = &d->delete_tokens[i];
1033 DBG_DEBUG("dt->name_hash = 0x%"PRIx32"\n",
1034 dt->name_hash);
1035 if (dt->name_hash == name_hash) {
1036 return dt;
1039 return NULL;
1042 /****************************************************************************
1043 Return the NT token and UNIX token if there's a match. Return true if
1044 found, false if not.
1045 ****************************************************************************/
1047 bool get_delete_on_close_token(struct share_mode_lock *lck,
1048 uint32_t name_hash,
1049 const struct security_token **pp_nt_tok,
1050 const struct security_unix_token **pp_tok,
1051 struct smb2_lease_key *parent_lease_key)
1053 struct share_mode_data *d = NULL;
1054 struct delete_token *dt;
1055 NTSTATUS status;
1057 status = share_mode_lock_access_private_data(lck, &d);
1058 if (!NT_STATUS_IS_OK(status)) {
1059 struct file_id id = share_mode_lock_file_id(lck);
1060 struct file_id_buf id_buf;
1061 /* Any error recovery possible here ? */
1062 DBG_ERR("share_mode_lock_access_private_data() failed for "
1063 "%s name_hash=%"PRIu32" - %s\n",
1064 file_id_str_buf(id, &id_buf), name_hash,
1065 nt_errstr(status));
1066 return false;
1069 dt = find_delete_on_close_token(d, name_hash);
1070 if (dt == NULL) {
1071 return false;
1073 *pp_nt_tok = dt->delete_nt_token;
1074 *pp_tok = dt->delete_token;
1075 *parent_lease_key = dt->parent_lease_key;
1076 return true;
1079 bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
1081 struct share_mode_data *d = NULL;
1082 NTSTATUS status;
1084 status = share_mode_lock_access_private_data(lck, &d);
1085 if (!NT_STATUS_IS_OK(status)) {
1086 struct file_id id = share_mode_lock_file_id(lck);
1087 struct file_id_buf id_buf;
1088 /* Any error recovery possible here ? */
1089 DBG_ERR("share_mode_lock_access_private_data() failed for "
1090 "%s name_hash=%"PRIu32" - %s\n",
1091 file_id_str_buf(id, &id_buf), name_hash,
1092 nt_errstr(status));
1093 return false;
1096 return find_delete_on_close_token(d, name_hash) != NULL;
1099 struct set_sticky_write_time_state {
1100 struct file_id fileid;
1101 struct timespec write_time;
1102 bool ok;
1105 static void set_sticky_write_time_fn(struct share_mode_lock *lck,
1106 void *private_data)
1108 struct set_sticky_write_time_state *state = private_data;
1109 struct share_mode_data *d = NULL;
1110 struct file_id_buf ftmp;
1111 struct timeval_buf tbuf;
1112 NTSTATUS status;
1114 status = share_mode_lock_access_private_data(lck, &d);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 /* Any error recovery possible here ? */
1117 DBG_ERR("share_mode_lock_access_private_data() failed for "
1118 "%s id=%s - %s\n",
1119 timespec_string_buf(&state->write_time, true, &tbuf),
1120 file_id_str_buf(state->fileid, &ftmp),
1121 nt_errstr(status));
1122 return;
1125 share_mode_set_changed_write_time(lck, state->write_time);
1127 state->ok = true;
1130 bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
1132 struct set_sticky_write_time_state state = {
1133 .fileid = fileid,
1134 .write_time = write_time,
1136 struct file_id_buf ftmp;
1137 struct timeval_buf tbuf;
1138 NTSTATUS status;
1140 status = share_mode_do_locked_vfs_denied(fileid,
1141 set_sticky_write_time_fn,
1142 &state);
1143 if (!NT_STATUS_IS_OK(status)) {
1144 /* Any error recovery possible here ? */
1145 DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
1146 "%s id=%s - %s\n",
1147 timespec_string_buf(&write_time, true, &tbuf),
1148 file_id_str_buf(fileid, &ftmp),
1149 nt_errstr(status));
1150 return false;
1153 return state.ok;
1156 struct set_write_time_state {
1157 struct file_id fileid;
1158 struct timespec write_time;
1159 bool ok;
1162 static void set_write_time_fn(struct share_mode_lock *lck,
1163 void *private_data)
1165 struct set_write_time_state *state = private_data;
1166 struct share_mode_data *d = NULL;
1167 struct file_id_buf idbuf;
1168 struct timeval_buf tbuf;
1169 NTSTATUS status;
1171 status = share_mode_lock_access_private_data(lck, &d);
1172 if (!NT_STATUS_IS_OK(status)) {
1173 /* Any error recovery possible here ? */
1174 DBG_ERR("share_mode_lock_access_private_data() failed for "
1175 "%s id=%s - %s\n",
1176 timespec_string_buf(&state->write_time, true, &tbuf),
1177 file_id_str_buf(state->fileid, &idbuf),
1178 nt_errstr(status));
1179 return;
1182 share_mode_set_old_write_time(lck, state->write_time);
1184 state->ok = true;
1187 bool set_write_time(struct file_id fileid, struct timespec write_time)
1189 struct set_write_time_state state = {
1190 .fileid = fileid,
1191 .write_time = write_time,
1193 struct file_id_buf idbuf;
1194 struct timeval_buf tbuf;
1195 NTSTATUS status;
1197 status = share_mode_do_locked_vfs_denied(fileid,
1198 set_write_time_fn,
1199 &state);
1200 if (!NT_STATUS_IS_OK(status)) {
1201 DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
1202 "%s id=%s - %s\n",
1203 timespec_string_buf(&write_time, true, &tbuf),
1204 file_id_str_buf(fileid, &idbuf),
1205 nt_errstr(status));
1206 return false;
1209 return state.ok;
1212 struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
1214 struct share_mode_data *d = NULL;
1215 NTSTATUS status;
1217 status = share_mode_lock_access_private_data(lck, &d);
1218 if (!NT_STATUS_IS_OK(status)) {
1219 struct file_id id = share_mode_lock_file_id(lck);
1220 struct file_id_buf id_buf;
1221 struct timespec ts_zero = {};
1222 /* Any error recovery possible here ? */
1223 DBG_ERR("share_mode_lock_access_private_data() failed for "
1224 "%s - %s\n",
1225 file_id_str_buf(id, &id_buf),
1226 nt_errstr(status));
1227 smb_panic(__location__);
1228 return ts_zero;
1231 if (!null_nttime(d->changed_write_time)) {
1232 return nt_time_to_full_timespec(d->changed_write_time);
1234 return nt_time_to_full_timespec(d->old_write_time);
1237 struct file_has_open_streams_state {
1238 bool found_one;
1239 bool ok;
1242 static bool file_has_open_streams_fn(
1243 struct share_mode_entry *e,
1244 bool *modified,
1245 void *private_data)
1247 struct file_has_open_streams_state *state = private_data;
1249 if ((e->private_options &
1250 NTCREATEX_FLAG_STREAM_BASEOPEN) == 0) {
1251 return false;
1254 if (share_entry_stale_pid(e)) {
1255 return false;
1258 state->found_one = true;
1259 return true;
1262 static void file_has_open_streams_locked(struct share_mode_lock *lck,
1263 void *private_data)
1265 struct file_has_open_streams_state *state = private_data;
1267 state->ok = share_mode_forall_entries(lck,
1268 file_has_open_streams_fn,
1269 private_data);
1272 bool file_has_open_streams(files_struct *fsp)
1274 struct file_has_open_streams_state state = { .found_one = false };
1275 NTSTATUS status;
1277 status = share_mode_do_locked_vfs_denied(fsp->file_id,
1278 file_has_open_streams_locked,
1279 &state);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 DBG_DEBUG("share_mode_do_locked_vfs_denied() failed - %s\n",
1282 nt_errstr(status));
1283 return false;
1286 if (!state.ok) {
1287 DBG_DEBUG("share_mode_forall_entries failed\n");
1288 return false;
1291 return state.found_one;
1295 * Walk share mode entries, looking at every lease only once
1298 struct share_mode_forall_leases_state {
1299 TALLOC_CTX *mem_ctx;
1300 struct leases_db_key *leases;
1301 bool (*fn)(struct share_mode_entry *e,
1302 void *private_data);
1303 void *private_data;
1304 NTSTATUS status;
1307 static bool share_mode_forall_leases_fn(
1308 struct share_mode_entry *e,
1309 bool *modified,
1310 void *private_data)
1312 struct share_mode_forall_leases_state *state = private_data;
1313 struct leases_db_key *leases = state->leases;
1314 size_t i, num_leases;
1315 bool stop;
1317 if (e->op_type != LEASE_OPLOCK) {
1318 return false;
1321 num_leases = talloc_array_length(leases);
1323 for (i=0; i<num_leases; i++) {
1324 struct leases_db_key *l = &leases[i];
1325 bool same = smb2_lease_equal(
1326 &e->client_guid,
1327 &e->lease_key,
1328 &l->client_guid,
1329 &l->lease_key);
1330 if (same) {
1331 return false;
1335 leases = talloc_realloc(
1336 state->mem_ctx,
1337 leases,
1338 struct leases_db_key,
1339 num_leases+1);
1340 if (leases == NULL) {
1341 state->status = NT_STATUS_NO_MEMORY;
1342 return true;
1344 leases[num_leases] = (struct leases_db_key) {
1345 .client_guid = e->client_guid,
1346 .lease_key = e->lease_key,
1348 state->leases = leases;
1350 stop = state->fn(e, state->private_data);
1351 return stop;
1354 bool share_mode_forall_leases(
1355 struct share_mode_lock *lck,
1356 bool (*fn)(struct share_mode_entry *e,
1357 void *private_data),
1358 void *private_data)
1360 struct share_mode_forall_leases_state state = {
1361 .mem_ctx = talloc_tos(),
1362 .fn = fn,
1363 .private_data = private_data
1365 bool ok;
1367 ok = share_mode_forall_entries(
1368 lck, share_mode_forall_leases_fn, &state);
1369 TALLOC_FREE(state.leases);
1370 if (!ok) {
1371 DBG_ERR("share_mode_forall_entries failed\n");
1372 return false;
1375 if (!NT_STATUS_IS_OK(state.status)) {
1376 DBG_ERR("share_mode_forall_leases_fn returned %s\n",
1377 nt_errstr(state.status));
1378 return false;
1381 return true;