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

Generated by: LCOV version 1.14