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 {
2020-08-18 18:42:25 +03:00
struct cli_credentials * creds = NULL ;
2008-02-28 19:23:20 +03:00
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
2021-01-13 18:11:17 +03:00
creds = context - > internal - > creds ;
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 (
2020-08-18 18:42:25 +03:00
frame , " " ,
creds ,
2011-07-03 22:53:55 +04:00
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 ) ;
TALLOC_FREE ( frame ) ;
2020-12-15 19:15:21 +03:00
errno = cli_status_to_errno ( status ) ;
2008-02-28 19:23:20 +03:00
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-03-04 02:13:33 +03:00
file = smbc_getFunctionOpendir ( context ) ( context , fname ) ;
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
2022-02-13 11:25:54 +03:00
if ( file = = NULL ) {
errno = cli_status_to_errno ( status ) ;
}
2008-02-28 19:23:20 +03:00
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 ) ) {
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
2020-12-15 19:15:21 +03:00
errno = cli_status_to_errno ( status ) ;
2008-02-28 19:23:20 +03:00
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 ) ) {
TALLOC_FREE ( frame ) ;
2020-12-15 19:15:21 +03:00
errno = cli_status_to_errno ( status ) ;
2015-05-28 01:13:15 +03:00
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 ( ) ;
2022-01-21 22:21:17 +03: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 ) ;
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
2022-01-21 22:21:17 +03:00
status = cli_close ( file - > targetcli , file - > cli_fd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2015-05-28 21:07:41 +03:00
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 */
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 ) ;
2022-01-21 22:21:17 +03:00
errno = cli_status_to_errno ( status ) ;
2008-02-28 19:23:20 +03:00
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
*/
2022-01-21 23:15:06 +03:00
NTSTATUS
2008-02-28 19:23:20 +03:00
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 } ;
2022-10-17 23:24:27 +03:00
struct timespec w_time_ts = { 0 } ;
2019-11-25 13:09:52 +03:00
time_t write_time = 0 ;
SMB_INO_T ino = 0 ;
2023-08-23 17:04:00 +03:00
mode_t mode = S_IFREG ;
2020-08-18 18:42:25 +03:00
struct cli_credentials * creds = NULL ;
2008-02-28 19:23:20 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2024-01-22 23:33:05 +03:00
NTSTATUS status = NT_STATUS_ACCESS_DENIED ;
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
TALLOC_FREE ( frame ) ;
2022-01-21 23:15:06 +03:00
return NT_STATUS_INVALID_PARAMETER ;
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 ) {
TALLOC_FREE ( frame ) ;
2022-01-21 23:15:06 +03:00
return NT_STATUS_NO_MEMORY ;
2008-02-28 19:23:20 +03:00
}
} else {
fixedpath = talloc_strdup ( frame , path ) ;
if ( ! fixedpath ) {
TALLOC_FREE ( frame ) ;
2022-01-21 23:15:06 +03:00
return NT_STATUS_NO_MEMORY ;
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
2021-01-13 18:11:17 +03:00
creds = context - > internal - > creds ;
2020-08-18 18:42:25 +03:00
status = cli_resolve_path ( frame , " " ,
creds ,
2011-07-03 22:53:55 +04:00
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 ) ;
TALLOC_FREE ( frame ) ;
2022-01-21 23:15:06 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
2008-02-28 19:23:20 +03:00
}
2009-11-22 00:52:12 +03:00
2019-11-25 13:09:52 +03:00
if ( ! srv - > no_pathinfo2 ) {
2022-10-17 23:24:27 +03:00
bool not_supported_error = false ;
2019-11-25 13:09:52 +03:00
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 ,
2023-08-23 14:47:20 +03:00
& ino ,
2023-08-23 17:04:00 +03:00
& mode ) ;
2019-11-25 13:09:52 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
goto setup_stat ;
}
2022-10-17 23:24:27 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_LEVEL ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_NOT_SUPPORTED ) ) {
not_supported_error = true ;
}
if ( ! not_supported_error ) {
/* "Normal error". Just return it to caller. */
TALLOC_FREE ( frame ) ;
return status ;
}
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 ) {
2022-10-17 23:24:27 +03:00
bool not_supported_error = false ;
2019-11-25 13:09:52 +03:00
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 ;
}
2022-10-17 23:24:27 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_LEVEL ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_NOT_SUPPORTED ) ) {
not_supported_error = true ;
}
if ( ! not_supported_error ) {
/* "Normal error". Just return it to caller. */
TALLOC_FREE ( frame ) ;
return status ;
}
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 ) ;
2022-10-17 23:24:27 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto all_failed ;
2008-02-28 19:23:20 +03:00
}
2022-10-17 23:24:27 +03:00
w_time_ts = convert_time_t_to_timespec ( write_time ) ;
access_time_ts = change_time_ts = write_time_ts = w_time_ts ;
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 ) ;
2023-08-23 17:04:00 +03:00
if ( ( context - > internal - > posix_extensions ) & & ( mode ! = S_IFREG ) ) {
sb - > st_mode = ( sb - > st_mode & ~ S_IFMT ) | mode ;
}
2019-11-25 13:09:52 +03:00
TALLOC_FREE ( frame ) ;
2022-01-21 23:15:06 +03:00
return NT_STATUS_OK ;
2019-11-25 13:09:52 +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
TALLOC_FREE ( frame ) ;
2022-10-17 23:24:27 +03:00
return status ;
2008-02-28 19:23:20 +03:00
}
/*
* 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 ;
2020-06-04 06:48:23 +03:00
uint32_t lattr = ( uint32_t ) attr ;
2022-01-21 22:43:04 +03:00
NTSTATUS status ;
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 */
2022-01-21 22:43:04 +03:00
status = cli_open ( srv - > cli , path , O_RDWR , DENY_NONE , & fd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
2022-01-21 22:43:04 +03:00
errno = cli_status_to_errno ( status ) ;
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 */
2022-01-22 11:25:34 +03:00
status = cli_setattrE (
srv - > cli ,
fd ,
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 .
*/
2022-01-22 11:25:34 +03:00
if ( NT_STATUS_IS_OK ( status ) & & attr ! = ( uint16_t ) - 1 ) {
status = 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
2022-01-22 11:25:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
2022-01-22 11:25:34 +03:00
errno = cli_status_to_errno ( status ) ;
2008-02-28 19:23:20 +03:00
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 ;
}