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
Copyright ( C ) Tom Jansen ( Ninja ISD ) 2002
Copyright ( C ) Derrell Lipman 2003 - 2008
Copyright ( C ) Jeremy Allison 2007 , 2008
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "libsmbclient.h"
# include "libsmb_internal.h"
/*
* 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 ;
int fd ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ; /* Best I can think of ... */
TALLOC_FREE ( frame ) ;
return NULL ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! fname ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return NULL ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +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 ,
& share ,
& path ,
& user ,
& password ,
NULL ) ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
2008-03-02 04:44:21 +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 ;
}
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
srv = SMBC_server ( frame , context , True ,
server , share , & workgroup , & user , & password ) ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! srv ) {
if ( errno = = EPERM ) errno = EACCES ;
TALLOC_FREE ( frame ) ;
return NULL ; /* SMBC_server sets errno */
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Hmmm, the test for a directory is suspect here ... FIXME */
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( strlen ( path ) > 0 & & path [ strlen ( path ) - 1 ] = = ' \\ ' ) {
fd = - 1 ;
} else {
file = SMB_MALLOC_P ( SMBCFILE ) ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! file ) {
errno = ENOMEM ;
TALLOC_FREE ( frame ) ;
return NULL ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
ZERO_STRUCTP ( file ) ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>open: resolving %s\n", path);*/
2009-03-18 00:53:06 +03:00
if ( ! cli_resolve_path ( frame , " " , context - > internal - > auth_info ,
srv - > cli , path ,
& targetcli , & targetpath ) ) {
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);*/
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ( fd = cli_open ( targetcli , targetpath , flags ,
2008-02-29 21:34:35 +03:00
context - > internal - > share_mode ) ) < 0 ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Handle the error ... */
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
SAFE_FREE ( file ) ;
errno = SMBC_errno ( context , targetcli ) ;
TALLOC_FREE ( frame ) ;
return NULL ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Fill in file struct */
2008-03-02 04:44:21 +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 ;
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
DLIST_ADD ( context - > internal - > files , file ) ;
2008-03-02 04:44:21 +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 ;
}
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return file ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Check if opendir needed ... */
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( fd = = - 1 ) {
int eno = 0 ;
2008-03-02 04:44:21 +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 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ; /* FIXME, correct errno ? */
TALLOC_FREE ( frame ) ;
return NULL ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
/*
* Routine to create a file
*/
SMBCFILE *
SMBC_creat_ctx ( SMBCCTX * context ,
const char * path ,
mode_t mode )
{
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
return NULL ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +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 )
{
int ret ;
char * server = NULL , * share = NULL , * user = NULL , * password = NULL ;
char * path = NULL ;
char * targetpath = NULL ;
struct cli_state * targetcli = NULL ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-03-02 04:44:21 +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 ;
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
DEBUG ( 4 , ( " smbc_read(%p, %d) \n " , file , ( int ) count ) ) ;
2008-03-02 04:44:21 +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 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
offset = file - > offset ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Check that the buffer exists ... */
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( buf = = NULL ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>read: parsing %s\n", file->fname);*/
if ( SMBC_parse_path ( frame ,
2008-03-02 04:44:21 +03:00
context ,
file - > fname ,
NULL ,
& server ,
& share ,
& path ,
& user ,
& password ,
NULL ) ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>read: resolving %s\n", path);*/
2009-03-18 00:53:06 +03:00
if ( ! cli_resolve_path ( frame , " " , context - > internal - > auth_info ,
file - > srv - > cli , path ,
& targetcli , & targetpath ) ) {
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
TALLOC_FREE ( frame ) ;
return - 1 ;
}
/*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
ret = cli_read ( targetcli , file - > cli_fd , ( char * ) buf , offset , count ) ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ret < 0 ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = SMBC_errno ( context , targetcli ) ;
TALLOC_FREE ( frame ) ;
return - 1 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
file - > offset + = ret ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
DEBUG ( 4 , ( " --> %d \n " , ret ) ) ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return ret ; /* Success, ret bytes of data ... */
2008-03-02 04:44:21 +03:00
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 )
{
int ret ;
off_t offset ;
char * server = NULL , * share = NULL , * user = NULL , * password = NULL ;
char * path = NULL ;
char * targetpath = NULL ;
struct cli_state * targetcli = NULL ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* First check all pointers before dereferencing them */
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +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 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Check that the buffer exists ... */
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( buf = = NULL ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
offset = file - > offset ; /* See "offset" comment in SMBC_read_ctx() */
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>write: parsing %s\n", file->fname);*/
if ( SMBC_parse_path ( frame ,
2008-03-02 04:44:21 +03:00
context ,
file - > fname ,
NULL ,
& server ,
& share ,
& path ,
& user ,
& password ,
NULL ) ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2009-02-20 07:00:46 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>write: resolving %s\n", path);*/
2009-03-18 00:53:06 +03:00
if ( ! cli_resolve_path ( frame , " " , context - > internal - > auth_info ,
file - > srv - > cli , path ,
& targetcli , & targetpath ) ) {
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
TALLOC_FREE ( frame ) ;
return - 1 ;
}
/*d_printf(">>>write: resolved path as %s\n", targetpath);*/
2008-03-02 04:44:21 +03:00
ret = cli_write ( targetcli , file - > cli_fd ,
0 , ( char * ) buf , offset , count ) ;
2008-02-28 19:23:20 +03:00
if ( ret < = 0 ) {
errno = SMBC_errno ( context , targetcli ) ;
TALLOC_FREE ( frame ) ;
return - 1 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
file - > offset + = ret ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return ret ; /* Success, 0 bytes of data ... */
}
/*
* Routine to close ( ) a file . . .
*/
int
SMBC_close_ctx ( SMBCCTX * context ,
SMBCFILE * file )
{
SMBCSRV * srv ;
char * server = NULL , * share = NULL , * user = NULL , * password = NULL ;
char * path = NULL ;
char * targetpath = NULL ;
struct cli_state * targetcli = NULL ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +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 ;
}
2008-03-02 04:44:21 +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
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>close: parsing %s\n", file->fname);*/
if ( SMBC_parse_path ( frame ,
2008-03-02 04:44:21 +03:00
context ,
file - > fname ,
NULL ,
& server ,
& share ,
& path ,
& user ,
& password ,
NULL ) ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>close: resolving %s\n", path);*/
2009-03-18 00:53:06 +03:00
if ( ! cli_resolve_path ( frame , " " , context - > internal - > auth_info ,
file - > srv - > cli , path ,
& targetcli , & targetpath ) ) {
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
TALLOC_FREE ( frame ) ;
return - 1 ;
}
/*d_printf(">>>close: resolved path as %s\n", targetpath);*/
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! cli_close ( targetcli , file - > cli_fd ) ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
DEBUG ( 3 , ( " cli_close failed on %s. purging server. \n " ,
file - > fname ) ) ;
/* Deallocate slot and remove the server
* from the server cache if unused */
errno = SMBC_errno ( context , targetcli ) ;
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 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +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 ) ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
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 ,
char * path ,
uint16 * mode ,
SMB_OFF_T * size ,
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 ( ) ;
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-03-02 04:44:21 +03:00
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
}
2008-03-02 04:44:21 +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 " ) ) ;
2008-03-02 04:44:21 +03:00
2009-03-18 00:53:06 +03:00
if ( ! cli_resolve_path ( frame , " " , context - > internal - > auth_info ,
srv - > cli , fixedpath ,
& targetcli , & targetpath ) ) {
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 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! srv - > no_pathinfo2 & &
cli_qpathinfo2 ( targetcli , targetpath ,
create_time_ts ,
access_time_ts ,
write_time_ts ,
change_time_ts ,
size , mode , ino ) ) {
TALLOC_FREE ( frame ) ;
return True ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* if this is NT then don't bother with the getatr */
if ( targetcli - > capabilities & CAP_NT_SMBS ) {
errno = EPERM ;
TALLOC_FREE ( frame ) ;
return False ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( cli_getatr ( targetcli , targetpath , mode , size , & write_time ) ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
struct timespec w_time_ts ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
w_time_ts = convert_time_t_to_timespec ( write_time ) ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( write_time_ts ! = NULL ) {
* write_time_ts = w_time_ts ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( create_time_ts ! = NULL ) {
* create_time_ts = w_time_ts ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( access_time_ts ! = NULL ) {
* access_time_ts = w_time_ts ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( change_time_ts ! = NULL ) {
* change_time_ts = w_time_ts ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
srv - > no_pathinfo2 = True ;
TALLOC_FREE ( frame ) ;
return True ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EPERM ;
TALLOC_FREE ( frame ) ;
return False ;
2008-03-02 04:44:21 +03:00
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 .
*
* " mode " ( attributes ) parameter may be set to - 1 if it is not to be set .
*/
bool
SMBC_setatr ( SMBCCTX * context , SMBCSRV * srv , char * path ,
time_t create_time ,
time_t access_time ,
time_t write_time ,
time_t change_time ,
uint16 mode )
{
int fd ;
int ret ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-03-02 04:44:21 +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 | |
! cli_setpathinfo ( srv - > cli , path ,
create_time ,
access_time ,
write_time ,
change_time ,
mode ) ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*
* setpathinfo is not supported ; go to plan B .
*
* 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 .
*/
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Don't try {q,set}pathinfo() again, with this server */
srv - > no_pathinfo = True ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Open the file */
if ( ( fd = cli_open ( srv - > cli , path , O_RDWR , DENY_NONE ) ) < 0 ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = SMBC_errno ( context , srv - > cli ) ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Set the new attributes */
ret = cli_setattrE ( srv - > cli , fd ,
change_time ,
access_time ,
write_time ) ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/* Close the file */
cli_close ( srv - > cli , fd ) ;
2008-03-02 04:44:21 +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 .
*/
if ( ret & & mode ! = ( uint16 ) - 1 ) {
ret = cli_setatr ( srv - > cli , path , mode , 0 ) ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! ret ) {
errno = SMBC_errno ( context , srv - > cli ) ;
TALLOC_FREE ( frame ) ;
return False ;
}
}
2008-03-02 04:44:21 +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 )
{
SMB_OFF_T size ;
char * server = NULL , * share = NULL , * user = NULL , * password = NULL ;
char * path = NULL ;
char * targetpath = NULL ;
struct cli_state * targetcli = NULL ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
if ( ! file | | ! SMBC_dlist_contains ( context - > internal - > files , file ) ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EBADF ;
TALLOC_FREE ( frame ) ;
return - 1 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! file - > file ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ; /* Can't lseek a dir ... */
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
switch ( whence ) {
case SEEK_SET :
file - > offset = offset ;
break ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
case SEEK_CUR :
file - > offset + = offset ;
break ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
case SEEK_END :
/*d_printf(">>>lseek: parsing %s\n", file->fname);*/
if ( SMBC_parse_path ( frame ,
2008-03-02 04:44:21 +03:00
context ,
file - > fname ,
NULL ,
& server ,
& share ,
& path ,
& user ,
& password ,
NULL ) ) {
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>lseek: resolving %s\n", path);*/
2009-03-18 00:53:06 +03:00
if ( ! cli_resolve_path ( frame , " " , context - > internal - > auth_info ,
file - > srv - > cli , path ,
& targetcli , & targetpath ) ) {
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
TALLOC_FREE ( frame ) ;
return - 1 ;
}
/*d_printf(">>>lseek: resolved path as %s\n", targetpath);*/
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! cli_qfileinfo ( targetcli , file - > cli_fd , NULL ,
& size , NULL , NULL , NULL , NULL , NULL ) )
{
2008-03-02 04:44:21 +03:00
SMB_OFF_T b_size = size ;
2008-02-28 19:23:20 +03:00
if ( ! cli_getattrE ( targetcli , file - > cli_fd ,
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 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
default :
errno = EINVAL ;
break ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return file - > offset ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}
/*
* 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 )
{
SMB_OFF_T size = length ;
char * server = NULL ;
char * share = NULL ;
char * user = NULL ;
char * password = NULL ;
char * path = NULL ;
char * targetpath = NULL ;
struct cli_state * targetcli = NULL ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-03-02 04:44:21 +03:00
2008-02-29 21:34:35 +03:00
if ( ! context | | ! context - > internal - > initialized ) {
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +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 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! file - > file ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>fstat: parsing %s\n", file->fname);*/
if ( SMBC_parse_path ( frame ,
context ,
file - > fname ,
NULL ,
& server ,
& share ,
& path ,
& user ,
& password ,
NULL ) ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
/*d_printf(">>>fstat: resolving %s\n", path);*/
2009-03-18 00:53:06 +03:00
if ( ! cli_resolve_path ( frame , " " , context - > internal - > auth_info ,
file - > srv - > cli , path ,
& targetcli , & targetpath ) ) {
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
TALLOC_FREE ( frame ) ;
return - 1 ;
}
/*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
if ( ! cli_ftruncate ( targetcli , file - > cli_fd , size ) ) {
errno = EINVAL ;
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
TALLOC_FREE ( frame ) ;
return 0 ;
2008-03-02 04:44:21 +03:00
2008-02-28 19:23:20 +03:00
}