/*
Unix SMB / Netbios implementation .
Version 2.0
SMB wrapper stat functions
Copyright ( C ) Andrew Tridgell 1998
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 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
extern int DEBUGLEVEL ;
extern int smbw_busy ;
/*****************************************************
setup basic info in a stat structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void smbw_setup_stat ( struct stat * st , char * fname , size_t size , int mode )
{
st - > st_mode = 0 ;
if ( IS_DOS_DIR ( mode ) ) {
st - > st_mode = SMBW_DIR_MODE ;
} else {
st - > st_mode = SMBW_FILE_MODE ;
}
if ( IS_DOS_ARCHIVE ( mode ) ) st - > st_mode | = S_IXUSR ;
if ( IS_DOS_SYSTEM ( mode ) ) st - > st_mode | = S_IXGRP ;
if ( IS_DOS_HIDDEN ( mode ) ) st - > st_mode | = S_IXOTH ;
if ( ! IS_DOS_READONLY ( mode ) ) st - > st_mode | = S_IWUSR ;
st - > st_size = size ;
st - > st_blksize = 512 ;
st - > st_blocks = ( size + 511 ) / 512 ;
st - > st_uid = getuid ( ) ;
st - > st_gid = getgid ( ) ;
if ( IS_DOS_DIR ( mode ) ) {
st - > st_nlink = 2 ;
} else {
st - > st_nlink = 1 ;
}
if ( st - > st_ino = = 0 ) {
st - > st_ino = smbw_inode ( fname ) ;
}
}
/*****************************************************
try to do a QPATHINFO and if that fails then do a getatr
this is needed because win95 sometimes refuses the qpathinfo
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL smbw_getatr ( struct smbw_server * srv , char * path ,
uint16 * mode , size_t * size ,
time_t * c_time , time_t * a_time , time_t * m_time ,
SMB_INO_T * ino )
{
DEBUG ( 4 , ( " sending qpathinfo \n " ) ) ;
if ( ! srv - > no_pathinfo2 & &
cli_qpathinfo2 ( & srv - > cli , path , c_time , a_time , m_time , NULL ,
size , mode , ino ) ) return True ;
/* if this is NT then don't bother with the getatr */
if ( srv - > cli . capabilities & CAP_NT_SMBS ) return False ;
if ( cli_getatr ( & srv - > cli , path , mode , size , m_time ) ) {
a_time = c_time = m_time ;
srv - > no_pathinfo2 = True ;
return True ;
}
return False ;
}
static struct print_job_info printjob ;
/*****************************************************
gather info from a printjob listing
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void smbw_printjob_stat ( struct print_job_info * job )
{
if ( strcmp ( job - > name , printjob . name ) = = 0 ) {
printjob = * job ;
}
}
/*****************************************************
stat a printjob
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_stat_printjob ( struct smbw_server * srv , char * path ,
size_t * size , time_t * m_time )
{
if ( path [ 0 ] = = ' \\ ' ) path + + ;
ZERO_STRUCT ( printjob ) ;
fstrcpy ( printjob . name , path ) ;
cli_print_queue ( & srv - > cli , smbw_printjob_stat ) ;
if ( size ) {
* size = printjob . size ;
}
if ( m_time ) {
* m_time = printjob . t ;
}
return printjob . id ;
}
/*****************************************************
a wrapper for fstat ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_fstat ( int fd , struct stat * st )
{
struct smbw_file * file ;
time_t c_time , a_time , m_time ;
size_t size ;
uint16 mode ;
SMB_INO_T ino = 0 ;
smbw_busy + + ;
ZERO_STRUCTP ( st ) ;
file = smbw_file ( fd ) ;
if ( ! file ) {
int ret = smbw_dir_fstat ( fd , st ) ;
smbw_busy - - ;
return ret ;
}
if ( ! cli_qfileinfo ( & file - > srv - > cli , file - > f - > cli_fd ,
& mode , & size , & c_time , & a_time , & m_time , NULL ,
& ino ) & &
! cli_getattrE ( & file - > srv - > cli , file - > f - > cli_fd ,
& mode , & size , & c_time , & a_time , & m_time ) ) {
errno = EINVAL ;
smbw_busy - - ;
return - 1 ;
}
st - > st_ino = ino ;
smbw_setup_stat ( st , file - > f - > fname , size , mode ) ;
st - > st_atime = a_time ;
st - > st_ctime = c_time ;
st - > st_mtime = m_time ;
st - > st_dev = file - > srv - > dev ;
smbw_busy - - ;
return 0 ;
}
/*****************************************************
a wrapper for stat ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smbw_stat ( const char * fname , struct stat * st )
{
struct smbw_server * srv ;
fstring server , share ;
pstring path ;
time_t m_time = 0 , a_time = 0 , c_time = 0 ;
size_t size = 0 ;
uint16 mode = 0 ;
SMB_INO_T ino = 0 ;
ZERO_STRUCTP ( st ) ;
if ( ! fname ) {
errno = EINVAL ;
return - 1 ;
}
DEBUG ( 4 , ( " stat(%s) \n " , fname ) ) ;
smbw_init ( ) ;
smbw_busy + + ;
/* work out what server they are after */
smbw_parse_path ( fname , server , share , path ) ;
/* get a connection to the server */
srv = smbw_server ( server , share ) ;
if ( ! srv ) {
/* smbw_server sets errno */
goto failed ;
}
DEBUG ( 4 , ( " smbw_stat \n " ) ) ;
if ( strncmp ( srv - > cli . dev , " IPC " , 3 ) = = 0 ) {
mode = aDIR | aRONLY ;
} else if ( strncmp ( srv - > cli . dev , " LPT " , 3 ) = = 0 ) {
if ( strcmp ( path , " \\ " ) = = 0 ) {
mode = aDIR | aRONLY ;
} else {
mode = aRONLY ;
smbw_stat_printjob ( srv , path , & size , & m_time ) ;
c_time = a_time = m_time ;
}
} else {
if ( ! smbw_getatr ( srv , path ,
& mode , & size , & c_time , & a_time , & m_time ,
& ino ) ) {
errno = smbw_errno ( & srv - > cli ) ;
goto failed ;
}
}
st - > st_ino = ino ;
smbw_setup_stat ( st , path , size , mode ) ;
st - > st_atime = a_time ;
st - > st_ctime = c_time ;
st - > st_mtime = m_time ;
st - > st_dev = srv - > dev ;
smbw_busy - - ;
return 0 ;
failed :
smbw_busy - - ;
return - 1 ;
}