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