1998-08-15 11:27:34 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-08-15 11:27:34 +04:00
Files [ ] structure handling
Copyright ( C ) Andrew Tridgell 1998
2010-03-22 11:11:24 +03:00
1998-08-15 11:27:34 +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
1998-08-15 11:27:34 +04:00
( at your option ) any later version .
2010-03-22 11:11:24 +03:00
1998-08-15 11:27:34 +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 .
2010-03-22 11:11:24 +03:00
1998-08-15 11:27:34 +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/>.
1998-08-15 11:27:34 +04:00
*/
# include "includes.h"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2009-01-08 14:03:45 +03:00
# include "smbd/globals.h"
2010-10-12 08:27:50 +04:00
# include "libcli/security/security.h"
2011-05-05 13:25:29 +04:00
# include "util_tdb.h"
2011-07-07 15:04:31 +04:00
# include "lib/util/bitmap.h"
1998-08-15 11:27:34 +04:00
1998-08-17 07:06:20 +04:00
# define FILE_HANDLE_OFFSET 0x1000
2012-06-07 18:13:36 +04:00
/**
* create new fsp to be used for file_new or a durable handle reconnect
*/
NTSTATUS fsp_new ( struct connection_struct * conn , TALLOC_CTX * mem_ctx ,
files_struct * * result )
{
NTSTATUS status = NT_STATUS_NO_MEMORY ;
files_struct * fsp = NULL ;
struct smbd_server_connection * sconn = conn - > sconn ;
fsp = talloc_zero ( mem_ctx , struct files_struct ) ;
if ( fsp = = NULL ) {
goto fail ;
}
/*
* This can ' t be a child of fsp because the file_handle can be ref ' d
* when doing a dos / fcb open , which will then share the file_handle
* across multiple fsps .
*/
fsp - > fh = talloc_zero ( mem_ctx , struct fd_handle ) ;
if ( fsp - > fh = = NULL ) {
goto fail ;
}
2019-01-30 20:45:34 +03:00
# if defined(HAVE_OFD_LOCKS)
2020-04-03 09:02:23 +03:00
fsp - > fsp_flags . use_ofd_locks = true ;
2019-01-30 20:45:34 +03:00
if ( lp_parm_bool ( SNUM ( conn ) ,
" smbd " ,
" force process locks " ,
false ) ) {
2020-04-03 09:02:23 +03:00
fsp - > fsp_flags . use_ofd_locks = false ;
2019-01-30 20:45:34 +03:00
}
# endif
2012-06-07 18:13:36 +04:00
fsp - > fh - > ref_count = 1 ;
fsp - > fh - > fd = - 1 ;
2012-06-12 19:56:43 +04:00
fsp - > fnum = FNUM_FIELD_INVALID ;
2012-06-07 18:13:36 +04:00
fsp - > conn = conn ;
2019-12-02 18:30:50 +03:00
fsp - > close_write_time = make_omit_timespec ( ) ;
2012-06-07 18:13:36 +04:00
DLIST_ADD ( sconn - > files , fsp ) ;
sconn - > num_files + = 1 ;
conn - > num_files_open + + ;
* result = fsp ;
return NT_STATUS_OK ;
fail :
if ( fsp ! = NULL ) {
TALLOC_FREE ( fsp - > fh ) ;
}
TALLOC_FREE ( fsp ) ;
return status ;
}
2019-09-16 13:54:32 +03:00
void fsp_set_gen_id ( files_struct * fsp )
{
static uint64_t gen_id = 1 ;
/*
* A billion of 64 - bit increments per second gives us
* more than 500 years of runtime without wrap .
*/
fsp - > fh - > gen_id = gen_id + + ;
}
2001-10-21 01:59:34 +04:00
/****************************************************************************
Find first available file slot .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-09 17:38:53 +04:00
NTSTATUS file_new ( struct smb_request * req , connection_struct * conn ,
files_struct * * result )
1998-08-15 11:27:34 +04:00
{
2010-09-27 08:06:02 +04:00
struct smbd_server_connection * sconn = conn - > sconn ;
2005-09-30 21:13:37 +04:00
files_struct * fsp ;
2009-07-11 01:50:37 +04:00
NTSTATUS status ;
1998-08-15 11:27:34 +04:00
2012-06-07 18:13:36 +04:00
status = fsp_new ( conn , conn , & fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
GetTimeOfDay ( & fsp - > open_time ) ;
2014-05-01 22:01:03 +04:00
if ( req ) {
2014-06-11 16:25:07 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2012-06-08 19:51:47 +04:00
struct smbXsrv_open * op = NULL ;
NTTIME now = timeval_to_nttime ( & fsp - > open_time ) ;
2005-09-30 21:13:37 +04:00
2014-06-11 16:25:07 +04:00
status = smbXsrv_open_create ( xconn ,
2012-06-08 19:51:47 +04:00
conn - > session_info ,
now , & op ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
file_free ( NULL , fsp ) ;
return status ;
2012-05-24 12:43:56 +04:00
}
2012-06-08 19:51:47 +04:00
fsp - > op = op ;
op - > compat = fsp ;
fsp - > fnum = op - > local_id ;
2014-05-01 22:01:03 +04:00
} else {
DEBUG ( 10 , ( " %s: req==NULL, INTERNAL_OPEN_ONLY, smbXsrv_open "
" allocated \n " , __func__ ) ) ;
2012-05-24 12:43:56 +04:00
}
2002-10-23 02:17:29 +04:00
2019-09-16 13:54:32 +03:00
fsp_set_gen_id ( fsp ) ;
2009-07-11 01:50:37 +04:00
/*
* Create an smb_filename with " " for the base_name . There are very
* few NULL checks , so make sure it ' s initialized with something . to
* be safe until an audit can be done .
*/
2020-05-03 16:07:45 +03:00
fsp - > fsp_name = synthetic_smb_fname ( fsp ,
" " ,
NULL ,
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2020-05-03 16:07:45 +03:00
0 ) ;
2013-04-15 13:03:44 +04:00
if ( fsp - > fsp_name = = NULL ) {
2012-05-24 13:22:11 +04:00
file_free ( NULL , fsp ) ;
2013-04-15 13:03:44 +04:00
return NT_STATUS_NO_MEMORY ;
2009-07-11 01:50:37 +04:00
}
2012-06-08 19:51:47 +04:00
DEBUG ( 5 , ( " allocated file structure %s (%u used) \n " ,
fsp_fnum_dbg ( fsp ) , ( unsigned int ) sconn - > num_files ) ) ;
1998-08-17 07:52:05 +04:00
2008-10-09 18:55:56 +04:00
if ( req ! = NULL ) {
2012-06-29 23:41:47 +04:00
fsp - > mid = req - > mid ;
2008-10-09 18:55:56 +04:00
req - > chain_fsp = fsp ;
}
2005-03-10 04:30:14 +03:00
2008-09-27 05:39:03 +04:00
/* A new fsp invalidates the positive and
negative fsp_fi_cache as the new fsp is pushed
at the start of the list and we search from
a cache hit to the * end * of the list . */
2010-09-27 08:06:02 +04:00
ZERO_STRUCT ( sconn - > fsp_fi_cache ) ;
2006-07-11 22:01:26 +04:00
* result = fsp ;
return NT_STATUS_OK ;
1998-08-15 11:27:34 +04:00
}
2020-03-23 13:36:42 +03:00
/*
* Create an internal fsp for an * existing * directory .
*
* This should only be used by callers in the VFS that need to control the
2020-03-16 20:53:15 +03:00
* opening of the directory . Otherwise use open_internal_dirfsp_at ( ) .
2020-03-23 13:36:42 +03:00
*/
NTSTATUS create_internal_dirfsp_at ( connection_struct * conn ,
const struct smb_filename * smb_dname ,
struct files_struct * * _fsp )
{
struct files_struct * fsp = NULL ;
NTSTATUS status ;
status = file_new ( NULL , conn , & fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
status = fsp_set_smb_fname ( fsp , smb_dname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
file_free ( NULL , fsp ) ;
return status ;
}
if ( ! VALID_STAT ( fsp - > fsp_name - > st ) ) {
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
if ( ! S_ISDIR ( fsp - > fsp_name - > st . st_ex_mode ) ) {
DBG_ERR ( " %s is not a directory! \n " ,
smb_fname_str_dbg ( smb_dname ) ) ;
file_free ( NULL , fsp ) ;
return NT_STATUS_NOT_A_DIRECTORY ;
}
fsp - > file_id = vfs_file_id_from_sbuf ( conn , & fsp - > fsp_name - > st ) ;
fsp - > access_mask = FILE_LIST_DIRECTORY ;
2020-04-02 19:21:11 +03:00
fsp - > fsp_flags . is_directory = true ;
2020-03-23 13:36:42 +03:00
* _fsp = fsp ;
return NT_STATUS_OK ;
}
2020-03-16 20:53:15 +03:00
/*
* Open an internal fsp for an * existing * directory .
*/
NTSTATUS open_internal_dirfsp_at ( connection_struct * conn ,
const struct smb_filename * smb_dname ,
2020-04-09 19:24:26 +03:00
int open_flags ,
2020-03-16 20:53:15 +03:00
struct files_struct * * _fsp )
{
struct files_struct * fsp = NULL ;
NTSTATUS status ;
2020-05-14 19:38:51 +03:00
status = create_internal_dirfsp_at ( conn , smb_dname , & fsp ) ;
2020-03-16 20:53:15 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
# ifdef O_DIRECTORY
open_flags | = O_DIRECTORY ;
# endif
status = fd_open ( conn , fsp , open_flags , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_INFO ( " Could not open fd for %s (%s) \n " ,
smb_fname_str_dbg ( smb_dname ) ,
nt_errstr ( status ) ) ;
file_free ( NULL , fsp ) ;
return status ;
}
* _fsp = fsp ;
return NT_STATUS_OK ;
}
1998-08-15 11:27:34 +04:00
/****************************************************************************
2001-10-21 01:59:34 +04:00
Close all open files for a connection .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
1998-08-15 11:27:34 +04:00
void file_close_conn ( connection_struct * conn )
{
1998-08-17 10:13:32 +04:00
files_struct * fsp , * next ;
2010-03-22 11:11:24 +03:00
2010-09-27 05:40:11 +04:00
for ( fsp = conn - > sconn - > files ; fsp ; fsp = next ) {
1998-08-17 10:13:32 +04:00
next = fsp - > next ;
2012-08-03 18:38:38 +04:00
if ( fsp - > conn ! = conn ) {
continue ;
1998-08-16 08:08:47 +04:00
}
2012-08-03 18:38:38 +04:00
if ( fsp - > op ! = NULL & & fsp - > op - > global - > durable ) {
/*
* A tree disconnect closes a durable handle
*/
fsp - > op - > global - > durable = false ;
}
close_file ( NULL , fsp , SHUTDOWN_CLOSE ) ;
1998-08-16 08:08:47 +04:00
}
1998-08-15 11:27:34 +04:00
}
/****************************************************************************
2001-10-21 01:59:34 +04:00
Initialise file structures .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-30 05:49:24 +04:00
2012-05-24 14:20:30 +04:00
static int files_max_open_fds ;
bool file_init_global ( void )
1998-08-15 11:27:34 +04:00
{
2012-05-24 14:20:30 +04:00
int request_max = lp_max_open_files ( ) ;
1998-10-16 10:16:10 +04:00
int real_lim ;
2012-05-24 14:20:30 +04:00
int real_max ;
if ( files_max_open_fds ! = 0 ) {
return true ;
}
1998-09-30 05:49:24 +04:00
1998-10-16 10:16:10 +04:00
/*
* Set the max_open files to be the requested
* max plus a fudgefactor to allow for the extra
* fd ' s we need such as log files etc . . .
*/
2012-05-24 14:20:30 +04:00
real_lim = set_maxfiles ( request_max + MAX_OPEN_FUDGEFACTOR ) ;
1998-10-16 10:16:10 +04:00
2012-05-24 14:20:30 +04:00
real_max = real_lim - MAX_OPEN_FUDGEFACTOR ;
1998-10-16 10:16:10 +04:00
2012-05-24 14:20:30 +04:00
if ( real_max + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536 ) {
real_max = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES ;
}
2002-10-23 02:17:29 +04:00
2012-05-24 14:20:30 +04:00
if ( real_max ! = request_max ) {
DEBUG ( 1 , ( " file_init_global: Information only: requested %d "
2010-08-09 17:57:38 +04:00
" open files, %d are available. \n " ,
2012-05-24 14:20:30 +04:00
request_max , real_max ) ) ;
1998-10-16 10:16:10 +04:00
}
1998-09-30 05:49:24 +04:00
2012-05-24 14:20:30 +04:00
SMB_ASSERT ( real_max > 100 ) ;
2002-10-23 02:17:29 +04:00
2012-05-24 14:20:30 +04:00
files_max_open_fds = real_max ;
return true ;
}
2010-03-22 11:11:24 +03:00
2012-05-24 14:20:30 +04:00
bool file_init ( struct smbd_server_connection * sconn )
{
bool ok ;
ok = file_init_global ( ) ;
if ( ! ok ) {
return false ;
}
sconn - > real_max_open_files = files_max_open_fds ;
2010-09-27 07:50:22 +04:00
return true ;
1998-08-15 11:27:34 +04:00
}
/****************************************************************************
2001-10-21 01:59:34 +04:00
Close files open by a specified vuid .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
2012-06-05 20:23:14 +04:00
void file_close_user ( struct smbd_server_connection * sconn , uint64_t vuid )
1998-08-15 11:27:34 +04:00
{
1998-08-17 10:13:32 +04:00
files_struct * fsp , * next ;
1998-08-16 08:08:47 +04:00
2010-09-27 05:46:12 +04:00
for ( fsp = sconn - > files ; fsp ; fsp = next ) {
1998-08-17 10:13:32 +04:00
next = fsp - > next ;
2000-04-24 23:23:51 +04:00
if ( fsp - > vuid = = vuid ) {
2008-10-09 18:27:49 +04:00
close_file ( NULL , fsp , SHUTDOWN_CLOSE ) ;
1998-08-15 11:27:34 +04:00
}
}
}
2009-05-18 11:46:05 +04:00
/*
* Walk the files table until " fn " returns non - NULL
*/
2010-03-22 11:16:57 +03:00
struct files_struct * files_forall (
2010-09-27 05:53:00 +04:00
struct smbd_server_connection * sconn ,
2009-05-18 11:46:05 +04:00
struct files_struct * ( * fn ) ( struct files_struct * fsp ,
void * private_data ) ,
void * private_data )
{
struct files_struct * fsp , * next ;
2010-09-27 05:53:00 +04:00
for ( fsp = sconn - > files ; fsp ; fsp = next ) {
2009-05-18 11:46:05 +04:00
struct files_struct * ret ;
next = fsp - > next ;
ret = fn ( fsp , private_data ) ;
if ( ret ! = NULL ) {
return ret ;
}
}
return NULL ;
}
2001-10-21 01:59:34 +04:00
/****************************************************************************
Find a fsp given a file descriptor .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-09-27 06:54:29 +04:00
files_struct * file_find_fd ( struct smbd_server_connection * sconn , int fd )
2001-10-21 01:59:34 +04:00
{
int count = 0 ;
files_struct * fsp ;
2010-09-27 06:54:29 +04:00
for ( fsp = sconn - > files ; fsp ; fsp = fsp - > next , count + + ) {
2005-07-08 08:51:27 +04:00
if ( fsp - > fh - > fd = = fd ) {
2001-10-21 01:59:34 +04:00
if ( count > 10 ) {
2010-09-27 06:54:29 +04:00
DLIST_PROMOTE ( sconn - > files , fsp ) ;
2001-10-21 01:59:34 +04:00
}
return fsp ;
}
}
return NULL ;
}
1998-08-15 11:27:34 +04:00
/****************************************************************************
2001-10-21 01:59:34 +04:00
Find a fsp given a device , inode and file_id .
1998-08-15 11:27:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-23 05:48:45 +04:00
2010-09-27 06:00:31 +04:00
files_struct * file_find_dif ( struct smbd_server_connection * sconn ,
struct file_id id , unsigned long gen_id )
1998-08-15 11:27:34 +04:00
{
1998-08-17 10:47:53 +04:00
int count = 0 ;
1998-08-16 08:08:47 +04:00
files_struct * fsp ;
2012-06-13 14:11:51 +04:00
if ( gen_id = = 0 ) {
return NULL ;
}
2010-09-27 06:00:31 +04:00
for ( fsp = sconn - > files ; fsp ; fsp = fsp - > next , count + + ) {
2005-07-08 08:51:27 +04:00
/* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
2007-05-29 13:30:34 +04:00
if ( file_id_equal ( & fsp - > file_id , & id ) & &
fsp - > fh - > gen_id = = gen_id ) {
1998-08-17 10:47:53 +04:00
if ( count > 10 ) {
2010-09-27 06:00:31 +04:00
DLIST_PROMOTE ( sconn - > files , fsp ) ;
1998-08-17 10:47:53 +04:00
}
2003-05-23 00:31:35 +04:00
/* Paranoia check. */
2005-09-30 21:13:37 +04:00
if ( ( fsp - > fh - > fd = = - 1 ) & &
2015-02-18 22:49:27 +03:00
( fsp - > oplock_type ! = NO_OPLOCK & &
fsp - > oplock_type ! = LEASE_OPLOCK ) ) {
2019-11-09 20:32:07 +03:00
struct file_id_buf idbuf ;
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " file_find_dif: file %s file_id = "
" %s, gen = %u oplock_type = %u is a "
" stat open with oplock type ! \n " ,
fsp_str_dbg ( fsp ) ,
2019-11-09 20:32:07 +03:00
file_id_str_buf ( fsp - > file_id , & idbuf ) ,
2007-05-29 13:30:34 +04:00
( unsigned int ) fsp - > fh - > gen_id ,
( unsigned int ) fsp - > oplock_type ) ) ;
2007-06-16 01:58:49 +04:00
smb_panic ( " file_find_dif " ) ;
2003-05-23 00:31:35 +04:00
}
1998-08-15 11:27:34 +04:00
return fsp ;
}
1998-08-16 08:08:47 +04:00
}
1998-08-15 11:27:34 +04:00
return NULL ;
}
1998-10-23 07:34:50 +04:00
/****************************************************************************
Find the first fsp given a device and inode .
2005-03-10 04:30:14 +03:00
We use a singleton cache here to speed up searching from getfilepathinfo
calls .
1998-10-23 07:34:50 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-09-27 06:05:25 +04:00
files_struct * file_find_di_first ( struct smbd_server_connection * sconn ,
struct file_id id )
1998-10-23 07:34:50 +04:00
{
2004-10-19 02:01:10 +04:00
files_struct * fsp ;
1998-10-23 07:34:50 +04:00
2010-09-27 08:06:02 +04:00
if ( file_id_equal ( & sconn - > fsp_fi_cache . id , & id ) ) {
2005-03-10 04:30:14 +03:00
/* Positive or negative cache hit. */
2010-09-27 08:06:02 +04:00
return sconn - > fsp_fi_cache . fsp ;
2005-03-10 04:30:14 +03:00
}
2010-09-27 08:06:02 +04:00
sconn - > fsp_fi_cache . id = id ;
2005-03-10 04:30:14 +03:00
2010-09-27 06:05:25 +04:00
for ( fsp = sconn - > files ; fsp ; fsp = fsp - > next ) {
2008-09-25 01:28:18 +04:00
if ( file_id_equal ( & fsp - > file_id , & id ) ) {
2005-03-10 04:30:14 +03:00
/* Setup positive cache. */
2010-09-27 08:06:02 +04:00
sconn - > fsp_fi_cache . fsp = fsp ;
2004-10-19 02:01:10 +04:00
return fsp ;
2005-03-10 04:30:14 +03:00
}
2004-10-19 02:01:10 +04:00
}
1998-10-23 07:34:50 +04:00
2005-03-10 04:30:14 +03:00
/* Setup negative cache. */
2010-09-27 08:06:02 +04:00
sconn - > fsp_fi_cache . fsp = NULL ;
2004-10-19 02:01:10 +04:00
return NULL ;
1998-10-23 07:34:50 +04:00
}
/****************************************************************************
Find the next fsp having the same device and inode .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
files_struct * file_find_di_next ( files_struct * start_fsp )
{
2004-10-19 02:01:10 +04:00
files_struct * fsp ;
1998-10-23 07:34:50 +04:00
2004-10-19 02:01:10 +04:00
for ( fsp = start_fsp - > next ; fsp ; fsp = fsp - > next ) {
2008-09-25 01:28:18 +04:00
if ( file_id_equal ( & fsp - > file_id , & start_fsp - > file_id ) ) {
2004-10-19 02:01:10 +04:00
return fsp ;
2007-05-29 13:30:34 +04:00
}
2004-10-19 02:01:10 +04:00
}
1998-10-23 07:34:50 +04:00
2004-10-19 02:01:10 +04:00
return NULL ;
1998-10-23 07:34:50 +04:00
}
1998-08-16 08:08:47 +04:00
2014-10-29 01:31:46 +03:00
struct files_struct * file_find_one_fsp_from_lease_key (
struct smbd_server_connection * sconn ,
const struct smb2_lease_key * lease_key )
{
struct files_struct * fsp ;
for ( fsp = sconn - > files ; fsp ; fsp = fsp - > next ) {
if ( ( fsp - > lease ! = NULL ) & &
( fsp - > lease - > lease . lease_key . data [ 0 ] = =
lease_key - > data [ 0 ] ) & &
( fsp - > lease - > lease . lease_key . data [ 1 ] = =
lease_key - > data [ 1 ] ) ) {
return fsp ;
}
}
return NULL ;
}
2009-02-26 22:42:23 +03:00
/****************************************************************************
Find any fsp open with a pathname below that of an already open path .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool file_find_subpath ( files_struct * dir_fsp )
{
files_struct * fsp ;
size_t dlen ;
2009-08-07 02:53:33 +04:00
char * d_fullname = NULL ;
2009-07-11 01:50:37 +04:00
d_fullname = talloc_asprintf ( talloc_tos ( ) , " %s/%s " ,
dir_fsp - > conn - > connectpath ,
dir_fsp - > fsp_name - > base_name ) ;
2009-02-26 22:42:23 +03:00
if ( ! d_fullname ) {
2009-10-08 02:43:43 +04:00
return false ;
2009-02-26 22:42:23 +03:00
}
dlen = strlen ( d_fullname ) ;
2010-09-27 06:12:15 +04:00
for ( fsp = dir_fsp - > conn - > sconn - > files ; fsp ; fsp = fsp - > next ) {
2009-02-26 22:42:23 +03:00
char * d1_fullname ;
if ( fsp = = dir_fsp ) {
continue ;
}
d1_fullname = talloc_asprintf ( talloc_tos ( ) ,
" %s/%s " ,
fsp - > conn - > connectpath ,
2009-07-11 01:50:37 +04:00
fsp - > fsp_name - > base_name ) ;
2009-02-26 22:42:23 +03:00
2009-10-08 02:39:38 +04:00
/*
* If the open file has a path that is a longer
* component , then it ' s a subpath .
*/
if ( strnequal ( d_fullname , d1_fullname , dlen ) & &
( d1_fullname [ dlen ] = = ' / ' ) ) {
2009-02-26 22:42:23 +03:00
TALLOC_FREE ( d1_fullname ) ;
2009-10-08 02:39:38 +04:00
TALLOC_FREE ( d_fullname ) ;
return true ;
2009-02-26 22:42:23 +03:00
}
TALLOC_FREE ( d1_fullname ) ;
2009-10-08 02:39:38 +04:00
}
2009-02-26 22:42:23 +03:00
TALLOC_FREE ( d_fullname ) ;
2009-10-08 02:43:43 +04:00
return false ;
2009-02-26 22:42:23 +03:00
}
1998-08-16 08:08:47 +04:00
/****************************************************************************
2001-10-21 01:59:34 +04:00
Free up a fsp .
1998-08-16 08:08:47 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-21 01:59:34 +04:00
2012-06-07 18:31:14 +04:00
void fsp_free ( files_struct * fsp )
{
struct smbd_server_connection * sconn = fsp - > conn - > sconn ;
2016-03-17 01:57:33 +03:00
if ( fsp = = sconn - > fsp_fi_cache . fsp ) {
ZERO_STRUCT ( sconn - > fsp_fi_cache ) ;
}
2012-06-07 18:31:14 +04:00
DLIST_REMOVE ( sconn - > files , fsp ) ;
SMB_ASSERT ( sconn - > num_files > 0 ) ;
sconn - > num_files - - ;
TALLOC_FREE ( fsp - > fake_file_handle ) ;
if ( fsp - > fh - > ref_count = = 1 ) {
TALLOC_FREE ( fsp - > fh ) ;
} else {
fsp - > fh - > ref_count - - ;
}
2014-10-29 01:31:46 +03:00
if ( fsp - > lease ! = NULL ) {
if ( fsp - > lease - > ref_count = = 1 ) {
TALLOC_FREE ( fsp - > lease ) ;
} else {
fsp - > lease - > ref_count - - ;
}
}
2012-06-07 18:31:14 +04:00
fsp - > conn - > num_files_open - - ;
/* this is paranoia, just in case someone tries to reuse the
information */
ZERO_STRUCTP ( fsp ) ;
/* fsp->fsp_name is a talloc child and is free'd automatically. */
TALLOC_FREE ( fsp ) ;
}
2008-10-09 18:27:49 +04:00
void file_free ( struct smb_request * req , files_struct * fsp )
1998-08-15 11:27:34 +04:00
{
2010-09-27 08:06:02 +04:00
struct smbd_server_connection * sconn = fsp - > conn - > sconn ;
2012-06-28 12:00:37 +04:00
uint64_t fnum = fsp - > fnum ;
2005-07-08 08:51:27 +04:00
2007-01-31 17:42:56 +03:00
if ( fsp - > notify ) {
2016-06-13 19:06:08 +03:00
size_t len = fsp_fullbasepath ( fsp , NULL , 0 ) ;
char fullpath [ len + 1 ] ;
fsp_fullbasepath ( fsp , fullpath , sizeof ( fullpath ) ) ;
/*
* Avoid / . at the end of the path name . notify can ' t
* deal with it .
*/
if ( len > 1 & & fullpath [ len - 1 ] = = ' . ' & &
fullpath [ len - 2 ] = = ' / ' ) {
fullpath [ len - 2 ] = ' \0 ' ;
}
notify_remove ( fsp - > conn - > sconn - > notify_ctx , fsp , fullpath ) ;
2007-01-31 17:42:56 +03:00
TALLOC_FREE ( fsp - > notify ) ;
}
2007-01-17 19:23:45 +03:00
2008-03-12 17:39:38 +03:00
/* Ensure this event will never fire. */
TALLOC_FREE ( fsp - > update_write_time_event ) ;
2012-06-08 19:51:47 +04:00
if ( fsp - > op ! = NULL ) {
fsp - > op - > compat = NULL ;
2012-05-24 12:43:56 +04:00
}
2012-06-08 19:51:47 +04:00
TALLOC_FREE ( fsp - > op ) ;
1998-08-16 08:08:47 +04:00
2008-10-09 18:55:56 +04:00
if ( ( req ! = NULL ) & & ( fsp = = req - > chain_fsp ) ) {
req - > chain_fsp = NULL ;
2004-10-19 02:01:10 +04:00
}
1998-08-17 07:52:05 +04:00
2010-06-09 08:20:07 +04:00
/*
* Clear all possible chained fsp
* pointers in the SMB2 request queue .
*/
2017-06-20 21:20:38 +03:00
remove_smb2_chained_fsp ( fsp ) ;
2010-06-09 08:20:07 +04:00
2007-10-16 00:59:37 +04:00
/* Drop all remaining extensions. */
2012-06-04 19:55:28 +04:00
vfs_remove_all_fsp_extensions ( fsp ) ;
2007-10-16 00:59:37 +04:00
2012-06-07 18:31:14 +04:00
fsp_free ( fsp ) ;
2012-06-07 18:27:24 +04:00
2012-06-28 12:00:37 +04:00
DEBUG ( 5 , ( " freed files structure %llu (%u used) \n " ,
( unsigned long long ) fnum , ( unsigned int ) sconn - > num_files ) ) ;
1998-08-15 11:27:34 +04:00
}
1998-08-17 07:52:05 +04:00
2006-07-11 22:01:26 +04:00
/****************************************************************************
2010-09-27 04:32:27 +04:00
Get an fsp from a packet given a 16 bit fnum .
2006-07-11 22:01:26 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-05-03 07:01:14 +03:00
files_struct * file_fsp ( struct smb_request * req , uint16_t fid )
2006-07-11 22:01:26 +04:00
{
2012-06-08 19:51:47 +04:00
struct smbXsrv_open * op ;
NTSTATUS status ;
NTTIME now = 0 ;
2006-07-11 22:01:26 +04:00
files_struct * fsp ;
2010-09-27 06:46:18 +04:00
if ( req = = NULL ) {
/*
* We should never get here . req = = NULL could in theory
* only happen from internal opens with a non - zero
* root_dir_fid . Internal opens just don ' t do that , at
* least they are not supposed to do so . And if they
* start to do so , they better fake up a smb_request
* from which we get the right smbd_server_conn . While
* this should never happen , let ' s return NULL here .
*/
return NULL ;
}
if ( req - > chain_fsp ! = NULL ) {
2020-04-03 09:06:27 +03:00
if ( req - > chain_fsp - > fsp_flags . closing ) {
2020-03-12 01:16:35 +03:00
return NULL ;
}
2008-10-09 18:55:56 +04:00
return req - > chain_fsp ;
2006-07-11 22:01:26 +04:00
}
2014-06-11 16:25:07 +04:00
if ( req - > xconn = = NULL ) {
2012-06-08 19:51:47 +04:00
return NULL ;
}
now = timeval_to_nttime ( & req - > request_time ) ;
2014-06-11 16:25:07 +04:00
status = smb1srv_open_lookup ( req - > xconn ,
2012-06-08 19:51:47 +04:00
fid , now , & op ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return NULL ;
}
fsp = op - > compat ;
2012-07-23 14:07:42 +04:00
if ( fsp = = NULL ) {
return NULL ;
2006-07-11 22:01:26 +04:00
}
2012-07-23 14:07:42 +04:00
2020-04-03 09:06:27 +03:00
if ( fsp - > fsp_flags . closing ) {
2020-03-12 01:16:35 +03:00
return NULL ;
}
2012-07-23 14:07:42 +04:00
req - > chain_fsp = fsp ;
2006-07-11 22:01:26 +04:00
return fsp ;
}
2013-01-15 20:23:04 +04:00
struct files_struct * file_fsp_get ( struct smbd_smb2_request * smb2req ,
uint64_t persistent_id ,
uint64_t volatile_id )
2012-06-08 12:11:57 +04:00
{
2012-06-08 19:51:47 +04:00
struct smbXsrv_open * op ;
NTSTATUS status ;
NTTIME now = 0 ;
2012-06-08 12:11:57 +04:00
struct files_struct * fsp ;
2012-06-08 19:51:47 +04:00
now = timeval_to_nttime ( & smb2req - > request_time ) ;
2012-06-08 12:11:57 +04:00
2014-06-11 16:25:07 +04:00
status = smb2srv_open_lookup ( smb2req - > xconn ,
2012-06-08 19:51:47 +04:00
persistent_id , volatile_id ,
now , & op ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-06-08 12:11:57 +04:00
return NULL ;
}
2012-06-13 14:13:01 +04:00
2012-06-08 19:51:47 +04:00
fsp = op - > compat ;
if ( fsp = = NULL ) {
2012-06-13 14:13:01 +04:00
return NULL ;
}
2012-06-08 12:11:57 +04:00
if ( smb2req - > tcon = = NULL ) {
return NULL ;
}
2012-03-27 13:09:05 +04:00
if ( smb2req - > tcon - > compat ! = fsp - > conn ) {
2012-06-08 12:11:57 +04:00
return NULL ;
}
if ( smb2req - > session = = NULL ) {
return NULL ;
}
2019-12-29 16:33:00 +03:00
if ( smb2req - > session - > global - > session_wire_id ! = fsp - > vuid ) {
2012-06-08 12:11:57 +04:00
return NULL ;
}
2020-04-03 09:06:27 +03:00
if ( fsp - > fsp_flags . closing ) {
2020-03-12 01:16:35 +03:00
return NULL ;
}
2013-01-15 20:23:04 +04:00
return fsp ;
}
struct files_struct * file_fsp_smb2 ( struct smbd_smb2_request * smb2req ,
uint64_t persistent_id ,
uint64_t volatile_id )
{
struct files_struct * fsp ;
if ( smb2req - > compat_chain_fsp ! = NULL ) {
2020-04-03 09:06:27 +03:00
if ( smb2req - > compat_chain_fsp - > fsp_flags . closing ) {
2020-03-12 01:16:35 +03:00
return NULL ;
}
2013-01-15 20:23:04 +04:00
return smb2req - > compat_chain_fsp ;
}
fsp = file_fsp_get ( smb2req , persistent_id , volatile_id ) ;
if ( fsp = = NULL ) {
return NULL ;
}
2012-06-08 12:11:57 +04:00
smb2req - > compat_chain_fsp = fsp ;
return fsp ;
}
2005-07-10 20:40:06 +04:00
/****************************************************************************
Duplicate the file handle part for a DOS or FCB open .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-07-25 17:20:04 +03:00
NTSTATUS dup_file_fsp (
struct smb_request * req ,
files_struct * from ,
uint32_t access_mask ,
uint32_t create_options ,
files_struct * to )
2005-07-08 08:51:27 +04:00
{
2012-06-04 20:10:51 +04:00
/* this can never happen for print files */
SMB_ASSERT ( from - > print_file = = NULL ) ;
2009-07-10 21:38:56 +04:00
TALLOC_FREE ( to - > fh ) ;
2008-11-21 23:14:53 +03:00
to - > fh = from - > fh ;
to - > fh - > ref_count + + ;
to - > file_id = from - > file_id ;
to - > initial_allocation_size = from - > initial_allocation_size ;
to - > file_pid = from - > file_pid ;
to - > vuid = from - > vuid ;
to - > open_time = from - > open_time ;
to - > access_mask = access_mask ;
to - > oplock_type = from - > oplock_type ;
2020-04-02 18:09:36 +03:00
to - > fsp_flags . can_lock = from - > fsp_flags . can_lock ;
2020-04-02 18:18:43 +03:00
to - > fsp_flags . can_read = ( ( access_mask & FILE_READ_DATA ) ! = 0 ) ;
2020-04-02 18:28:32 +03:00
to - > fsp_flags . can_write =
2012-06-08 16:26:52 +04:00
CAN_WRITE ( from - > conn ) & &
( ( access_mask & ( FILE_WRITE_DATA | FILE_APPEND_DATA ) ) ! = 0 ) ;
2020-04-02 18:37:02 +03:00
to - > fsp_flags . modified = from - > fsp_flags . modified ;
2020-04-02 19:21:11 +03:00
to - > fsp_flags . is_directory = from - > fsp_flags . is_directory ;
2020-04-03 08:39:34 +03:00
to - > fsp_flags . aio_write_behind = from - > fsp_flags . aio_write_behind ;
2010-04-24 01:26:33 +04:00
2009-07-11 01:50:37 +04:00
return fsp_set_smb_fname ( to , from - > fsp_name ) ;
}
2011-01-26 00:49:01 +03:00
/**
* Return a jenkins hash of a pathname on a connection .
*/
NTSTATUS file_name_hash ( connection_struct * conn ,
const char * name , uint32_t * p_name_hash )
{
2013-12-14 13:45:42 +04:00
char tmpbuf [ PATH_MAX ] ;
2013-12-06 18:34:05 +04:00
char * fullpath , * to_free ;
2014-12-05 16:38:48 +03:00
ssize_t len ;
2015-03-12 18:00:58 +03:00
TDB_DATA key ;
2011-01-26 00:49:01 +03:00
/* Set the hash of the full pathname. */
2013-12-06 18:34:05 +04:00
len = full_path_tos ( conn - > connectpath , name , tmpbuf , sizeof ( tmpbuf ) ,
& fullpath , & to_free ) ;
if ( len = = - 1 ) {
2011-01-26 00:49:01 +03:00
return NT_STATUS_NO_MEMORY ;
}
2015-03-12 18:00:58 +03:00
key = ( TDB_DATA ) { . dptr = ( uint8_t * ) fullpath , . dsize = len + 1 } ;
* p_name_hash = tdb_jenkins_hash ( & key ) ;
2011-01-26 00:49:01 +03:00
DEBUG ( 10 , ( " file_name_hash: %s hash 0x%x \n " ,
2013-12-06 18:34:05 +04:00
fullpath ,
2011-01-26 00:49:01 +03:00
( unsigned int ) * p_name_hash ) ) ;
2013-12-06 18:34:05 +04:00
TALLOC_FREE ( to_free ) ;
2011-01-26 00:49:01 +03:00
return NT_STATUS_OK ;
}
2009-07-11 01:50:37 +04:00
/**
* The only way that the fsp - > fsp_name field should ever be set .
*/
NTSTATUS fsp_set_smb_fname ( struct files_struct * fsp ,
const struct smb_filename * smb_fname_in )
{
struct smb_filename * smb_fname_new ;
2013-04-11 18:26:45 +04:00
smb_fname_new = cp_smb_filename ( fsp , smb_fname_in ) ;
if ( smb_fname_new = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2009-07-11 01:50:37 +04:00
}
TALLOC_FREE ( fsp - > fsp_name ) ;
fsp - > fsp_name = smb_fname_new ;
2011-01-26 00:49:01 +03:00
return file_name_hash ( fsp - > conn ,
smb_fname_str_dbg ( fsp - > fsp_name ) ,
& fsp - > name_hash ) ;
2005-07-08 08:51:27 +04:00
}
2014-11-05 08:46:14 +03:00
2016-06-13 17:12:54 +03:00
size_t fsp_fullbasepath ( struct files_struct * fsp , char * buf , size_t buflen )
{
2019-05-21 16:36:45 +03:00
int len = 0 ;
char tmp_buf [ 1 ] = { ' \0 ' } ;
/*
* Don ' t pass NULL buffer to snprintf ( to satisfy static checker )
* Some callers will call this function with NULL for buf and
* 0 for buflen in order to get length of fullbasepatch ( without
* needing to allocate or write to buf )
*/
if ( buf = = NULL ) {
buf = tmp_buf ;
}
2016-06-13 17:12:54 +03:00
len = snprintf ( buf , buflen , " %s/%s " , fsp - > conn - > connectpath ,
fsp - > fsp_name - > base_name ) ;
SMB_ASSERT ( len > 0 ) ;
return len ;
}