1996-05-04 11:50:46 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Locking functions
2000-04-28 01:12:33 +04:00
Copyright ( C ) Andrew Tridgell 1992 - 2000
2006-04-10 19:33:04 +04:00
Copyright ( C ) Jeremy Allison 1992 - 2006
2005-07-08 08:51:27 +04:00
Copyright ( C ) Volker Lendecke 2005
2011-05-28 12:24:20 +04:00
1996-05-04 11:50:46 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( at your option ) any later version .
2011-05-28 12:24:20 +04:00
1996-05-04 11:50:46 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2011-05-28 12:24:20 +04:00
1996-05-04 11:50:46 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-08-15 19:11:34 +04:00
Revision History :
12 aug 96 : Erik . Devriendt @ te6 . siemens . be
added support for shared memory implementation of share mode locking
1997-05-20 04:32:51 +04:00
May 1997. Jeremy Allison ( jallison @ whistle . com ) . Modified share mode
locking to deal with multiple share modes per open file .
1997-10-07 22:46:19 +04:00
September 1997. Jeremy Allison ( jallison @ whistle . com ) . Added oplock
support .
2011-12-15 18:48:33 +04:00
rewritten completely to use new tdb code . Tridge , Dec ' 99
2000-04-28 01:12:33 +04:00
Added POSIX locking support . Jeremy Allison ( jeremy @ valinux . com ) , Apr . 2000.
2006-04-10 19:33:04 +04:00
Added Unix Extensions POSIX locking support . Jeremy Allison Mar 2006.
1996-05-04 11:50:46 +04:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-03-23 14:43:17 +03:00
# include "locking/proto.h"
2010-07-04 20:18:58 +04:00
# include "smbd/globals.h"
2011-07-07 19:42:08 +04:00
# include "dbwrap/dbwrap.h"
2011-07-06 18:40:21 +04:00
# include "dbwrap/dbwrap_open.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-02-25 01:05:57 +03:00
# include "serverid.h"
2011-03-24 17:31:06 +03:00
# include "messages.h"
2011-05-05 13:25:29 +04:00
# include "util_tdb.h"
2011-11-24 17:11:28 +04:00
# include "../librpc/gen_ndr/ndr_open_files.h"
2014-10-11 01:32:19 +04:00
# include "locking/leases_db.h"
1996-05-04 11:50:46 +04:00
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
2007-07-17 04:50:48 +04:00
# define NO_LOCKING_COUNT (-1)
2000-04-12 21:59:09 +04:00
/****************************************************************************
2006-04-10 19:33:04 +04:00
Debugging aids : - ) .
2000-04-12 21:59:09 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-04-10 19:33:04 +04:00
const char * lock_type_name ( enum brl_type lock_type )
2000-04-12 21:59:09 +04:00
{
2006-04-10 19:33:04 +04:00
switch ( lock_type ) {
case READ_LOCK :
return " READ " ;
case WRITE_LOCK :
return " WRITE " ;
2006-07-29 23:14:24 +04:00
case PENDING_READ_LOCK :
return " PENDING_READ " ;
case PENDING_WRITE_LOCK :
return " PENDING_WRITE " ;
2006-04-10 19:33:04 +04:00
default :
return " other " ;
}
}
const char * lock_flav_name ( enum brl_flavour lock_flav )
{
return ( lock_flav = = WINDOWS_LOCK ) ? " WINDOWS_LOCK " : " POSIX_LOCK " ;
2000-04-12 21:59:09 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1998-07-23 04:10:26 +04:00
Utility function called to see if a file region is locked .
2006-04-10 19:33:04 +04:00
Called in the read / write codepath .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-12 21:59:09 +04:00
2009-03-14 00:15:28 +03:00
void init_strict_lock_struct ( files_struct * fsp ,
2010-05-07 17:20:50 +04:00
uint64_t smblctx ,
2009-03-14 00:15:28 +03:00
br_off start ,
br_off size ,
enum brl_type lock_type ,
struct lock_struct * plock )
{
SMB_ASSERT ( lock_type = = READ_LOCK | | lock_type = = WRITE_LOCK ) ;
2010-05-07 17:20:50 +04:00
plock - > context . smblctx = smblctx ;
2009-03-14 00:15:28 +03:00
plock - > context . tid = fsp - > conn - > cnum ;
2011-12-15 14:50:43 +04:00
plock - > context . pid = messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ;
2009-03-14 00:15:28 +03:00
plock - > start = start ;
plock - > size = size ;
plock - > fnum = fsp - > fnum ;
plock - > lock_type = lock_type ;
plock - > lock_flav = lp_posix_cifsu_locktype ( fsp ) ;
}
bool strict_lock_default ( files_struct * fsp , struct lock_struct * plock )
1996-05-04 11:50:46 +04:00
{
2014-07-11 00:23:37 +04:00
struct byte_range_lock * br_lck ;
2006-11-11 20:05:11 +03:00
int strict_locking = lp_strict_locking ( fsp - > conn - > params ) ;
2009-03-14 00:15:28 +03:00
bool ret = False ;
if ( plock - > size = = 0 ) {
return True ;
2006-04-10 19:33:04 +04:00
}
1996-05-04 11:50:46 +04:00
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) | | ! strict_locking ) {
2009-03-14 00:15:28 +03:00
return True ;
2006-04-10 19:33:04 +04:00
}
1998-07-28 22:26:47 +04:00
2004-12-11 03:30:28 +03:00
if ( strict_locking = = Auto ) {
2014-07-11 00:23:37 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) & &
( plock - > lock_type = = READ_LOCK | |
plock - > lock_type = = WRITE_LOCK ) ) {
DEBUG ( 10 , ( " is_locked: optimisation - exclusive oplock "
" on file %s \n " , fsp_str_dbg ( fsp ) ) ) ;
return true ;
2004-12-11 03:30:28 +03:00
}
2014-07-11 00:23:37 +04:00
if ( ( fsp - > oplock_type = = LEVEL_II_OPLOCK ) & &
( plock - > lock_type = = READ_LOCK ) ) {
DEBUG ( 10 , ( " is_locked: optimisation - level II oplock "
" on file %s \n " , fsp_str_dbg ( fsp ) ) ) ;
return true ;
2006-04-10 19:33:04 +04:00
}
2004-12-10 01:10:40 +03:00
}
2001-06-30 05:59:48 +04:00
2014-07-11 00:23:37 +04:00
br_lck = brl_get_locks_readonly ( fsp ) ;
if ( ! br_lck ) {
return true ;
}
2014-07-11 17:35:45 +04:00
ret = brl_locktest ( br_lck , plock ) ;
2014-07-11 00:23:37 +04:00
2014-08-19 16:36:55 +04:00
if ( ! ret ) {
/*
* We got a lock conflict . Retry with rw locks to enable
* autocleanup . This is the slow path anyway .
*/
br_lck = brl_get_locks ( talloc_tos ( ) , fsp ) ;
ret = brl_locktest ( br_lck , plock ) ;
TALLOC_FREE ( br_lck ) ;
}
2014-07-11 14:52:06 +04:00
DEBUG ( 10 , ( " strict_lock_default: flavour = %s brl start=%ju "
" len=%ju %s for fnum %ju file %s \n " ,
lock_flav_name ( plock - > lock_flav ) ,
( uintmax_t ) plock - > start , ( uintmax_t ) plock - > size ,
ret ? " unlocked " : " locked " ,
( uintmax_t ) plock - > fnum , fsp_str_dbg ( fsp ) ) ) ;
1996-05-04 11:50:46 +04:00
2006-04-10 19:33:04 +04:00
return ret ;
}
2009-03-14 00:15:28 +03:00
void strict_unlock_default ( files_struct * fsp , struct lock_struct * plock )
{
}
2006-04-10 19:33:04 +04:00
/****************************************************************************
Find out if a lock could be granted - return who is blocking us if we can ' t .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-12 21:59:09 +04:00
2006-04-10 19:33:04 +04:00
NTSTATUS query_lock ( files_struct * fsp ,
2010-05-07 17:20:50 +04:00
uint64_t * psmblctx ,
2008-10-14 03:59:36 +04:00
uint64_t * pcount ,
uint64_t * poffset ,
2006-04-10 19:33:04 +04:00
enum brl_type * plock_type ,
enum brl_flavour lock_flav )
{
struct byte_range_lock * br_lck = NULL ;
2000-04-12 21:59:09 +04:00
2006-07-11 22:01:26 +04:00
if ( ! fsp - > can_lock ) {
return fsp - > is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE ;
2001-06-30 05:59:48 +04:00
}
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) ) {
2006-04-10 19:33:04 +04:00
return NT_STATUS_OK ;
}
2009-11-16 11:40:47 +03:00
br_lck = brl_get_locks_readonly ( fsp ) ;
2006-04-10 19:33:04 +04:00
if ( ! br_lck ) {
return NT_STATUS_NO_MEMORY ;
}
2009-11-16 11:40:47 +03:00
return brl_lockquery ( br_lck ,
2010-05-07 17:20:50 +04:00
psmblctx ,
2011-12-15 14:50:43 +04:00
messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ,
2006-04-10 19:33:04 +04:00
poffset ,
pcount ,
plock_type ,
lock_flav ) ;
2000-04-12 21:59:09 +04:00
}
1996-05-04 11:50:46 +04:00
2009-02-10 08:51:29 +03:00
static void increment_current_lock_count ( files_struct * fsp ,
enum brl_flavour lock_flav )
{
if ( lock_flav = = WINDOWS_LOCK & &
fsp - > current_lock_count ! = NO_LOCKING_COUNT ) {
/* blocking ie. pending, locks also count here,
* as this is an efficiency counter to avoid checking
* the lock db . on close . JRA . */
fsp - > current_lock_count + + ;
} else {
/* Notice that this has had a POSIX lock request.
* We can ' t count locks after this so forget them .
*/
fsp - > current_lock_count = NO_LOCKING_COUNT ;
}
}
static void decrement_current_lock_count ( files_struct * fsp ,
enum brl_flavour lock_flav )
{
if ( lock_flav = = WINDOWS_LOCK & &
fsp - > current_lock_count ! = NO_LOCKING_COUNT ) {
SMB_ASSERT ( fsp - > current_lock_count > 0 ) ;
fsp - > current_lock_count - - ;
}
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1998-07-23 04:10:26 +04:00
Utility function called by locking requests .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-12 21:59:09 +04:00
2007-05-14 17:01:28 +04:00
struct byte_range_lock * do_lock ( struct messaging_context * msg_ctx ,
files_struct * fsp ,
2010-05-07 17:20:50 +04:00
uint64_t smblctx ,
2008-10-14 03:59:36 +04:00
uint64_t count ,
uint64_t offset ,
2006-04-10 19:33:04 +04:00
enum brl_type lock_type ,
enum brl_flavour lock_flav ,
2007-10-19 04:40:25 +04:00
bool blocking_lock ,
2007-05-20 00:57:12 +04:00
NTSTATUS * perr ,
2014-07-03 18:08:26 +04:00
uint64_t * psmblctx )
1996-05-04 11:50:46 +04:00
{
2006-04-10 19:33:04 +04:00
struct byte_range_lock * br_lck = NULL ;
1999-12-21 12:25:59 +03:00
2010-04-29 03:42:04 +04:00
/* silently return ok on print files as we don't do locking there */
if ( fsp - > print_file ) {
* perr = NT_STATUS_OK ;
return NULL ;
}
2006-07-11 22:01:26 +04:00
if ( ! fsp - > can_lock ) {
2006-07-18 05:05:51 +04:00
* perr = fsp - > is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE ;
return NULL ;
2006-04-10 19:33:04 +04:00
}
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) ) {
2006-07-18 05:05:51 +04:00
* perr = NT_STATUS_OK ;
return NULL ;
2006-04-10 19:33:04 +04:00
}
1999-12-21 12:25:59 +03:00
2001-08-24 08:55:28 +04:00
/* NOTE! 0 byte long ranges ARE allowed and should be stored */
2014-06-01 17:16:16 +04:00
DEBUG ( 10 , ( " do_lock: lock flavour %s lock type %s start=%ju len=%ju "
2012-06-14 14:25:43 +04:00
" blocking_lock=%s requested for %s file %s \n " ,
2006-04-10 19:33:04 +04:00
lock_flav_name ( lock_flav ) , lock_type_name ( lock_type ) ,
2014-06-01 17:16:16 +04:00
( uintmax_t ) offset , ( uintmax_t ) count , blocking_lock ? " true " :
2012-06-14 14:25:43 +04:00
" false " , fsp_fnum_dbg ( fsp ) , fsp_str_dbg ( fsp ) ) ) ;
2006-04-10 19:33:04 +04:00
2008-01-06 18:15:45 +03:00
br_lck = brl_get_locks ( talloc_tos ( ) , fsp ) ;
2006-04-10 19:33:04 +04:00
if ( ! br_lck ) {
2006-07-18 05:05:51 +04:00
* perr = NT_STATUS_NO_MEMORY ;
return NULL ;
2000-01-13 15:09:36 +03:00
}
1999-12-21 12:25:59 +03:00
2007-05-14 17:01:28 +04:00
* perr = brl_lock ( msg_ctx ,
br_lck ,
2010-05-07 17:20:50 +04:00
smblctx ,
2011-12-15 14:50:43 +04:00
messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ,
2006-04-10 19:33:04 +04:00
offset ,
2010-05-07 17:20:50 +04:00
count ,
2006-04-10 19:33:04 +04:00
lock_type ,
lock_flav ,
2007-05-20 00:57:12 +04:00
blocking_lock ,
2014-07-03 18:05:03 +04:00
psmblctx ) ;
2006-04-10 19:33:04 +04:00
2009-02-10 08:51:29 +03:00
DEBUG ( 10 , ( " do_lock: returning status=%s \n " , nt_errstr ( * perr ) ) ) ;
2007-03-07 00:59:51 +03:00
2009-02-10 08:51:29 +03:00
increment_current_lock_count ( fsp , lock_flav ) ;
2006-07-18 05:05:51 +04:00
return br_lck ;
1996-05-04 11:50:46 +04:00
}
2002-03-13 23:28:19 +03:00
/****************************************************************************
2006-07-18 01:09:02 +04:00
Utility function called by unlocking requests .
2002-03-13 23:28:19 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-05-14 17:01:28 +04:00
NTSTATUS do_unlock ( struct messaging_context * msg_ctx ,
files_struct * fsp ,
2010-05-07 17:20:50 +04:00
uint64_t smblctx ,
2008-10-14 03:59:36 +04:00
uint64_t count ,
uint64_t offset ,
2006-07-18 01:09:02 +04:00
enum brl_flavour lock_flav )
2002-03-13 23:28:19 +03:00
{
2007-10-19 04:40:25 +04:00
bool ok = False ;
2006-07-18 01:09:02 +04:00
struct byte_range_lock * br_lck = NULL ;
2011-05-28 12:24:20 +04:00
2006-07-18 01:09:02 +04:00
if ( ! fsp - > can_lock ) {
return fsp - > is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE ;
2006-04-10 19:33:04 +04:00
}
2011-05-28 12:24:20 +04:00
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) ) {
2006-07-18 01:09:02 +04:00
return NT_STATUS_OK ;
}
2011-05-28 12:24:20 +04:00
2014-07-11 14:52:06 +04:00
DEBUG ( 10 , ( " do_unlock: unlock start=%ju len=%ju requested for %s file "
" %s \n " , ( uintmax_t ) offset , ( uintmax_t ) count ,
fsp_fnum_dbg ( fsp ) , fsp_str_dbg ( fsp ) ) ) ;
2002-03-13 23:49:57 +03:00
2008-01-06 18:15:45 +03:00
br_lck = brl_get_locks ( talloc_tos ( ) , fsp ) ;
2006-07-18 01:09:02 +04:00
if ( ! br_lck ) {
return NT_STATUS_NO_MEMORY ;
}
2006-04-10 19:33:04 +04:00
2007-05-14 17:01:28 +04:00
ok = brl_unlock ( msg_ctx ,
br_lck ,
2010-05-07 17:20:50 +04:00
smblctx ,
2011-12-15 14:50:43 +04:00
messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ,
2006-07-18 01:09:02 +04:00
offset ,
count ,
lock_flav ) ;
2011-05-28 12:24:20 +04:00
2006-07-18 01:09:02 +04:00
TALLOC_FREE ( br_lck ) ;
2006-04-10 19:33:04 +04:00
2006-07-18 01:09:02 +04:00
if ( ! ok ) {
DEBUG ( 10 , ( " do_unlock: returning ERRlock. \n " ) ) ;
return NT_STATUS_RANGE_NOT_LOCKED ;
2002-03-13 23:28:19 +03:00
}
2006-07-18 01:09:02 +04:00
2009-02-10 08:51:29 +03:00
decrement_current_lock_count ( fsp , lock_flav ) ;
2006-07-18 01:09:02 +04:00
return NT_STATUS_OK ;
2002-03-13 23:28:19 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2006-07-18 01:09:02 +04:00
Cancel any pending blocked locks .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-13 03:01:11 +04:00
2006-07-18 01:09:02 +04:00
NTSTATUS do_lock_cancel ( files_struct * fsp ,
2010-05-07 17:20:50 +04:00
uint64 smblctx ,
2008-10-14 03:59:36 +04:00
uint64_t count ,
uint64_t offset ,
2014-07-03 18:10:22 +04:00
enum brl_flavour lock_flav )
1996-05-04 11:50:46 +04:00
{
2007-10-19 04:40:25 +04:00
bool ok = False ;
2006-04-10 19:33:04 +04:00
struct byte_range_lock * br_lck = NULL ;
2009-02-10 08:51:29 +03:00
2006-07-11 22:01:26 +04:00
if ( ! fsp - > can_lock ) {
2006-07-18 01:09:02 +04:00
return fsp - > is_directory ?
NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE ;
2006-04-10 19:33:04 +04:00
}
2011-05-28 12:24:20 +04:00
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) ) {
2006-07-18 01:09:02 +04:00
return NT_STATUS_DOS ( ERRDOS , ERRcancelviolation ) ;
2000-04-26 00:30:58 +04:00
}
2006-07-18 01:09:02 +04:00
2014-07-11 14:52:06 +04:00
DEBUG ( 10 , ( " do_lock_cancel: cancel start=%ju len=%ju requested for "
" %s file %s \n " , ( uintmax_t ) offset , ( uintmax_t ) count ,
fsp_fnum_dbg ( fsp ) , fsp_str_dbg ( fsp ) ) ) ;
2000-04-12 21:59:09 +04:00
2008-01-06 18:15:45 +03:00
br_lck = brl_get_locks ( talloc_tos ( ) , fsp ) ;
2006-04-10 19:33:04 +04:00
if ( ! br_lck ) {
return NT_STATUS_NO_MEMORY ;
}
2003-04-05 00:38:12 +04:00
2006-07-18 01:09:02 +04:00
ok = brl_lock_cancel ( br_lck ,
2010-05-07 17:20:50 +04:00
smblctx ,
2011-12-15 14:50:43 +04:00
messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ,
2006-04-10 19:33:04 +04:00
offset ,
count ,
2014-07-03 18:03:12 +04:00
lock_flav ) ;
2009-02-10 08:51:29 +03:00
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( br_lck ) ;
2006-04-10 19:33:04 +04:00
1999-12-21 12:25:59 +03:00
if ( ! ok ) {
2006-07-18 01:09:02 +04:00
DEBUG ( 10 , ( " do_lock_cancel: returning ERRcancelviolation. \n " ) ) ;
return NT_STATUS_DOS ( ERRDOS , ERRcancelviolation ) ;
1999-12-21 12:25:59 +03:00
}
2006-04-10 19:33:04 +04:00
2009-02-10 08:51:29 +03:00
decrement_current_lock_count ( fsp , lock_flav ) ;
2001-09-04 11:13:01 +04:00
return NT_STATUS_OK ;
1996-05-04 11:50:46 +04:00
}
2000-04-26 00:30:58 +04:00
/****************************************************************************
Remove any locks on this fd . Called from file_close ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-05-14 17:01:28 +04:00
void locking_close_file ( struct messaging_context * msg_ctx ,
2010-05-07 12:20:26 +04:00
files_struct * fsp ,
enum file_close_type close_type )
2000-04-26 00:30:58 +04:00
{
2006-04-10 19:33:04 +04:00
struct byte_range_lock * br_lck ;
2000-04-26 00:30:58 +04:00
2006-11-11 20:05:11 +03:00
if ( ! lp_locking ( fsp - > conn - > params ) ) {
2000-04-26 00:30:58 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
2000-04-26 00:30:58 +04:00
2013-09-10 16:01:58 +04:00
/* If we have no outstanding locks or pending
2007-03-07 00:59:51 +03:00
* locks then we don ' t need to look in the lock db .
*/
if ( fsp - > current_lock_count = = 0 ) {
return ;
}
2008-01-06 18:15:45 +03:00
br_lck = brl_get_locks ( talloc_tos ( ) , fsp ) ;
2006-07-18 01:09:02 +04:00
2006-07-11 22:01:26 +04:00
if ( br_lck ) {
2010-05-07 12:20:26 +04:00
cancel_pending_lock_requests_by_fid ( fsp , br_lck , close_type ) ;
2007-05-14 17:01:28 +04:00
brl_close_fnum ( msg_ctx , br_lck ) ;
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( br_lck ) ;
2000-04-26 00:30:58 +04:00
}
}
2002-01-08 03:52:36 +03:00
/*******************************************************************
Print out a share mode .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-05-27 22:23:59 +04:00
char * share_mode_str ( TALLOC_CTX * ctx , int num , const struct share_mode_entry * e )
2002-01-08 03:52:36 +03:00
{
2011-12-14 13:35:56 +04:00
return talloc_asprintf ( ctx , " share_mode_entry[%d]: "
2005-09-30 21:13:37 +04:00
" pid = %s, share_access = 0x%x, private_options = 0x%x, "
2011-12-25 14:35:07 +04:00
" access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %llu, "
2011-01-26 01:01:52 +03:00
" uid = %u, flags = %u, file_id %s, name_hash = 0x%x " ,
2006-01-27 22:54:39 +03:00
num ,
procid_str_static ( & e - > pid ) ,
2005-07-08 08:51:27 +04:00
e - > share_access , e - > private_options ,
2010-04-13 08:40:28 +04:00
e - > access_mask , ( unsigned long long ) e - > op_mid ,
2012-01-07 02:25:06 +04:00
e - > op_type , ( unsigned long long ) e - > share_file_id ,
2007-02-07 00:05:34 +03:00
( unsigned int ) e - > uid , ( unsigned int ) e - > flags ,
2011-01-26 01:01:52 +03:00
file_id_string_tos ( & e - > id ) ,
( unsigned int ) e - > name_hash ) ;
2002-01-08 03:52:36 +03:00
}
2012-01-13 02:46:45 +04:00
/*******************************************************************
Fetch a share mode where we know one MUST exist . This call reference
counts it internally to allow for nested lock fetches .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-02-19 17:23:56 +04:00
struct share_mode_lock * get_existing_share_mode_lock ( TALLOC_CTX * mem_ctx ,
const struct file_id id )
2012-01-09 17:30:53 +04:00
{
2012-02-19 17:27:49 +04:00
return get_share_mode_lock ( mem_ctx , id , NULL , NULL , NULL ) ;
2012-01-09 17:30:53 +04:00
}
2005-12-13 01:07:36 +03:00
/*******************************************************************
Sets the service name and filename for rename .
2005-12-13 21:11:50 +03:00
At this point we emit " file renamed " messages to all
process id ' s that have this file open .
Based on an initial code idea from SATOH Fumiyasu < fumiya @ samba . gr . jp >
2005-12-13 01:07:36 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool rename_share_filename ( struct messaging_context * msg_ctx ,
2007-05-14 17:01:28 +04:00
struct share_mode_lock * lck ,
2014-03-20 17:36:11 +04:00
struct file_id id ,
2005-12-13 01:07:36 +03:00
const char * servicepath ,
2011-01-26 01:01:52 +03:00
uint32_t orig_name_hash ,
uint32_t new_name_hash ,
2009-07-09 03:22:44 +04:00
const struct smb_filename * smb_fname_dst )
2005-12-13 01:07:36 +03:00
{
2012-01-10 16:56:37 +04:00
struct share_mode_data * d = lck - > data ;
2005-12-13 21:11:50 +03:00
size_t sp_len ;
2009-07-09 03:22:44 +04:00
size_t bn_len ;
size_t sn_len ;
2005-12-13 21:11:50 +03:00
size_t msg_len ;
2006-01-13 01:17:54 +03:00
char * frm = NULL ;
2005-12-13 21:11:50 +03:00
int i ;
2009-07-09 03:22:44 +04:00
bool strip_two_chars = false ;
bool has_stream = smb_fname_dst - > stream_name ! = NULL ;
2012-06-15 16:29:08 +04:00
struct server_id self_pid = messaging_server_id ( msg_ctx ) ;
2005-12-13 21:11:50 +03:00
DEBUG ( 10 , ( " rename_share_filename: servicepath %s newname %s \n " ,
2009-07-09 03:22:44 +04:00
servicepath , smb_fname_dst - > base_name ) ) ;
2005-12-13 21:11:50 +03:00
2005-12-13 01:07:36 +03:00
/*
* rename_internal_fsp ( ) and rename_internals ( ) add ' . / ' to
* head of newname if newname does not contain a ' / ' .
*/
2009-07-09 03:22:44 +04:00
if ( smb_fname_dst - > base_name [ 0 ] & &
smb_fname_dst - > base_name [ 1 ] & &
smb_fname_dst - > base_name [ 0 ] = = ' . ' & &
smb_fname_dst - > base_name [ 1 ] = = ' / ' ) {
strip_two_chars = true ;
2005-12-13 01:07:36 +03:00
}
2012-01-10 16:56:37 +04:00
d - > servicepath = talloc_strdup ( d , servicepath ) ;
d - > base_name = talloc_strdup ( d , smb_fname_dst - > base_name +
2009-07-09 03:22:44 +04:00
( strip_two_chars ? 2 : 0 ) ) ;
2012-01-10 16:56:37 +04:00
d - > stream_name = talloc_strdup ( d , smb_fname_dst - > stream_name ) ;
if ( d - > base_name = = NULL | |
( has_stream & & d - > stream_name = = NULL ) | |
d - > servicepath = = NULL ) {
2005-12-13 01:07:36 +03:00
DEBUG ( 0 , ( " rename_share_filename: talloc failed \n " ) ) ;
return False ;
}
2012-01-10 16:56:37 +04:00
d - > modified = True ;
2005-12-13 21:11:50 +03:00
2012-01-10 16:56:37 +04:00
sp_len = strlen ( d - > servicepath ) ;
bn_len = strlen ( d - > base_name ) ;
sn_len = has_stream ? strlen ( d - > stream_name ) : 0 ;
2005-12-13 21:11:50 +03:00
2009-07-09 03:22:44 +04:00
msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + bn_len + 1 +
sn_len + 1 ;
2005-12-13 21:11:50 +03:00
/* Set up the name changed message. */
2012-01-10 16:56:37 +04:00
frm = talloc_array ( d , char , msg_len ) ;
2005-12-13 21:11:50 +03:00
if ( ! frm ) {
return False ;
}
2006-01-13 01:17:54 +03:00
2014-03-20 17:36:11 +04:00
push_file_id_24 ( frm , & id ) ;
2005-12-13 21:11:50 +03:00
2006-06-16 05:35:08 +04:00
DEBUG ( 10 , ( " rename_share_filename: msg_len = %u \n " , ( unsigned int ) msg_len ) ) ;
2005-12-13 21:11:50 +03:00
2011-05-04 01:01:20 +04:00
strlcpy ( & frm [ 24 ] ,
2012-01-10 16:56:37 +04:00
d - > servicepath ? d - > servicepath : " " ,
2011-05-04 01:01:20 +04:00
sp_len + 1 ) ;
strlcpy ( & frm [ 24 + sp_len + 1 ] ,
2012-01-10 16:56:37 +04:00
d - > base_name ? d - > base_name : " " ,
2011-05-04 01:01:20 +04:00
bn_len + 1 ) ;
strlcpy ( & frm [ 24 + sp_len + 1 + bn_len + 1 ] ,
2012-01-10 16:56:37 +04:00
d - > stream_name ? d - > stream_name : " " ,
2011-05-04 01:01:20 +04:00
sn_len + 1 ) ;
2005-12-13 21:11:50 +03:00
/* Send the messages. */
2012-01-10 16:56:37 +04:00
for ( i = 0 ; i < d - > num_share_modes ; i + + ) {
struct share_mode_entry * se = & d - > share_modes [ i ] ;
2005-12-13 21:11:50 +03:00
if ( ! is_valid_share_mode_entry ( se ) ) {
continue ;
}
2011-01-26 01:01:52 +03:00
/* If this is a hardlink to the inode
with a different name , skip this . */
if ( se - > name_hash ! = orig_name_hash ) {
continue ;
}
se - > name_hash = new_name_hash ;
2005-12-13 21:11:50 +03:00
/* But not to ourselves... */
2012-06-16 02:26:26 +04:00
if ( serverid_equal ( & se - > pid , & self_pid ) ) {
2005-12-13 21:11:50 +03:00
continue ;
}
2012-05-07 17:23:10 +04:00
if ( share_mode_stale_pid ( d , i ) ) {
continue ;
}
2009-07-09 03:22:44 +04:00
DEBUG ( 10 , ( " rename_share_filename: sending rename message to "
" pid %s file_id %s sharepath %s base_name %s "
" stream_name %s \n " ,
2007-05-29 13:30:34 +04:00
procid_str_static ( & se - > pid ) ,
2014-03-20 17:36:11 +04:00
file_id_string_tos ( & id ) ,
2012-01-10 16:56:37 +04:00
d - > servicepath , d - > base_name ,
has_stream ? d - > stream_name : " " ) ) ;
2005-12-13 21:11:50 +03:00
2007-05-27 13:29:26 +04:00
messaging_send_buf ( msg_ctx , se - > pid , MSG_SMB_FILE_RENAME ,
( uint8 * ) frm , msg_len ) ;
2005-12-13 21:11:50 +03:00
}
2005-12-13 01:07:36 +03:00
return True ;
}
2008-04-01 13:40:23 +04:00
void get_file_infos ( struct file_id id ,
2011-01-26 00:57:38 +03:00
uint32_t name_hash ,
2008-04-01 13:40:23 +04:00
bool * delete_on_close ,
struct timespec * write_time )
2008-03-12 17:32:47 +03:00
{
struct share_mode_lock * lck ;
2008-04-01 13:40:23 +04:00
if ( delete_on_close ) {
* delete_on_close = false ;
}
if ( write_time ) {
ZERO_STRUCTP ( write_time ) ;
}
2008-03-12 17:32:47 +03:00
2009-07-09 03:22:44 +04:00
if ( ! ( lck = fetch_share_mode_unlocked ( talloc_tos ( ) , id ) ) ) {
2008-04-01 13:40:23 +04:00
return ;
2008-03-12 17:32:47 +03:00
}
2008-04-01 13:40:23 +04:00
if ( delete_on_close ) {
2011-01-26 01:23:19 +03:00
* delete_on_close = is_delete_on_close_set ( lck , name_hash ) ;
2008-03-12 17:32:47 +03:00
}
2008-04-01 13:40:23 +04:00
if ( write_time ) {
2013-11-22 18:36:49 +04:00
* write_time = get_share_mode_write_time ( lck ) ;
2007-05-27 13:57:05 +04:00
}
2008-04-01 13:40:23 +04:00
2007-05-27 13:57:05 +04:00
TALLOC_FREE ( lck ) ;
1998-10-23 07:34:50 +04:00
}
2007-10-19 04:40:25 +04:00
bool is_valid_share_mode_entry ( const struct share_mode_entry * e )
1998-10-23 07:34:50 +04:00
{
2005-09-30 21:13:37 +04:00
int num_props = 0 ;
2013-08-30 16:49:43 +04:00
if ( e - > stale ) {
return false ;
}
2005-09-30 21:13:37 +04:00
num_props + = ( ( e - > op_type = = NO_OPLOCK ) ? 1 : 0 ) ;
num_props + = ( EXCLUSIVE_OPLOCK_TYPE ( e - > op_type ) ? 1 : 0 ) ;
num_props + = ( LEVEL_II_OPLOCK_TYPE ( e - > op_type ) ? 1 : 0 ) ;
2014-11-27 20:34:56 +03:00
num_props + = ( e - > op_type = = LEASE_OPLOCK ) ;
2005-09-30 21:13:37 +04:00
2012-06-01 17:15:07 +04:00
if ( ( num_props > 1 ) & & serverid_exists ( & e - > pid ) ) {
2012-05-14 16:57:34 +04:00
smb_panic ( " Invalid share mode entry " ) ;
}
2005-09-30 21:13:37 +04:00
return ( num_props ! = 0 ) ;
1998-10-23 07:34:50 +04:00
}
2014-10-11 01:32:19 +04:00
/*
* See if we need to remove a lease being referred to by a
* share mode that is being marked stale or deleted .
*/
static void remove_share_mode_lease ( struct share_mode_data * d ,
struct share_mode_entry * e )
{
struct GUID client_guid ;
struct smb2_lease_key lease_key ;
uint16_t op_type ;
uint32_t lease_idx ;
uint32_t i ;
op_type = e - > op_type ;
e - > op_type = NO_OPLOCK ;
d - > modified = true ;
if ( op_type ! = LEASE_OPLOCK ) {
return ;
}
/*
* This used to reference a lease . If there ' s no other one referencing
* it , remove it .
*/
lease_idx = e - > lease_idx ;
e - > lease_idx = UINT32_MAX ;
for ( i = 0 ; i < d - > num_share_modes ; i + + ) {
if ( d - > share_modes [ i ] . stale ) {
continue ;
}
if ( e = = & d - > share_modes [ i ] ) {
/* Not ourselves. */
continue ;
}
if ( d - > share_modes [ i ] . lease_idx = = lease_idx ) {
break ;
}
}
if ( i < d - > num_share_modes ) {
/*
* Found another one
*/
return ;
}
memcpy ( & client_guid ,
& d - > leases [ lease_idx ] . client_guid ,
sizeof ( client_guid ) ) ;
lease_key = d - > leases [ lease_idx ] . lease_key ;
d - > num_leases - = 1 ;
d - > leases [ lease_idx ] = d - > leases [ d - > num_leases ] ;
/*
* We changed the lease array . Fix all references to it .
*/
for ( i = 0 ; i < d - > num_share_modes ; i + + ) {
if ( d - > share_modes [ i ] . lease_idx = = d - > num_leases ) {
d - > share_modes [ i ] . lease_idx = lease_idx ;
d - > share_modes [ i ] . lease = & d - > leases [ lease_idx ] ;
}
}
{
NTSTATUS status ;
status = leases_db_del ( & client_guid ,
& lease_key ,
& e - > id ) ;
DEBUG ( 10 , ( " %s: leases_db_del returned %s \n " , __func__ ,
nt_errstr ( status ) ) ) ;
}
}
2012-05-07 14:57:07 +04:00
/*
* In case d - > share_modes [ i ] conflicts with something or otherwise is
* being used , we need to make sure the corresponding process still
2013-08-30 16:49:43 +04:00
* exists .
2012-05-07 14:57:07 +04:00
*/
2013-09-26 05:39:27 +04:00
bool share_mode_stale_pid ( struct share_mode_data * d , uint32_t idx )
2012-05-07 14:57:07 +04:00
{
struct share_mode_entry * e ;
2013-08-30 16:27:36 +04:00
if ( idx > d - > num_share_modes ) {
2012-05-07 14:57:07 +04:00
DEBUG ( 1 , ( " Asking for index %u, only %u around \n " ,
2013-08-30 16:27:36 +04:00
idx , ( unsigned ) d - > num_share_modes ) ) ;
2012-05-07 14:57:07 +04:00
return false ;
}
2013-08-30 16:27:36 +04:00
e = & d - > share_modes [ idx ] ;
2013-09-23 06:16:56 +04:00
if ( e - > stale ) {
/*
* Checked before
*/
return true ;
}
2012-05-07 14:57:07 +04:00
if ( serverid_exists ( & e - > pid ) ) {
DEBUG ( 10 , ( " PID %s (index %u out of %u) still exists \n " ,
2013-08-30 16:27:36 +04:00
procid_str_static ( & e - > pid ) , idx ,
2012-05-07 14:57:07 +04:00
( unsigned ) d - > num_share_modes ) ) ;
return false ;
}
DEBUG ( 10 , ( " PID %s (index %u out of %u) does not exist anymore \n " ,
2013-08-30 16:27:36 +04:00
procid_str_static ( & e - > pid ) , idx ,
2012-05-07 14:57:07 +04:00
( unsigned ) d - > num_share_modes ) ) ;
2012-05-22 23:27:06 +04:00
2013-08-30 16:49:43 +04:00
e - > stale = true ;
if ( d - > num_delete_tokens ! = 0 ) {
uint32_t i , num_stale ;
2012-05-22 23:27:06 +04:00
/*
* We cannot have any delete tokens
* if there are no valid share modes .
*/
2013-08-30 16:49:43 +04:00
num_stale = 0 ;
for ( i = 0 ; i < d - > num_share_modes ; i + + ) {
if ( d - > share_modes [ i ] . stale ) {
num_stale + = 1 ;
}
}
if ( num_stale = = d - > num_share_modes ) {
/*
* No non - stale share mode found
*/
TALLOC_FREE ( d - > delete_tokens ) ;
d - > num_delete_tokens = 0 ;
}
2012-05-22 23:27:06 +04:00
}
2014-10-11 01:32:19 +04:00
remove_share_mode_lease ( d , e ) ;
2012-05-07 14:57:07 +04:00
d - > modified = true ;
return true ;
}
2013-09-02 15:37:57 +04:00
void remove_stale_share_mode_entries ( struct share_mode_data * d )
{
uint32_t i ;
i = 0 ;
while ( i < d - > num_share_modes ) {
if ( d - > share_modes [ i ] . stale ) {
struct share_mode_entry * m = d - > share_modes ;
m [ i ] = m [ d - > num_share_modes - 1 ] ;
d - > num_share_modes - = 1 ;
} else {
i + = 1 ;
}
}
}
2014-11-27 20:34:56 +03:00
bool set_share_mode ( struct share_mode_lock * lck , struct files_struct * fsp ,
uid_t uid , uint64_t mid , uint16_t op_type ,
uint32_t lease_idx )
1999-12-13 16:27:58 +03:00
{
2013-09-17 01:02:48 +04:00
struct share_mode_data * d = lck - > data ;
struct share_mode_entry * tmp , * e ;
2014-11-27 20:34:56 +03:00
struct share_mode_lease * lease = NULL ;
if ( lease_idx = = UINT32_MAX ) {
lease = NULL ;
} else if ( lease_idx > = d - > num_leases ) {
return false ;
} else {
lease = & d - > leases [ lease_idx ] ;
}
2013-09-17 01:02:48 +04:00
tmp = talloc_realloc ( d , d - > share_modes , struct share_mode_entry ,
d - > num_share_modes + 1 ) ;
if ( tmp = = NULL ) {
return false ;
}
d - > share_modes = tmp ;
e = & d - > share_modes [ d - > num_share_modes ] ;
d - > num_share_modes + = 1 ;
d - > modified = true ;
2005-09-30 21:13:37 +04:00
ZERO_STRUCTP ( e ) ;
2011-12-15 14:50:43 +04:00
e - > pid = messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ;
2005-09-30 21:13:37 +04:00
e - > share_access = fsp - > share_access ;
e - > private_options = fsp - > fh - > private_options ;
e - > access_mask = fsp - > access_mask ;
e - > op_mid = mid ;
e - > op_type = op_type ;
2014-11-27 20:34:56 +03:00
e - > lease_idx = lease_idx ;
e - > lease = lease ;
2005-09-30 21:13:37 +04:00
e - > time . tv_sec = fsp - > open_time . tv_sec ;
e - > time . tv_usec = fsp - > open_time . tv_usec ;
2007-05-29 13:30:34 +04:00
e - > id = fsp - > file_id ;
e - > share_file_id = fsp - > fh - > gen_id ;
2006-06-21 06:31:12 +04:00
e - > uid = ( uint32 ) uid ;
2007-02-07 00:05:34 +03:00
e - > flags = fsp - > posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0 ;
2011-01-26 01:01:52 +03:00
e - > name_hash = fsp - > name_hash ;
2013-09-14 15:48:03 +04:00
return true ;
2005-09-30 21:13:37 +04:00
}
1999-12-13 16:27:58 +03:00
2013-09-03 18:40:58 +04:00
static struct share_mode_entry * find_share_mode_entry (
2013-09-17 00:58:54 +04:00
struct share_mode_lock * lck , files_struct * fsp )
2005-09-30 21:13:37 +04:00
{
2013-09-17 00:58:54 +04:00
struct share_mode_data * d = lck - > data ;
struct server_id pid ;
2005-09-30 21:13:37 +04:00
int i ;
2004-06-08 20:14:31 +04:00
2013-09-17 00:58:54 +04:00
pid = messaging_server_id ( fsp - > conn - > sconn - > msg_ctx ) ;
2013-09-03 18:38:47 +04:00
2012-01-10 16:56:37 +04:00
for ( i = 0 ; i < d - > num_share_modes ; i + + ) {
struct share_mode_entry * e = & d - > share_modes [ i ] ;
2013-09-17 00:58:54 +04:00
if ( ! is_valid_share_mode_entry ( e ) ) {
continue ;
}
if ( ! serverid_equal ( & pid , & e - > pid ) ) {
continue ;
2005-09-30 21:13:37 +04:00
}
2013-09-17 00:58:54 +04:00
if ( ! file_id_equal ( & fsp - > file_id , & e - > id ) ) {
continue ;
}
if ( fsp - > fh - > gen_id ! = e - > share_file_id ) {
continue ;
}
return e ;
2005-09-30 21:13:37 +04:00
}
return NULL ;
}
2004-06-08 20:14:31 +04:00
/*******************************************************************
2005-09-30 21:13:37 +04:00
Del the share mode of a file for this process . Return the number of
entries left .
2004-06-08 20:14:31 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool del_share_mode ( struct share_mode_lock * lck , files_struct * fsp )
2004-06-08 20:14:31 +04:00
{
2013-09-17 00:58:54 +04:00
struct share_mode_entry * e ;
2004-06-08 20:14:31 +04:00
2013-09-17 00:58:54 +04:00
e = find_share_mode_entry ( lck , fsp ) ;
2005-09-30 21:13:37 +04:00
if ( e = = NULL ) {
return False ;
2004-06-08 20:14:31 +04:00
}
2014-10-11 01:32:19 +04:00
remove_share_mode_lease ( lck - > data , e ) ;
2012-01-10 16:56:37 +04:00
* e = lck - > data - > share_modes [ lck - > data - > num_share_modes - 1 ] ;
lck - > data - > num_share_modes - = 1 ;
lck - > data - > modified = True ;
2005-09-30 21:13:37 +04:00
return True ;
2004-06-08 20:14:31 +04:00
}
2012-08-03 18:31:32 +04:00
bool mark_share_mode_disconnected ( struct share_mode_lock * lck ,
struct files_struct * fsp )
{
2013-09-17 00:58:54 +04:00
struct share_mode_entry * e ;
2012-08-03 18:31:32 +04:00
if ( lck - > data - > num_share_modes ! = 1 ) {
return false ;
}
if ( fsp - > op = = NULL ) {
return false ;
}
if ( ! fsp - > op - > global - > durable ) {
return false ;
}
2013-09-17 00:58:54 +04:00
e = find_share_mode_entry ( lck , fsp ) ;
2012-08-03 18:31:32 +04:00
if ( e = = NULL ) {
return false ;
}
DEBUG ( 10 , ( " Marking share mode entry disconnected for durable handle \n " ) ) ;
server_id_set_disconnected ( & e - > pid ) ;
/*
* On reopen the caller needs to check that
* the client comes with the correct handle .
*/
e - > share_file_id = fsp - > op - > global - > open_persistent_id ;
lck - > data - > modified = true ;
return true ;
}
2004-06-08 20:14:31 +04:00
/*******************************************************************
2005-09-30 21:13:37 +04:00
Remove an oplock mid and mode entry from a share mode .
2004-06-08 20:14:31 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool remove_share_oplock ( struct share_mode_lock * lck , files_struct * fsp )
2004-06-08 20:14:31 +04:00
{
2014-10-11 01:32:19 +04:00
struct share_mode_data * d = lck - > data ;
2013-09-17 00:58:54 +04:00
struct share_mode_entry * e ;
2004-06-08 20:14:31 +04:00
2013-09-17 00:58:54 +04:00
e = find_share_mode_entry ( lck , fsp ) ;
2005-09-30 21:13:37 +04:00
if ( e = = NULL ) {
return False ;
}
2004-06-08 20:14:31 +04:00
2014-10-11 01:32:19 +04:00
remove_share_mode_lease ( d , e ) ;
d - > modified = True ;
return true ;
2005-09-30 21:13:37 +04:00
}
2004-06-08 20:14:31 +04:00
2005-09-30 21:13:37 +04:00
/*******************************************************************
Downgrade a oplock type from exclusive to level II .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-08 20:14:31 +04:00
2007-10-19 04:40:25 +04:00
bool downgrade_share_oplock ( struct share_mode_lock * lck , files_struct * fsp )
2005-09-30 21:13:37 +04:00
{
2013-09-17 00:58:54 +04:00
struct share_mode_entry * e ;
2004-06-08 20:14:31 +04:00
2013-09-17 00:58:54 +04:00
e = find_share_mode_entry ( lck , fsp ) ;
2005-09-30 21:13:37 +04:00
if ( e = = NULL ) {
return False ;
2004-06-08 20:14:31 +04:00
}
2005-09-30 21:13:37 +04:00
e - > op_type = LEVEL_II_OPLOCK ;
2012-01-10 16:56:37 +04:00
lck - > data - > modified = True ;
2005-09-30 21:13:37 +04:00
return True ;
2004-06-08 20:14:31 +04:00
}
2014-10-29 01:31:46 +03:00
NTSTATUS downgrade_share_lease ( struct smbd_server_connection * sconn ,
struct share_mode_lock * lck ,
const struct smb2_lease_key * key ,
uint32_t new_lease_state ,
struct share_mode_lease * * _l )
{
struct share_mode_data * d = lck - > data ;
struct share_mode_lease * l ;
uint32_t i ;
* _l = NULL ;
for ( i = 0 ; i < d - > num_leases ; i + + ) {
if ( smb2_lease_equal ( & sconn - > client - > connections - > smb2 . client . guid ,
key ,
& d - > leases [ i ] . client_guid ,
& d - > leases [ i ] . lease_key ) ) {
break ;
}
}
if ( i = = d - > num_leases ) {
DEBUG ( 10 , ( " lease not found \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
l = & d - > leases [ i ] ;
if ( ! l - > breaking ) {
DEBUG ( 1 , ( " Attempt to break from %d to %d - but we're not in breaking state \n " ,
( int ) l - > current_state , ( int ) new_lease_state ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
/*
* Can ' t upgrade anything : l - > breaking_to_requested ( and l - > current_state )
* must be a strict bitwise superset of new_lease_state
*/
if ( ( new_lease_state & l - > breaking_to_requested ) ! = new_lease_state ) {
DEBUG ( 1 , ( " Attempt to upgrade from %d to %d - expected %d \n " ,
( int ) l - > current_state , ( int ) new_lease_state ,
( int ) l - > breaking_to_requested ) ) ;
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
if ( l - > current_state ! = new_lease_state ) {
l - > current_state = new_lease_state ;
d - > modified = true ;
}
if ( ( new_lease_state & ~ l - > breaking_to_required ) ! = 0 ) {
DEBUG ( 5 , ( " lease state %d not fully broken from %d to %d \n " ,
( int ) new_lease_state ,
( int ) l - > current_state ,
( int ) l - > breaking_to_required ) ) ;
l - > breaking_to_requested = l - > breaking_to_required ;
if ( l - > current_state & ( ~ SMB2_LEASE_READ ) ) {
/*
* Here we break in steps , as windows does
* see the breaking3 and v2_breaking3 tests .
*/
l - > breaking_to_requested | = SMB2_LEASE_READ ;
}
d - > modified = true ;
* _l = l ;
return NT_STATUS_OPLOCK_BREAK_IN_PROGRESS ;
}
DEBUG ( 10 , ( " breaking from %d to %d - expected %d \n " ,
( int ) l - > current_state , ( int ) new_lease_state ,
( int ) l - > breaking_to_requested ) ) ;
l - > breaking_to_requested = 0 ;
l - > breaking_to_required = 0 ;
l - > breaking = false ;
d - > modified = true ;
return NT_STATUS_OK ;
}
2006-02-02 23:44:50 +03:00
/****************************************************************************
2011-01-26 01:23:19 +03:00
Adds a delete on close token .
2006-02-02 23:44:50 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-01-10 16:56:37 +04:00
static bool add_delete_on_close_token ( struct share_mode_data * d ,
2011-01-26 01:23:19 +03:00
uint32_t name_hash ,
2012-04-05 01:54:02 +04:00
const struct security_token * nt_tok ,
2011-02-11 10:49:15 +03:00
const struct security_unix_token * tok )
2006-02-02 23:44:50 +03:00
{
2011-11-21 20:12:00 +04:00
struct delete_token * tmp , * dtl ;
2006-02-02 23:44:50 +03:00
2012-01-10 16:56:37 +04:00
tmp = talloc_realloc ( d , d - > delete_tokens , struct delete_token ,
d - > num_delete_tokens + 1 ) ;
2011-11-21 20:12:00 +04:00
if ( tmp = = NULL ) {
2011-01-26 01:23:19 +03:00
return false ;
}
2012-01-10 16:56:37 +04:00
d - > delete_tokens = tmp ;
dtl = & d - > delete_tokens [ d - > num_delete_tokens ] ;
2011-01-26 01:23:19 +03:00
dtl - > name_hash = name_hash ;
2012-04-05 01:54:02 +04:00
dtl - > delete_nt_token = dup_nt_token ( d - > delete_tokens , nt_tok ) ;
if ( dtl - > delete_nt_token = = NULL ) {
return false ;
}
2012-01-10 16:56:37 +04:00
dtl - > delete_token = copy_unix_token ( d - > delete_tokens , tok ) ;
2011-01-26 01:23:19 +03:00
if ( dtl - > delete_token = = NULL ) {
return false ;
}
2012-01-10 16:56:37 +04:00
d - > num_delete_tokens + = 1 ;
d - > modified = true ;
2011-01-26 01:23:19 +03:00
return true ;
2006-02-02 23:44:50 +03:00
}
2005-09-30 21:13:37 +04:00
/****************************************************************************
Sets the delete on close flag over all share modes on this file .
Modify the share mode entry for all files open
on this device and inode to tell other smbds we have
changed the delete on close flag . This will be noticed
in the close code , the last closer will delete the file
if flag is set .
2011-02-11 10:49:15 +03:00
This makes a copy of any struct security_unix_token into the
2007-01-19 00:51:52 +03:00
lck entry . This function is used when the lock is already granted .
2005-09-30 21:13:37 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-08 20:14:31 +04:00
2011-01-26 01:23:19 +03:00
void set_delete_on_close_lck ( files_struct * fsp ,
struct share_mode_lock * lck ,
bool delete_on_close ,
2012-04-05 01:54:02 +04:00
const struct security_token * nt_tok ,
2011-02-11 10:49:15 +03:00
const struct security_unix_token * tok )
2007-01-19 00:51:52 +03:00
{
2012-01-10 16:56:37 +04:00
struct share_mode_data * d = lck - > data ;
2011-11-21 20:12:00 +04:00
int i ;
2011-01-26 01:23:19 +03:00
bool ret ;
if ( delete_on_close ) {
2012-04-05 01:54:02 +04:00
SMB_ASSERT ( nt_tok ! = NULL ) ;
2011-01-26 01:23:19 +03:00
SMB_ASSERT ( tok ! = NULL ) ;
} else {
2012-04-05 01:54:02 +04:00
SMB_ASSERT ( nt_tok = = NULL ) ;
2011-01-26 01:23:19 +03:00
SMB_ASSERT ( tok = = NULL ) ;
}
2012-01-10 16:56:37 +04:00
for ( i = 0 ; i < d - > num_delete_tokens ; i + + ) {
struct delete_token * dt = & d - > delete_tokens [ i ] ;
2011-11-21 20:12:00 +04:00
if ( dt - > name_hash = = fsp - > name_hash ) {
2012-01-10 16:56:37 +04:00
d - > modified = true ;
2011-01-26 01:23:19 +03:00
if ( delete_on_close = = false ) {
/* Delete this entry. */
2012-04-05 01:54:02 +04:00
TALLOC_FREE ( dt - > delete_nt_token ) ;
2011-11-21 20:12:00 +04:00
TALLOC_FREE ( dt - > delete_token ) ;
2012-01-10 16:56:37 +04:00
* dt = d - > delete_tokens [
d - > num_delete_tokens - 1 ] ;
d - > num_delete_tokens - = 1 ;
2012-04-07 02:35:55 +04:00
} else {
/* Replace this token with the
given tok . */
TALLOC_FREE ( dt - > delete_nt_token ) ;
dt - > delete_nt_token = dup_nt_token ( dt , nt_tok ) ;
SMB_ASSERT ( dt - > delete_nt_token ! = NULL ) ;
TALLOC_FREE ( dt - > delete_token ) ;
dt - > delete_token = copy_unix_token ( dt , tok ) ;
SMB_ASSERT ( dt - > delete_token ! = NULL ) ;
2011-01-26 01:23:19 +03:00
}
2012-04-07 02:35:55 +04:00
return ;
2007-01-19 00:51:52 +03:00
}
}
2011-01-26 01:23:19 +03:00
if ( ! delete_on_close ) {
/* Nothing to delete - not found. */
return ;
}
2012-04-05 01:54:02 +04:00
ret = add_delete_on_close_token ( lck - > data , fsp - > name_hash , nt_tok , tok ) ;
2011-01-26 01:23:19 +03:00
SMB_ASSERT ( ret ) ;
2007-01-19 00:51:52 +03:00
}
2012-04-05 01:54:02 +04:00
bool set_delete_on_close ( files_struct * fsp , bool delete_on_close ,
const struct security_token * nt_tok ,
const struct security_unix_token * tok )
2004-06-08 20:14:31 +04:00
{
2005-09-30 21:13:37 +04:00
struct share_mode_lock * lck ;
2011-05-28 12:24:20 +04:00
2005-09-30 21:13:37 +04:00
DEBUG ( 10 , ( " set_delete_on_close: %s delete on close flag for "
2012-06-14 14:25:43 +04:00
" %s, file %s \n " ,
delete_on_close ? " Adding " : " Removing " , fsp_fnum_dbg ( fsp ) ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) ) ) ;
2004-06-08 20:14:31 +04:00
2012-02-19 17:23:56 +04:00
lck = get_existing_share_mode_lock ( talloc_tos ( ) , fsp - > file_id ) ;
2005-09-30 21:13:37 +04:00
if ( lck = = NULL ) {
2004-06-08 20:14:31 +04:00
return False ;
}
2006-02-02 23:44:50 +03:00
2012-04-05 01:54:02 +04:00
if ( delete_on_close ) {
set_delete_on_close_lck ( fsp , lck , true ,
nt_tok ,
tok ) ;
} else {
set_delete_on_close_lck ( fsp , lck , false ,
NULL ,
NULL ) ;
}
2006-02-01 07:14:07 +03:00
2007-01-20 00:46:12 +03:00
if ( fsp - > is_directory ) {
2009-07-11 01:50:37 +04:00
SMB_ASSERT ( ! is_ntfs_stream_smb_fname ( fsp - > fsp_name ) ) ;
2010-07-07 00:43:14 +04:00
send_stat_cache_delete_message ( fsp - > conn - > sconn - > msg_ctx ,
fsp - > fsp_name - > base_name ) ;
2007-01-20 00:46:12 +03:00
}
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( lck ) ;
2010-01-13 03:04:44 +03:00
fsp - > delete_on_close = delete_on_close ;
2005-09-30 21:13:37 +04:00
return True ;
}
2001-08-21 05:25:45 +04:00
2012-06-01 17:50:39 +04:00
static struct delete_token * find_delete_on_close_token (
struct share_mode_data * d , uint32_t name_hash )
{
uint32_t i ;
DEBUG ( 10 , ( " find_delete_on_close_token: name_hash = 0x%x \n " ,
( unsigned int ) name_hash ) ) ;
for ( i = 0 ; i < d - > num_delete_tokens ; i + + ) {
struct delete_token * dt = & d - > delete_tokens [ i ] ;
DEBUG ( 10 , ( " find__delete_on_close_token: dt->name_hash = 0x%x \n " ,
( unsigned int ) dt - > name_hash ) ) ;
if ( dt - > name_hash = = name_hash ) {
return dt ;
}
}
return NULL ;
}
2012-04-05 01:54:02 +04:00
/****************************************************************************
Return the NT token and UNIX token if there ' s a match . Return true if
found , false if not .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool get_delete_on_close_token ( struct share_mode_lock * lck ,
uint32_t name_hash ,
const struct security_token * * pp_nt_tok ,
const struct security_unix_token * * pp_tok )
2011-01-26 01:23:19 +03:00
{
2012-06-01 17:50:39 +04:00
struct delete_token * dt ;
2011-01-26 01:23:19 +03:00
2012-06-01 17:50:39 +04:00
dt = find_delete_on_close_token ( lck - > data , name_hash ) ;
if ( dt = = NULL ) {
return false ;
}
2012-06-01 17:52:14 +04:00
* pp_nt_tok = dt - > delete_nt_token ;
* pp_tok = dt - > delete_token ;
2012-06-01 17:50:39 +04:00
return true ;
2011-01-26 01:23:19 +03:00
}
bool is_delete_on_close_set ( struct share_mode_lock * lck , uint32_t name_hash )
{
2012-06-01 17:50:39 +04:00
return find_delete_on_close_token ( lck - > data , name_hash ) ! = NULL ;
2011-01-26 01:23:19 +03:00
}
2009-07-08 04:27:50 +04:00
bool set_sticky_write_time ( struct file_id fileid , struct timespec write_time )
2008-03-12 17:32:47 +03:00
{
struct share_mode_lock * lck ;
2008-09-06 06:00:48 +04:00
DEBUG ( 5 , ( " set_sticky_write_time: %s id=%s \n " ,
2009-11-03 12:59:18 +03:00
timestring ( talloc_tos ( ) ,
2008-03-12 17:32:47 +03:00
convert_timespec_to_time_t ( write_time ) ) ,
2008-09-06 06:00:48 +04:00
file_id_string_tos ( & fileid ) ) ) ;
2008-03-12 17:32:47 +03:00
2012-02-19 17:23:56 +04:00
lck = get_existing_share_mode_lock ( talloc_tos ( ) , fileid ) ;
2008-03-12 17:32:47 +03:00
if ( lck = = NULL ) {
return False ;
}
2012-01-10 16:56:37 +04:00
if ( timespec_compare ( & lck - > data - > changed_write_time , & write_time ) ! = 0 ) {
lck - > data - > modified = True ;
lck - > data - > changed_write_time = write_time ;
2008-03-12 17:32:47 +03:00
}
TALLOC_FREE ( lck ) ;
return True ;
}
2008-09-06 06:00:48 +04:00
bool set_write_time ( struct file_id fileid , struct timespec write_time )
{
struct share_mode_lock * lck ;
2008-09-06 07:37:00 +04:00
DEBUG ( 5 , ( " set_write_time: %s id=%s \n " ,
2009-11-03 12:59:18 +03:00
timestring ( talloc_tos ( ) ,
2008-09-06 06:00:48 +04:00
convert_timespec_to_time_t ( write_time ) ) ,
file_id_string_tos ( & fileid ) ) ) ;
2012-02-19 17:23:56 +04:00
lck = get_existing_share_mode_lock ( talloc_tos ( ) , fileid ) ;
2008-09-06 06:00:48 +04:00
if ( lck = = NULL ) {
return False ;
}
2012-01-10 16:56:37 +04:00
if ( timespec_compare ( & lck - > data - > old_write_time , & write_time ) ! = 0 ) {
lck - > data - > modified = True ;
lck - > data - > old_write_time = write_time ;
2008-09-06 06:00:48 +04:00
}
TALLOC_FREE ( lck ) ;
return True ;
}
2013-11-22 18:36:49 +04:00
struct timespec get_share_mode_write_time ( struct share_mode_lock * lck )
{
struct share_mode_data * d = lck - > data ;
if ( ! null_timespec ( d - > changed_write_time ) ) {
return d - > changed_write_time ;
}
return d - > old_write_time ;
}