LCOV - code coverage report
Current view: top level - source3/locking - locking.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 257 433 59.4 %
Date: 2024-06-13 04:01:37 Functions: 27 35 77.1 %

          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         796 : 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         796 :         SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
      97             : 
      98         796 :         plock->context.smblctx = smblctx;
      99         796 :         plock->context.tid = fsp->conn->cnum;
     100         796 :         plock->context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
     101         796 :         plock->start = start;
     102         796 :         plock->size = size;
     103         796 :         plock->fnum = fsp->fnum;
     104         796 :         plock->lock_type = lock_type;
     105         796 :         plock->lock_flav = lp_posix_cifsu_locktype(fsp);
     106         796 : }
     107             : 
     108         792 : bool strict_lock_check_default(files_struct *fsp, struct lock_struct *plock)
     109             : {
     110             :         struct byte_range_lock *br_lck;
     111         792 :         int strict_locking = lp_strict_locking(fsp->conn->params);
     112         792 :         bool ret = False;
     113             : 
     114         792 :         if (plock->size == 0) {
     115           0 :                 return True;
     116             :         }
     117             : 
     118         792 :         if (!lp_locking(fsp->conn->params) || !strict_locking) {
     119           0 :                 return True;
     120             :         }
     121             : 
     122         792 :         if (strict_locking == Auto) {
     123         792 :                 uint32_t lease_type = fsp_lease_type(fsp);
     124             : 
     125         792 :                 if ((lease_type & SMB2_LEASE_READ) &&
     126           0 :                      (plock->lock_type == READ_LOCK))
     127             :                 {
     128           0 :                         DBG_DEBUG("optimisation - read lease on file %s\n",
     129             :                                   fsp_str_dbg(fsp));
     130           0 :                         return true;
     131             :                 }
     132             : 
     133         792 :                 if ((lease_type & SMB2_LEASE_WRITE) &&
     134           0 :                      (plock->lock_type == WRITE_LOCK))
     135             :                 {
     136           0 :                         DBG_DEBUG("optimisation - write lease on file %s\n",
     137             :                                   fsp_str_dbg(fsp));
     138           0 :                         return true;
     139             :                 }
     140             :         }
     141             : 
     142         792 :         br_lck = brl_get_locks_readonly(fsp);
     143         792 :         if (!br_lck) {
     144           0 :                 return true;
     145             :         }
     146         792 :         ret = brl_locktest(br_lck, plock);
     147             : 
     148         792 :         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           0 :                 br_lck = brl_get_locks(talloc_tos(), fsp);
     154           0 :                 if (br_lck == NULL) {
     155           0 :                         return true;
     156             :                 }
     157           0 :                 ret = brl_locktest(br_lck, plock);
     158           0 :                 TALLOC_FREE(br_lck);
     159             :         }
     160             : 
     161         792 :         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         792 :         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           5 : static void increment_current_lock_count(files_struct *fsp,
     209             :     enum brl_flavour lock_flav)
     210             : {
     211           8 :         if (lock_flav == WINDOWS_LOCK &&
     212           5 :             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           5 :                 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           0 :                 fsp->current_lock_count = NO_LOCKING_COUNT;
     223             :         }
     224           5 : }
     225             : 
     226           4 : static void decrement_current_lock_count(files_struct *fsp,
     227             :     enum brl_flavour lock_flav)
     228             : {
     229           6 :         if (lock_flav == WINDOWS_LOCK &&
     230           4 :             fsp->current_lock_count != NO_LOCKING_COUNT) {
     231           4 :                 SMB_ASSERT(fsp->current_lock_count > 0);
     232           4 :                 fsp->current_lock_count--;
     233             :         }
     234           4 : }
     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           5 : static void do_lock_fn(
     256             :         const uint8_t *buf,
     257             :         size_t buflen,
     258             :         bool *modified_dependent,
     259             :         void *private_data)
     260             : {
     261           5 :         struct do_lock_state *state = private_data;
     262           5 :         struct byte_range_lock *br_lck = NULL;
     263             : 
     264           8 :         br_lck = brl_get_locks_for_locking(talloc_tos(),
     265           5 :                                            state->fsp,
     266             :                                            state->req_mem_ctx,
     267             :                                            state->req_guid);
     268           5 :         if (br_lck == NULL) {
     269           0 :                 state->status = NT_STATUS_NO_MEMORY;
     270           0 :                 return;
     271             :         }
     272             : 
     273           8 :         state->status = brl_lock(
     274             :                 br_lck,
     275             :                 state->smblctx,
     276           5 :                 messaging_server_id(state->fsp->conn->sconn->msg_ctx),
     277             :                 state->offset,
     278             :                 state->count,
     279             :                 state->lock_type,
     280             :                 state->lock_flav,
     281             :                 &state->blocker_pid,
     282             :                 &state->blocker_smblctx);
     283             : 
     284           5 :         TALLOC_FREE(br_lck);
     285             : }
     286             : 
     287           5 : NTSTATUS do_lock(files_struct *fsp,
     288             :                  TALLOC_CTX *req_mem_ctx,
     289             :                  const struct GUID *req_guid,
     290             :                  uint64_t smblctx,
     291             :                  uint64_t count,
     292             :                  uint64_t offset,
     293             :                  enum brl_type lock_type,
     294             :                  enum brl_flavour lock_flav,
     295             :                  struct server_id *pblocker_pid,
     296             :                  uint64_t *psmblctx)
     297             : {
     298           5 :         struct do_lock_state state = {
     299             :                 .fsp = fsp,
     300             :                 .req_mem_ctx = req_mem_ctx,
     301             :                 .req_guid = req_guid,
     302             :                 .smblctx = smblctx,
     303             :                 .count = count,
     304             :                 .offset = offset,
     305             :                 .lock_type = lock_type,
     306             :                 .lock_flav = lock_flav,
     307             :         };
     308             :         NTSTATUS status;
     309             : 
     310             :         /* silently return ok on print files as we don't do locking there */
     311           5 :         if (fsp->print_file) {
     312           0 :                 return NT_STATUS_OK;
     313             :         }
     314             : 
     315           5 :         if (!fsp->fsp_flags.can_lock) {
     316           0 :                 if (fsp->fsp_flags.is_directory) {
     317           0 :                         return NT_STATUS_INVALID_DEVICE_REQUEST;
     318             :                 }
     319           0 :                 return NT_STATUS_INVALID_HANDLE;
     320             :         }
     321             : 
     322           5 :         if (!lp_locking(fsp->conn->params)) {
     323           0 :                 return NT_STATUS_OK;
     324             :         }
     325             : 
     326             :         /* NOTE! 0 byte long ranges ARE allowed and should be stored  */
     327             : 
     328           5 :         DBG_DEBUG("lock flavour %s lock type %s start=%"PRIu64" len=%"PRIu64" "
     329             :                   "requested for %s file %s\n",
     330             :                   lock_flav_name(lock_flav),
     331             :                   lock_type_name(lock_type),
     332             :                   offset,
     333             :                   count,
     334             :                   fsp_fnum_dbg(fsp),
     335             :                   fsp_str_dbg(fsp));
     336             : 
     337           5 :         status = share_mode_do_locked(fsp->file_id, do_lock_fn, &state);
     338           5 :         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           5 :         if (psmblctx != NULL) {
     345           5 :                 *psmblctx = state.blocker_smblctx;
     346             :         }
     347           5 :         if (pblocker_pid != NULL) {
     348           5 :                 *pblocker_pid = state.blocker_pid;
     349             :         }
     350             : 
     351           5 :         DBG_DEBUG("returning status=%s\n", nt_errstr(state.status));
     352             : 
     353           5 :         increment_current_lock_count(fsp, lock_flav);
     354             : 
     355           5 :         return state.status;
     356             : }
     357             : 
     358             : /****************************************************************************
     359             :  Utility function called by unlocking requests.
     360             : ****************************************************************************/
     361             : 
     362           8 : 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           8 :         bool ok = False;
     369           8 :         struct byte_range_lock *br_lck = NULL;
     370             : 
     371           8 :         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           8 :         if (!lp_locking(fsp->conn->params)) {
     378           0 :                 return NT_STATUS_OK;
     379             :         }
     380             : 
     381           8 :         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           8 :         br_lck = brl_get_locks(talloc_tos(), fsp);
     389           8 :         if (!br_lck) {
     390           0 :                 return NT_STATUS_NO_MEMORY;
     391             :         }
     392             : 
     393           8 :         ok = brl_unlock(br_lck,
     394             :                         smblctx,
     395           8 :                         messaging_server_id(fsp->conn->sconn->msg_ctx),
     396             :                         offset,
     397             :                         count,
     398             :                         lock_flav);
     399             : 
     400           8 :         TALLOC_FREE(br_lck);
     401             : 
     402           8 :         if (!ok) {
     403           4 :                 DEBUG(10,("do_unlock: returning ERRlock.\n" ));
     404           4 :                 return NT_STATUS_RANGE_NOT_LOCKED;
     405             :         }
     406             : 
     407           4 :         decrement_current_lock_count(fsp, lock_flav);
     408           4 :         return NT_STATUS_OK;
     409             : }
     410             : 
     411             : /****************************************************************************
     412             :  Remove any locks on this fd. Called from file_close().
     413             : ****************************************************************************/
     414             : 
     415        1850 : void locking_close_file(files_struct *fsp,
     416             :                         enum file_close_type close_type)
     417             : {
     418             :         struct byte_range_lock *br_lck;
     419             : 
     420        1850 :         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        1850 :         if (fsp->current_lock_count == 0) {
     429        1849 :                 return;
     430             :         }
     431             : 
     432           1 :         br_lck = brl_get_locks(talloc_tos(),fsp);
     433             : 
     434           1 :         if (br_lck) {
     435             :                 /*
     436             :                  * Unlocks must trigger dbwrap_watch watchers,
     437             :                  * normally in smbd_do_unlocking. Here it's done
     438             :                  * implictly, we're closing the file and thus remove a
     439             :                  * share mode. This will wake the waiters.
     440             :                  */
     441           1 :                 brl_close_fnum(br_lck);
     442           1 :                 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             :         struct server_id_buf tmp;
     455             :         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_lock *lck;
     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           0 : static bool rename_lease_fn(struct share_mode_entry *e,
     481             :                             void *private_data)
     482             : {
     483           0 :         struct rename_share_filename_state *state = private_data;
     484           0 :         struct share_mode_data *d = state->lck->data;
     485             :         NTSTATUS status;
     486             : 
     487           0 :         status = leases_db_rename(&e->client_guid,
     488           0 :                                   &e->lease_key,
     489           0 :                                   &d->id,
     490             :                                   d->servicepath,
     491             :                                   d->base_name,
     492             :                                   d->stream_name);
     493             : 
     494           0 :         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           0 :         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          20 : static bool rename_share_filename_fn(
     514             :         struct share_mode_entry *e,
     515             :         bool *modified,
     516             :         void *private_data)
     517             : {
     518          20 :         struct rename_share_filename_state *state = private_data;
     519             :         DATA_BLOB blob;
     520             :         enum ndr_err_code ndr_err;
     521             :         bool ok;
     522             : 
     523             :         /*
     524             :          * If this is a hardlink to the inode with a different name,
     525             :          * skip this.
     526             :          */
     527          20 :         if (e->name_hash != state->orig_name_hash) {
     528           0 :                 return false;
     529             :         }
     530          20 :         e->name_hash = state->new_name_hash;
     531          20 :         *modified = true;
     532             : 
     533          20 :         ok = server_id_equal(&e->pid, &state->self);
     534          20 :         if (ok) {
     535          20 :                 return false;
     536             :         }
     537             : 
     538           0 :         state->msg.share_file_id = e->share_file_id;
     539             : 
     540           0 :         ndr_err = ndr_push_struct_blob(
     541             :                 &blob,
     542             :                 talloc_tos(),
     543           0 :                 &state->msg,
     544             :                 (ndr_push_flags_fn_t)ndr_push_file_rename_message);
     545           0 :         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           0 :         if (DEBUGLEVEL >= 10) {
     551             :                 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           0 :         messaging_send(state->msg_ctx, e->pid, MSG_SMB_FILE_RENAME, &blob);
     558             : 
     559           0 :         TALLOC_FREE(blob.data);
     560             : 
     561           0 :         return false;
     562             : }
     563             : 
     564          20 : 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          50 :         struct rename_share_filename_state state = {
     573             :                 .lck = lck,
     574             :                 .msg_ctx = msg_ctx,
     575          10 :                 .self = messaging_server_id(msg_ctx),
     576             :                 .orig_name_hash = orig_name_hash,
     577             :                 .new_name_hash = new_name_hash,
     578             :                 .msg.id = id,
     579             :                 .msg.servicepath = servicepath,
     580          20 :                 .msg.base_name = smb_fname_dst->base_name,
     581          20 :                 .msg.stream_name = smb_fname_dst->stream_name,
     582             :         };
     583          20 :         struct share_mode_data *d = lck->data;
     584             :         bool ok;
     585             : 
     586          20 :         DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
     587             :                    servicepath, smb_fname_dst->base_name));
     588             : 
     589             :         /*
     590             :          * rename_internal_fsp() and rename_internals() add './' to
     591             :          * head of newname if newname does not contain a '/'.
     592             :          */
     593             : 
     594          20 :         if (strncmp(state.msg.base_name, "./", 2) == 0) {
     595           0 :                 state.msg.base_name += 2;
     596             :         }
     597             : 
     598          20 :         d->servicepath = talloc_strdup(d, state.msg.servicepath);
     599          20 :         d->base_name = talloc_strdup(d, state.msg.base_name);
     600          20 :         d->stream_name = talloc_strdup(d, state.msg.stream_name);
     601          30 :         if ((d->servicepath == NULL) ||
     602          30 :             (d->base_name == NULL) ||
     603          20 :             ((state.msg.stream_name != NULL) && (d->stream_name == NULL))) {
     604           0 :                 DBG_WARNING("talloc failed\n");
     605           0 :                 return false;
     606             :         }
     607          20 :         d->modified = True;
     608             : 
     609          20 :         ok = share_mode_forall_entries(
     610             :                 lck, rename_share_filename_fn, &state);
     611          20 :         if (!ok) {
     612           0 :                 DBG_WARNING("share_mode_forall_entries failed\n");
     613             :         }
     614             : 
     615          20 :         ok = share_mode_forall_leases(lck, rename_lease_fn, &state);
     616          20 :         if (!ok) {
     617             :                 /*
     618             :                  * Ignore error here. Not sure what to do..
     619             :                  */
     620           0 :                 DBG_WARNING("share_mode_forall_leases failed\n");
     621             :         }
     622             : 
     623          20 :         return True;
     624             : }
     625             : 
     626        1826 : void get_file_infos(struct file_id id,
     627             :                     uint32_t name_hash,
     628             :                     bool *delete_on_close,
     629             :                     struct timespec *write_time)
     630             : {
     631             :         struct share_mode_lock *lck;
     632             : 
     633        1826 :         if (delete_on_close) {
     634         910 :                 *delete_on_close = false;
     635             :         }
     636             : 
     637        1826 :         if (write_time) {
     638        1826 :                 *write_time = make_omit_timespec();
     639             :         }
     640             : 
     641        1826 :         if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
     642         916 :                 return;
     643             :         }
     644             : 
     645         910 :         if (delete_on_close) {
     646         910 :                 *delete_on_close = is_delete_on_close_set(lck, name_hash);
     647             :         }
     648             : 
     649         910 :         if (write_time) {
     650         910 :                 *write_time = get_share_mode_write_time(lck);
     651             :         }
     652             : 
     653         910 :         TALLOC_FREE(lck);
     654             : }
     655             : 
     656           0 : bool is_valid_share_mode_entry(const struct share_mode_entry *e)
     657             : {
     658           0 :         int num_props = 0;
     659             : 
     660           0 :         if (e->stale) {
     661           0 :                 return false;
     662             :         }
     663             : 
     664           0 :         num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
     665           0 :         num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
     666           0 :         num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
     667           0 :         num_props += (e->op_type == LEASE_OPLOCK);
     668             : 
     669           0 :         if ((num_props > 1) && serverid_exists(&e->pid)) {
     670           0 :                 smb_panic("Invalid share mode entry");
     671             :         }
     672           0 :         return (num_props != 0);
     673             : }
     674             : 
     675             : struct find_lease_ref_state {
     676             :         const struct GUID *client_guid;
     677             :         const struct smb2_lease_key *lease_key;
     678             :         bool found_same;
     679             : };
     680             : 
     681           0 : static bool find_lease_ref_fn(
     682             :         struct share_mode_entry *e,
     683             :         bool *modified,
     684             :         void *private_data)
     685             : {
     686           0 :         struct find_lease_ref_state *state = private_data;
     687             : 
     688           0 :         if (e->stale) {
     689           0 :                 return false;
     690             :         }
     691           0 :         if (e->op_type != LEASE_OPLOCK) {
     692           0 :                 return false;
     693             :         }
     694             : 
     695           0 :         state->found_same = smb2_lease_equal(
     696           0 :                 &e->client_guid,
     697           0 :                 &e->lease_key,
     698             :                 state->client_guid,
     699             :                 state->lease_key);
     700             :         /*
     701             :          * If we found a lease reference, look no further (i.e. return true)
     702             :          */
     703           0 :         return state->found_same;
     704             : }
     705             : 
     706           0 : NTSTATUS remove_lease_if_stale(struct share_mode_lock *lck,
     707             :                                const struct GUID *client_guid,
     708             :                                const struct smb2_lease_key *lease_key)
     709             : {
     710           0 :         struct find_lease_ref_state state = {
     711             :                 .client_guid = client_guid, .lease_key = lease_key,
     712             :         };
     713           0 :         struct share_mode_data *d = lck->data;
     714             :         NTSTATUS status;
     715             :         bool ok;
     716             : 
     717           0 :         ok = share_mode_forall_entries(lck, find_lease_ref_fn, &state);
     718           0 :         if (!ok) {
     719           0 :                 return NT_STATUS_INTERNAL_ERROR;
     720             :         }
     721             : 
     722           0 :         if (state.found_same) {
     723           0 :                 return NT_STATUS_RESOURCE_IN_USE;
     724             :         }
     725             : 
     726           0 :         status = leases_db_del(client_guid, lease_key, &d->id);
     727           0 :         if (!NT_STATUS_IS_OK(status)) {
     728           0 :                 int level = DBGLVL_DEBUG;
     729             : 
     730           0 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     731           0 :                         level = DBGLVL_ERR;
     732             :                 }
     733           0 :                 DBG_PREFIX(level, ("leases_db_del failed: %s\n",
     734             :                            nt_errstr(status)));
     735             :         }
     736           0 :         return status;
     737             : }
     738             : 
     739          55 : bool share_entry_stale_pid(struct share_mode_entry *e)
     740             : {
     741             :         struct server_id_buf buf;
     742             :         bool exists;
     743             : 
     744          55 :         if (e->stale) {
     745           0 :                 return true;
     746             :         }
     747             : 
     748          55 :         exists = serverid_exists(&e->pid);
     749          55 :         if (exists) {
     750          55 :                 DBG_DEBUG("PID %s still exists\n",
     751             :                           server_id_str_buf(e->pid, &buf));
     752          55 :                 return false;
     753             :         }
     754             : 
     755           0 :         DBG_DEBUG("PID %s does not exist anymore\n",
     756             :                   server_id_str_buf(e->pid, &buf));
     757             : 
     758           0 :         e->stale = true;
     759             : 
     760           0 :         return true;
     761             : }
     762             : 
     763             : /****************************************************************************
     764             :  Adds a delete on close token.
     765             : ****************************************************************************/
     766             : 
     767        1368 : static bool add_delete_on_close_token(struct share_mode_data *d,
     768             :                         uint32_t name_hash,
     769             :                         const struct security_token *nt_tok,
     770             :                         const struct security_unix_token *tok)
     771             : {
     772             :         struct delete_token *tmp, *dtl;
     773             : 
     774        1368 :         tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
     775             :                              d->num_delete_tokens+1);
     776        1368 :         if (tmp == NULL) {
     777           0 :                 return false;
     778             :         }
     779        1368 :         d->delete_tokens = tmp;
     780        1368 :         dtl = &d->delete_tokens[d->num_delete_tokens];
     781             : 
     782        1368 :         dtl->name_hash = name_hash;
     783        1368 :         dtl->delete_nt_token = dup_nt_token(d->delete_tokens, nt_tok);
     784        1368 :         if (dtl->delete_nt_token == NULL) {
     785           0 :                 return false;
     786             :         }
     787        1368 :         dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
     788        1368 :         if (dtl->delete_token == NULL) {
     789           0 :                 return false;
     790             :         }
     791        1368 :         d->num_delete_tokens += 1;
     792        1368 :         d->modified = true;
     793        1368 :         return true;
     794             : }
     795             : 
     796         560 : void reset_delete_on_close_lck(files_struct *fsp,
     797             :                                struct share_mode_lock *lck)
     798             : {
     799         560 :         struct share_mode_data *d = lck->data;
     800             :         uint32_t i;
     801             : 
     802        1120 :         for (i=0; i<d->num_delete_tokens; i++) {
     803         560 :                 struct delete_token *dt = &d->delete_tokens[i];
     804             : 
     805         560 :                 if (dt->name_hash == fsp->name_hash) {
     806         560 :                         d->modified = true;
     807             : 
     808             :                         /* Delete this entry. */
     809         560 :                         TALLOC_FREE(dt->delete_nt_token);
     810         560 :                         TALLOC_FREE(dt->delete_token);
     811         560 :                         *dt = d->delete_tokens[d->num_delete_tokens-1];
     812         560 :                         d->num_delete_tokens -= 1;
     813             :                 }
     814             :         }
     815         560 : }
     816             : 
     817             : struct set_delete_on_close_state {
     818             :         struct messaging_context *msg_ctx;
     819             :         DATA_BLOB blob;
     820             : };
     821             : 
     822        1369 : static bool set_delete_on_close_fn(
     823             :         struct share_mode_entry *e,
     824             :         bool *modified,
     825             :         void *private_data)
     826             : {
     827        1369 :         struct set_delete_on_close_state *state = private_data;
     828             :         NTSTATUS status;
     829             : 
     830        1369 :         status = messaging_send(
     831             :                 state->msg_ctx,
     832             :                 e->pid,
     833             :                 MSG_SMB_NOTIFY_CANCEL_DELETED,
     834        1369 :                 &state->blob);
     835             : 
     836        1369 :         if (!NT_STATUS_IS_OK(status)) {
     837             :                 struct server_id_buf tmp;
     838           0 :                 DBG_DEBUG("messaging_send to %s returned %s\n",
     839             :                           server_id_str_buf(e->pid, &tmp),
     840             :                           nt_errstr(status));
     841             :         }
     842             : 
     843        1369 :         return false;
     844             : }
     845             : 
     846             : /****************************************************************************
     847             :  Sets the delete on close flag over all share modes on this file.
     848             :  Modify the share mode entry for all files open
     849             :  on this device and inode to tell other smbds we have
     850             :  changed the delete on close flag. This will be noticed
     851             :  in the close code, the last closer will delete the file
     852             :  if flag is set.
     853             :  This makes a copy of any struct security_unix_token into the
     854             :  lck entry. This function is used when the lock is already granted.
     855             : ****************************************************************************/
     856             : 
     857        1368 : void set_delete_on_close_lck(files_struct *fsp,
     858             :                         struct share_mode_lock *lck,
     859             :                         const struct security_token *nt_tok,
     860             :                         const struct security_unix_token *tok)
     861             : {
     862        1368 :         struct share_mode_data *d = lck->data;
     863        2597 :         struct set_delete_on_close_state state = {
     864        1368 :                 .msg_ctx = fsp->conn->sconn->msg_ctx
     865             :         };
     866             :         uint32_t i;
     867             :         bool ret;
     868             :         enum ndr_err_code ndr_err;
     869             : 
     870        1368 :         SMB_ASSERT(nt_tok != NULL);
     871        1368 :         SMB_ASSERT(tok != NULL);
     872             : 
     873        1368 :         for (i=0; i<d->num_delete_tokens; i++) {
     874           0 :                 struct delete_token *dt = &d->delete_tokens[i];
     875           0 :                 if (dt->name_hash == fsp->name_hash) {
     876           0 :                         d->modified = true;
     877             : 
     878             :                         /* Replace this token with the given tok. */
     879           0 :                         TALLOC_FREE(dt->delete_nt_token);
     880           0 :                         dt->delete_nt_token = dup_nt_token(dt, nt_tok);
     881           0 :                         SMB_ASSERT(dt->delete_nt_token != NULL);
     882           0 :                         TALLOC_FREE(dt->delete_token);
     883           0 :                         dt->delete_token = copy_unix_token(dt, tok);
     884           0 :                         SMB_ASSERT(dt->delete_token != NULL);
     885             : 
     886           0 :                         return;
     887             :                 }
     888             :         }
     889             : 
     890        1368 :         ret = add_delete_on_close_token(lck->data, fsp->name_hash, nt_tok, tok);
     891        1368 :         SMB_ASSERT(ret);
     892             : 
     893        1368 :         ndr_err = ndr_push_struct_blob(
     894             :                 &state.blob,
     895             :                 talloc_tos(),
     896        1368 :                 &fsp->file_id,
     897             :                 (ndr_push_flags_fn_t)ndr_push_file_id);
     898        1368 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     899           0 :                 DEBUG(10, ("ndr_push_file_id failed: %s\n",
     900             :                            ndr_errstr(ndr_err)));
     901             :         }
     902             : 
     903        1368 :         ret = share_mode_forall_entries(
     904             :                 lck, set_delete_on_close_fn, &state);
     905        1368 :         if (!ret) {
     906           0 :                 DBG_DEBUG("share_mode_forall_entries failed\n");
     907             :         }
     908             : 
     909        1368 :         TALLOC_FREE(state.blob.data);
     910             : }
     911             : 
     912         802 : bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
     913             :                         const struct security_token *nt_tok,
     914             :                         const struct security_unix_token *tok)
     915             : {
     916             :         struct share_mode_lock *lck;
     917             : 
     918         802 :         DEBUG(10,("set_delete_on_close: %s delete on close flag for "
     919             :                   "%s, file %s\n",
     920             :                   delete_on_close ? "Adding" : "Removing", fsp_fnum_dbg(fsp),
     921             :                   fsp_str_dbg(fsp)));
     922             : 
     923         802 :         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
     924         802 :         if (lck == NULL) {
     925           0 :                 return False;
     926             :         }
     927             : 
     928         802 :         if (delete_on_close) {
     929         802 :                 set_delete_on_close_lck(fsp, lck, nt_tok, tok);
     930             :         } else {
     931           0 :                 reset_delete_on_close_lck(fsp, lck);
     932             :         }
     933             : 
     934         802 :         if (fsp->fsp_flags.is_directory) {
     935         798 :                 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
     936         798 :                 send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
     937         798 :                                                fsp->fsp_name->base_name);
     938             :         }
     939             : 
     940         802 :         TALLOC_FREE(lck);
     941             : 
     942         802 :         fsp->fsp_flags.delete_on_close = delete_on_close;
     943             : 
     944         802 :         return True;
     945             : }
     946             : 
     947       26188 : static struct delete_token *find_delete_on_close_token(
     948             :         struct share_mode_data *d, uint32_t name_hash)
     949             : {
     950             :         uint32_t i;
     951             : 
     952       26188 :         DBG_DEBUG("name_hash = 0x%"PRIx32"\n", name_hash);
     953             : 
     954       26188 :         for (i=0; i<d->num_delete_tokens; i++) {
     955        1929 :                 struct delete_token *dt = &d->delete_tokens[i];
     956             : 
     957        1929 :                 DBG_DEBUG("dt->name_hash = 0x%"PRIx32"\n",
     958             :                           dt->name_hash);
     959        1929 :                 if (dt->name_hash == name_hash) {
     960        1929 :                         return dt;
     961             :                 }
     962             :         }
     963       24259 :         return NULL;
     964             : }
     965             : 
     966             : /****************************************************************************
     967             :  Return the NT token and UNIX token if there's a match. Return true if
     968             :  found, false if not.
     969             : ****************************************************************************/
     970             : 
     971       10776 : bool get_delete_on_close_token(struct share_mode_lock *lck,
     972             :                                         uint32_t name_hash,
     973             :                                         const struct security_token **pp_nt_tok,
     974             :                                         const struct security_unix_token **pp_tok)
     975             : {
     976             :         struct delete_token *dt;
     977             : 
     978       10776 :         dt = find_delete_on_close_token(lck->data, name_hash);
     979       10776 :         if (dt == NULL) {
     980        9408 :                 return false;
     981             :         }
     982        1368 :         *pp_nt_tok = dt->delete_nt_token;
     983        1368 :         *pp_tok =  dt->delete_token;
     984        1368 :         return true;
     985             : }
     986             : 
     987       15412 : bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
     988             : {
     989       15412 :         return find_delete_on_close_token(lck->data, name_hash) != NULL;
     990             : }
     991             : 
     992           1 : bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
     993             : {
     994             :         struct share_mode_lock *lck;
     995             :         struct file_id_buf ftmp;
     996             :         struct timeval_buf tbuf;
     997           1 :         NTTIME nt = full_timespec_to_nt_time(&write_time);
     998             : 
     999           1 :         DBG_INFO("%s id=%s\n",
    1000             :                  timespec_string_buf(&write_time, true, &tbuf),
    1001             :                  file_id_str_buf(fileid, &ftmp));
    1002             : 
    1003           1 :         lck = get_existing_share_mode_lock(talloc_tos(), fileid);
    1004           1 :         if (lck == NULL) {
    1005           0 :                 return False;
    1006             :         }
    1007             : 
    1008           1 :         if (lck->data->changed_write_time != nt) {
    1009           1 :                 lck->data->modified = True;
    1010           1 :                 lck->data->changed_write_time = nt;
    1011             :         }
    1012             : 
    1013           1 :         TALLOC_FREE(lck);
    1014           1 :         return True;
    1015             : }
    1016             : 
    1017         436 : bool set_write_time(struct file_id fileid, struct timespec write_time)
    1018             : {
    1019             :         struct share_mode_lock *lck;
    1020             :         struct file_id_buf idbuf;
    1021             :         struct timeval_buf tbuf;
    1022         436 :         NTTIME nt = full_timespec_to_nt_time(&write_time);
    1023             : 
    1024         436 :         DBG_INFO("%s id=%s\n",
    1025             :                  timespec_string_buf(&write_time, true, &tbuf),
    1026             :                  file_id_str_buf(fileid, &idbuf));
    1027             : 
    1028         436 :         lck = get_existing_share_mode_lock(talloc_tos(), fileid);
    1029         436 :         if (lck == NULL) {
    1030           0 :                 return False;
    1031             :         }
    1032             : 
    1033         436 :         if (lck->data->old_write_time != nt) {
    1034         436 :                 lck->data->modified = True;
    1035         436 :                 lck->data->old_write_time = nt;
    1036             :         }
    1037             : 
    1038         436 :         TALLOC_FREE(lck);
    1039         436 :         return True;
    1040             : }
    1041             : 
    1042       12976 : struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
    1043             : {
    1044       12976 :         struct share_mode_data *d = lck->data;
    1045             : 
    1046       12976 :         if (!null_nttime(d->changed_write_time)) {
    1047           1 :                 return nt_time_to_full_timespec(d->changed_write_time);
    1048             :         }
    1049       12975 :         return nt_time_to_full_timespec(d->old_write_time);
    1050             : }
    1051             : 
    1052             : struct file_has_open_streams_state {
    1053             :         bool found_one;
    1054             : };
    1055             : 
    1056          21 : static bool file_has_open_streams_fn(
    1057             :         struct share_mode_entry *e,
    1058             :         bool *modified,
    1059             :         void *private_data)
    1060             : {
    1061          21 :         struct file_has_open_streams_state *state = private_data;
    1062             : 
    1063          21 :         if ((e->private_options &
    1064             :              NTCREATEX_FLAG_STREAM_BASEOPEN) == 0) {
    1065          21 :                 return false;
    1066             :         }
    1067             : 
    1068           0 :         if (share_entry_stale_pid(e)) {
    1069           0 :                 return false;
    1070             :         }
    1071             : 
    1072           0 :         state->found_one = true;
    1073           0 :         return true;
    1074             : }
    1075             : 
    1076          21 : bool file_has_open_streams(files_struct *fsp)
    1077             : {
    1078          21 :         struct file_has_open_streams_state state = { .found_one = false };
    1079          21 :         struct share_mode_lock *lock = NULL;
    1080             :         bool ok;
    1081             : 
    1082          21 :         lock = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
    1083          21 :         if (lock == NULL) {
    1084           0 :                 return false;
    1085             :         }
    1086             : 
    1087          21 :         ok = share_mode_forall_entries(
    1088             :                 lock, file_has_open_streams_fn, &state);
    1089          21 :         TALLOC_FREE(lock);
    1090             : 
    1091          21 :         if (!ok) {
    1092           0 :                 DBG_DEBUG("share_mode_forall_entries failed\n");
    1093           0 :                 return false;
    1094             :         }
    1095          21 :         return state.found_one;
    1096             : }
    1097             : 
    1098             : /*
    1099             :  * Walk share mode entries, looking at every lease only once
    1100             :  */
    1101             : 
    1102             : struct share_mode_forall_leases_state {
    1103             :         TALLOC_CTX *mem_ctx;
    1104             :         struct leases_db_key *leases;
    1105             :         bool (*fn)(struct share_mode_entry *e,
    1106             :                    void *private_data);
    1107             :         void *private_data;
    1108             :         NTSTATUS status;
    1109             : };
    1110             : 
    1111          20 : static bool share_mode_forall_leases_fn(
    1112             :         struct share_mode_entry *e,
    1113             :         bool *modified,
    1114             :         void *private_data)
    1115             : {
    1116          20 :         struct share_mode_forall_leases_state *state = private_data;
    1117          20 :         struct leases_db_key *leases = state->leases;
    1118             :         size_t i, num_leases;
    1119             :         bool stop;
    1120             : 
    1121          20 :         if (e->op_type != LEASE_OPLOCK) {
    1122          20 :                 return false;
    1123             :         }
    1124             : 
    1125           0 :         num_leases = talloc_array_length(leases);
    1126             : 
    1127           0 :         for (i=0; i<num_leases; i++) {
    1128           0 :                 struct leases_db_key *l = &leases[i];
    1129           0 :                 bool same = smb2_lease_equal(
    1130           0 :                         &e->client_guid,
    1131           0 :                         &e->lease_key,
    1132           0 :                         &l->client_guid,
    1133           0 :                         &l->lease_key);
    1134           0 :                 if (same) {
    1135           0 :                         return false;
    1136             :                 }
    1137             :         }
    1138             : 
    1139           0 :         leases = talloc_realloc(
    1140             :                 state->mem_ctx,
    1141             :                 leases,
    1142             :                 struct leases_db_key,
    1143             :                 num_leases+1);
    1144           0 :         if (leases == NULL) {
    1145           0 :                 state->status = NT_STATUS_NO_MEMORY;
    1146           0 :                 return true;
    1147             :         }
    1148           0 :         leases[num_leases] = (struct leases_db_key) {
    1149           0 :                 .client_guid = e->client_guid,
    1150           0 :                 .lease_key = e->lease_key,
    1151             :         };
    1152           0 :         state->leases = leases;
    1153             : 
    1154           0 :         stop = state->fn(e, state->private_data);
    1155           0 :         return stop;
    1156             : }
    1157             : 
    1158          20 : bool share_mode_forall_leases(
    1159             :         struct share_mode_lock *lck,
    1160             :         bool (*fn)(struct share_mode_entry *e,
    1161             :                    void *private_data),
    1162             :         void *private_data)
    1163             : {
    1164          40 :         struct share_mode_forall_leases_state state = {
    1165          20 :                 .mem_ctx = talloc_tos(),
    1166             :                 .fn = fn,
    1167             :                 .private_data = private_data
    1168             :         };
    1169             :         bool ok;
    1170             : 
    1171          20 :         ok = share_mode_forall_entries(
    1172             :                 lck, share_mode_forall_leases_fn, &state);
    1173          20 :         TALLOC_FREE(state.leases);
    1174          20 :         if (!ok) {
    1175           0 :                 DBG_DEBUG("share_mode_forall_entries failed\n");
    1176           0 :                 return false;
    1177             :         }
    1178             : 
    1179          20 :         if (!NT_STATUS_IS_OK(state.status)) {
    1180           0 :                 DBG_DEBUG("share_mode_forall_leases_fn returned %s\n",
    1181             :                           nt_errstr(state.status));
    1182           0 :                 return false;
    1183             :         }
    1184             : 
    1185          20 :         return true;
    1186             : }

Generated by: LCOV version 1.13