Line data Source code
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
7 :
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.
12 :
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.
17 :
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/>.
20 :
21 : Revision History:
22 :
23 : 12 aug 96: Erik.Devriendt@te6.siemens.be
24 : added support for shared memory implementation of share mode locking
25 :
26 : May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27 : locking to deal with multiple share modes per open file.
28 :
29 : September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
30 : support.
31 :
32 : rewritten completely to use new tdb code. Tridge, Dec '99
33 :
34 : Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
35 : Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
36 : */
37 :
38 : #include "includes.h"
39 : #include "lib/util/time_basic.h"
40 : #include "system/filesys.h"
41 : #include "lib/util/server_id.h"
42 : #include "share_mode_lock.h"
43 : #include "share_mode_lock_private.h"
44 : #include "locking/proto.h"
45 : #include "smbd/globals.h"
46 : #include "dbwrap/dbwrap.h"
47 : #include "dbwrap/dbwrap_open.h"
48 : #include "../libcli/security/security.h"
49 : #include "serverid.h"
50 : #include "messages.h"
51 : #include "util_tdb.h"
52 : #include "../librpc/gen_ndr/ndr_open_files.h"
53 : #include "librpc/gen_ndr/ndr_file_id.h"
54 : #include "librpc/gen_ndr/ndr_leases_db.h"
55 : #include "locking/leases_db.h"
56 :
57 : #undef DBGC_CLASS
58 : #define DBGC_CLASS DBGC_LOCKING
59 :
60 : #define NO_LOCKING_COUNT (-1)
61 :
62 : /****************************************************************************
63 : Debugging aids :-).
64 : ****************************************************************************/
65 :
66 0 : const char *lock_type_name(enum brl_type lock_type)
67 : {
68 0 : switch (lock_type) {
69 0 : case READ_LOCK:
70 0 : return "READ";
71 0 : case WRITE_LOCK:
72 0 : return "WRITE";
73 0 : default:
74 0 : return "other";
75 : }
76 : }
77 :
78 0 : const char *lock_flav_name(enum brl_flavour lock_flav)
79 : {
80 0 : return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
81 : }
82 :
83 : /****************************************************************************
84 : Utility function called to see if a file region is locked.
85 : Called in the read/write codepath.
86 : ****************************************************************************/
87 :
88 204502 : void init_strict_lock_struct(files_struct *fsp,
89 : uint64_t smblctx,
90 : br_off start,
91 : br_off size,
92 : enum brl_type lock_type,
93 : enum brl_flavour lock_flav,
94 : struct lock_struct *plock)
95 : {
96 204502 : SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
97 :
98 204623 : *plock = (struct lock_struct) {
99 : .context.smblctx = smblctx,
100 204502 : .context.tid = fsp->conn->cnum,
101 204502 : .context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx),
102 : .start = start,
103 : .size = size,
104 204502 : .fnum = fsp->fnum,
105 : .lock_type = lock_type,
106 204502 : .lock_flav = lp_posix_cifsu_locktype(fsp),
107 : };
108 204502 : }
109 :
110 204087 : bool strict_lock_check_default(files_struct *fsp, struct lock_struct *plock)
111 : {
112 121 : struct byte_range_lock *br_lck;
113 204087 : int strict_locking = lp_strict_locking(fsp->conn->params);
114 204087 : bool ret = False;
115 :
116 204087 : if (plock->size == 0) {
117 150 : return True;
118 : }
119 :
120 203932 : if (!lp_locking(fsp->conn->params) || !strict_locking) {
121 0 : return True;
122 : }
123 :
124 203932 : if (strict_locking == Auto) {
125 203932 : uint32_t lease_type = fsp_lease_type(fsp);
126 :
127 203932 : if ((lease_type & SMB2_LEASE_READ) &&
128 234 : (plock->lock_type == READ_LOCK))
129 : {
130 78 : DBG_DEBUG("optimisation - read lease on file %s\n",
131 : fsp_str_dbg(fsp));
132 78 : return true;
133 : }
134 :
135 203854 : if ((lease_type & SMB2_LEASE_WRITE) &&
136 122 : (plock->lock_type == WRITE_LOCK))
137 : {
138 122 : DBG_DEBUG("optimisation - write lease on file %s\n",
139 : fsp_str_dbg(fsp));
140 122 : return true;
141 : }
142 : }
143 :
144 203732 : br_lck = brl_get_locks_readonly(fsp);
145 203732 : if (!br_lck) {
146 0 : return true;
147 : }
148 203732 : ret = brl_locktest(br_lck, plock);
149 :
150 203732 : if (!ret) {
151 : /*
152 : * We got a lock conflict. Retry with rw locks to enable
153 : * autocleanup. This is the slow path anyway.
154 : */
155 129 : br_lck = brl_get_locks(talloc_tos(), fsp);
156 129 : if (br_lck == NULL) {
157 0 : return true;
158 : }
159 129 : ret = brl_locktest(br_lck, plock);
160 129 : TALLOC_FREE(br_lck);
161 : }
162 :
163 203732 : DBG_DEBUG("flavour = %s brl start=%" PRIu64 " "
164 : "len=%" PRIu64 " %s for fnum %" PRIu64 " file %s\n",
165 : lock_flav_name(plock->lock_flav),
166 : plock->start,
167 : plock->size,
168 : ret ? "unlocked" : "locked",
169 : plock->fnum,
170 : fsp_str_dbg(fsp));
171 :
172 203616 : return ret;
173 : }
174 :
175 : /****************************************************************************
176 : Find out if a lock could be granted - return who is blocking us if we can't.
177 : ****************************************************************************/
178 :
179 0 : NTSTATUS query_lock(files_struct *fsp,
180 : uint64_t *psmblctx,
181 : uint64_t *pcount,
182 : uint64_t *poffset,
183 : enum brl_type *plock_type,
184 : enum brl_flavour lock_flav)
185 : {
186 0 : struct byte_range_lock *br_lck = NULL;
187 :
188 0 : if (!fsp->fsp_flags.can_lock) {
189 0 : return fsp->fsp_flags.is_directory ?
190 0 : NT_STATUS_INVALID_DEVICE_REQUEST :
191 : NT_STATUS_INVALID_HANDLE;
192 : }
193 :
194 0 : if (!lp_locking(fsp->conn->params)) {
195 0 : return NT_STATUS_OK;
196 : }
197 :
198 0 : br_lck = brl_get_locks_readonly(fsp);
199 0 : if (!br_lck) {
200 0 : return NT_STATUS_NO_MEMORY;
201 : }
202 :
203 0 : return brl_lockquery(br_lck,
204 : psmblctx,
205 0 : messaging_server_id(fsp->conn->sconn->msg_ctx),
206 : poffset,
207 : pcount,
208 : plock_type,
209 : lock_flav);
210 : }
211 :
212 6753 : static void increment_current_lock_count(files_struct *fsp,
213 : enum brl_flavour lock_flav)
214 : {
215 6779 : if (lock_flav == WINDOWS_LOCK &&
216 5837 : fsp->current_lock_count != NO_LOCKING_COUNT) {
217 : /* blocking ie. pending, locks also count here,
218 : * as this is an efficiency counter to avoid checking
219 : * the lock db. on close. JRA. */
220 :
221 5833 : fsp->current_lock_count++;
222 : } else {
223 : /* Notice that this has had a POSIX lock request.
224 : * We can't count locks after this so forget them.
225 : */
226 920 : fsp->current_lock_count = NO_LOCKING_COUNT;
227 : }
228 6727 : }
229 :
230 2158 : static void decrement_current_lock_count(files_struct *fsp,
231 : enum brl_flavour lock_flav)
232 : {
233 2158 : if (lock_flav == WINDOWS_LOCK &&
234 2150 : fsp->current_lock_count != NO_LOCKING_COUNT) {
235 2150 : SMB_ASSERT(fsp->current_lock_count > 0);
236 2150 : fsp->current_lock_count--;
237 : }
238 2158 : }
239 :
240 : /****************************************************************************
241 : Utility function called by locking requests.
242 : ****************************************************************************/
243 :
244 : struct do_lock_state {
245 : struct files_struct *fsp;
246 : TALLOC_CTX *req_mem_ctx;
247 : const struct GUID *req_guid;
248 : uint64_t smblctx;
249 : uint64_t count;
250 : uint64_t offset;
251 : enum brl_type lock_type;
252 : enum brl_flavour lock_flav;
253 :
254 : struct server_id blocker_pid;
255 : uint64_t blocker_smblctx;
256 : NTSTATUS status;
257 : };
258 :
259 6753 : static void do_lock_fn(
260 : struct share_mode_lock *lck,
261 : void *private_data)
262 : {
263 6753 : struct do_lock_state *state = private_data;
264 6753 : struct byte_range_lock *br_lck = NULL;
265 :
266 6753 : br_lck = brl_get_locks_for_locking(talloc_tos(),
267 6753 : state->fsp,
268 : state->req_mem_ctx,
269 : state->req_guid);
270 6753 : if (br_lck == NULL) {
271 0 : state->status = NT_STATUS_NO_MEMORY;
272 0 : return;
273 : }
274 :
275 6753 : state->status = brl_lock(
276 : br_lck,
277 : state->smblctx,
278 6753 : messaging_server_id(state->fsp->conn->sconn->msg_ctx),
279 : state->offset,
280 : state->count,
281 : state->lock_type,
282 : state->lock_flav,
283 : &state->blocker_pid,
284 : &state->blocker_smblctx);
285 :
286 6753 : TALLOC_FREE(br_lck);
287 : }
288 :
289 6753 : NTSTATUS do_lock(files_struct *fsp,
290 : TALLOC_CTX *req_mem_ctx,
291 : const struct GUID *req_guid,
292 : uint64_t smblctx,
293 : uint64_t count,
294 : uint64_t offset,
295 : enum brl_type lock_type,
296 : enum brl_flavour lock_flav,
297 : struct server_id *pblocker_pid,
298 : uint64_t *psmblctx)
299 : {
300 6753 : struct do_lock_state state = {
301 : .fsp = fsp,
302 : .req_mem_ctx = req_mem_ctx,
303 : .req_guid = req_guid,
304 : .smblctx = smblctx,
305 : .count = count,
306 : .offset = offset,
307 : .lock_type = lock_type,
308 : .lock_flav = lock_flav,
309 : };
310 26 : NTSTATUS status;
311 :
312 : /* silently return ok on print files as we don't do locking there */
313 6753 : if (fsp->print_file) {
314 0 : return NT_STATUS_OK;
315 : }
316 :
317 6753 : if (!fsp->fsp_flags.can_lock) {
318 0 : if (fsp->fsp_flags.is_directory) {
319 0 : return NT_STATUS_INVALID_DEVICE_REQUEST;
320 : }
321 0 : return NT_STATUS_INVALID_HANDLE;
322 : }
323 :
324 6753 : if (!lp_locking(fsp->conn->params)) {
325 0 : return NT_STATUS_OK;
326 : }
327 :
328 : /* NOTE! 0 byte long ranges ARE allowed and should be stored */
329 :
330 6753 : DBG_DEBUG("lock flavour %s lock type %s start=%"PRIu64" len=%"PRIu64" "
331 : "requested for %s file %s\n",
332 : lock_flav_name(lock_flav),
333 : lock_type_name(lock_type),
334 : offset,
335 : count,
336 : fsp_fnum_dbg(fsp),
337 : fsp_str_dbg(fsp));
338 :
339 6753 : status = share_mode_do_locked_vfs_allowed(fsp->file_id,
340 : do_lock_fn,
341 : &state);
342 6753 : if (!NT_STATUS_IS_OK(status)) {
343 0 : DBG_DEBUG("share_mode_do_locked returned %s\n",
344 : nt_errstr(status));
345 0 : return status;
346 : }
347 :
348 6753 : if (psmblctx != NULL) {
349 5869 : *psmblctx = state.blocker_smblctx;
350 : }
351 6753 : if (pblocker_pid != NULL) {
352 5869 : *pblocker_pid = state.blocker_pid;
353 : }
354 :
355 6753 : DBG_DEBUG("returning status=%s\n", nt_errstr(state.status));
356 :
357 6753 : increment_current_lock_count(fsp, lock_flav);
358 :
359 6753 : return state.status;
360 : }
361 :
362 : /****************************************************************************
363 : Utility function called by unlocking requests.
364 : ****************************************************************************/
365 :
366 2362 : NTSTATUS do_unlock(files_struct *fsp,
367 : uint64_t smblctx,
368 : uint64_t count,
369 : uint64_t offset,
370 : enum brl_flavour lock_flav)
371 : {
372 2362 : bool ok = False;
373 2362 : struct byte_range_lock *br_lck = NULL;
374 :
375 2362 : if (!fsp->fsp_flags.can_lock) {
376 0 : return fsp->fsp_flags.is_directory ?
377 0 : NT_STATUS_INVALID_DEVICE_REQUEST :
378 : NT_STATUS_INVALID_HANDLE;
379 : }
380 :
381 2362 : if (!lp_locking(fsp->conn->params)) {
382 0 : return NT_STATUS_OK;
383 : }
384 :
385 2362 : DBG_DEBUG("unlock start=%"PRIu64" len=%"PRIu64" requested for %s file "
386 : "%s\n",
387 : offset,
388 : count,
389 : fsp_fnum_dbg(fsp),
390 : fsp_str_dbg(fsp));
391 :
392 2362 : br_lck = brl_get_locks(talloc_tos(), fsp);
393 2362 : if (!br_lck) {
394 0 : return NT_STATUS_NO_MEMORY;
395 : }
396 :
397 2362 : ok = brl_unlock(br_lck,
398 : smblctx,
399 2362 : messaging_server_id(fsp->conn->sconn->msg_ctx),
400 : offset,
401 : count,
402 : lock_flav);
403 :
404 2362 : TALLOC_FREE(br_lck);
405 :
406 2362 : if (!ok) {
407 204 : DEBUG(10,("do_unlock: returning ERRlock.\n" ));
408 204 : return NT_STATUS_RANGE_NOT_LOCKED;
409 : }
410 :
411 2158 : decrement_current_lock_count(fsp, lock_flav);
412 2158 : return NT_STATUS_OK;
413 : }
414 :
415 : /****************************************************************************
416 : Remove any locks on this fd. Called from file_close().
417 : ****************************************************************************/
418 :
419 358185 : void locking_close_file(files_struct *fsp,
420 : enum file_close_type close_type)
421 : {
422 593 : struct byte_range_lock *br_lck;
423 :
424 358185 : if (!lp_locking(fsp->conn->params)) {
425 0 : return;
426 : }
427 :
428 : /* If we have no outstanding locks or pending
429 : * locks then we don't need to look in the lock db.
430 : */
431 :
432 358185 : if (fsp->current_lock_count == 0) {
433 356699 : return;
434 : }
435 :
436 899 : br_lck = brl_get_locks(talloc_tos(),fsp);
437 :
438 899 : if (br_lck) {
439 : /*
440 : * Unlocks must trigger dbwrap_watch watchers,
441 : * normally in smbd_do_unlocking. Here it's done
442 : * implicitly, we're closing the file and thus remove a
443 : * share mode. This will wake the waiters.
444 : */
445 899 : brl_close_fnum(br_lck);
446 899 : TALLOC_FREE(br_lck);
447 : }
448 : }
449 :
450 : /*******************************************************************
451 : Print out a share mode.
452 : ********************************************************************/
453 :
454 0 : char *share_mode_str(TALLOC_CTX *ctx, int num,
455 : const struct file_id *id,
456 : const struct share_mode_entry *e)
457 : {
458 0 : struct server_id_buf tmp;
459 0 : struct file_id_buf ftmp;
460 :
461 0 : return talloc_asprintf(ctx, "share_mode_entry[%d]: "
462 : "pid = %s, share_access = 0x%x, private_options = 0x%x, "
463 : "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
464 : "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
465 : num,
466 : server_id_str_buf(e->pid, &tmp),
467 0 : e->share_access, e->private_options,
468 0 : e->access_mask, (unsigned long long)e->op_mid,
469 0 : e->op_type, (unsigned long long)e->share_file_id,
470 0 : (unsigned int)e->uid, (unsigned int)e->flags,
471 : file_id_str_buf(*id, &ftmp),
472 0 : (unsigned int)e->name_hash);
473 : }
474 :
475 : struct rename_share_filename_state {
476 : struct share_mode_data *data;
477 : struct messaging_context *msg_ctx;
478 : struct server_id self;
479 : uint32_t orig_name_hash;
480 : uint32_t new_name_hash;
481 : struct file_rename_message msg;
482 : };
483 :
484 10 : static bool rename_lease_fn(struct share_mode_entry *e,
485 : void *private_data)
486 : {
487 10 : struct rename_share_filename_state *state = private_data;
488 10 : struct share_mode_data *d = state->data;
489 0 : NTSTATUS status;
490 :
491 10 : status = leases_db_rename(&e->client_guid,
492 10 : &e->lease_key,
493 10 : &d->id,
494 : d->servicepath,
495 : d->base_name,
496 : d->stream_name);
497 :
498 10 : if (!NT_STATUS_IS_OK(status)) {
499 : /* Any error recovery possible here ? */
500 0 : DBG_WARNING("Failed to rename lease key for "
501 : "renamed file %s:%s. %s\n",
502 : d->base_name,
503 : d->stream_name,
504 : nt_errstr(status));
505 : }
506 :
507 10 : return false;
508 : }
509 :
510 : /*******************************************************************
511 : Sets the service name and filename for rename.
512 : At this point we emit "file renamed" messages to all
513 : process id's that have this file open.
514 : Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
515 : ********************************************************************/
516 :
517 1043 : static bool rename_share_filename_fn(
518 : struct share_mode_entry *e,
519 : bool *modified,
520 : void *private_data)
521 : {
522 1043 : struct rename_share_filename_state *state = private_data;
523 23 : DATA_BLOB blob;
524 23 : enum ndr_err_code ndr_err;
525 23 : bool ok;
526 :
527 : /*
528 : * If this is a hardlink to the inode with a different name,
529 : * skip this.
530 : */
531 1043 : if (e->name_hash != state->orig_name_hash) {
532 0 : return false;
533 : }
534 1043 : e->name_hash = state->new_name_hash;
535 1043 : *modified = true;
536 :
537 1043 : ok = server_id_equal(&e->pid, &state->self);
538 1043 : if (ok) {
539 998 : return false;
540 : }
541 :
542 24 : state->msg.share_file_id = e->share_file_id;
543 :
544 24 : ndr_err = ndr_push_struct_blob(
545 : &blob,
546 : talloc_tos(),
547 24 : &state->msg,
548 : (ndr_push_flags_fn_t)ndr_push_file_rename_message);
549 24 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
550 0 : DBG_DEBUG("ndr_push_file_rename_message failed: %s\n",
551 : ndr_errstr(ndr_err));
552 0 : return false;
553 : }
554 24 : if (DEBUGLEVEL >= 10) {
555 0 : struct server_id_buf tmp;
556 0 : DBG_DEBUG("sending rename message to %s\n",
557 : server_id_str_buf(e->pid, &tmp));
558 0 : NDR_PRINT_DEBUG(file_rename_message, &state->msg);
559 : }
560 :
561 24 : messaging_send(state->msg_ctx, e->pid, MSG_SMB_FILE_RENAME, &blob);
562 :
563 24 : TALLOC_FREE(blob.data);
564 :
565 22 : return false;
566 : }
567 :
568 960 : bool rename_share_filename(struct messaging_context *msg_ctx,
569 : struct share_mode_lock *lck,
570 : struct file_id id,
571 : const char *servicepath,
572 : uint32_t orig_name_hash,
573 : uint32_t new_name_hash,
574 : const struct smb_filename *smb_fname_dst)
575 : {
576 1920 : struct rename_share_filename_state state = {
577 : .msg_ctx = msg_ctx,
578 960 : .self = messaging_server_id(msg_ctx),
579 : .orig_name_hash = orig_name_hash,
580 : .new_name_hash = new_name_hash,
581 : .msg.id = id,
582 : .msg.servicepath = servicepath,
583 960 : .msg.base_name = smb_fname_dst->base_name,
584 960 : .msg.stream_name = smb_fname_dst->stream_name,
585 : };
586 960 : struct share_mode_data *d = NULL;
587 16 : NTSTATUS status;
588 16 : bool ok;
589 :
590 960 : DBG_DEBUG("servicepath %s newname %s\n",
591 : servicepath,
592 : smb_fname_dst->base_name);
593 :
594 960 : status = share_mode_lock_access_private_data(lck, &d);
595 960 : if (!NT_STATUS_IS_OK(status)) {
596 : /* Any error recovery possible here ? */
597 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
598 : "servicepath %s newname %s - %s\n",
599 : servicepath, smb_fname_dst->base_name,
600 : nt_errstr(status));
601 0 : return false;
602 : }
603 960 : state.data = d;
604 :
605 : /*
606 : * rename_internal_fsp() and rename_internals() add './' to
607 : * head of newname if newname does not contain a '/'.
608 : */
609 :
610 960 : if (strncmp(state.msg.base_name, "./", 2) == 0) {
611 0 : state.msg.base_name += 2;
612 : }
613 :
614 960 : d->servicepath = talloc_strdup(d, state.msg.servicepath);
615 960 : d->base_name = talloc_strdup(d, state.msg.base_name);
616 960 : d->stream_name = talloc_strdup(d, state.msg.stream_name);
617 960 : if ((d->servicepath == NULL) ||
618 960 : (d->base_name == NULL) ||
619 960 : ((state.msg.stream_name != NULL) && (d->stream_name == NULL))) {
620 0 : DBG_WARNING("talloc failed\n");
621 0 : return false;
622 : }
623 960 : d->modified = True;
624 :
625 960 : ok = share_mode_forall_entries(
626 : lck, rename_share_filename_fn, &state);
627 960 : if (!ok) {
628 0 : DBG_WARNING("share_mode_forall_entries failed\n");
629 : }
630 :
631 960 : ok = share_mode_forall_leases(lck, rename_lease_fn, &state);
632 960 : if (!ok) {
633 : /*
634 : * Ignore error here. Not sure what to do..
635 : */
636 0 : DBG_WARNING("share_mode_forall_leases failed\n");
637 : }
638 :
639 944 : return True;
640 : }
641 :
642 871940 : void get_file_infos(struct file_id id,
643 : uint32_t name_hash,
644 : bool *delete_on_close,
645 : struct timespec *write_time)
646 : {
647 1284 : struct share_mode_lock *lck;
648 :
649 871940 : if (delete_on_close) {
650 153437 : *delete_on_close = false;
651 : }
652 :
653 871940 : if (write_time) {
654 744854 : *write_time = make_omit_timespec();
655 : }
656 :
657 871940 : if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
658 824786 : return;
659 : }
660 :
661 46719 : if (delete_on_close) {
662 45789 : *delete_on_close = is_delete_on_close_set(lck, name_hash);
663 : }
664 :
665 46719 : if (write_time) {
666 20289 : *write_time = get_share_mode_write_time(lck);
667 : }
668 :
669 46719 : TALLOC_FREE(lck);
670 : }
671 :
672 10 : bool is_valid_share_mode_entry(const struct share_mode_entry *e)
673 : {
674 10 : int num_props = 0;
675 :
676 10 : if (e->stale) {
677 0 : return false;
678 : }
679 :
680 10 : num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
681 10 : num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
682 10 : num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
683 10 : num_props += (e->op_type == LEASE_OPLOCK);
684 :
685 10 : if ((num_props > 1) && serverid_exists(&e->pid)) {
686 0 : smb_panic("Invalid share mode entry");
687 : }
688 10 : return (num_props != 0);
689 : }
690 :
691 : struct find_lease_ref_state {
692 : const struct GUID *client_guid;
693 : const struct smb2_lease_key *lease_key;
694 : bool found_same;
695 : };
696 :
697 1356 : static bool find_lease_ref_fn(
698 : struct share_mode_entry *e,
699 : bool *modified,
700 : void *private_data)
701 : {
702 1356 : struct find_lease_ref_state *state = private_data;
703 :
704 1356 : if (e->stale) {
705 0 : return false;
706 : }
707 1356 : if (e->op_type != LEASE_OPLOCK) {
708 964 : return false;
709 : }
710 :
711 784 : state->found_same = smb2_lease_equal(
712 392 : &e->client_guid,
713 392 : &e->lease_key,
714 : state->client_guid,
715 : state->lease_key);
716 : /*
717 : * If we found a lease reference, look no further (i.e. return true)
718 : */
719 392 : return state->found_same;
720 : }
721 :
722 962 : NTSTATUS remove_lease_if_stale(struct share_mode_lock *lck,
723 : const struct GUID *client_guid,
724 : const struct smb2_lease_key *lease_key)
725 : {
726 962 : struct find_lease_ref_state state = {
727 : .client_guid = client_guid, .lease_key = lease_key,
728 : };
729 962 : struct file_id id = share_mode_lock_file_id(lck);
730 0 : NTSTATUS status;
731 0 : bool ok;
732 :
733 962 : ok = share_mode_forall_entries(lck, find_lease_ref_fn, &state);
734 962 : if (!ok) {
735 0 : DBG_ERR("share_mode_forall_entries failed\n");
736 0 : return NT_STATUS_INTERNAL_ERROR;
737 : }
738 :
739 962 : if (state.found_same) {
740 212 : return NT_STATUS_RESOURCE_IN_USE;
741 : }
742 :
743 750 : status = leases_db_del(client_guid, lease_key, &id);
744 750 : if (!NT_STATUS_IS_OK(status)) {
745 0 : int level = DBGLVL_DEBUG;
746 :
747 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
748 0 : level = DBGLVL_ERR;
749 : }
750 0 : DBG_PREFIX(level, ("leases_db_del failed: %s\n",
751 : nt_errstr(status)));
752 : }
753 750 : return status;
754 : }
755 :
756 42150 : bool share_entry_stale_pid(struct share_mode_entry *e)
757 : {
758 223 : struct server_id_buf buf;
759 223 : bool exists;
760 :
761 42150 : if (e->stale) {
762 16 : return true;
763 : }
764 :
765 42134 : exists = serverid_exists(&e->pid);
766 42134 : if (exists) {
767 42108 : DBG_DEBUG("PID %s still exists\n",
768 : server_id_str_buf(e->pid, &buf));
769 42108 : return false;
770 : }
771 :
772 26 : DBG_DEBUG("PID %s does not exist anymore\n",
773 : server_id_str_buf(e->pid, &buf));
774 :
775 26 : e->stale = true;
776 :
777 26 : return true;
778 : }
779 :
780 : /****************************************************************************
781 : Adds a delete on close token.
782 : ****************************************************************************/
783 :
784 170455 : static bool add_delete_on_close_token(struct share_mode_data *d,
785 : uint32_t name_hash,
786 : const struct security_token *nt_tok,
787 : const struct security_unix_token *tok)
788 : {
789 340 : struct delete_token *tmp, *dtl;
790 :
791 170455 : tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
792 : d->num_delete_tokens+1);
793 170455 : if (tmp == NULL) {
794 0 : return false;
795 : }
796 170455 : d->delete_tokens = tmp;
797 170455 : dtl = &d->delete_tokens[d->num_delete_tokens];
798 :
799 170455 : dtl->name_hash = name_hash;
800 170455 : dtl->delete_nt_token = security_token_duplicate(d->delete_tokens, nt_tok);
801 170455 : if (dtl->delete_nt_token == NULL) {
802 0 : return false;
803 : }
804 170455 : dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
805 170455 : if (dtl->delete_token == NULL) {
806 0 : return false;
807 : }
808 170455 : d->num_delete_tokens += 1;
809 170455 : d->modified = true;
810 170455 : return true;
811 : }
812 :
813 159329 : void reset_delete_on_close_lck(files_struct *fsp,
814 : struct share_mode_lock *lck)
815 : {
816 159329 : struct share_mode_data *d = NULL;
817 277 : NTSTATUS status;
818 277 : uint32_t i;
819 :
820 159329 : status = share_mode_lock_access_private_data(lck, &d);
821 159329 : if (!NT_STATUS_IS_OK(status)) {
822 : /* Any error recovery possible here ? */
823 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
824 : "%s - %s\n", fsp_str_dbg(fsp), nt_errstr(status));
825 0 : smb_panic(__location__);
826 : return;
827 : }
828 :
829 318643 : for (i=0; i<d->num_delete_tokens; i++) {
830 159314 : struct delete_token *dt = &d->delete_tokens[i];
831 :
832 159314 : if (dt->name_hash == fsp->name_hash) {
833 159314 : d->modified = true;
834 :
835 : /* Delete this entry. */
836 159314 : TALLOC_FREE(dt->delete_nt_token);
837 159314 : TALLOC_FREE(dt->delete_token);
838 159314 : *dt = d->delete_tokens[d->num_delete_tokens-1];
839 159314 : d->num_delete_tokens -= 1;
840 : }
841 : }
842 : }
843 :
844 : struct set_delete_on_close_state {
845 : struct messaging_context *msg_ctx;
846 : DATA_BLOB blob;
847 : };
848 :
849 170724 : static bool set_delete_on_close_fn(
850 : struct share_mode_entry *e,
851 : bool *modified,
852 : void *private_data)
853 : {
854 170724 : struct set_delete_on_close_state *state = private_data;
855 356 : NTSTATUS status;
856 :
857 170724 : status = messaging_send(
858 : state->msg_ctx,
859 : e->pid,
860 : MSG_SMB_NOTIFY_CANCEL_DELETED,
861 170724 : &state->blob);
862 :
863 170724 : if (!NT_STATUS_IS_OK(status)) {
864 0 : struct server_id_buf tmp;
865 0 : DBG_DEBUG("messaging_send to %s returned %s\n",
866 : server_id_str_buf(e->pid, &tmp),
867 : nt_errstr(status));
868 : }
869 :
870 170724 : return false;
871 : }
872 :
873 : /****************************************************************************
874 : Sets the delete on close flag over all share modes on this file.
875 : Modify the share mode entry for all files open
876 : on this device and inode to tell other smbds we have
877 : changed the delete on close flag. This will be noticed
878 : in the close code, the last closer will delete the file
879 : if flag is set.
880 : This makes a copy of any struct security_unix_token into the
881 : lck entry. This function is used when the lock is already granted.
882 : ****************************************************************************/
883 :
884 170457 : void set_delete_on_close_lck(files_struct *fsp,
885 : struct share_mode_lock *lck,
886 : const struct security_token *nt_tok,
887 : const struct security_unix_token *tok)
888 : {
889 170457 : struct share_mode_data *d = NULL;
890 170457 : struct set_delete_on_close_state state = {
891 170457 : .msg_ctx = fsp->conn->sconn->msg_ctx
892 : };
893 340 : uint32_t i;
894 340 : bool ret;
895 340 : enum ndr_err_code ndr_err;
896 340 : NTSTATUS status;
897 :
898 170457 : status = share_mode_lock_access_private_data(lck, &d);
899 170457 : if (!NT_STATUS_IS_OK(status)) {
900 : /* Any error recovery possible here ? */
901 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
902 : "%s - %s\n", fsp_str_dbg(fsp), nt_errstr(status));
903 0 : smb_panic(__location__);
904 2 : return;
905 : }
906 :
907 170457 : SMB_ASSERT(nt_tok != NULL);
908 170457 : SMB_ASSERT(tok != NULL);
909 :
910 170457 : for (i=0; i<d->num_delete_tokens; i++) {
911 2 : struct delete_token *dt = &d->delete_tokens[i];
912 2 : if (dt->name_hash == fsp->name_hash) {
913 2 : d->modified = true;
914 :
915 : /* Replace this token with the given tok. */
916 2 : TALLOC_FREE(dt->delete_nt_token);
917 2 : dt->delete_nt_token = security_token_duplicate(dt, nt_tok);
918 2 : SMB_ASSERT(dt->delete_nt_token != NULL);
919 2 : TALLOC_FREE(dt->delete_token);
920 2 : dt->delete_token = copy_unix_token(dt, tok);
921 2 : SMB_ASSERT(dt->delete_token != NULL);
922 :
923 2 : return;
924 : }
925 : }
926 :
927 170455 : ret = add_delete_on_close_token(d, fsp->name_hash, nt_tok, tok);
928 170455 : SMB_ASSERT(ret);
929 :
930 170455 : ndr_err = ndr_push_struct_blob(
931 : &state.blob,
932 : talloc_tos(),
933 170455 : &fsp->file_id,
934 : (ndr_push_flags_fn_t)ndr_push_file_id);
935 170455 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
936 0 : DBG_ERR("ndr_push_file_id failed: %s\n",
937 : ndr_errstr(ndr_err));
938 0 : smb_panic(__location__);
939 : }
940 :
941 170455 : ret = share_mode_forall_entries(
942 : lck, set_delete_on_close_fn, &state);
943 170455 : if (!ret) {
944 0 : DBG_ERR("share_mode_forall_entries failed\n");
945 0 : smb_panic(__location__);
946 : }
947 :
948 170455 : TALLOC_FREE(state.blob.data);
949 : }
950 :
951 : struct set_delete_on_close_locked_state {
952 : struct files_struct *fsp;
953 : bool delete_on_close;
954 : const struct security_token *nt_tok;
955 : const struct security_unix_token *tok;
956 : };
957 :
958 33437 : static void set_delete_on_close_locked(struct share_mode_lock *lck,
959 : void *private_data)
960 : {
961 33437 : struct set_delete_on_close_locked_state *state =
962 : (struct set_delete_on_close_locked_state *)private_data;
963 :
964 33437 : if (state->delete_on_close) {
965 33390 : set_delete_on_close_lck(state->fsp,
966 : lck,
967 : state->nt_tok,
968 : state->tok);
969 : } else {
970 47 : reset_delete_on_close_lck(state->fsp, lck);
971 : }
972 :
973 33437 : state->fsp->fsp_flags.delete_on_close = state->delete_on_close;
974 33437 : }
975 :
976 33445 : bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
977 : const struct security_token *nt_tok,
978 : const struct security_unix_token *tok)
979 : {
980 33445 : struct set_delete_on_close_locked_state state = {
981 : .fsp = fsp,
982 : .delete_on_close = delete_on_close,
983 : .nt_tok = nt_tok,
984 : .tok = tok,
985 : };
986 206 : NTSTATUS status;
987 :
988 33445 : DEBUG(10,("set_delete_on_close: %s delete on close flag for "
989 : "%s, file %s\n",
990 : delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
991 : fsp_str_dbg(fsp)));
992 :
993 33445 : if (fsp->fsp_flags.is_directory) {
994 9149 : SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
995 : }
996 :
997 33445 : status = share_mode_do_locked_vfs_denied(fsp->file_id,
998 : set_delete_on_close_locked,
999 : &state);
1000 33445 : if (!NT_STATUS_IS_OK(status)) {
1001 8 : return false;
1002 : }
1003 :
1004 33231 : return True;
1005 : }
1006 :
1007 1245934 : static struct delete_token *find_delete_on_close_token(
1008 : struct share_mode_data *d, uint32_t name_hash)
1009 : {
1010 3169 : uint32_t i;
1011 :
1012 1245934 : DBG_DEBUG("name_hash = 0x%"PRIx32"\n", name_hash);
1013 :
1014 1245934 : for (i=0; i<d->num_delete_tokens; i++) {
1015 341623 : struct delete_token *dt = &d->delete_tokens[i];
1016 :
1017 341623 : DBG_DEBUG("dt->name_hash = 0x%"PRIx32"\n",
1018 : dt->name_hash);
1019 341623 : if (dt->name_hash == name_hash) {
1020 341623 : return dt;
1021 : }
1022 : }
1023 901900 : return NULL;
1024 : }
1025 :
1026 : /****************************************************************************
1027 : Return the NT token and UNIX token if there's a match. Return true if
1028 : found, false if not.
1029 : ****************************************************************************/
1030 :
1031 170421 : bool get_delete_on_close_token(struct share_mode_lock *lck,
1032 : uint32_t name_hash,
1033 : const struct security_token **pp_nt_tok,
1034 : const struct security_unix_token **pp_tok)
1035 : {
1036 170421 : struct share_mode_data *d = NULL;
1037 336 : struct delete_token *dt;
1038 336 : NTSTATUS status;
1039 :
1040 170421 : status = share_mode_lock_access_private_data(lck, &d);
1041 170421 : if (!NT_STATUS_IS_OK(status)) {
1042 0 : struct file_id id = share_mode_lock_file_id(lck);
1043 0 : struct file_id_buf id_buf;
1044 : /* Any error recovery possible here ? */
1045 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
1046 : "%s name_hash=%"PRIu32" - %s\n",
1047 : file_id_str_buf(id, &id_buf), name_hash,
1048 : nt_errstr(status));
1049 0 : return false;
1050 : }
1051 :
1052 170421 : dt = find_delete_on_close_token(d, name_hash);
1053 170421 : if (dt == NULL) {
1054 0 : return false;
1055 : }
1056 170421 : *pp_nt_tok = dt->delete_nt_token;
1057 170421 : *pp_tok = dt->delete_token;
1058 170421 : return true;
1059 : }
1060 :
1061 1075513 : bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
1062 : {
1063 1075513 : struct share_mode_data *d = NULL;
1064 2833 : NTSTATUS status;
1065 :
1066 1075513 : status = share_mode_lock_access_private_data(lck, &d);
1067 1075513 : if (!NT_STATUS_IS_OK(status)) {
1068 0 : struct file_id id = share_mode_lock_file_id(lck);
1069 0 : struct file_id_buf id_buf;
1070 : /* Any error recovery possible here ? */
1071 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
1072 : "%s name_hash=%"PRIu32" - %s\n",
1073 : file_id_str_buf(id, &id_buf), name_hash,
1074 : nt_errstr(status));
1075 0 : return false;
1076 : }
1077 :
1078 1075513 : return find_delete_on_close_token(d, name_hash) != NULL;
1079 : }
1080 :
1081 : struct set_sticky_write_time_state {
1082 : struct file_id fileid;
1083 : struct timespec write_time;
1084 : bool ok;
1085 : };
1086 :
1087 1048 : static void set_sticky_write_time_fn(struct share_mode_lock *lck,
1088 : void *private_data)
1089 : {
1090 1048 : struct set_sticky_write_time_state *state = private_data;
1091 1048 : struct share_mode_data *d = NULL;
1092 25 : struct file_id_buf ftmp;
1093 25 : struct timeval_buf tbuf;
1094 25 : NTSTATUS status;
1095 :
1096 1048 : status = share_mode_lock_access_private_data(lck, &d);
1097 1048 : if (!NT_STATUS_IS_OK(status)) {
1098 : /* Any error recovery possible here ? */
1099 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
1100 : "%s id=%s - %s\n",
1101 : timespec_string_buf(&state->write_time, true, &tbuf),
1102 : file_id_str_buf(state->fileid, &ftmp),
1103 : nt_errstr(status));
1104 0 : return;
1105 : }
1106 :
1107 1048 : share_mode_set_changed_write_time(lck, state->write_time);
1108 :
1109 1048 : state->ok = true;
1110 : }
1111 :
1112 1213 : bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
1113 : {
1114 1213 : struct set_sticky_write_time_state state = {
1115 : .fileid = fileid,
1116 : .write_time = write_time,
1117 : };
1118 26 : struct file_id_buf ftmp;
1119 26 : struct timeval_buf tbuf;
1120 26 : NTSTATUS status;
1121 :
1122 1213 : status = share_mode_do_locked_vfs_denied(fileid,
1123 : set_sticky_write_time_fn,
1124 : &state);
1125 1213 : if (!NT_STATUS_IS_OK(status)) {
1126 : /* Any error recovery possible here ? */
1127 165 : DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
1128 : "%s id=%s - %s\n",
1129 : timespec_string_buf(&write_time, true, &tbuf),
1130 : file_id_str_buf(fileid, &ftmp),
1131 : nt_errstr(status));
1132 165 : return false;
1133 : }
1134 :
1135 1048 : return state.ok;
1136 : }
1137 :
1138 : struct set_write_time_state {
1139 : struct file_id fileid;
1140 : struct timespec write_time;
1141 : bool ok;
1142 : };
1143 :
1144 5667 : static void set_write_time_fn(struct share_mode_lock *lck,
1145 : void *private_data)
1146 : {
1147 5667 : struct set_write_time_state *state = private_data;
1148 5667 : struct share_mode_data *d = NULL;
1149 21 : struct file_id_buf idbuf;
1150 21 : struct timeval_buf tbuf;
1151 21 : NTSTATUS status;
1152 :
1153 5667 : status = share_mode_lock_access_private_data(lck, &d);
1154 5667 : if (!NT_STATUS_IS_OK(status)) {
1155 : /* Any error recovery possible here ? */
1156 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
1157 : "%s id=%s - %s\n",
1158 : timespec_string_buf(&state->write_time, true, &tbuf),
1159 : file_id_str_buf(state->fileid, &idbuf),
1160 : nt_errstr(status));
1161 0 : return;
1162 : }
1163 :
1164 5667 : share_mode_set_old_write_time(lck, state->write_time);
1165 :
1166 5667 : state->ok = true;
1167 : }
1168 :
1169 5675 : bool set_write_time(struct file_id fileid, struct timespec write_time)
1170 : {
1171 5675 : struct set_write_time_state state = {
1172 : .fileid = fileid,
1173 : .write_time = write_time,
1174 : };
1175 21 : struct file_id_buf idbuf;
1176 21 : struct timeval_buf tbuf;
1177 21 : NTSTATUS status;
1178 :
1179 5675 : status = share_mode_do_locked_vfs_denied(fileid,
1180 : set_write_time_fn,
1181 : &state);
1182 5675 : if (!NT_STATUS_IS_OK(status)) {
1183 8 : DBG_ERR("share_mode_do_locked_vfs_denied() failed for "
1184 : "%s id=%s - %s\n",
1185 : timespec_string_buf(&write_time, true, &tbuf),
1186 : file_id_str_buf(fileid, &idbuf),
1187 : nt_errstr(status));
1188 8 : return false;
1189 : }
1190 :
1191 5667 : return state.ok;
1192 : }
1193 :
1194 461186 : struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
1195 : {
1196 461186 : struct share_mode_data *d = NULL;
1197 1767 : NTSTATUS status;
1198 :
1199 461186 : status = share_mode_lock_access_private_data(lck, &d);
1200 461186 : if (!NT_STATUS_IS_OK(status)) {
1201 0 : struct file_id id = share_mode_lock_file_id(lck);
1202 0 : struct file_id_buf id_buf;
1203 0 : struct timespec ts_zero = {};
1204 : /* Any error recovery possible here ? */
1205 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
1206 : "%s - %s\n",
1207 : file_id_str_buf(id, &id_buf),
1208 : nt_errstr(status));
1209 0 : smb_panic(__location__);
1210 : return ts_zero;
1211 : }
1212 :
1213 461186 : if (!null_nttime(d->changed_write_time)) {
1214 1983 : return nt_time_to_full_timespec(d->changed_write_time);
1215 : }
1216 459203 : return nt_time_to_full_timespec(d->old_write_time);
1217 : }
1218 :
1219 : struct file_has_open_streams_state {
1220 : bool found_one;
1221 : bool ok;
1222 : };
1223 :
1224 1195 : static bool file_has_open_streams_fn(
1225 : struct share_mode_entry *e,
1226 : bool *modified,
1227 : void *private_data)
1228 : {
1229 1195 : struct file_has_open_streams_state *state = private_data;
1230 :
1231 1195 : if ((e->private_options &
1232 : NTCREATEX_FLAG_STREAM_BASEOPEN) == 0) {
1233 1152 : return false;
1234 : }
1235 :
1236 16 : if (share_entry_stale_pid(e)) {
1237 0 : return false;
1238 : }
1239 :
1240 16 : state->found_one = true;
1241 16 : return true;
1242 : }
1243 :
1244 1094 : static void file_has_open_streams_locked(struct share_mode_lock *lck,
1245 : void *private_data)
1246 : {
1247 1094 : struct file_has_open_streams_state *state = private_data;
1248 :
1249 1094 : state->ok = share_mode_forall_entries(lck,
1250 : file_has_open_streams_fn,
1251 : private_data);
1252 1094 : }
1253 :
1254 1094 : bool file_has_open_streams(files_struct *fsp)
1255 : {
1256 1094 : struct file_has_open_streams_state state = { .found_one = false };
1257 20 : NTSTATUS status;
1258 :
1259 1094 : status = share_mode_do_locked_vfs_denied(fsp->file_id,
1260 : file_has_open_streams_locked,
1261 : &state);
1262 1094 : if (!NT_STATUS_IS_OK(status)) {
1263 0 : DBG_DEBUG("share_mode_do_locked_vfs_denied() failed - %s\n",
1264 : nt_errstr(status));
1265 0 : return false;
1266 : }
1267 :
1268 1094 : if (!state.ok) {
1269 0 : DBG_DEBUG("share_mode_forall_entries failed\n");
1270 0 : return false;
1271 : }
1272 :
1273 1094 : return state.found_one;
1274 : }
1275 :
1276 : /*
1277 : * Walk share mode entries, looking at every lease only once
1278 : */
1279 :
1280 : struct share_mode_forall_leases_state {
1281 : TALLOC_CTX *mem_ctx;
1282 : struct leases_db_key *leases;
1283 : bool (*fn)(struct share_mode_entry *e,
1284 : void *private_data);
1285 : void *private_data;
1286 : NTSTATUS status;
1287 : };
1288 :
1289 1229 : static bool share_mode_forall_leases_fn(
1290 : struct share_mode_entry *e,
1291 : bool *modified,
1292 : void *private_data)
1293 : {
1294 1229 : struct share_mode_forall_leases_state *state = private_data;
1295 1229 : struct leases_db_key *leases = state->leases;
1296 23 : size_t i, num_leases;
1297 23 : bool stop;
1298 :
1299 1229 : if (e->op_type != LEASE_OPLOCK) {
1300 1098 : return false;
1301 : }
1302 :
1303 108 : num_leases = talloc_array_length(leases);
1304 :
1305 162 : for (i=0; i<num_leases; i++) {
1306 54 : struct leases_db_key *l = &leases[i];
1307 54 : bool same = smb2_lease_equal(
1308 54 : &e->client_guid,
1309 54 : &e->lease_key,
1310 54 : &l->client_guid,
1311 54 : &l->lease_key);
1312 54 : if (same) {
1313 0 : return false;
1314 : }
1315 : }
1316 :
1317 108 : leases = talloc_realloc(
1318 : state->mem_ctx,
1319 : leases,
1320 : struct leases_db_key,
1321 : num_leases+1);
1322 108 : if (leases == NULL) {
1323 0 : state->status = NT_STATUS_NO_MEMORY;
1324 0 : return true;
1325 : }
1326 108 : leases[num_leases] = (struct leases_db_key) {
1327 108 : .client_guid = e->client_guid,
1328 108 : .lease_key = e->lease_key,
1329 : };
1330 108 : state->leases = leases;
1331 :
1332 108 : stop = state->fn(e, state->private_data);
1333 108 : return stop;
1334 : }
1335 :
1336 1058 : bool share_mode_forall_leases(
1337 : struct share_mode_lock *lck,
1338 : bool (*fn)(struct share_mode_entry *e,
1339 : void *private_data),
1340 : void *private_data)
1341 : {
1342 2116 : struct share_mode_forall_leases_state state = {
1343 1058 : .mem_ctx = talloc_tos(),
1344 : .fn = fn,
1345 : .private_data = private_data
1346 : };
1347 16 : bool ok;
1348 :
1349 1058 : ok = share_mode_forall_entries(
1350 : lck, share_mode_forall_leases_fn, &state);
1351 1058 : TALLOC_FREE(state.leases);
1352 1058 : if (!ok) {
1353 0 : DBG_ERR("share_mode_forall_entries failed\n");
1354 0 : return false;
1355 : }
1356 :
1357 1058 : if (!NT_STATUS_IS_OK(state.status)) {
1358 0 : DBG_ERR("share_mode_forall_leases_fn returned %s\n",
1359 : nt_errstr(state.status));
1360 0 : return false;
1361 : }
1362 :
1363 1042 : return true;
1364 : }
|