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
2011-12-04 09:36:47 +04:00
status = cli_open ( targetcli , targetpath , flags ,
2009-05-01 02:26:43 +04:00
context - > internal - > share_mode , & fd ) ;
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
2008-02-28 19:23:20 +03:00
DEBUG ( 4 , ( " smbc_read(%p, %d) \n " , file , ( int ) count ) ) ;
2009-11-22 00:52:12 +03:00
2008-02-29 21:34:35 +03:00
if ( ! file | | ! 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
2011-07-22 16:22:29 +04:00
DEBUG ( 4 , ( " --> %ld \n " , ( unsigned long ) 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 )
{
off_t written ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
NTSTATUS status ;
if ( ! context | | ! context - > internal - > initialized ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
if ( ! srcfile | |
! SMBC_dlist_contains ( context - > internal - > files , srcfile ) )
{
errno = EBADF ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
if ( ! dstfile | |
! SMBC_dlist_contains ( context - > internal - > files , dstfile ) )
{
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
2008-02-29 21:34:35 +03:00
if ( ! file | | ! 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
2008-02-29 21:34:35 +03:00
if ( ! file | | ! 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 ,
2015-05-10 02:59:45 +03:00
uint16_t * mode ,
2012-04-05 08:53:08 +04:00
off_t * size ,
2008-02-28 19:23:20 +03:00
struct timespec * create_time_ts ,
struct timespec * access_time_ts ,
struct timespec * write_time_ts ,
struct timespec * change_time_ts ,
SMB_INO_T * ino )
{
char * fixedpath = NULL ;
char * targetpath = NULL ;
struct cli_state * targetcli = NULL ;
time_t write_time ;
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 .. */
if ( strequal ( path , " . " ) | | strequal ( path , " .. " ) ) {
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
2008-02-28 19:23:20 +03:00
if ( ! srv - > no_pathinfo2 & &
2010-07-26 11:27:11 +04:00
NT_STATUS_IS_OK ( cli_qpathinfo2 ( targetcli , targetpath ,
2008-02-28 19:23:20 +03:00
create_time_ts ,
access_time_ts ,
write_time_ts ,
change_time_ts ,
2010-07-26 11:27:11 +04:00
size , mode , ino ) ) ) {
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return True ;
}
2009-11-22 00:52:12 +03:00
2013-10-11 12:59:59 +04:00
srv - > no_pathinfo2 = True ;
2013-10-11 13:02:24 +04:00
if ( ! srv - > no_pathinfo3 & &
NT_STATUS_IS_OK ( cli_qpathinfo3 ( targetcli , targetpath ,
create_time_ts ,
access_time_ts ,
write_time_ts ,
change_time_ts ,
size , mode , ino ) ) ) {
TALLOC_FREE ( frame ) ;
return True ;
}
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
2009-05-06 07:59:22 +04:00
if ( NT_STATUS_IS_OK ( cli_getatr ( targetcli , targetpath , mode , size , & write_time ) ) ) {
2008-02-28 19:23:20 +03:00
struct timespec w_time_ts ;
2009-11-22 00:52:12 +03:00
2008-02-28 19:23:20 +03:00
w_time_ts = convert_time_t_to_timespec ( write_time ) ;
if ( write_time_ts ! = NULL ) {
* write_time_ts = w_time_ts ;
}
if ( create_time_ts ! = NULL ) {
* create_time_ts = w_time_ts ;
}
if ( access_time_ts ! = NULL ) {
* access_time_ts = w_time_ts ;
}
if ( change_time_ts ! = NULL ) {
* change_time_ts = w_time_ts ;
}
2013-10-11 13:00:48 +04:00
if ( ino ) {
* ino = 0 ;
}
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return True ;
}
2009-11-22 00:52:12 +03:00
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 .
*
* " mode " ( attributes ) parameter may be set to - 1 if it is not to be set .
*/
bool
2013-06-21 19:56:08 +04:00
SMBC_setatr ( SMBCCTX * context , SMBCSRV * srv , char * path ,
2008-02-28 19:23:20 +03:00
time_t create_time ,
time_t access_time ,
time_t write_time ,
time_t change_time ,
2015-05-10 02:59:45 +03:00
uint16_t mode )
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 ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2009-11-22 00:52:12 +03:00
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 | |
2011-01-16 14:56:09 +03:00
! NT_STATUS_IS_OK ( cli_setpathinfo_basic ( srv - > cli , path ,
create_time ,
access_time ,
write_time ,
change_time ,
mode ) ) ) {
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 ) ;
return - 1 ;
}
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 ,
2008-02-28 19:23:20 +03:00
change_time ,
access_time ,
2009-05-07 02:07:05 +04:00
write_time ) ) ;
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
* setting the access mode ( attributes ) . We ' ll have to try
* cli_setatr ( ) for that , and with only this parameter , it
* seems to work on win98 .
*/
2015-05-10 02:59:45 +03:00
if ( ret & & mode ! = ( uint16_t ) - 1 ) {
2009-05-07 03:13:42 +04:00
ret = NT_STATUS_IS_OK ( cli_setatr ( srv - > cli , path , mode , 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
2008-02-29 21:34:35 +03:00
if ( ! file | | ! 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 ) ) ) {
2012-04-05 08:53:08 +04:00
off_t b_size = size ;
2015-05-28 21:07:41 +03:00
if ( ! NT_STATUS_IS_OK ( cli_getattrE ( file - > targetcli , file - > cli_fd ,
2009-05-06 03:28:44 +04:00
NULL , & b_size , NULL , NULL , NULL ) ) ) {
2008-03-02 04:44:21 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
} else
size = b_size ;
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
2008-02-29 21:34:35 +03:00
if ( ! file | | ! 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 ;
}