2013-06-21 19:56:08 +04:00
/*
2008-02-28 19:23:20 +03:00
Unix SMB / Netbios implementation .
SMB client library implementation
Copyright ( C ) Andrew Tridgell 1998
Copyright ( C ) Richard Sharpe 2000 , 2002
Copyright ( C ) John Terpstra 2000
2013-06-21 19:56:08 +04:00
Copyright ( C ) Tom Jansen ( Ninja ISD ) 2002
2008-02-28 19:23:20 +03:00
Copyright ( C ) Derrell Lipman 2003 - 2008
Copyright ( C ) Jeremy Allison 2007 , 2008
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03: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
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03: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 .
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
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-05-06 13:47:43 +04:00
# include "libsmb/libsmb.h"
2008-02-28 19:23:20 +03:00
# include "libsmbclient.h"
# include "libsmb_internal.h"
2012-05-19 20:23:40 +04:00
# include "../libcli/smb/smbXcli_base.h"
2008-02-28 19:23:20 +03:00
/*
* Routine to open ( ) a file . . .
*/
SMBCFILE *
SMBC_open_ctx ( SMBCCTX * context ,
const char * fname ,
int flags ,
mode_t mode )
{
2008-03-02 04:44:21 +03:00
char * server = NULL ;
char * share = NULL ;
char * user = NULL ;
char * password = NULL ;
char * workgroup = NULL ;
2008-02-28 19:23:20 +03:00
char * path = NULL ;
char * targetpath = NULL ;
struct cli_state * targetcli = NULL ;
SMBCSRV * srv = NULL ;
SMBCFILE * file = NULL ;
2009-05-01 02:26:43 +04:00
uint16_t fd ;
2013-04-16 23:09:41 +04:00
uint16_t port = 0 ;
2009-05-01 02:26:43 +04:00
NTSTATUS status = NT_STATUS_OBJECT_PATH_INVALID ;
2008-02-28 19:23:20 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ; /* Best I can think of ... */
TALLOC_FREE ( frame ) ;
return NULL ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( ! fname ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( SMBC_parse_path ( frame ,
2008-03-02 04:44:21 +03:00
context ,
fname ,
& workgroup ,
& server ,
2013-04-16 23:09:41 +04:00
& port ,
2008-03-02 04:44:21 +03:00
& share ,
& path ,
& user ,
& password ,
NULL ) ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( ! user | | user [ 0 ] = = ( char ) 0 ) {
2008-03-04 02:13:33 +03:00
user = talloc_strdup ( frame , smbc_getUser ( context ) ) ;
2008-02-28 19:23:20 +03:00
if ( ! user ) {
errno = ENOMEM ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
srv = SMBC_server ( frame , context , True ,
2013-04-17 01:11:08 +04:00
server , port , share , & workgroup , & user , & password ) ;
2008-02-28 19:23:20 +03:00
if ( ! srv ) {
if ( errno = = EPERM ) errno = EACCES ;
TALLOC_FREE ( frame ) ;
return NULL ; /* SMBC_server sets errno */
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Hmmm, the test for a directory is suspect here ... FIXME */
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( strlen ( path ) > 0 & & path [ strlen ( path ) - 1 ] = = ' \\ ' ) {
2009-05-01 02:26:43 +04:00
status = NT_STATUS_OBJECT_PATH_INVALID ;
2008-02-28 19:23:20 +03:00
} else {
file = SMB_MALLOC_P ( SMBCFILE ) ;
if ( ! file ) {
errno = ENOMEM ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
ZERO_STRUCTP ( file ) ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>open: resolving %s\n", path);*/
2011-07-03 22:53:55 +04:00
status = cli_resolve_path (
frame , " " , context - > internal - > auth_info ,
srv - > cli , path , & targetcli , & targetpath ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 19:23:20 +03:00
d_printf ( " Could not resolve %s \n " , path ) ;
2009-03-28 01:02:46 +03:00
errno = ENOENT ;
2008-02-28 19:23:20 +03:00
SAFE_FREE ( file ) ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
/*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/
2009-11-22 00:52:12 +03:00
2020-03-10 21:51:09 +03:00
status = cli_open ( targetcli , targetpath , flags ,
context - > internal - > share_mode , & fd ) ;
2009-05-01 02:26:43 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Handle the error ... */
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
SAFE_FREE ( file ) ;
errno = SMBC_errno ( context , targetcli ) ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Fill in file struct */
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
file - > cli_fd = fd ;
file - > fname = SMB_STRDUP ( fname ) ;
file - > srv = srv ;
file - > offset = 0 ;
file - > file = True ;
2015-05-28 21:07:41 +03:00
/*
* targetcli is either equal to srv - > cli or
* is a subsidiary DFS connection . Either way
* file - > cli_fd belongs to it so we must cache
* it for read / write / close , not re - resolve each time .
* Re - resolving is both slow and incorrect .
*/
file - > targetcli = targetcli ;
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
DLIST_ADD ( context - > internal - > files , file ) ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/*
* If the file was opened in O_APPEND mode , all write
* operations should be appended to the file . To do that ,
* though , using this protocol , would require a getattrE ( )
* call for each and every write , to determine where the end
* of the file is . ( There does not appear to be an append flag
* in the protocol . ) Rather than add all of that overhead of
* retrieving the current end - of - file offset prior to each
* write operation , we ' ll assume that most append operations
* will continuously write , so we ' ll just set the offset to
* the end of the file now and hope that ' s adequate .
*
* Note to self : If this proves inadequate , and O_APPEND
* should , in some cases , be forced for each write , add a
* field in the context options structure , for
* " strict_append_mode " which would select between the current
* behavior ( if FALSE ) or issuing a getattrE ( ) prior to each
* write and forcing the write to the end of the file ( if
* TRUE ) . Adding that capability will likely require adding
* an " append " flag into the _SMBCFILE structure to track
* whether a file was opened in O_APPEND mode . - - djl
*/
if ( flags & O_APPEND ) {
if ( SMBC_lseek_ctx ( context , file , 0 , SEEK_END ) < 0 ) {
( void ) SMBC_close_ctx ( context , file ) ;
errno = ENXIO ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return file ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Check if opendir needed ... */
2009-11-22 00:52:12 +03:00
2009-05-01 02:26:43 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 19:23:20 +03:00
int eno = 0 ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
eno = SMBC_errno ( context , srv - > cli ) ;
2008-03-04 02:13:33 +03:00
file = smbc_getFunctionOpendir ( context ) ( context , fname ) ;
2008-02-28 19:23:20 +03:00
if ( ! file ) errno = eno ;
TALLOC_FREE ( frame ) ;
return file ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ; /* FIXME, correct errno ? */
TALLOC_FREE ( frame ) ;
return NULL ;
}
/*
2013-06-21 19:56:08 +04:00
* Routine to create a file
2008-02-28 19:23:20 +03:00
*/
SMBCFILE *
SMBC_creat_ctx ( SMBCCTX * context ,
const char * path ,
mode_t mode )
{
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
return NULL ;
}
2009-11-22 00:52:12 +03:00
2008-03-02 04:44:21 +03:00
return SMBC_open_ctx ( context , path ,
O_WRONLY | O_CREAT | O_TRUNC , mode ) ;
2008-02-28 19:23:20 +03:00
}
/*
* Routine to read ( ) a file . . .
*/
ssize_t
SMBC_read_ctx ( SMBCCTX * context ,
SMBCFILE * file ,
void * buf ,
size_t count )
{
2011-07-22 16:22:29 +04:00
size_t ret ;
2008-02-28 19:23:20 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2011-07-03 22:53:55 +04:00
NTSTATUS status ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/*
* offset :
*
* Compiler bug ( possibly ) - - gcc ( GCC ) 3.3 .5 ( Debian 1 : 3.3 .5 - 2 ) - -
* appears to pass file - > offset ( which is type off_t ) differently than
* a local variable of type off_t . Using local variable " offset " in
* the call to cli_read ( ) instead of file - > offset fixes a problem
* retrieving data at an offset greater than 4 GB .
*/
off_t offset ;
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2020-02-22 13:52:51 +03:00
DEBUG ( 4 , ( " smbc_read(%p, %zu) \n " , file , count ) ) ;
2009-11-22 00:52:12 +03:00
2020-02-22 00:35:44 +03:00
if ( ! SMBC_dlist_contains ( context - > internal - > files , file ) ) {
2008-02-28 19:23:20 +03:00
errno = EBADF ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
offset = file - > offset ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Check that the buffer exists ... */
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( buf = = NULL ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2015-05-28 21:07:41 +03:00
status = cli_read ( file - > targetcli , file - > cli_fd , ( char * ) buf , offset ,
2011-07-22 16:22:29 +04:00
count , & ret ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2015-05-28 21:07:41 +03:00
errno = SMBC_errno ( context , file - > targetcli ) ;
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
file - > offset + = ret ;
2009-11-22 00:52:12 +03:00
2020-02-22 13:52:51 +03:00
DEBUG ( 4 , ( " --> %zu \n " , ret ) ) ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return ret ; /* Success, ret bytes of data ... */
}
2015-05-28 01:13:15 +03:00
off_t
SMBC_splice_ctx ( SMBCCTX * context ,
SMBCFILE * srcfile ,
SMBCFILE * dstfile ,
off_t count ,
int ( * splice_cb ) ( off_t n , void * priv ) ,
void * priv )
{
2018-07-06 21:46:44 +03:00
off_t written = 0 ;
2015-05-28 01:13:15 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
NTSTATUS status ;
if ( ! context | | ! context - > internal - > initialized ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2020-02-22 00:35:44 +03:00
if ( ! SMBC_dlist_contains ( context - > internal - > files , srcfile ) ) {
2015-05-28 01:13:15 +03:00
errno = EBADF ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2020-02-22 00:35:44 +03:00
if ( ! SMBC_dlist_contains ( context - > internal - > files , dstfile ) ) {
2015-05-28 01:13:15 +03:00
errno = EBADF ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2015-06-08 20:07:49 +03:00
status = cli_splice ( srcfile - > targetcli , dstfile - > targetcli ,
2015-05-28 01:13:15 +03:00
srcfile - > cli_fd , dstfile - > cli_fd ,
count , srcfile - > offset , dstfile - > offset , & written ,
splice_cb , priv ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2015-06-08 20:07:49 +03:00
errno = SMBC_errno ( context , srcfile - > targetcli ) ;
2015-05-28 01:13:15 +03:00
TALLOC_FREE ( frame ) ;
return - 1 ;
}
srcfile - > offset + = written ;
dstfile - > offset + = written ;
TALLOC_FREE ( frame ) ;
return written ;
}
2008-02-28 19:23:20 +03:00
/*
* Routine to write ( ) a file . . .
*/
ssize_t
SMBC_write_ctx ( SMBCCTX * context ,
SMBCFILE * file ,
2008-07-16 14:05:52 +04:00
const void * buf ,
2008-02-28 19:23:20 +03:00
size_t count )
{
off_t offset ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2011-04-02 13:46:30 +04:00
NTSTATUS status ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* First check all pointers before dereferencing them */
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2020-02-22 00:35:44 +03:00
if ( ! SMBC_dlist_contains ( context - > internal - > files , file ) ) {
2008-02-28 19:23:20 +03:00
errno = EBADF ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Check that the buffer exists ... */
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( buf = = NULL ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
offset = file - > offset ; /* See "offset" comment in SMBC_read_ctx() */
2009-11-22 00:52:12 +03:00
2015-05-28 21:07:41 +03:00
status = cli_writeall ( file - > targetcli , file - > cli_fd ,
2011-05-05 21:41:59 +04:00
0 , ( const uint8_t * ) buf , offset , count , NULL ) ;
2011-04-02 13:46:30 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2011-04-02 13:46:30 +04:00
file - > offset + = count ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
2011-04-02 13:46:30 +04:00
return count ; /* Success, 0 bytes of data ... */
2008-02-28 19:23:20 +03:00
}
/*
* Routine to close ( ) a file . . .
*/
int
SMBC_close_ctx ( SMBCCTX * context ,
SMBCFILE * file )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2020-02-22 00:35:44 +03:00
if ( ! SMBC_dlist_contains ( context - > internal - > files , file ) ) {
2008-02-28 19:23:20 +03:00
errno = EBADF ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* IS a dir ... */
if ( ! file - > file ) {
TALLOC_FREE ( frame ) ;
2008-03-04 02:13:33 +03:00
return smbc_getFunctionClosedir ( context ) ( context , file ) ;
2008-02-28 19:23:20 +03:00
}
2009-11-22 00:52:12 +03:00
2015-05-28 21:07:41 +03:00
if ( ! NT_STATUS_IS_OK ( cli_close ( file - > targetcli , file - > cli_fd ) ) ) {
SMBCSRV * srv ;
2013-06-21 19:56:08 +04:00
DEBUG ( 3 , ( " cli_close failed on %s. purging server. \n " ,
2008-02-28 19:23:20 +03:00
file - > fname ) ) ;
2013-06-21 19:56:08 +04:00
/* Deallocate slot and remove the server
2008-02-28 19:23:20 +03:00
* from the server cache if unused */
2015-05-28 21:07:41 +03:00
errno = SMBC_errno ( context , file - > targetcli ) ;
2008-02-28 19:23:20 +03:00
srv = file - > srv ;
2008-02-29 21:34:35 +03:00
DLIST_REMOVE ( context - > internal - > files , file ) ;
2008-02-28 19:23:20 +03:00
SAFE_FREE ( file - > fname ) ;
SAFE_FREE ( file ) ;
2008-03-04 02:13:33 +03:00
smbc_getFunctionRemoveUnusedServer ( context ) ( context , srv ) ;
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
DLIST_REMOVE ( context - > internal - > files , file ) ;
2008-02-28 19:23:20 +03:00
SAFE_FREE ( file - > fname ) ;
SAFE_FREE ( file ) ;
TALLOC_FREE ( frame ) ;
return 0 ;
}
/*
* Get info from an SMB server on a file . Use a qpathinfo call first
* and if that fails , use getatr , as Win95 sometimes refuses qpathinfo
*/
bool
SMBC_getatr ( SMBCCTX * context ,
SMBCSRV * srv ,
2011-05-06 00:42:05 +04:00
const char * path ,
2019-11-25 13:09:52 +03:00
struct stat * sb )
2008-02-28 19:23:20 +03:00
{
char * fixedpath = NULL ;
char * targetpath = NULL ;
struct cli_state * targetcli = NULL ;
2020-06-03 23:15:17 +03:00
uint32_t attr = 0 ;
2019-11-25 13:09:52 +03:00
off_t size = 0 ;
struct timespec create_time_ts = { 0 } ;
struct timespec access_time_ts = { 0 } ;
struct timespec write_time_ts = { 0 } ;
struct timespec change_time_ts = { 0 } ;
time_t write_time = 0 ;
SMB_INO_T ino = 0 ;
2008-02-28 19:23:20 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2011-07-03 22:53:55 +04:00
NTSTATUS status ;
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
2008-10-24 18:26:56 +04:00
return False ;
2008-02-28 19:23:20 +03:00
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* path fixup for . and .. */
2020-02-22 13:48:45 +03:00
if ( ISDOT ( path ) | | ISDOTDOT ( path ) ) {
2008-02-28 19:23:20 +03:00
fixedpath = talloc_strdup ( frame , " \\ " ) ;
if ( ! fixedpath ) {
errno = ENOMEM ;
TALLOC_FREE ( frame ) ;
2008-10-24 18:26:56 +04:00
return False ;
2008-02-28 19:23:20 +03:00
}
} else {
fixedpath = talloc_strdup ( frame , path ) ;
if ( ! fixedpath ) {
errno = ENOMEM ;
TALLOC_FREE ( frame ) ;
2008-10-24 18:26:56 +04:00
return False ;
2008-02-28 19:23:20 +03:00
}
trim_string ( fixedpath , NULL , " \\ .. " ) ;
trim_string ( fixedpath , NULL , " \\ . " ) ;
}
DEBUG ( 4 , ( " SMBC_getatr: sending qpathinfo \n " ) ) ;
2009-11-22 00:52:12 +03:00
2011-07-03 22:53:55 +04:00
status = cli_resolve_path ( frame , " " , context - > internal - > auth_info ,
srv - > cli , fixedpath ,
& targetcli , & targetpath ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 19:23:20 +03:00
d_printf ( " Couldn't resolve %s \n " , path ) ;
2009-03-28 01:02:46 +03:00
errno = ENOENT ;
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return False ;
}
2009-11-22 00:52:12 +03:00
2019-11-25 13:09:52 +03:00
if ( ! srv - > no_pathinfo2 ) {
status = cli_qpathinfo2 ( targetcli ,
targetpath ,
& create_time_ts ,
& access_time_ts ,
& write_time_ts ,
& change_time_ts ,
& size ,
2020-06-03 23:28:04 +03:00
& attr ,
2019-11-25 13:09:52 +03:00
& ino ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
goto setup_stat ;
}
2008-02-28 19:23:20 +03:00
}
2009-11-22 00:52:12 +03:00
2013-10-11 12:59:59 +04:00
srv - > no_pathinfo2 = True ;
2019-11-25 13:09:52 +03:00
if ( ! srv - > no_pathinfo3 ) {
status = cli_qpathinfo3 ( targetcli ,
targetpath ,
& create_time_ts ,
& access_time_ts ,
& write_time_ts ,
& change_time_ts ,
& size ,
2020-06-03 23:36:05 +03:00
& attr ,
2019-11-25 13:09:52 +03:00
& ino ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
goto setup_stat ;
}
2013-10-11 13:02:24 +04:00
}
srv - > no_pathinfo3 = True ;
2008-02-28 19:23:20 +03:00
/* if this is NT then don't bother with the getatr */
2012-05-19 20:23:40 +04:00
if ( smb1cli_conn_capabilities ( targetcli - > conn ) & CAP_NT_SMBS ) {
2013-10-18 17:32:55 +04:00
goto all_failed ;
2008-02-28 19:23:20 +03:00
}
2009-11-22 00:52:12 +03:00
2020-06-03 23:15:17 +03:00
status = cli_getatr ( targetcli , targetpath , & attr , & size , & write_time ) ;
2019-11-25 13:09:52 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
struct timespec w_time_ts =
convert_time_t_to_timespec ( write_time ) ;
2009-11-22 00:52:12 +03:00
2019-11-25 13:09:52 +03:00
access_time_ts = change_time_ts = write_time_ts = w_time_ts ;
goto setup_stat ;
2008-02-28 19:23:20 +03:00
}
2009-11-22 00:52:12 +03:00
2019-11-25 13:09:52 +03:00
setup_stat :
setup_stat ( sb ,
path ,
size ,
2020-06-03 23:36:05 +03:00
attr ,
2019-11-25 13:09:52 +03:00
ino ,
srv - > dev ,
access_time_ts ,
change_time_ts ,
write_time_ts ) ;
TALLOC_FREE ( frame ) ;
return true ;
2013-10-18 17:32:55 +04:00
all_failed :
srv - > no_pathinfo2 = False ;
srv - > no_pathinfo3 = False ;
2008-02-28 19:23:20 +03:00
errno = EPERM ;
TALLOC_FREE ( frame ) ;
return False ;
}
/*
* Set file info on an SMB server . Use setpathinfo call first . If that
* fails , use setattrE . .
*
* Access and modification time parameters are always used and must be
* provided . Create time , if zero , will be determined from the actual create
* time of the file . If non - zero , the create time will be set as well .
*
2020-06-03 23:07:41 +03:00
* " attr " ( attributes ) parameter may be set to - 1 if it is not to be set .
2008-02-28 19:23:20 +03:00
*/
bool
2013-06-21 19:56:08 +04:00
SMBC_setatr ( SMBCCTX * context , SMBCSRV * srv , char * path ,
2020-03-26 14:29:13 +03:00
struct timespec create_time ,
struct timespec access_time ,
struct timespec write_time ,
struct timespec change_time ,
2020-06-03 23:07:41 +03:00
uint16_t attr )
2008-02-28 19:23:20 +03:00
{
2009-05-01 02:26:43 +04:00
uint16_t fd ;
2008-02-28 19:23:20 +03:00
int ret ;
2020-06-04 06:48:23 +03:00
uint32_t lattr = ( uint32_t ) attr ;
2008-02-28 19:23:20 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2009-11-22 00:52:12 +03:00
2020-06-04 06:48:23 +03:00
if ( attr = = ( uint16_t ) - 1 ) {
/*
* External ABI only passes in
* 16 - bits of attribute . Make
* sure we correctly map to
* ( uint32_t ) - 1 meaning don ' t
* change attributes if attr was
* passed in as 16 - bit - 1.
*/
lattr = ( uint32_t ) - 1 ;
}
2008-02-28 19:23:20 +03:00
/*
* First , try setpathinfo ( if qpathinfo succeeded ) , for it is the
* modern function for " new code " to be using , and it works given a
* filename rather than requiring that the file be opened to have its
* attributes manipulated .
*/
if ( srv - > no_pathinfo | |
2020-03-26 16:42:39 +03:00
! NT_STATUS_IS_OK ( cli_setpathinfo_ext ( srv - > cli , path ,
create_time ,
access_time ,
write_time ,
change_time ,
2020-06-04 06:48:23 +03:00
lattr ) ) ) {
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/*
2013-06-21 19:56:08 +04:00
* setpathinfo is not supported ; go to plan B .
2008-02-28 19:23:20 +03:00
*
* cli_setatr ( ) does not work on win98 , and it also doesn ' t
* support setting the access time ( only the modification
* time ) , so in all cases , we open the specified file and use
* cli_setattrE ( ) which should work on all OS versions , and
* supports both times .
*/
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Don't try {q,set}pathinfo() again, with this server */
srv - > no_pathinfo = True ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Open the file */
2011-12-04 09:36:47 +04:00
if ( ! NT_STATUS_IS_OK ( cli_open ( srv - > cli , path , O_RDWR , DENY_NONE , & fd ) ) ) {
2008-02-28 19:23:20 +03:00
errno = SMBC_errno ( context , srv - > cli ) ;
TALLOC_FREE ( frame ) ;
2019-05-16 22:03:42 +03:00
return False ;
2008-02-28 19:23:20 +03:00
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Set the new attributes */
2009-05-07 02:07:05 +04:00
ret = NT_STATUS_IS_OK ( cli_setattrE ( srv - > cli , fd ,
2020-03-26 14:29:13 +03:00
change_time . tv_sec ,
access_time . tv_sec ,
write_time . tv_sec ) ) ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/* Close the file */
cli_close ( srv - > cli , fd ) ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
/*
* Unfortunately , setattrE ( ) doesn ' t have a provision for
2020-06-03 23:07:41 +03:00
* setting the access attr ( attributes ) . We ' ll have to try
2008-02-28 19:23:20 +03:00
* cli_setatr ( ) for that , and with only this parameter , it
* seems to work on win98 .
*/
2020-06-03 23:07:41 +03:00
if ( ret & & attr ! = ( uint16_t ) - 1 ) {
2020-06-04 00:12:38 +03:00
ret = NT_STATUS_IS_OK ( cli_setatr ( srv - > cli , path , ( uint32_t ) attr , 0 ) ) ;
2008-02-28 19:23:20 +03:00
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( ! ret ) {
errno = SMBC_errno ( context , srv - > cli ) ;
TALLOC_FREE ( frame ) ;
return False ;
}
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return True ;
}
/*
* A routine to lseek ( ) a file
*/
off_t
SMBC_lseek_ctx ( SMBCCTX * context ,
SMBCFILE * file ,
off_t offset ,
int whence )
{
2012-04-05 08:53:08 +04:00
off_t size ;
2008-02-28 19:23:20 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2020-02-22 00:35:44 +03:00
if ( ! SMBC_dlist_contains ( context - > internal - > files , file ) ) {
2008-02-28 19:23:20 +03:00
errno = EBADF ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( ! file - > file ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ; /* Can't lseek a dir ... */
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
switch ( whence ) {
case SEEK_SET :
file - > offset = offset ;
break ;
case SEEK_CUR :
file - > offset + = offset ;
break ;
case SEEK_END :
2010-10-24 00:37:16 +04:00
if ( ! NT_STATUS_IS_OK ( cli_qfileinfo_basic (
2015-05-28 21:07:41 +03:00
file - > targetcli , file - > cli_fd , NULL ,
2010-10-24 00:37:16 +04:00
& size , NULL , NULL , NULL , NULL ,
NULL ) ) ) {
2020-06-04 09:43:49 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
2008-02-28 19:23:20 +03:00
}
file - > offset = size + offset ;
break ;
default :
errno = EINVAL ;
break ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return file - > offset ;
}
/*
* Routine to truncate a file given by its file descriptor , to a specified size
*/
int
SMBC_ftruncate_ctx ( SMBCCTX * context ,
SMBCFILE * file ,
off_t length )
{
2012-04-05 08:53:08 +04:00
off_t size = length ;
2008-02-28 19:23:20 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2020-02-22 00:35:44 +03:00
if ( ! SMBC_dlist_contains ( context - > internal - > files , file ) ) {
2008-02-28 19:23:20 +03:00
errno = EBADF ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
if ( ! file - > file ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2015-05-28 21:07:41 +03:00
if ( ! NT_STATUS_IS_OK ( cli_ftruncate ( file - > targetcli , file - > cli_fd , ( uint64_t ) size ) ) ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return 0 ;
}