LCOV - code coverage report
Current view: top level - source3/locking - locking.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 414 531 78.0 %
Date: 2024-04-13 12:30:31 Functions: 35 39 89.7 %

          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      204493 : 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      204493 :         SMB_ASSERT(lock_type == READ_LOCK || lock_type == WRITE_LOCK);
      97             : 
      98      204493 :         plock->context.smblctx = smblctx;
      99      204493 :         plock->context.tid = fsp->conn->cnum;
     100      204493 :         plock->context.pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
     101      204493 :         plock->start = start;
     102      204493 :         plock->size = size;
     103      204493 :         plock->fnum = fsp->fnum;
     104      204493 :         plock->lock_type = lock_type;
     105      204493 :         plock->lock_flav = lp_posix_cifsu_locktype(fsp);
     106      204493 : }
     107             : 
     108      204077 : bool strict_lock_check_default(files_struct *fsp, struct lock_struct *plock)
     109             : {
     110         121 :         struct byte_range_lock *br_lck;
     111      204077 :         int strict_locking = lp_strict_locking(fsp->conn->params);
     112      204077 :         bool ret = False;
     113             : 
     114      204077 :         if (plock->size == 0) {
     115         150 :                 return True;
     116             :         }
     117             : 
     118      203922 :         if (!lp_locking(fsp->conn->params) || !strict_locking) {
     119           0 :                 return True;
     120             :         }
     121             : 
     122      203922 :         if (strict_locking == Auto) {
     123      203922 :                 uint32_t lease_type = fsp_lease_type(fsp);
     124             : 
     125      203922 :                 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      203844 :                 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      203722 :         br_lck = brl_get_locks_readonly(fsp);
     143      203722 :         if (!br_lck) {
     144           0 :                 return true;
     145             :         }
     146      203722 :         ret = brl_locktest(br_lck, plock);
     147             : 
     148      203722 :         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      203722 :         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      203606 :         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      357005 : 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      357005 :         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      357005 :         if (fsp->current_lock_count == 0) {
     429      355519 :                 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      743066 : 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      743066 :         if (delete_on_close) {
     645       24860 :                 *delete_on_close = false;
     646             :         }
     647             : 
     648      743066 :         if (write_time) {
     649      743006 :                 *write_time = make_omit_timespec();
     650             :         }
     651             : 
     652      743066 :         if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
     653      723344 :                 return;
     654             :         }
     655             : 
     656       19630 :         if (delete_on_close) {
     657       18700 :                 *delete_on_close = is_delete_on_close_set(lck, name_hash);
     658             :         }
     659             : 
     660       19630 :         if (write_time) {
     661       19618 :                 *write_time = get_share_mode_write_time(lck);
     662             :         }
     663             : 
     664       19630 :         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       42828 : bool share_entry_stale_pid(struct share_mode_entry *e)
     752             : {
     753         223 :         struct server_id_buf buf;
     754         223 :         bool exists;
     755             : 
     756       42828 :         if (e->stale) {
     757          16 :                 return true;
     758             :         }
     759             : 
     760       42812 :         exists = serverid_exists(&e->pid);
     761       42812 :         if (exists) {
     762       42786 :                 DBG_DEBUG("PID %s still exists\n",
     763             :                           server_id_str_buf(e->pid, &buf));
     764       42786 :                 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      170349 : 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      170349 :         tmp = talloc_realloc(d, d->delete_tokens, struct delete_token,
     787             :                              d->num_delete_tokens+1);
     788      170349 :         if (tmp == NULL) {
     789           0 :                 return false;
     790             :         }
     791      170349 :         d->delete_tokens = tmp;
     792      170349 :         dtl = &d->delete_tokens[d->num_delete_tokens];
     793             : 
     794      170349 :         dtl->name_hash = name_hash;
     795      170349 :         dtl->delete_nt_token = security_token_duplicate(d->delete_tokens, nt_tok);
     796      170349 :         if (dtl->delete_nt_token == NULL) {
     797           0 :                 return false;
     798             :         }
     799      170349 :         dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
     800      170349 :         if (dtl->delete_token == NULL) {
     801           0 :                 return false;
     802             :         }
     803      170349 :         d->num_delete_tokens += 1;
     804      170349 :         d->modified = true;
     805      170349 :         return true;
     806             : }
     807             : 
     808      159263 : void reset_delete_on_close_lck(files_struct *fsp,
     809             :                                struct share_mode_lock *lck)
     810             : {
     811      159263 :         struct share_mode_data *d = NULL;
     812         277 :         NTSTATUS status;
     813         277 :         uint32_t i;
     814             : 
     815      159263 :         status = share_mode_lock_access_private_data(lck, &d);
     816      159263 :         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      318511 :         for (i=0; i<d->num_delete_tokens; i++) {
     825      159248 :                 struct delete_token *dt = &d->delete_tokens[i];
     826             : 
     827      159248 :                 if (dt->name_hash == fsp->name_hash) {
     828      159248 :                         d->modified = true;
     829             : 
     830             :                         /* Delete this entry. */
     831      159248 :                         TALLOC_FREE(dt->delete_nt_token);
     832      159248 :                         TALLOC_FREE(dt->delete_token);
     833      159248 :                         *dt = d->delete_tokens[d->num_delete_tokens-1];
     834      159248 :                         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      170618 : static bool set_delete_on_close_fn(
     845             :         struct share_mode_entry *e,
     846             :         bool *modified,
     847             :         void *private_data)
     848             : {
     849      170618 :         struct set_delete_on_close_state *state = private_data;
     850         356 :         NTSTATUS status;
     851             : 
     852      170618 :         status = messaging_send(
     853             :                 state->msg_ctx,
     854             :                 e->pid,
     855             :                 MSG_SMB_NOTIFY_CANCEL_DELETED,
     856      170618 :                 &state->blob);
     857             : 
     858      170618 :         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      170618 :         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      170351 : 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      170351 :         struct share_mode_data *d = NULL;
     885      170351 :         struct set_delete_on_close_state state = {
     886      170351 :                 .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      170351 :         status = share_mode_lock_access_private_data(lck, &d);
     894      170351 :         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      170351 :         SMB_ASSERT(nt_tok != NULL);
     903      170351 :         SMB_ASSERT(tok != NULL);
     904             : 
     905      170351 :         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      170349 :         ret = add_delete_on_close_token(d, fsp->name_hash, nt_tok, tok);
     923      170349 :         SMB_ASSERT(ret);
     924             : 
     925      170349 :         ndr_err = ndr_push_struct_blob(
     926             :                 &state.blob,
     927             :                 talloc_tos(),
     928      170349 :                 &fsp->file_id,
     929             :                 (ndr_push_flags_fn_t)ndr_push_file_id);
     930      170349 :         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      170349 :         ret = share_mode_forall_entries(
     937             :                 lck, set_delete_on_close_fn, &state);
     938      170349 :         if (!ret) {
     939           0 :                 DBG_ERR("share_mode_forall_entries failed\n");
     940           0 :                 smb_panic(__location__);
     941             :         }
     942             : 
     943      170349 :         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       33395 : static void set_delete_on_close_locked(struct share_mode_lock *lck,
     954             :                                        void *private_data)
     955             : {
     956       33395 :         struct set_delete_on_close_locked_state *state =
     957             :                 (struct set_delete_on_close_locked_state *)private_data;
     958             : 
     959       33395 :         if (state->delete_on_close) {
     960       33348 :                 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       33395 :         state->fsp->fsp_flags.delete_on_close = state->delete_on_close;
     969       33395 : }
     970             : 
     971       33403 : 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       33403 :         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       33403 :         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       33403 :         if (fsp->fsp_flags.is_directory) {
     989        9111 :                 SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
     990             :         }
     991             : 
     992       33403 :         status = share_mode_do_locked_vfs_denied(fsp->file_id,
     993             :                                                  set_delete_on_close_locked,
     994             :                                                  &state);
     995       33403 :         if (!NT_STATUS_IS_OK(status)) {
     996           8 :                 return false;
     997             :         }
     998             : 
     999       33189 :         return True;
    1000             : }
    1001             : 
    1002     1246167 : 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     1246167 :         DBG_DEBUG("name_hash = 0x%"PRIx32"\n", name_hash);
    1008             : 
    1009     1246167 :         for (i=0; i<d->num_delete_tokens; i++) {
    1010      341407 :                 struct delete_token *dt = &d->delete_tokens[i];
    1011             : 
    1012      341407 :                 DBG_DEBUG("dt->name_hash = 0x%"PRIx32"\n",
    1013             :                           dt->name_hash);
    1014      341407 :                 if (dt->name_hash == name_hash) {
    1015      341407 :                         return dt;
    1016             :                 }
    1017             :         }
    1018      902349 :         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      170315 : 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      170315 :         struct share_mode_data *d = NULL;
    1032         336 :         struct delete_token *dt;
    1033         336 :         NTSTATUS status;
    1034             : 
    1035      170315 :         status = share_mode_lock_access_private_data(lck, &d);
    1036      170315 :         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      170315 :         dt = find_delete_on_close_token(d, name_hash);
    1048      170315 :         if (dt == NULL) {
    1049           0 :                 return false;
    1050             :         }
    1051      170315 :         *pp_nt_tok = dt->delete_nt_token;
    1052      170315 :         *pp_tok =  dt->delete_token;
    1053      170315 :         return true;
    1054             : }
    1055             : 
    1056     1075852 : bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
    1057             : {
    1058     1075852 :         struct share_mode_data *d = NULL;
    1059        2833 :         NTSTATUS status;
    1060             : 
    1061     1075852 :         status = share_mode_lock_access_private_data(lck, &d);
    1062     1075852 :         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     1075852 :         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        5656 : static void set_write_time_fn(struct share_mode_lock *lck,
    1140             :                               void *private_data)
    1141             : {
    1142        5656 :         struct set_write_time_state *state = private_data;
    1143        5656 :         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        5656 :         status = share_mode_lock_access_private_data(lck, &d);
    1149        5656 :         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        5656 :         share_mode_set_old_write_time(lck, state->write_time);
    1160             : 
    1161        5656 :         state->ok = true;
    1162             : }
    1163             : 
    1164        5664 : bool set_write_time(struct file_id fileid, struct timespec write_time)
    1165             : {
    1166        5664 :         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        5664 :         status = share_mode_do_locked_vfs_denied(fileid,
    1175             :                                                  set_write_time_fn,
    1176             :                                                  &state);
    1177        5664 :         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        5656 :         return state.ok;
    1187             : }
    1188             : 
    1189      460939 : struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
    1190             : {
    1191      460939 :         struct share_mode_data *d = NULL;
    1192        1767 :         NTSTATUS status;
    1193             : 
    1194      460939 :         status = share_mode_lock_access_private_data(lck, &d);
    1195      460939 :         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      460939 :         if (!null_nttime(d->changed_write_time)) {
    1209        1983 :                 return nt_time_to_full_timespec(d->changed_write_time);
    1210             :         }
    1211      458956 :         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        1198 : static bool file_has_open_streams_fn(
    1220             :         struct share_mode_entry *e,
    1221             :         bool *modified,
    1222             :         void *private_data)
    1223             : {
    1224        1198 :         struct file_has_open_streams_state *state = private_data;
    1225             : 
    1226        1198 :         if ((e->private_options &
    1227             :              NTCREATEX_FLAG_STREAM_BASEOPEN) == 0) {
    1228        1155 :                 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        1095 : static void file_has_open_streams_locked(struct share_mode_lock *lck,
    1240             :                                          void *private_data)
    1241             : {
    1242        1095 :         struct file_has_open_streams_state *state = private_data;
    1243             : 
    1244        1095 :         state->ok = share_mode_forall_entries(lck,
    1245             :                                               file_has_open_streams_fn,
    1246             :                                               private_data);
    1247        1095 : }
    1248             : 
    1249        1095 : bool file_has_open_streams(files_struct *fsp)
    1250             : {
    1251        1095 :         struct file_has_open_streams_state state = { .found_one = false };
    1252          20 :         NTSTATUS status;
    1253             : 
    1254        1095 :         status = share_mode_do_locked_vfs_denied(fsp->file_id,
    1255             :                                                  file_has_open_streams_locked,
    1256             :                                                  &state);
    1257        1095 :         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        1095 :         if (!state.ok) {
    1264           0 :                 DBG_DEBUG("share_mode_forall_entries failed\n");
    1265           0 :                 return false;
    1266             :         }
    1267             : 
    1268        1095 :         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             : }

Generated by: LCOV version 1.14