2006-04-25 11:36:15 +00:00
/*
Unix SMB / CIFS implementation .
2006-09-15 21:39:38 +00:00
simpler Samba VFS filesystem backend for clients which support the
CIFS Unix Extensions or newer CIFS POSIX protocol extensions
2006-04-25 11:36:15 +00:00
Copyright ( C ) Andrew Tridgell 2003
2006-09-15 21:39:38 +00:00
Copyright ( C ) Steve French 2006
2006-04-25 11:36:15 +00: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
2007-07-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2006-04-25 11:36:15 +00:00
( 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
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-04-25 11:36:15 +00:00
*/
/*
2006-09-15 21:39:38 +00:00
utility functions for cifs posix backend
2006-04-25 11:36:15 +00:00
*/
# include "includes.h"
# include "system/filesys.h"
2006-09-15 21:39:38 +00:00
# include "cifsposix.h"
# include "system/time.h"
2006-04-25 11:36:15 +00:00
# include "system/dir.h"
# include "ntvfs/ntvfs.h"
/*
convert a windows path to a unix path - don ' t do any manging or case sensitive handling
*/
2006-09-15 21:39:38 +00:00
char * cifspsx_unix_path ( struct ntvfs_module_context * ntvfs ,
2006-04-25 11:36:15 +00:00
struct ntvfs_request * req , const char * name )
{
2006-09-15 21:39:38 +00:00
struct cifspsx_private * private = ntvfs - > private_data ;
2006-04-25 11:36:15 +00:00
char * ret ;
if ( * name ! = ' \\ ' ) {
ret = talloc_asprintf ( req , " %s/%s " , private - > connectpath , name ) ;
} else {
ret = talloc_asprintf ( req , " %s%s " , private - > connectpath , name ) ;
}
all_string_sub ( ret , " \\ " , " / " , 0 ) ;
strlower ( ret + strlen ( private - > connectpath ) ) ;
return ret ;
}
/*
read a directory and find all matching file names and stat info
returned names are separate unix and DOS names . The returned names
are relative to the directory
*/
2006-09-15 21:39:38 +00:00
struct cifspsx_dir * cifspsx_list_unix ( TALLOC_CTX * mem_ctx , struct ntvfs_request * req , const char * unix_path )
2006-04-25 11:36:15 +00:00
{
char * p , * mask ;
2006-09-15 21:39:38 +00:00
struct cifspsx_dir * dir ;
2006-04-25 11:36:15 +00:00
DIR * odir ;
struct dirent * dent ;
uint_t allocated = 0 ;
char * low_mask ;
2006-09-15 21:39:38 +00:00
dir = talloc ( mem_ctx , struct cifspsx_dir ) ;
2006-04-25 11:36:15 +00:00
if ( ! dir ) { return NULL ; }
dir - > count = 0 ;
dir - > files = 0 ;
/* find the base directory */
p = strrchr ( unix_path , ' / ' ) ;
if ( ! p ) { return NULL ; }
dir - > unix_dir = talloc_strndup ( mem_ctx , unix_path , PTR_DIFF ( p , unix_path ) ) ;
if ( ! dir - > unix_dir ) { return NULL ; }
/* the wildcard pattern is the last part */
mask = p + 1 ;
low_mask = talloc_strdup ( mem_ctx , mask ) ;
if ( ! low_mask ) { return NULL ; }
strlower ( low_mask ) ;
odir = opendir ( dir - > unix_dir ) ;
if ( ! odir ) { return NULL ; }
while ( ( dent = readdir ( odir ) ) ) {
uint_t i = dir - > count ;
char * full_name ;
char * low_name ;
if ( strchr ( dent - > d_name , ' : ' ) & & ! strchr ( unix_path , ' : ' ) ) {
/* don't show streams in dir listing */
continue ;
}
low_name = talloc_strdup ( mem_ctx , dent - > d_name ) ;
if ( ! low_name ) { continue ; }
strlower ( low_name ) ;
/* check it matches the wildcard pattern */
if ( ms_fnmatch ( low_mask , low_name , PROTOCOL_NT1 ) ! = 0 ) {
continue ;
}
if ( dir - > count > = allocated ) {
allocated = ( allocated + 100 ) * 1.2 ;
2006-09-15 21:39:38 +00:00
dir - > files = talloc_realloc ( dir , dir - > files , struct cifspsx_dirfile , allocated ) ;
2006-04-25 11:36:15 +00:00
if ( ! dir - > files ) {
closedir ( odir ) ;
return NULL ;
}
}
dir - > files [ i ] . name = low_name ;
if ( ! dir - > files [ i ] . name ) { continue ; }
asprintf ( & full_name , " %s/%s " , dir - > unix_dir , dir - > files [ i ] . name ) ;
if ( ! full_name ) { continue ; }
if ( stat ( full_name , & dir - > files [ i ] . st ) = = 0 ) {
dir - > count + + ;
}
free ( full_name ) ;
}
closedir ( odir ) ;
return dir ;
}
/*
read a directory and find all matching file names and stat info
returned names are separate unix and DOS names . The returned names
are relative to the directory
*/
2006-09-15 21:39:38 +00:00
struct cifspsx_dir * cifspsx_list ( struct ntvfs_module_context * ntvfs , struct ntvfs_request * req , const char * pattern )
2006-04-25 11:36:15 +00:00
{
2006-09-15 21:39:38 +00:00
struct cifspsx_private * private = ntvfs - > private_data ;
2006-04-25 11:36:15 +00:00
char * unix_path ;
2006-09-15 21:39:38 +00:00
unix_path = cifspsx_unix_path ( ntvfs , req , pattern ) ;
2006-04-25 11:36:15 +00:00
if ( ! unix_path ) { return NULL ; }
2006-09-15 21:39:38 +00:00
return cifspsx_list_unix ( private , req , unix_path ) ;
2006-04-25 11:36:15 +00:00
}
/*******************************************************************
set the time on a file via file descriptor
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-15 21:39:38 +00:00
int cifspsx_file_utime ( int fd , struct utimbuf * times )
2006-04-25 11:36:15 +00:00
{
char * fd_path = NULL ;
int ret ;
asprintf ( & fd_path , " /proc/self/%d " , fd ) ;
if ( ! fd_path ) {
errno = ENOMEM ;
return - 1 ;
}
ret = utime ( fd_path , times ) ;
free ( fd_path ) ;
return ret ;
}
/*
map a unix file attrib to a DOS attribute
*/
2006-09-15 21:39:38 +00:00
uint16_t cifspsx_unix_to_dos_attrib ( mode_t mode )
2006-04-25 11:36:15 +00:00
{
uint16_t ret = 0 ;
if ( S_ISDIR ( mode ) ) ret | = FILE_ATTRIBUTE_DIRECTORY ;
if ( ! ( mode & S_IWUSR ) ) ret | = FILE_ATTRIBUTE_READONLY ;
return ret ;
}