2011-12-29 17:06:33 +04:00
/*
* fs / cifs / smb2inode . c
*
* Copyright ( C ) International Business Machines Corp . , 2002 , 2011
* Etersoft , 2012
* Author ( s ) : Pavel Shilovsky ( pshilovsky @ samba . org ) ,
* Steve French ( sfrench @ us . ibm . com )
*
* This library is free software ; you can redistribute it and / or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation ; either version 2.1 of the License , or
* ( at your option ) any later version .
*
* This library 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 Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/fs.h>
# include <linux/stat.h>
# include <linux/slab.h>
# include <linux/pagemap.h>
# include <asm/div64.h>
# include "cifsfs.h"
# include "cifspdu.h"
# include "cifsglob.h"
# include "cifsproto.h"
# include "cifs_debug.h"
# include "cifs_fs_sb.h"
# include "cifs_unicode.h"
# include "fscache.h"
# include "smb2glob.h"
# include "smb2pdu.h"
# include "smb2proto.h"
2019-03-13 08:02:47 +03:00
static void
free_set_inf_compound ( struct smb_rqst * rqst )
{
if ( rqst [ 1 ] . rq_iov )
SMB2_set_info_free ( & rqst [ 1 ] ) ;
if ( rqst [ 2 ] . rq_iov )
SMB2_close_free ( & rqst [ 2 ] ) ;
}
2018-09-03 06:33:41 +03:00
static int
smb2_compound_op ( const unsigned int xid , struct cifs_tcon * tcon ,
struct cifs_sb_info * cifs_sb , const char * full_path ,
__u32 desired_access , __u32 create_disposition ,
2018-09-03 06:33:45 +03:00
__u32 create_options , void * ptr , int command )
2018-09-03 06:33:41 +03:00
{
int rc ;
__le16 * utf16_path = NULL ;
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE ;
struct cifs_open_parms oparms ;
struct cifs_fid fid ;
struct cifs_ses * ses = tcon - > ses ;
int num_rqst = 0 ;
struct smb_rqst rqst [ 3 ] ;
int resp_buftype [ 3 ] ;
struct kvec rsp_iov [ 3 ] ;
struct kvec open_iov [ SMB2_CREATE_IOV_SIZE ] ;
struct kvec qi_iov [ 1 ] ;
2018-09-03 06:33:50 +03:00
struct kvec si_iov [ SMB2_SET_INFO_IOV_SIZE ] ;
2018-09-03 06:33:41 +03:00
struct kvec close_iov [ 1 ] ;
2018-09-03 06:33:45 +03:00
struct smb2_query_info_rsp * qi_rsp = NULL ;
2018-09-03 06:33:41 +03:00
int flags = 0 ;
2018-09-03 06:33:45 +03:00
__u8 delete_pending [ 8 ] = { 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2018-09-03 06:33:49 +03:00
unsigned int size [ 2 ] ;
void * data [ 2 ] ;
struct smb2_file_rename_info rename_info ;
struct smb2_file_link_info link_info ;
int len ;
2018-09-03 06:33:41 +03:00
if ( smb3_encryption_required ( tcon ) )
flags | = CIFS_TRANSFORM_REQ ;
memset ( rqst , 0 , sizeof ( rqst ) ) ;
resp_buftype [ 0 ] = resp_buftype [ 1 ] = resp_buftype [ 2 ] = CIFS_NO_BUFFER ;
memset ( rsp_iov , 0 , sizeof ( rsp_iov ) ) ;
/* Open */
utf16_path = cifs_convert_path_to_utf16 ( full_path , cifs_sb ) ;
if ( ! utf16_path )
return - ENOMEM ;
oparms . tcon = tcon ;
oparms . desired_access = desired_access ;
oparms . disposition = create_disposition ;
oparms . create_options = create_options ;
2018-08-29 00:14:21 +03:00
if ( backup_cred ( cifs_sb ) )
oparms . create_options | = CREATE_OPEN_BACKUP_INTENT ;
2018-09-03 06:33:41 +03:00
oparms . fid = & fid ;
oparms . reconnect = false ;
memset ( & open_iov , 0 , sizeof ( open_iov ) ) ;
rqst [ num_rqst ] . rq_iov = open_iov ;
rqst [ num_rqst ] . rq_nvec = SMB2_CREATE_IOV_SIZE ;
rc = SMB2_open_init ( tcon , & rqst [ num_rqst ] , & oplock , & oparms ,
utf16_path ) ;
kfree ( utf16_path ) ;
if ( rc )
goto finished ;
2018-12-31 06:43:40 +03:00
smb2_set_next_command ( tcon , & rqst [ num_rqst + + ] ) ;
2018-09-03 06:33:41 +03:00
/* Operation */
switch ( command ) {
case SMB2_OP_QUERY_INFO :
memset ( & qi_iov , 0 , sizeof ( qi_iov ) ) ;
rqst [ num_rqst ] . rq_iov = qi_iov ;
rqst [ num_rqst ] . rq_nvec = 1 ;
rc = SMB2_query_info_init ( tcon , & rqst [ num_rqst ] , COMPOUND_FID ,
COMPOUND_FID , FILE_ALL_INFORMATION ,
SMB2_O_INFO_FILE , 0 ,
sizeof ( struct smb2_file_all_info ) +
2018-10-08 03:19:58 +03:00
PATH_MAX * 2 , 0 , NULL ) ;
2018-12-31 06:43:40 +03:00
smb2_set_next_command ( tcon , & rqst [ num_rqst ] ) ;
2018-09-03 06:33:41 +03:00
smb2_set_related ( & rqst [ num_rqst + + ] ) ;
2019-03-13 08:02:47 +03:00
trace_smb3_query_info_compound_enter ( xid , ses - > Suid , tcon - > tid ,
full_path ) ;
2018-09-03 06:33:41 +03:00
break ;
2018-09-03 06:33:43 +03:00
case SMB2_OP_DELETE :
2019-03-13 08:02:47 +03:00
trace_smb3_delete_enter ( xid , ses - > Suid , tcon - > tid , full_path ) ;
2018-09-03 06:33:43 +03:00
break ;
2018-09-03 06:33:42 +03:00
case SMB2_OP_MKDIR :
/*
* Directories are created through parameters in the
* SMB2_open ( ) call .
*/
2019-03-13 08:02:47 +03:00
trace_smb3_mkdir_enter ( xid , ses - > Suid , tcon - > tid , full_path ) ;
2018-09-03 06:33:42 +03:00
break ;
2018-09-03 06:33:45 +03:00
case SMB2_OP_RMDIR :
memset ( & si_iov , 0 , sizeof ( si_iov ) ) ;
rqst [ num_rqst ] . rq_iov = si_iov ;
rqst [ num_rqst ] . rq_nvec = 1 ;
2018-12-19 02:49:05 +03:00
size [ 0 ] = 1 ; /* sizeof __u8 See MS-FSCC section 2.4.11 */
2018-09-03 06:33:45 +03:00
data [ 0 ] = & delete_pending [ 0 ] ;
rc = SMB2_set_info_init ( tcon , & rqst [ num_rqst ] , COMPOUND_FID ,
COMPOUND_FID , current - > tgid ,
FILE_DISPOSITION_INFORMATION ,
SMB2_O_INFO_FILE , 0 , data , size ) ;
2018-12-31 06:43:40 +03:00
smb2_set_next_command ( tcon , & rqst [ num_rqst ] ) ;
2018-09-03 06:33:45 +03:00
smb2_set_related ( & rqst [ num_rqst + + ] ) ;
2019-03-13 08:02:47 +03:00
trace_smb3_rmdir_enter ( xid , ses - > Suid , tcon - > tid , full_path ) ;
2018-09-03 06:33:45 +03:00
break ;
2018-09-03 06:33:46 +03:00
case SMB2_OP_SET_EOF :
memset ( & si_iov , 0 , sizeof ( si_iov ) ) ;
rqst [ num_rqst ] . rq_iov = si_iov ;
rqst [ num_rqst ] . rq_nvec = 1 ;
size [ 0 ] = 8 ; /* sizeof __le64 */
data [ 0 ] = ptr ;
rc = SMB2_set_info_init ( tcon , & rqst [ num_rqst ] , COMPOUND_FID ,
COMPOUND_FID , current - > tgid ,
FILE_END_OF_FILE_INFORMATION ,
SMB2_O_INFO_FILE , 0 , data , size ) ;
2018-12-31 06:43:40 +03:00
smb2_set_next_command ( tcon , & rqst [ num_rqst ] ) ;
2018-09-03 06:33:46 +03:00
smb2_set_related ( & rqst [ num_rqst + + ] ) ;
2019-03-13 08:02:47 +03:00
trace_smb3_set_eof_enter ( xid , ses - > Suid , tcon - > tid , full_path ) ;
2018-09-03 06:33:46 +03:00
break ;
2018-09-03 06:33:48 +03:00
case SMB2_OP_SET_INFO :
memset ( & si_iov , 0 , sizeof ( si_iov ) ) ;
rqst [ num_rqst ] . rq_iov = si_iov ;
rqst [ num_rqst ] . rq_nvec = 1 ;
2018-09-03 06:33:49 +03:00
2018-09-03 06:33:48 +03:00
size [ 0 ] = sizeof ( FILE_BASIC_INFO ) ;
data [ 0 ] = ptr ;
rc = SMB2_set_info_init ( tcon , & rqst [ num_rqst ] , COMPOUND_FID ,
COMPOUND_FID , current - > tgid ,
FILE_BASIC_INFORMATION ,
SMB2_O_INFO_FILE , 0 , data , size ) ;
2018-12-31 06:43:40 +03:00
smb2_set_next_command ( tcon , & rqst [ num_rqst ] ) ;
2018-09-03 06:33:48 +03:00
smb2_set_related ( & rqst [ num_rqst + + ] ) ;
2019-03-13 08:02:47 +03:00
trace_smb3_set_info_compound_enter ( xid , ses - > Suid , tcon - > tid ,
full_path ) ;
2018-09-03 06:33:48 +03:00
break ;
2018-09-03 06:33:49 +03:00
case SMB2_OP_RENAME :
memset ( & si_iov , 0 , sizeof ( si_iov ) ) ;
rqst [ num_rqst ] . rq_iov = si_iov ;
rqst [ num_rqst ] . rq_nvec = 2 ;
len = ( 2 * UniStrnlen ( ( wchar_t * ) ptr , PATH_MAX ) ) ;
rename_info . ReplaceIfExists = 1 ;
rename_info . RootDirectory = 0 ;
rename_info . FileNameLength = cpu_to_le32 ( len ) ;
size [ 0 ] = sizeof ( struct smb2_file_rename_info ) ;
data [ 0 ] = & rename_info ;
size [ 1 ] = len + 2 /* null */ ;
data [ 1 ] = ( __le16 * ) ptr ;
rc = SMB2_set_info_init ( tcon , & rqst [ num_rqst ] , COMPOUND_FID ,
COMPOUND_FID , current - > tgid ,
FILE_RENAME_INFORMATION ,
SMB2_O_INFO_FILE , 0 , data , size ) ;
2018-12-31 06:43:40 +03:00
smb2_set_next_command ( tcon , & rqst [ num_rqst ] ) ;
2018-09-03 06:33:49 +03:00
smb2_set_related ( & rqst [ num_rqst + + ] ) ;
2019-03-13 08:02:47 +03:00
trace_smb3_rename_enter ( xid , ses - > Suid , tcon - > tid , full_path ) ;
2018-09-03 06:33:49 +03:00
break ;
case SMB2_OP_HARDLINK :
memset ( & si_iov , 0 , sizeof ( si_iov ) ) ;
rqst [ num_rqst ] . rq_iov = si_iov ;
rqst [ num_rqst ] . rq_nvec = 2 ;
len = ( 2 * UniStrnlen ( ( wchar_t * ) ptr , PATH_MAX ) ) ;
link_info . ReplaceIfExists = 0 ;
link_info . RootDirectory = 0 ;
link_info . FileNameLength = cpu_to_le32 ( len ) ;
size [ 0 ] = sizeof ( struct smb2_file_link_info ) ;
data [ 0 ] = & link_info ;
size [ 1 ] = len + 2 /* null */ ;
data [ 1 ] = ( __le16 * ) ptr ;
rc = SMB2_set_info_init ( tcon , & rqst [ num_rqst ] , COMPOUND_FID ,
COMPOUND_FID , current - > tgid ,
FILE_LINK_INFORMATION ,
SMB2_O_INFO_FILE , 0 , data , size ) ;
2018-12-31 06:43:40 +03:00
smb2_set_next_command ( tcon , & rqst [ num_rqst ] ) ;
2018-09-03 06:33:49 +03:00
smb2_set_related ( & rqst [ num_rqst + + ] ) ;
2019-03-13 08:02:47 +03:00
trace_smb3_hardlink_enter ( xid , ses - > Suid , tcon - > tid , full_path ) ;
2018-09-03 06:33:49 +03:00
break ;
2018-09-03 06:33:41 +03:00
default :
cifs_dbg ( VFS , " Invalid command \n " ) ;
rc = - EINVAL ;
}
if ( rc )
goto finished ;
/* Close */
memset ( & close_iov , 0 , sizeof ( close_iov ) ) ;
rqst [ num_rqst ] . rq_iov = close_iov ;
rqst [ num_rqst ] . rq_nvec = 1 ;
rc = SMB2_close_init ( tcon , & rqst [ num_rqst ] , COMPOUND_FID ,
COMPOUND_FID ) ;
smb2_set_related ( & rqst [ num_rqst + + ] ) ;
if ( rc )
goto finished ;
rc = compound_send_recv ( xid , ses , flags , num_rqst , rqst ,
resp_buftype , rsp_iov ) ;
finished :
SMB2_open_free ( & rqst [ 0 ] ) ;
switch ( command ) {
case SMB2_OP_QUERY_INFO :
if ( rc = = 0 ) {
2018-09-03 06:33:45 +03:00
qi_rsp = ( struct smb2_query_info_rsp * )
rsp_iov [ 1 ] . iov_base ;
2018-09-03 06:33:41 +03:00
rc = smb2_validate_and_copy_iov (
2018-09-03 06:33:45 +03:00
le16_to_cpu ( qi_rsp - > OutputBufferOffset ) ,
le32_to_cpu ( qi_rsp - > OutputBufferLength ) ,
2018-09-03 06:33:41 +03:00
& rsp_iov [ 1 ] , sizeof ( struct smb2_file_all_info ) ,
2018-09-03 06:33:45 +03:00
ptr ) ;
2018-09-03 06:33:41 +03:00
}
if ( rqst [ 1 ] . rq_iov )
SMB2_query_info_free ( & rqst [ 1 ] ) ;
if ( rqst [ 2 ] . rq_iov )
SMB2_close_free ( & rqst [ 2 ] ) ;
2019-03-13 08:02:47 +03:00
if ( rc )
trace_smb3_query_info_compound_err ( xid , ses - > Suid ,
tcon - > tid , rc ) ;
else
trace_smb3_query_info_compound_done ( xid , ses - > Suid ,
tcon - > tid ) ;
2018-09-03 06:33:41 +03:00
break ;
2018-09-03 06:33:43 +03:00
case SMB2_OP_DELETE :
2019-03-13 08:02:47 +03:00
if ( rc )
trace_smb3_delete_err ( xid , ses - > Suid , tcon - > tid , rc ) ;
else
trace_smb3_delete_done ( xid , ses - > Suid , tcon - > tid ) ;
if ( rqst [ 1 ] . rq_iov )
SMB2_close_free ( & rqst [ 1 ] ) ;
break ;
2018-09-03 06:33:42 +03:00
case SMB2_OP_MKDIR :
2019-03-13 08:02:47 +03:00
if ( rc )
trace_smb3_mkdir_err ( xid , ses - > Suid , tcon - > tid , rc ) ;
else
trace_smb3_mkdir_done ( xid , ses - > Suid , tcon - > tid ) ;
2018-09-03 06:33:42 +03:00
if ( rqst [ 1 ] . rq_iov )
SMB2_close_free ( & rqst [ 1 ] ) ;
break ;
2018-09-03 06:33:49 +03:00
case SMB2_OP_HARDLINK :
2019-03-13 08:02:47 +03:00
if ( rc )
trace_smb3_hardlink_err ( xid , ses - > Suid , tcon - > tid , rc ) ;
else
trace_smb3_hardlink_done ( xid , ses - > Suid , tcon - > tid ) ;
free_set_inf_compound ( rqst ) ;
break ;
2018-09-03 06:33:49 +03:00
case SMB2_OP_RENAME :
2019-03-13 08:02:47 +03:00
if ( rc )
trace_smb3_rename_err ( xid , ses - > Suid , tcon - > tid , rc ) ;
else
trace_smb3_rename_done ( xid , ses - > Suid , tcon - > tid ) ;
free_set_inf_compound ( rqst ) ;
break ;
2018-09-03 06:33:45 +03:00
case SMB2_OP_RMDIR :
2019-03-13 08:02:47 +03:00
if ( rc )
trace_smb3_rmdir_err ( xid , ses - > Suid , tcon - > tid , rc ) ;
else
trace_smb3_rmdir_done ( xid , ses - > Suid , tcon - > tid ) ;
free_set_inf_compound ( rqst ) ;
break ;
2018-09-03 06:33:48 +03:00
case SMB2_OP_SET_EOF :
2019-03-13 08:02:47 +03:00
if ( rc )
trace_smb3_set_eof_err ( xid , ses - > Suid , tcon - > tid , rc ) ;
else
trace_smb3_set_eof_done ( xid , ses - > Suid , tcon - > tid ) ;
free_set_inf_compound ( rqst ) ;
break ;
2018-09-03 06:33:48 +03:00
case SMB2_OP_SET_INFO :
2019-03-13 08:02:47 +03:00
if ( rc )
trace_smb3_set_info_compound_err ( xid , ses - > Suid ,
tcon - > tid , rc ) ;
else
trace_smb3_set_info_compound_done ( xid , ses - > Suid ,
tcon - > tid ) ;
free_set_inf_compound ( rqst ) ;
2018-09-03 06:33:45 +03:00
break ;
2018-09-03 06:33:41 +03:00
}
free_rsp_buf ( resp_buftype [ 0 ] , rsp_iov [ 0 ] . iov_base ) ;
free_rsp_buf ( resp_buftype [ 1 ] , rsp_iov [ 1 ] . iov_base ) ;
free_rsp_buf ( resp_buftype [ 2 ] , rsp_iov [ 2 ] . iov_base ) ;
return rc ;
}
2012-09-19 03:20:26 +04:00
void
2011-12-29 17:06:33 +04:00
move_smb2_info_to_cifs ( FILE_ALL_INFO * dst , struct smb2_file_all_info * src )
{
memcpy ( dst , src , ( size_t ) ( & src - > CurrentByteOffset ) - ( size_t ) src ) ;
dst - > CurrentByteOffset = src - > CurrentByteOffset ;
dst - > Mode = src - > Mode ;
dst - > AlignmentRequirement = src - > AlignmentRequirement ;
dst - > IndexNumber1 = 0 ; /* we don't use it */
}
int
smb2_query_path_info ( const unsigned int xid , struct cifs_tcon * tcon ,
struct cifs_sb_info * cifs_sb , const char * full_path ,
2013-10-23 17:49:47 +04:00
FILE_ALL_INFO * data , bool * adjust_tz , bool * symlink )
2011-12-29 17:06:33 +04:00
{
int rc ;
struct smb2_file_all_info * smb2_data ;
2018-10-19 08:32:41 +03:00
__u32 create_options = 0 ;
2019-01-16 22:48:42 +03:00
struct cifs_fid fid ;
bool no_cached_open = tcon - > nohandlecache ;
2011-12-29 17:06:33 +04:00
* adjust_tz = false ;
2013-10-23 17:49:47 +04:00
* symlink = false ;
2011-12-29 17:06:33 +04:00
2014-08-22 13:32:11 +04:00
smb2_data = kzalloc ( sizeof ( struct smb2_file_all_info ) + PATH_MAX * 2 ,
2011-12-29 17:06:33 +04:00
GFP_KERNEL ) ;
if ( smb2_data = = NULL )
return - ENOMEM ;
2019-01-16 22:48:42 +03:00
/* If it is a root and its handle is cached then use it */
if ( ! strlen ( full_path ) & & ! no_cached_open ) {
rc = open_shroot ( xid , tcon , & fid ) ;
if ( rc )
goto out ;
2019-03-12 06:58:31 +03:00
if ( tcon - > crfid . file_all_info_is_valid ) {
move_smb2_info_to_cifs ( data ,
& tcon - > crfid . file_all_info ) ;
} else {
rc = SMB2_query_info ( xid , tcon , fid . persistent_fid ,
fid . volatile_fid , smb2_data ) ;
if ( ! rc )
move_smb2_info_to_cifs ( data , smb2_data ) ;
}
2019-01-16 22:48:42 +03:00
close_shroot ( & tcon - > crfid ) ;
goto out ;
}
2018-10-19 08:32:41 +03:00
if ( backup_cred ( cifs_sb ) )
create_options | = CREATE_OPEN_BACKUP_INTENT ;
2011-12-29 17:06:33 +04:00
2018-09-03 06:33:41 +03:00
rc = smb2_compound_op ( xid , tcon , cifs_sb , full_path ,
2018-10-19 08:32:41 +03:00
FILE_READ_ATTRIBUTES , FILE_OPEN , create_options ,
2018-09-03 06:33:41 +03:00
smb2_data , SMB2_OP_QUERY_INFO ) ;
2013-10-23 17:49:47 +04:00
if ( rc = = - EOPNOTSUPP ) {
* symlink = true ;
2018-10-19 08:32:41 +03:00
create_options | = OPEN_REPARSE_POINT ;
2013-10-23 17:49:47 +04:00
/* Failed on a symbolic link - query a reparse point info */
2018-09-03 06:33:41 +03:00
rc = smb2_compound_op ( xid , tcon , cifs_sb , full_path ,
FILE_READ_ATTRIBUTES , FILE_OPEN ,
2018-10-19 08:32:41 +03:00
create_options , smb2_data ,
2018-09-03 06:33:41 +03:00
SMB2_OP_QUERY_INFO ) ;
2013-10-23 17:49:47 +04:00
}
2011-12-29 17:06:33 +04:00
if ( rc )
goto out ;
move_smb2_info_to_cifs ( data , smb2_data ) ;
out :
kfree ( smb2_data ) ;
return rc ;
}
2011-07-19 12:56:37 +04:00
int
smb2_mkdir ( const unsigned int xid , struct cifs_tcon * tcon , const char * name ,
struct cifs_sb_info * cifs_sb )
{
2018-09-03 06:33:42 +03:00
return smb2_compound_op ( xid , tcon , cifs_sb , name ,
FILE_WRITE_ATTRIBUTES , FILE_CREATE ,
CREATE_NOT_FILE , NULL , SMB2_OP_MKDIR ) ;
2011-07-19 12:56:37 +04:00
}
void
smb2_mkdir_setinfo ( struct inode * inode , const char * name ,
struct cifs_sb_info * cifs_sb , struct cifs_tcon * tcon ,
const unsigned int xid )
{
FILE_BASIC_INFO data ;
struct cifsInodeInfo * cifs_i ;
u32 dosattrs ;
int tmprc ;
memset ( & data , 0 , sizeof ( data ) ) ;
cifs_i = CIFS_I ( inode ) ;
dosattrs = cifs_i - > cifsAttrs | ATTR_READONLY ;
data . Attributes = cpu_to_le32 ( dosattrs ) ;
2018-09-03 06:33:48 +03:00
tmprc = smb2_compound_op ( xid , tcon , cifs_sb , name ,
FILE_WRITE_ATTRIBUTES , FILE_CREATE ,
CREATE_NOT_FILE , & data , SMB2_OP_SET_INFO ) ;
2011-07-19 12:56:37 +04:00
if ( tmprc = = 0 )
cifs_i - > cifsAttrs = dosattrs ;
}
2012-07-10 16:14:38 +04:00
int
smb2_rmdir ( const unsigned int xid , struct cifs_tcon * tcon , const char * name ,
struct cifs_sb_info * cifs_sb )
{
2018-09-03 06:33:45 +03:00
return smb2_compound_op ( xid , tcon , cifs_sb , name , DELETE , FILE_OPEN ,
CREATE_NOT_FILE ,
NULL , SMB2_OP_RMDIR ) ;
2012-07-10 16:14:38 +04:00
}
2012-09-19 03:20:25 +04:00
int
smb2_unlink ( const unsigned int xid , struct cifs_tcon * tcon , const char * name ,
struct cifs_sb_info * cifs_sb )
{
2018-09-03 06:33:43 +03:00
return smb2_compound_op ( xid , tcon , cifs_sb , name , DELETE , FILE_OPEN ,
CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT ,
NULL , SMB2_OP_DELETE ) ;
2012-09-19 03:20:25 +04:00
}
2012-09-19 03:20:31 +04:00
2012-09-19 03:20:31 +04:00
static int
smb2_set_path_attr ( const unsigned int xid , struct cifs_tcon * tcon ,
const char * from_name , const char * to_name ,
struct cifs_sb_info * cifs_sb , __u32 access , int command )
2012-09-19 03:20:31 +04:00
{
__le16 * smb2_to_name = NULL ;
int rc ;
smb2_to_name = cifs_convert_path_to_utf16 ( to_name , cifs_sb ) ;
if ( smb2_to_name = = NULL ) {
rc = - ENOMEM ;
goto smb2_rename_path ;
}
2018-09-03 06:33:49 +03:00
rc = smb2_compound_op ( xid , tcon , cifs_sb , from_name , access ,
FILE_OPEN , 0 , smb2_to_name , command ) ;
2012-09-19 03:20:31 +04:00
smb2_rename_path :
kfree ( smb2_to_name ) ;
return rc ;
}
2012-09-19 03:20:31 +04:00
int
smb2_rename_path ( const unsigned int xid , struct cifs_tcon * tcon ,
const char * from_name , const char * to_name ,
struct cifs_sb_info * cifs_sb )
{
return smb2_set_path_attr ( xid , tcon , from_name , to_name , cifs_sb ,
DELETE , SMB2_OP_RENAME ) ;
}
int
smb2_create_hardlink ( const unsigned int xid , struct cifs_tcon * tcon ,
const char * from_name , const char * to_name ,
struct cifs_sb_info * cifs_sb )
{
return smb2_set_path_attr ( xid , tcon , from_name , to_name , cifs_sb ,
FILE_READ_ATTRIBUTES , SMB2_OP_HARDLINK ) ;
}
2012-09-19 03:20:32 +04:00
int
smb2_set_path_size ( const unsigned int xid , struct cifs_tcon * tcon ,
const char * full_path , __u64 size ,
struct cifs_sb_info * cifs_sb , bool set_alloc )
{
__le64 eof = cpu_to_le64 ( size ) ;
2018-09-03 06:33:46 +03:00
return smb2_compound_op ( xid , tcon , cifs_sb , full_path ,
FILE_WRITE_DATA , FILE_OPEN , 0 , & eof ,
SMB2_OP_SET_EOF ) ;
2012-09-19 03:20:32 +04:00
}
2012-09-19 03:20:32 +04:00
int
smb2_set_file_info ( struct inode * inode , const char * full_path ,
FILE_BASIC_INFO * buf , const unsigned int xid )
{
struct cifs_sb_info * cifs_sb = CIFS_SB ( inode - > i_sb ) ;
struct tcon_link * tlink ;
int rc ;
2016-09-26 22:23:08 +03:00
if ( ( buf - > CreationTime = = 0 ) & & ( buf - > LastAccessTime = = 0 ) & &
2018-08-03 04:28:18 +03:00
( buf - > LastWriteTime = = 0 ) & & ( buf - > ChangeTime = = 0 ) & &
2016-09-26 22:23:08 +03:00
( buf - > Attributes = = 0 ) )
return 0 ; /* would be a no op, no sense sending this */
2012-09-19 03:20:32 +04:00
tlink = cifs_sb_tlink ( cifs_sb ) ;
if ( IS_ERR ( tlink ) )
return PTR_ERR ( tlink ) ;
2016-09-26 22:23:08 +03:00
2018-09-03 06:33:48 +03:00
rc = smb2_compound_op ( xid , tlink_tcon ( tlink ) , cifs_sb , full_path ,
FILE_WRITE_ATTRIBUTES , FILE_OPEN , 0 , buf ,
SMB2_OP_SET_INFO ) ;
2012-09-19 03:20:32 +04:00
cifs_put_tlink ( tlink ) ;
return rc ;
}