2007-11-17 04:07:11 +03:00
/*
2005-03-18 16:13:38 +03:00
* Catia VFS module
*
* Implement a fixed mapping of forbidden NT characters in filenames that are
* used a lot by the CAD package Catia .
*
* Yes , this a BAD BAD UGLY INCOMPLETE hack , but it helps quite some people
* out there . Catia V4 on AIX uses characters like " <*$ a *lot*, all forbidden
* under Windows . . .
*
* Copyright ( C ) Volker Lendecke , 2005
*
* 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-09 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2005-03-18 16:13:38 +03:00
* ( at your option ) any later version .
2007-11-17 04:07:11 +03:00
*
2005-03-18 16:13:38 +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 .
2007-11-17 04:07:11 +03:00
*
2005-03-18 16:13:38 +03:00
* You should have received a copy of the GNU General Public License
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2005-03-18 16:13:38 +03:00
*/
# include "includes.h"
2007-11-17 04:07:11 +03:00
static char * catia_string_replace ( TALLOC_CTX * ctx ,
const char * s ,
unsigned char oldc ,
unsigned char newc )
2005-03-18 16:13:38 +03:00
{
2007-11-17 04:07:11 +03:00
smb_ucs2_t * tmpbuf = NULL ;
smb_ucs2_t * ptr = NULL ;
smb_ucs2_t old = oldc ;
char * ret = NULL ;
2008-04-30 01:36:24 +04:00
size_t converted_size ;
2007-11-17 04:07:11 +03:00
if ( ! s ) {
return NULL ;
}
2008-04-30 01:36:24 +04:00
if ( ! push_ucs2_talloc ( ctx , & tmpbuf , s , & converted_size ) ) {
2007-11-17 04:07:11 +03:00
return NULL ;
}
ptr = tmpbuf ;
for ( ; * ptr ; ptr + + ) {
if ( * ptr = = old ) {
* ptr = newc ;
}
}
2008-04-30 01:36:24 +04:00
if ( ! pull_ucs2_talloc ( ctx , & ret , tmpbuf , & converted_size ) ) {
2007-11-17 04:07:11 +03:00
TALLOC_FREE ( tmpbuf ) ;
return NULL ;
}
TALLOC_FREE ( tmpbuf ) ;
return ret ;
2005-03-18 16:13:38 +03:00
}
2007-11-17 04:07:11 +03:00
static char * from_unix ( TALLOC_CTX * ctx , const char * s )
2005-03-18 16:13:38 +03:00
{
2007-11-17 04:07:11 +03:00
char * ret = catia_string_replace ( ctx , s , ' \x22 ' , ' \xa8 ' ) ;
ret = catia_string_replace ( ctx , ret , ' \x2a ' , ' \xa4 ' ) ;
ret = catia_string_replace ( ctx , ret , ' \x2f ' , ' \xf8 ' ) ;
ret = catia_string_replace ( ctx , ret , ' \x3a ' , ' \xf7 ' ) ;
ret = catia_string_replace ( ctx , ret , ' \x3c ' , ' \xab ' ) ;
ret = catia_string_replace ( ctx , ret , ' \x3e ' , ' \xbb ' ) ;
ret = catia_string_replace ( ctx , ret , ' \x3f ' , ' \xbf ' ) ;
ret = catia_string_replace ( ctx , ret , ' \x5c ' , ' \xff ' ) ;
ret = catia_string_replace ( ctx , ret , ' \x7c ' , ' \xa6 ' ) ;
return catia_string_replace ( ctx , ret , ' ' , ' \xb1 ' ) ;
2005-03-18 16:13:38 +03:00
}
2007-11-17 04:07:11 +03:00
static char * to_unix ( TALLOC_CTX * ctx , const char * s )
2005-03-18 16:13:38 +03:00
{
2007-11-17 04:07:11 +03:00
char * ret = catia_string_replace ( ctx , s , ' \xa8 ' , ' \x22 ' ) ;
ret = catia_string_replace ( ctx , ret , ' \xa4 ' , ' \x2a ' ) ;
ret = catia_string_replace ( ctx , ret , ' \xf8 ' , ' \x2f ' ) ;
ret = catia_string_replace ( ctx , ret , ' \xf7 ' , ' \x3a ' ) ;
ret = catia_string_replace ( ctx , ret , ' \xab ' , ' \x3c ' ) ;
ret = catia_string_replace ( ctx , ret , ' \xbb ' , ' \x3e ' ) ;
ret = catia_string_replace ( ctx , ret , ' \xbf ' , ' \x3f ' ) ;
ret = catia_string_replace ( ctx , ret , ' \xff ' , ' \x5c ' ) ;
ret = catia_string_replace ( ctx , ret , ' \xa6 ' , ' \x7c ' ) ;
return catia_string_replace ( ctx , ret , ' \xb1 ' , ' ' ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static SMB_STRUCT_DIR * catia_opendir ( vfs_handle_struct * handle ,
const char * fname , const char * mask , uint32 attr )
2005-03-18 16:13:38 +03:00
{
2007-11-17 04:07:11 +03:00
char * name = to_unix ( talloc_tos ( ) , fname ) ;
2005-03-18 16:13:38 +03:00
2007-11-17 04:07:11 +03:00
if ( ! name ) {
errno = ENOMEM ;
return NULL ;
}
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_OPENDIR ( handle , name , mask , attr ) ;
2005-03-18 16:13:38 +03:00
}
2007-11-17 04:07:11 +03:00
static SMB_STRUCT_DIRENT * catia_readdir ( vfs_handle_struct * handle ,
2006-07-11 22:01:26 +04:00
SMB_STRUCT_DIR * dirp )
2005-03-18 16:13:38 +03:00
{
2009-01-23 07:14:38 +03:00
SMB_STRUCT_DIRENT * result = NULL ;
SMB_STRUCT_DIRENT * newdirent = NULL ;
2007-11-17 04:07:11 +03:00
char * newname ;
size_t newnamelen ;
2009-01-23 07:14:38 +03:00
result = SMB_VFS_NEXT_READDIR ( handle , dirp , NULL ) ;
2007-11-17 04:07:11 +03:00
if ( result = = NULL ) {
return result ;
}
newname = from_unix ( talloc_tos ( ) , result - > d_name ) ;
if ( ! newname ) {
return NULL ;
}
newnamelen = strlen ( newname ) + 1 ;
newdirent = ( SMB_STRUCT_DIRENT * ) TALLOC_ARRAY ( talloc_tos ( ) ,
char ,
sizeof ( SMB_STRUCT_DIRENT ) +
newnamelen ) ;
if ( ! newdirent ) {
return NULL ;
}
memcpy ( newdirent , result , sizeof ( SMB_STRUCT_DIRENT ) ) ;
memcpy ( & newdirent - > d_name , newname , newnamelen ) ;
return newdirent ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_open ( vfs_handle_struct * handle ,
2009-06-16 23:01:13 +04:00
struct smb_filename * smb_fname ,
2007-11-17 04:07:11 +03:00
files_struct * fsp ,
int flags ,
mode_t mode )
2005-03-18 16:13:38 +03:00
{
2009-06-16 23:01:13 +04:00
char * name ;
char * tmp_base_name ;
int ret ;
2005-03-18 16:13:38 +03:00
2009-06-16 23:01:13 +04:00
name = to_unix ( talloc_tos ( ) , smb_fname - > base_name ) ;
2007-11-17 04:07:11 +03:00
if ( ! name ) {
errno = ENOMEM ;
return - 1 ;
}
2009-06-16 23:01:13 +04:00
tmp_base_name = smb_fname - > base_name ;
smb_fname - > base_name = name ;
ret = SMB_VFS_NEXT_OPEN ( handle , name , fsp , flags , mode ) ;
smb_fname - > base_name = tmp_base_name ;
TALLOC_FREE ( name ) ;
return ret ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_rename ( vfs_handle_struct * handle ,
2005-06-25 13:07:42 +04:00
const char * oldname , const char * newname )
2005-03-18 16:13:38 +03:00
{
2007-11-17 04:07:11 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
char * oname = to_unix ( ctx , oldname ) ;
char * nname = to_unix ( ctx , newname ) ;
2005-03-18 16:13:38 +03:00
2007-11-17 04:07:11 +03:00
if ( ! oname | | ! nname ) {
errno = ENOMEM ;
return - 1 ;
}
DEBUG ( 10 , ( " converted old name: %s \n " , oname ) ) ;
DEBUG ( 10 , ( " converted new name: %s \n " , nname ) ) ;
2005-03-18 16:13:38 +03:00
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_RENAME ( handle , oname , nname ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_stat ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * fname , SMB_STRUCT_STAT * sbuf )
{
2007-11-17 04:07:11 +03:00
char * name = to_unix ( talloc_tos ( ) , fname ) ;
2005-03-18 16:13:38 +03:00
2007-11-17 04:07:11 +03:00
if ( ! name ) {
errno = ENOMEM ;
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_STAT ( handle , name , sbuf ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_lstat ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * path , SMB_STRUCT_STAT * sbuf )
{
2007-11-17 04:07:11 +03:00
char * name = to_unix ( talloc_tos ( ) , path ) ;
2005-03-18 16:13:38 +03:00
2007-11-17 04:07:11 +03:00
if ( ! name ) {
errno = ENOMEM ;
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_LSTAT ( handle , name , sbuf ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_unlink ( vfs_handle_struct * handle , const char * path )
2005-03-18 16:13:38 +03:00
{
2007-11-17 04:07:11 +03:00
char * name = to_unix ( talloc_tos ( ) , path ) ;
2005-03-18 16:13:38 +03:00
2007-11-17 04:07:11 +03:00
if ( ! name ) {
errno = ENOMEM ;
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_UNLINK ( handle , name ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_chmod ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * path , mode_t mode )
{
2007-11-17 04:07:11 +03:00
char * name = to_unix ( talloc_tos ( ) , path ) ;
2005-03-18 16:13:38 +03:00
2007-11-17 04:07:11 +03:00
if ( ! name ) {
errno = ENOMEM ;
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_CHMOD ( handle , name , mode ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_chown ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * path , uid_t uid , gid_t gid )
{
2007-11-17 04:07:11 +03:00
char * name = to_unix ( talloc_tos ( ) , path ) ;
2005-03-18 16:13:38 +03:00
2007-11-17 04:07:11 +03:00
if ( ! name ) {
errno = ENOMEM ;
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_CHOWN ( handle , name , uid , gid ) ;
2005-03-18 16:13:38 +03:00
}
2007-05-24 03:55:12 +04:00
static int catia_lchown ( vfs_handle_struct * handle ,
const char * path , uid_t uid , gid_t gid )
{
2007-11-17 04:07:11 +03:00
char * name = to_unix ( talloc_tos ( ) , path ) ;
2007-05-24 03:55:12 +04:00
2007-11-17 04:07:11 +03:00
if ( ! name ) {
errno = ENOMEM ;
return - 1 ;
}
2007-05-24 03:55:12 +04:00
return SMB_VFS_NEXT_LCHOWN ( handle , name , uid , gid ) ;
}
2006-07-11 22:01:26 +04:00
static int catia_chdir ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * path )
{
2007-11-17 04:07:11 +03:00
char * name = to_unix ( talloc_tos ( ) , path ) ;
2005-03-18 16:13:38 +03:00
2007-11-17 04:07:11 +03:00
if ( ! name ) {
errno = ENOMEM ;
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_CHDIR ( handle , name ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static char * catia_getwd ( vfs_handle_struct * handle , char * buf )
2005-03-18 16:13:38 +03:00
{
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_GETWD ( handle , buf ) ;
2005-03-18 16:13:38 +03:00
}
2007-03-06 02:40:03 +03:00
static int catia_ntimes ( vfs_handle_struct * handle ,
2009-01-24 01:40:19 +03:00
const char * path , struct smb_file_time * ft )
2005-03-18 16:13:38 +03:00
{
2009-01-24 01:40:19 +03:00
return SMB_VFS_NEXT_NTIMES ( handle , path , ft ) ;
2005-03-18 16:13:38 +03:00
}
2007-10-19 04:40:25 +04:00
static bool catia_symlink ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * oldpath , const char * newpath )
{
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_SYMLINK ( handle , oldpath , newpath ) ;
2005-03-18 16:13:38 +03:00
}
2007-10-19 04:40:25 +04:00
static bool catia_readlink ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * path , char * buf , size_t bufsiz )
{
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_READLINK ( handle , path , buf , bufsiz ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_link ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * oldpath , const char * newpath )
{
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_LINK ( handle , oldpath , newpath ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_mknod ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * path , mode_t mode , SMB_DEV_T dev )
{
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_MKNOD ( handle , path , mode , dev ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static char * catia_realpath ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * path , char * resolved_path )
{
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_REALPATH ( handle , path , resolved_path ) ;
2005-03-18 16:13:38 +03:00
}
2008-08-14 21:58:50 +04:00
static NTSTATUS catia_get_nt_acl ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * name , uint32 security_info ,
2007-07-05 14:32:51 +04:00
struct security_descriptor * * ppdesc )
2005-03-18 16:13:38 +03:00
{
2007-12-05 11:53:10 +03:00
return SMB_VFS_NEXT_GET_NT_ACL ( handle , name , security_info , ppdesc ) ;
2005-03-18 16:13:38 +03:00
}
2006-07-11 22:01:26 +04:00
static int catia_chmod_acl ( vfs_handle_struct * handle ,
2005-03-18 16:13:38 +03:00
const char * name , mode_t mode )
{
/* If the underlying VFS doesn't have ACL support... */
if ( ! handle - > vfs_next . ops . chmod_acl ) {
errno = ENOSYS ;
return - 1 ;
}
2006-07-11 22:01:26 +04:00
return SMB_VFS_NEXT_CHMOD_ACL ( handle , name , mode ) ;
2005-03-18 16:13:38 +03:00
}
/* VFS operations structure */
static vfs_op_tuple catia_op_tuples [ ] = {
/* Directory operations */
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_opendir ) , SMB_VFS_OP_OPENDIR ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_readdir ) , SMB_VFS_OP_READDIR ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
/* File operations */
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_open ) , SMB_VFS_OP_OPEN ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_rename ) , SMB_VFS_OP_RENAME ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_stat ) , SMB_VFS_OP_STAT ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_lstat ) , SMB_VFS_OP_LSTAT ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_unlink ) , SMB_VFS_OP_UNLINK ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_chmod ) , SMB_VFS_OP_CHMOD ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_chown ) , SMB_VFS_OP_CHOWN ,
2007-05-24 03:55:12 +04:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_lchown ) , SMB_VFS_OP_LCHOWN ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_chdir ) , SMB_VFS_OP_CHDIR ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_getwd ) , SMB_VFS_OP_GETWD ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_ntimes ) , SMB_VFS_OP_NTIMES ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_symlink ) , SMB_VFS_OP_SYMLINK ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_readlink ) , SMB_VFS_OP_READLINK ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_link ) , SMB_VFS_OP_LINK ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_mknod ) , SMB_VFS_OP_MKNOD ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_realpath ) , SMB_VFS_OP_REALPATH ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
/* NT File ACL operations */
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_get_nt_acl ) , SMB_VFS_OP_GET_NT_ACL ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
/* POSIX ACL operations */
2007-11-17 04:07:11 +03:00
{ SMB_VFS_OP ( catia_chmod_acl ) , SMB_VFS_OP_CHMOD_ACL ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_TRANSPARENT } ,
2007-11-17 04:07:11 +03:00
{ NULL , SMB_VFS_OP_NOOP ,
2005-03-18 16:13:38 +03:00
SMB_VFS_LAYER_NOOP }
} ;
2006-12-19 23:16:52 +03:00
NTSTATUS vfs_catia_init ( void ) ;
2006-07-11 22:01:26 +04:00
NTSTATUS vfs_catia_init ( void )
2005-03-18 16:13:38 +03:00
{
2007-11-17 04:07:11 +03:00
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " catia " ,
2005-03-18 16:13:38 +03:00
catia_op_tuples ) ;
}