2010-03-08 14:59:40 +03:00
/*
* Copyright ( c ) Björn Jacke 2010
*
* 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
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* 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 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-02-26 02:56:46 +03:00
# include "transfer_file.h"
2011-04-14 02:36:23 +04:00
# include "smbprofile.h"
2010-03-08 14:59:40 +03:00
# define MODULE "crossrename"
2012-04-05 08:53:08 +04:00
static off_t module_sizelimit ;
2010-03-08 14:59:40 +03:00
static int crossrename_connect (
struct vfs_handle_struct * handle ,
const char * service ,
const char * user )
{
int ret = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( ret < 0 ) {
return ret ;
}
2012-04-05 08:53:08 +04:00
module_sizelimit = ( off_t ) lp_parm_int ( SNUM ( handle - > conn ) ,
2010-03-08 14:59:40 +03:00
MODULE , " sizelimit " , 20 ) ;
/* convert from MiB to byte: */
module_sizelimit * = 1048576 ;
return 0 ;
}
/*********************************************************
For rename across filesystems initial Patch from Warren Birnbaum
< warrenb @ hpcvscdp . cv . hp . com >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-06-17 07:01:33 +03:00
static NTSTATUS copy_reg ( vfs_handle_struct * handle ,
struct files_struct * srcfsp ,
const struct smb_filename * source ,
struct files_struct * dstfsp ,
const struct smb_filename * dest )
2010-03-08 14:59:40 +03:00
{
2021-06-17 07:01:33 +03:00
NTSTATUS status ;
struct smb_filename * full_fname_src = NULL ;
struct smb_filename * full_fname_dst = NULL ;
int ret ;
2010-03-08 14:59:40 +03:00
2021-06-17 07:01:33 +03:00
if ( ! VALID_STAT ( source - > st ) ) {
status = NT_STATUS_OBJECT_PATH_NOT_FOUND ;
goto out ;
}
if ( ! S_ISREG ( source - > st . st_ex_mode ) ) {
status = NT_STATUS_OBJECT_PATH_NOT_FOUND ;
goto out ;
2013-02-20 13:45:06 +04:00
}
2010-03-08 14:59:40 +03:00
2021-06-17 07:01:33 +03:00
if ( source - > st . st_ex_size > module_sizelimit ) {
DBG_INFO ( " %s: size of %s larger than sizelimit (%lld > %lld), "
" rename prohibited \n " ,
MODULE ,
source - > base_name ,
( long long ) source - > st . st_ex_size ,
( long long ) module_sizelimit ) ;
status = NT_STATUS_INVALID_PARAMETER ;
goto out ;
}
2010-03-08 14:59:40 +03:00
2021-06-17 07:01:33 +03:00
full_fname_src = full_path_from_dirfsp_atname ( talloc_tos ( ) ,
srcfsp ,
source ) ;
2022-01-07 15:16:26 +03:00
if ( full_fname_src = = NULL ) {
2021-06-17 07:01:33 +03:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
full_fname_dst = full_path_from_dirfsp_atname ( talloc_tos ( ) ,
dstfsp ,
dest ) ;
if ( full_fname_dst = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2010-03-08 14:59:40 +03:00
2021-06-17 07:01:33 +03:00
ret = SMB_VFS_NEXT_UNLINKAT ( handle ,
dstfsp ,
dest ,
0 ) ;
if ( ret = = - 1 ) {
status = map_nt_error_from_unix ( errno ) ;
goto out ;
}
2010-03-08 14:59:40 +03:00
/*
2021-06-17 07:01:33 +03:00
* copy_internals ( ) takes attribute values from the NTrename call .
*
* From MS - CIFS :
*
* " If the attribute is 0x0000, then only normal files are renamed.
* If the system file or hidden attributes are specified , then the
* rename is inclusive of both special types . "
2010-03-08 14:59:40 +03:00
*/
2021-06-17 07:01:33 +03:00
status = copy_internals ( talloc_tos ( ) ,
handle - > conn ,
NULL ,
2022-07-28 21:49:35 +03:00
srcfsp , /* src_dirfsp */
2021-06-17 07:01:33 +03:00
full_fname_src ,
2022-07-28 21:49:35 +03:00
dstfsp , /* dst_dirfsp */
2021-06-17 07:01:33 +03:00
full_fname_dst ,
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto out ;
2010-03-08 14:59:40 +03:00
}
2021-06-17 07:01:33 +03:00
ret = SMB_VFS_NEXT_UNLINKAT ( handle ,
srcfsp ,
source ,
0 ) ;
if ( ret = = - 1 ) {
status = map_nt_error_from_unix ( errno ) ;
goto out ;
2010-03-08 14:59:40 +03:00
}
2021-06-17 07:01:33 +03:00
out :
2010-03-08 14:59:40 +03:00
2021-06-17 07:01:33 +03:00
TALLOC_FREE ( full_fname_src ) ;
TALLOC_FREE ( full_fname_dst ) ;
return status ;
2010-03-08 14:59:40 +03:00
}
2019-08-10 00:16:12 +03:00
static int crossrename_renameat ( vfs_handle_struct * handle ,
files_struct * srcfsp ,
const struct smb_filename * smb_fname_src ,
files_struct * dstfsp ,
2024-08-06 14:21:34 +03:00
const struct smb_filename * smb_fname_dst ,
const struct vfs_rename_how * how )
2019-08-10 00:16:12 +03:00
{
int result = - 1 ;
START_PROFILE ( syscall_renameat ) ;
if ( smb_fname_src - > stream_name | | smb_fname_dst - > stream_name ) {
errno = ENOENT ;
goto out ;
}
2021-06-17 07:01:33 +03:00
result = SMB_VFS_NEXT_RENAMEAT ( handle ,
srcfsp ,
smb_fname_src ,
dstfsp ,
2024-08-06 14:21:34 +03:00
smb_fname_dst ,
how ) ;
2021-06-17 07:01:33 +03:00
2019-08-10 00:16:12 +03:00
if ( ( result = = - 1 ) & & ( errno = = EXDEV ) ) {
/* Rename across filesystems needed. */
2021-06-17 07:01:33 +03:00
NTSTATUS status = copy_reg ( handle ,
srcfsp ,
smb_fname_src ,
dstfsp ,
smb_fname_dst ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
result = - 1 ;
}
2019-08-10 00:16:12 +03:00
}
out :
END_PROFILE ( syscall_renameat ) ;
return result ;
}
2010-03-08 14:59:40 +03:00
static struct vfs_fn_pointers vfs_crossrename_fns = {
. connect_fn = crossrename_connect ,
2019-08-10 00:16:12 +03:00
. renameat_fn = crossrename_renameat
2010-03-08 14:59:40 +03:00
} ;
2017-12-16 01:32:12 +03:00
static_decl_vfs ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_crossrename_init ( TALLOC_CTX * ctx )
2010-03-08 14:59:40 +03:00
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , MODULE ,
& vfs_crossrename_fns ) ;
}