2007-10-22 20:14:57 +04:00
/*
* Store posix - level xattrs in a tdb
*
* Copyright ( C ) Volker Lendecke , 2007
*
* 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"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2007-10-22 20:14:57 +04:00
# include "librpc/gen_ndr/xattr.h"
# include "librpc/gen_ndr/ndr_xattr.h"
2010-08-05 17:14:04 +04:00
# include "../librpc/gen_ndr/ndr_netlogon.h"
2010-08-18 20:59:23 +04:00
# include "dbwrap.h"
2007-10-22 20:14:57 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
/*
* unmarshall tdb_xattrs
*/
2008-01-15 19:06:12 +03:00
static NTSTATUS xattr_tdb_pull_attrs ( TALLOC_CTX * mem_ctx ,
const TDB_DATA * data ,
struct tdb_xattrs * * presult )
2007-10-22 20:14:57 +04:00
{
DATA_BLOB blob ;
enum ndr_err_code ndr_err ;
struct tdb_xattrs * result ;
if ( ! ( result = TALLOC_ZERO_P ( mem_ctx , struct tdb_xattrs ) ) ) {
return NT_STATUS_NO_MEMORY ;
}
if ( data - > dsize = = 0 ) {
* presult = result ;
return NT_STATUS_OK ;
}
blob = data_blob_const ( data - > dptr , data - > dsize ) ;
2010-05-10 02:42:06 +04:00
ndr_err = ndr_pull_struct_blob ( & blob , result , result ,
2007-10-22 20:14:57 +04:00
( ndr_pull_flags_fn_t ) ndr_pull_tdb_xattrs ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( " ndr_pull_tdb_xattrs failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ) ;
TALLOC_FREE ( result ) ;
2011-02-02 14:50:42 +03:00
return ndr_map_error2ntstatus ( ndr_err ) ;
2007-10-22 20:14:57 +04:00
}
* presult = result ;
return NT_STATUS_OK ;
}
/*
* marshall tdb_xattrs
*/
2008-01-15 19:06:12 +03:00
static NTSTATUS xattr_tdb_push_attrs ( TALLOC_CTX * mem_ctx ,
const struct tdb_xattrs * attribs ,
TDB_DATA * data )
2007-10-22 20:14:57 +04:00
{
DATA_BLOB blob ;
enum ndr_err_code ndr_err ;
2010-05-10 02:42:06 +04:00
ndr_err = ndr_push_struct_blob ( & blob , mem_ctx , attribs ,
2007-10-22 20:14:57 +04:00
( ndr_push_flags_fn_t ) ndr_push_tdb_xattrs ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( " ndr_push_tdb_xattrs failed: %s \n " ,
ndr_errstr ( ndr_err ) ) ) ;
2011-02-02 14:50:42 +03:00
return ndr_map_error2ntstatus ( ndr_err ) ;
2007-10-22 20:14:57 +04:00
}
* data = make_tdb_data ( blob . data , blob . length ) ;
return NT_STATUS_OK ;
}
/*
* Load tdb_xattrs for a file from the tdb
*/
2008-01-15 19:06:12 +03:00
static NTSTATUS xattr_tdb_load_attrs ( TALLOC_CTX * mem_ctx ,
struct db_context * db_ctx ,
const struct file_id * id ,
struct tdb_xattrs * * presult )
2007-10-22 20:14:57 +04:00
{
uint8 id_buf [ 16 ] ;
NTSTATUS status ;
TDB_DATA data ;
2009-02-16 10:45:28 +03:00
/* For backwards compatibility only store the dev/inode. */
2007-10-22 20:14:57 +04:00
push_file_id_16 ( ( char * ) id_buf , id ) ;
if ( db_ctx - > fetch ( db_ctx , mem_ctx ,
make_tdb_data ( id_buf , sizeof ( id_buf ) ) ,
& data ) = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2008-01-15 19:06:12 +03:00
status = xattr_tdb_pull_attrs ( mem_ctx , & data , presult ) ;
2007-10-22 20:14:57 +04:00
TALLOC_FREE ( data . dptr ) ;
2008-01-19 17:44:48 +03:00
return status ;
2007-10-22 20:14:57 +04:00
}
/*
* fetch_lock the tdb_ea record for a file
*/
2008-01-15 19:06:12 +03:00
static struct db_record * xattr_tdb_lock_attrs ( TALLOC_CTX * mem_ctx ,
struct db_context * db_ctx ,
const struct file_id * id )
2007-10-22 20:14:57 +04:00
{
uint8 id_buf [ 16 ] ;
2009-02-16 10:45:28 +03:00
/* For backwards compatibility only store the dev/inode. */
2007-10-22 20:14:57 +04:00
push_file_id_16 ( ( char * ) id_buf , id ) ;
return db_ctx - > fetch_locked ( db_ctx , mem_ctx ,
make_tdb_data ( id_buf , sizeof ( id_buf ) ) ) ;
}
/*
* Save tdb_xattrs to a previously fetch_locked record
*/
2008-01-15 19:06:12 +03:00
static NTSTATUS xattr_tdb_save_attrs ( struct db_record * rec ,
const struct tdb_xattrs * attribs )
2007-10-22 20:14:57 +04:00
{
2008-01-16 22:31:02 +03:00
TDB_DATA data = tdb_null ;
2007-10-22 20:14:57 +04:00
NTSTATUS status ;
2008-01-15 19:06:12 +03:00
status = xattr_tdb_push_attrs ( talloc_tos ( ) , attribs , & data ) ;
2007-10-22 20:14:57 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-15 19:06:12 +03:00
DEBUG ( 0 , ( " xattr_tdb_push_attrs failed: %s \n " ,
2007-10-22 20:14:57 +04:00
nt_errstr ( status ) ) ) ;
return status ;
}
status = rec - > store ( rec , data , 0 ) ;
TALLOC_FREE ( data . dptr ) ;
return status ;
}
/*
* Worker routine for getxattr and fgetxattr
*/
2008-01-15 19:06:12 +03:00
static ssize_t xattr_tdb_getattr ( struct db_context * db_ctx ,
const struct file_id * id ,
const char * name , void * value , size_t size )
2007-10-22 20:14:57 +04:00
{
struct tdb_xattrs * attribs ;
uint32_t i ;
ssize_t result = - 1 ;
NTSTATUS status ;
2008-01-20 15:55:27 +03:00
DEBUG ( 10 , ( " xattr_tdb_getattr called for file %s, name %s \n " ,
file_id_string_tos ( id ) , name ) ) ;
2008-01-15 19:06:12 +03:00
status = xattr_tdb_load_attrs ( talloc_tos ( ) , db_ctx , id , & attribs ) ;
2007-10-22 20:14:57 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-15 19:06:12 +03:00
DEBUG ( 10 , ( " xattr_tdb_fetch_attrs failed: %s \n " ,
2007-10-22 20:14:57 +04:00
nt_errstr ( status ) ) ) ;
errno = EINVAL ;
return - 1 ;
}
2008-10-15 17:57:39 +04:00
for ( i = 0 ; i < attribs - > num_eas ; i + + ) {
if ( strcmp ( attribs - > eas [ i ] . name , name ) = = 0 ) {
2007-10-22 20:14:57 +04:00
break ;
}
}
2008-10-15 17:57:39 +04:00
if ( i = = attribs - > num_eas ) {
2007-10-22 20:14:57 +04:00
errno = ENOATTR ;
goto fail ;
}
2008-10-15 17:57:39 +04:00
if ( attribs - > eas [ i ] . value . length > size ) {
2007-10-22 20:14:57 +04:00
errno = ERANGE ;
goto fail ;
}
2008-10-15 17:57:39 +04:00
memcpy ( value , attribs - > eas [ i ] . value . data ,
attribs - > eas [ i ] . value . length ) ;
result = attribs - > eas [ i ] . value . length ;
2007-10-22 20:14:57 +04:00
fail :
TALLOC_FREE ( attribs ) ;
return result ;
}
2008-01-15 19:06:12 +03:00
static ssize_t xattr_tdb_getxattr ( struct vfs_handle_struct * handle ,
const char * path , const char * name ,
void * value , size_t size )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
2009-06-23 02:26:56 +04:00
if ( vfs_stat_smb_fname ( handle - > conn , path , & sbuf ) = = - 1 ) {
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2009-02-16 10:38:53 +03:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
return xattr_tdb_getattr ( db , & id , name , value , size ) ;
2007-10-22 20:14:57 +04:00
}
2008-01-15 19:06:12 +03:00
static ssize_t xattr_tdb_fgetxattr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
const char * name , void * value , size_t size )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
if ( SMB_VFS_FSTAT ( fsp , & sbuf ) = = - 1 ) {
return - 1 ;
}
2009-02-16 10:38:53 +03:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
return xattr_tdb_getattr ( db , & id , name , value , size ) ;
2007-10-22 20:14:57 +04:00
}
/*
* Worker routine for setxattr and fsetxattr
*/
2008-01-15 19:06:12 +03:00
static int xattr_tdb_setattr ( struct db_context * db_ctx ,
const struct file_id * id , const char * name ,
const void * value , size_t size , int flags )
2007-10-22 20:14:57 +04:00
{
NTSTATUS status ;
struct db_record * rec ;
struct tdb_xattrs * attribs ;
uint32_t i ;
2008-01-20 15:55:27 +03:00
DEBUG ( 10 , ( " xattr_tdb_setattr called for file %s, name %s \n " ,
file_id_string_tos ( id ) , name ) ) ;
2008-01-15 19:06:12 +03:00
rec = xattr_tdb_lock_attrs ( talloc_tos ( ) , db_ctx , id ) ;
2007-10-22 20:14:57 +04:00
if ( rec = = NULL ) {
2008-01-15 19:06:12 +03:00
DEBUG ( 0 , ( " xattr_tdb_lock_attrs failed \n " ) ) ;
2007-10-22 20:14:57 +04:00
errno = EINVAL ;
return - 1 ;
}
2008-01-15 19:06:12 +03:00
status = xattr_tdb_pull_attrs ( rec , & rec - > value , & attribs ) ;
2007-10-22 20:14:57 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-15 19:06:12 +03:00
DEBUG ( 10 , ( " xattr_tdb_fetch_attrs failed: %s \n " ,
2007-10-22 20:14:57 +04:00
nt_errstr ( status ) ) ) ;
TALLOC_FREE ( rec ) ;
return - 1 ;
}
2008-10-15 17:57:39 +04:00
for ( i = 0 ; i < attribs - > num_eas ; i + + ) {
if ( strcmp ( attribs - > eas [ i ] . name , name ) = = 0 ) {
2008-01-20 13:20:58 +03:00
if ( flags & XATTR_CREATE ) {
TALLOC_FREE ( rec ) ;
errno = EEXIST ;
return - 1 ;
}
2007-10-22 20:14:57 +04:00
break ;
}
}
2008-10-15 17:57:39 +04:00
if ( i = = attribs - > num_eas ) {
struct xattr_EA * tmp ;
2007-10-22 20:14:57 +04:00
2008-01-20 13:20:58 +03:00
if ( flags & XATTR_REPLACE ) {
TALLOC_FREE ( rec ) ;
errno = ENOATTR ;
return - 1 ;
}
2007-10-22 20:14:57 +04:00
tmp = TALLOC_REALLOC_ARRAY (
2008-10-15 17:57:39 +04:00
attribs , attribs - > eas , struct xattr_EA ,
attribs - > num_eas + 1 ) ;
2007-10-22 20:14:57 +04:00
if ( tmp = = NULL ) {
DEBUG ( 0 , ( " TALLOC_REALLOC_ARRAY failed \n " ) ) ;
TALLOC_FREE ( rec ) ;
errno = ENOMEM ;
return - 1 ;
}
2008-10-15 17:57:39 +04:00
attribs - > eas = tmp ;
attribs - > num_eas + = 1 ;
2007-10-22 20:14:57 +04:00
}
2008-10-15 17:57:39 +04:00
attribs - > eas [ i ] . name = name ;
attribs - > eas [ i ] . value . data = CONST_DISCARD ( uint8 * , value ) ;
attribs - > eas [ i ] . value . length = size ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
status = xattr_tdb_save_attrs ( rec , attribs ) ;
2007-10-22 20:14:57 +04:00
TALLOC_FREE ( rec ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " save failed: %s \n " , nt_errstr ( status ) ) ) ;
return - 1 ;
}
return 0 ;
}
2008-01-15 19:06:12 +03:00
static int xattr_tdb_setxattr ( struct vfs_handle_struct * handle ,
const char * path , const char * name ,
const void * value , size_t size , int flags )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
2009-06-23 02:26:56 +04:00
if ( vfs_stat_smb_fname ( handle - > conn , path , & sbuf ) = = - 1 ) {
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2009-02-16 10:38:53 +03:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
return xattr_tdb_setattr ( db , & id , name , value , size , flags ) ;
2007-10-22 20:14:57 +04:00
}
2008-01-15 19:06:12 +03:00
static int xattr_tdb_fsetxattr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
const char * name , const void * value ,
size_t size , int flags )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
if ( SMB_VFS_FSTAT ( fsp , & sbuf ) = = - 1 ) {
return - 1 ;
}
2009-02-16 10:38:53 +03:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
return xattr_tdb_setattr ( db , & id , name , value , size , flags ) ;
2007-10-22 20:14:57 +04:00
}
/*
* Worker routine for listxattr and flistxattr
*/
2008-01-15 19:06:12 +03:00
static ssize_t xattr_tdb_listattr ( struct db_context * db_ctx ,
const struct file_id * id , char * list ,
size_t size )
2007-10-22 20:14:57 +04:00
{
NTSTATUS status ;
struct tdb_xattrs * attribs ;
uint32_t i ;
size_t len = 0 ;
2008-01-15 19:06:12 +03:00
status = xattr_tdb_load_attrs ( talloc_tos ( ) , db_ctx , id , & attribs ) ;
2007-10-22 20:14:57 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-15 19:06:12 +03:00
DEBUG ( 10 , ( " xattr_tdb_fetch_attrs failed: %s \n " ,
2007-10-22 20:14:57 +04:00
nt_errstr ( status ) ) ) ;
errno = EINVAL ;
return - 1 ;
}
2008-01-15 19:06:12 +03:00
DEBUG ( 10 , ( " xattr_tdb_listattr: Found %d xattrs \n " ,
2008-10-15 17:57:39 +04:00
attribs - > num_eas ) ) ;
2007-10-22 20:14:57 +04:00
2008-10-15 17:57:39 +04:00
for ( i = 0 ; i < attribs - > num_eas ; i + + ) {
2007-10-22 20:14:57 +04:00
size_t tmp ;
2008-01-15 19:06:12 +03:00
DEBUG ( 10 , ( " xattr_tdb_listattr: xattrs[i].name: %s \n " ,
2008-10-15 17:57:39 +04:00
attribs - > eas [ i ] . name ) ) ;
2007-10-22 20:14:57 +04:00
2008-10-15 17:57:39 +04:00
tmp = strlen ( attribs - > eas [ i ] . name ) ;
2007-10-22 20:14:57 +04:00
/*
* Try to protect against overflow
*/
if ( len + ( tmp + 1 ) < len ) {
TALLOC_FREE ( attribs ) ;
errno = EINVAL ;
return - 1 ;
}
/*
* Take care of the terminating NULL
*/
len + = ( tmp + 1 ) ;
}
if ( len > size ) {
TALLOC_FREE ( attribs ) ;
errno = ERANGE ;
return - 1 ;
}
len = 0 ;
2008-10-15 17:57:39 +04:00
for ( i = 0 ; i < attribs - > num_eas ; i + + ) {
strlcpy ( list + len , attribs - > eas [ i ] . name ,
2007-10-22 20:14:57 +04:00
size - len ) ;
2008-10-15 17:57:39 +04:00
len + = ( strlen ( attribs - > eas [ i ] . name ) + 1 ) ;
2007-10-22 20:14:57 +04:00
}
TALLOC_FREE ( attribs ) ;
return len ;
}
2008-01-15 19:06:12 +03:00
static ssize_t xattr_tdb_listxattr ( struct vfs_handle_struct * handle ,
const char * path , char * list , size_t size )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
2009-06-23 02:26:56 +04:00
if ( vfs_stat_smb_fname ( handle - > conn , path , & sbuf ) = = - 1 ) {
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2009-02-16 10:38:53 +03:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
return xattr_tdb_listattr ( db , & id , list , size ) ;
2007-10-22 20:14:57 +04:00
}
2008-01-15 19:06:12 +03:00
static ssize_t xattr_tdb_flistxattr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , char * list ,
size_t size )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
if ( SMB_VFS_FSTAT ( fsp , & sbuf ) = = - 1 ) {
return - 1 ;
}
2009-02-16 10:38:53 +03:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
return xattr_tdb_listattr ( db , & id , list , size ) ;
2007-10-22 20:14:57 +04:00
}
/*
* Worker routine for removexattr and fremovexattr
*/
2008-01-15 19:06:12 +03:00
static int xattr_tdb_removeattr ( struct db_context * db_ctx ,
const struct file_id * id , const char * name )
2007-10-22 20:14:57 +04:00
{
NTSTATUS status ;
struct db_record * rec ;
struct tdb_xattrs * attribs ;
uint32_t i ;
2008-01-15 19:06:12 +03:00
rec = xattr_tdb_lock_attrs ( talloc_tos ( ) , db_ctx , id ) ;
2007-10-22 20:14:57 +04:00
if ( rec = = NULL ) {
2008-01-15 19:06:12 +03:00
DEBUG ( 0 , ( " xattr_tdb_lock_attrs failed \n " ) ) ;
2007-10-22 20:14:57 +04:00
errno = EINVAL ;
return - 1 ;
}
2008-01-15 19:06:12 +03:00
status = xattr_tdb_pull_attrs ( rec , & rec - > value , & attribs ) ;
2007-10-22 20:14:57 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-15 19:06:12 +03:00
DEBUG ( 10 , ( " xattr_tdb_fetch_attrs failed: %s \n " ,
2007-10-22 20:14:57 +04:00
nt_errstr ( status ) ) ) ;
TALLOC_FREE ( rec ) ;
return - 1 ;
}
2008-10-15 17:57:39 +04:00
for ( i = 0 ; i < attribs - > num_eas ; i + + ) {
if ( strcmp ( attribs - > eas [ i ] . name , name ) = = 0 ) {
2007-10-22 20:14:57 +04:00
break ;
}
}
2008-10-15 17:57:39 +04:00
if ( i = = attribs - > num_eas ) {
2007-10-22 20:14:57 +04:00
TALLOC_FREE ( rec ) ;
errno = ENOATTR ;
return - 1 ;
}
2008-10-15 17:57:39 +04:00
attribs - > eas [ i ] =
attribs - > eas [ attribs - > num_eas - 1 ] ;
attribs - > num_eas - = 1 ;
2007-10-22 20:14:57 +04:00
2008-10-15 17:57:39 +04:00
if ( attribs - > num_eas = = 0 ) {
2007-10-22 20:14:57 +04:00
rec - > delete_rec ( rec ) ;
TALLOC_FREE ( rec ) ;
return 0 ;
}
2008-01-15 19:06:12 +03:00
status = xattr_tdb_save_attrs ( rec , attribs ) ;
2007-10-22 20:14:57 +04:00
TALLOC_FREE ( rec ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " save failed: %s \n " , nt_errstr ( status ) ) ) ;
return - 1 ;
}
return 0 ;
}
2008-01-15 19:06:12 +03:00
static int xattr_tdb_removexattr ( struct vfs_handle_struct * handle ,
const char * path , const char * name )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
2009-06-23 02:26:56 +04:00
if ( vfs_stat_smb_fname ( handle - > conn , path , & sbuf ) = = - 1 ) {
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2009-02-16 10:38:53 +03:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
return xattr_tdb_removeattr ( db , & id , name ) ;
2007-10-22 20:14:57 +04:00
}
2008-01-15 19:06:12 +03:00
static int xattr_tdb_fremovexattr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , const char * name )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
if ( SMB_VFS_FSTAT ( fsp , & sbuf ) = = - 1 ) {
return - 1 ;
}
2009-02-16 10:38:53 +03:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
return xattr_tdb_removeattr ( db , & id , name ) ;
2007-10-22 20:14:57 +04:00
}
/*
* Open the tdb file upon VFS_CONNECT
*/
2008-01-15 19:06:12 +03:00
static bool xattr_tdb_init ( int snum , struct db_context * * p_db )
2007-10-22 20:14:57 +04:00
{
struct db_context * db ;
const char * dbname ;
2009-01-16 01:43:00 +03:00
char * def_dbname ;
2007-10-22 20:14:57 +04:00
2009-01-16 01:43:00 +03:00
def_dbname = state_path ( " xattr.tdb " ) ;
if ( def_dbname = = NULL ) {
2008-01-25 22:52:20 +03:00
errno = ENOSYS ;
2007-10-22 20:14:57 +04:00
return false ;
}
2009-01-16 01:43:00 +03:00
dbname = lp_parm_const_string ( snum , " xattr_tdb " , " file " , def_dbname ) ;
/* now we know dbname is not NULL */
2007-10-22 20:14:57 +04:00
become_root ( ) ;
db = db_open ( NULL , dbname , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
unbecome_root ( ) ;
if ( db = = NULL ) {
2008-02-25 19:05:21 +03:00
# if defined(ENOTSUP)
2007-10-22 20:14:57 +04:00
errno = ENOTSUP ;
2008-02-25 19:05:21 +03:00
# else
errno = ENOSYS ;
# endif
2009-01-16 01:43:00 +03:00
TALLOC_FREE ( def_dbname ) ;
2007-10-22 20:14:57 +04:00
return false ;
}
* p_db = db ;
2009-01-16 01:43:00 +03:00
TALLOC_FREE ( def_dbname ) ;
2007-10-22 20:14:57 +04:00
return true ;
}
/*
* On unlink we need to delete the tdb record
*/
2009-07-02 20:27:44 +04:00
static int xattr_tdb_unlink ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname )
2007-10-22 20:14:57 +04:00
{
2009-07-02 20:27:44 +04:00
struct smb_filename * smb_fname_tmp = NULL ;
2007-10-22 20:14:57 +04:00
struct file_id id ;
struct db_context * db ;
struct db_record * rec ;
2009-07-02 20:27:44 +04:00
NTSTATUS status ;
int ret = - 1 ;
2009-08-13 03:27:17 +04:00
bool remove_record = false ;
2007-10-22 20:14:57 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
2009-07-02 20:27:44 +04:00
status = copy_smb_filename ( talloc_tos ( ) , smb_fname , & smb_fname_tmp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2009-10-17 03:37:20 +04:00
if ( lp_posix_pathnames ( ) ) {
ret = SMB_VFS_LSTAT ( handle - > conn , smb_fname_tmp ) ;
} else {
ret = SMB_VFS_STAT ( handle - > conn , smb_fname_tmp ) ;
}
if ( ret = = - 1 ) {
2009-07-02 20:27:44 +04:00
goto out ;
}
2009-10-17 03:37:20 +04:00
2009-08-13 03:27:17 +04:00
if ( smb_fname_tmp - > st . st_ex_nlink = = 1 ) {
/* Only remove record on last link to file. */
remove_record = true ;
}
2009-07-02 20:27:44 +04:00
ret = SMB_VFS_NEXT_UNLINK ( handle , smb_fname_tmp ) ;
2007-10-22 20:14:57 +04:00
if ( ret = = - 1 ) {
2009-07-02 20:27:44 +04:00
goto out ;
2007-10-22 20:14:57 +04:00
}
2009-08-13 03:27:17 +04:00
if ( ! remove_record ) {
goto out ;
}
2009-07-02 20:27:44 +04:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & smb_fname_tmp - > st ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
rec = xattr_tdb_lock_attrs ( talloc_tos ( ) , db , & id ) ;
2007-10-22 20:14:57 +04:00
/*
* If rec = = NULL there ' s not much we can do about it
*/
if ( rec ! = NULL ) {
rec - > delete_rec ( rec ) ;
TALLOC_FREE ( rec ) ;
}
2009-07-02 20:27:44 +04:00
out :
TALLOC_FREE ( smb_fname_tmp ) ;
return ret ;
2007-10-22 20:14:57 +04:00
}
/*
* On rmdir we need to delete the tdb record
*/
2008-01-15 19:06:12 +03:00
static int xattr_tdb_rmdir ( vfs_handle_struct * handle , const char * path )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
struct db_record * rec ;
int ret ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context , return - 1 ) ;
2009-06-23 02:26:56 +04:00
if ( vfs_stat_smb_fname ( handle - > conn , path , & sbuf ) = = - 1 ) {
2007-10-22 20:14:57 +04:00
return - 1 ;
}
ret = SMB_VFS_NEXT_RMDIR ( handle , path ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
2009-02-16 10:38:53 +03:00
id = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2008-01-15 19:06:12 +03:00
rec = xattr_tdb_lock_attrs ( talloc_tos ( ) , db , & id ) ;
2007-10-22 20:14:57 +04:00
/*
* If rec = = NULL there ' s not much we can do about it
*/
if ( rec ! = NULL ) {
rec - > delete_rec ( rec ) ;
TALLOC_FREE ( rec ) ;
}
return 0 ;
}
/*
* Destructor for the VFS private data
*/
2008-01-20 13:10:06 +03:00
static void close_xattr_db ( void * * data )
2007-10-22 20:14:57 +04:00
{
struct db_context * * p_db = ( struct db_context * * ) data ;
TALLOC_FREE ( * p_db ) ;
}
2008-01-15 19:06:12 +03:00
static int xattr_tdb_connect ( vfs_handle_struct * handle , const char * service ,
2007-10-22 20:14:57 +04:00
const char * user )
{
2010-11-10 02:07:49 +03:00
char * sname = NULL ;
2007-10-22 20:14:57 +04:00
int res , snum ;
struct db_context * db ;
res = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( res < 0 ) {
return res ;
}
2010-11-10 02:07:49 +03:00
snum = find_service ( talloc_tos ( ) , service , & sname ) ;
if ( snum = = - 1 | | sname = = NULL ) {
2007-10-22 20:14:57 +04:00
/*
* Should not happen , but we should not fail just * here * .
*/
return 0 ;
}
2008-01-15 19:06:12 +03:00
if ( ! xattr_tdb_init ( snum , & db ) ) {
2008-01-20 13:10:06 +03:00
DEBUG ( 5 , ( " Could not init xattr tdb \n " ) ) ;
2007-10-22 20:14:57 +04:00
lp_do_parameter ( snum , " ea support " , " False " ) ;
return 0 ;
}
lp_do_parameter ( snum , " ea support " , " True " ) ;
2008-01-20 13:10:06 +03:00
SMB_VFS_HANDLE_SET_DATA ( handle , db , close_xattr_db ,
2007-10-22 20:14:57 +04:00
struct db_context , return - 1 ) ;
return 0 ;
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_xattr_tdb_fns = {
. getxattr = xattr_tdb_getxattr ,
. fgetxattr = xattr_tdb_fgetxattr ,
. setxattr = xattr_tdb_setxattr ,
. fsetxattr = xattr_tdb_fsetxattr ,
. listxattr = xattr_tdb_listxattr ,
. flistxattr = xattr_tdb_flistxattr ,
. removexattr = xattr_tdb_removexattr ,
. fremovexattr = xattr_tdb_fremovexattr ,
. unlink = xattr_tdb_unlink ,
. rmdir = xattr_tdb_rmdir ,
. connect_fn = xattr_tdb_connect ,
2007-10-22 20:14:57 +04:00
} ;
2008-01-15 19:06:12 +03:00
NTSTATUS vfs_xattr_tdb_init ( void ) ;
NTSTATUS vfs_xattr_tdb_init ( void )
2007-10-22 20:14:57 +04:00
{
2008-01-15 19:06:12 +03:00
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " xattr_tdb " ,
2009-07-24 04:28:58 +04:00
& vfs_xattr_tdb_fns ) ;
2007-10-22 20:14:57 +04:00
}