2007-10-22 20:14:57 +04:00
/*
* Store posix - level xattrs in a tdb
*
* Copyright ( C ) Volker Lendecke , 2007
2012-08-20 13:20:19 +04:00
* Copyright ( C ) Andrew Bartlett , 2012
2007-10-22 20:14:57 +04: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
* 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"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2011-07-07 19:42:08 +04:00
# include "dbwrap/dbwrap.h"
2011-07-06 18:40:21 +04:00
# include "dbwrap/dbwrap_open.h"
2012-04-16 09:49:13 +04:00
# include "source3/lib/xattr_tdb.h"
2018-06-21 18:04:22 +03:00
# include "lib/util/tevent_unix.h"
2007-10-22 20:14:57 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
2012-08-20 13:20:19 +04:00
static bool xattr_tdb_init ( int snum , TALLOC_CTX * mem_ctx , struct db_context * * p_db ) ;
2012-08-16 04:02:44 +04:00
static int xattr_tdb_get_file_id ( struct vfs_handle_struct * handle ,
const char * path , struct file_id * id )
{
int ret ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-04-12 13:09:25 +04:00
struct smb_filename * smb_fname ;
2016-03-19 07:19:38 +03:00
smb_fname = synthetic_smb_fname ( frame , path , NULL , NULL , 0 ) ;
2013-04-12 13:09:25 +04:00
if ( smb_fname = = NULL ) {
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
2012-08-16 04:02:44 +04:00
return - 1 ;
}
ret = SMB_VFS_NEXT_STAT ( handle , smb_fname ) ;
if ( ret = = - 1 ) {
TALLOC_FREE ( frame ) ;
return - 1 ;
}
* id = SMB_VFS_NEXT_FILE_ID_CREATE ( handle , & smb_fname - > st ) ;
TALLOC_FREE ( frame ) ;
return 0 ;
}
2008-01-15 19:06:12 +03:00
static ssize_t xattr_tdb_getxattr ( struct vfs_handle_struct * handle ,
2017-05-26 02:42:04 +03:00
const struct smb_filename * smb_fname ,
const char * name ,
void * value ,
size_t size )
2007-10-22 20:14:57 +04:00
{
struct file_id id ;
struct db_context * db ;
2012-04-16 11:14:06 +04:00
ssize_t xattr_size ;
2012-08-16 04:02:44 +04:00
int ret ;
2012-04-16 11:14:06 +04:00
DATA_BLOB blob ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2007-10-22 20:14:57 +04:00
2012-07-17 23:33:31 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
2012-08-20 13:20:19 +04:00
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2007-10-22 20:14:57 +04:00
2017-05-26 02:42:04 +03:00
ret = xattr_tdb_get_file_id ( handle , smb_fname - > base_name , & id ) ;
2012-08-16 04:02:44 +04:00
if ( ret = = - 1 ) {
2012-04-16 11:14:06 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2012-04-16 11:14:06 +04:00
xattr_size = xattr_tdb_getattr ( db , frame , & id , name , & blob ) ;
if ( xattr_size < 0 ) {
2012-08-15 16:22:26 +04:00
errno = ENOATTR ;
2012-04-16 11:14:06 +04:00
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2017-04-13 12:50:47 +03:00
if ( size = = 0 ) {
TALLOC_FREE ( frame ) ;
return xattr_size ;
}
2012-04-16 11:14:06 +04:00
if ( blob . length > size ) {
TALLOC_FREE ( frame ) ;
errno = ERANGE ;
return - 1 ;
}
2012-05-21 16:41:40 +04:00
memcpy ( value , blob . data , xattr_size ) ;
2012-07-17 23:33:31 +04:00
TALLOC_FREE ( frame ) ;
2012-04-16 11:14:06 +04:00
return xattr_size ;
2007-10-22 20:14:57 +04:00
}
2018-06-21 18:04:22 +03:00
struct xattr_tdb_getxattrat_state {
struct vfs_aio_state vfs_aio_state ;
ssize_t xattr_size ;
uint8_t * xattr_value ;
} ;
static struct tevent_req * xattr_tdb_getxattrat_send (
TALLOC_CTX * mem_ctx ,
const struct smb_vfs_ev_glue * evg ,
struct vfs_handle_struct * handle ,
files_struct * dir_fsp ,
const struct smb_filename * smb_fname ,
const char * xattr_name ,
size_t alloc_hint )
{
struct tevent_context * ev = smb_vfs_ev_glue_ev_ctx ( evg ) ;
struct tevent_req * req = NULL ;
struct xattr_tdb_getxattrat_state * state = NULL ;
struct smb_filename * cwd = NULL ;
struct db_context * db = NULL ;
struct file_id id ;
int ret ;
int error ;
int cwd_ret ;
DATA_BLOB xattr_blob ;
req = tevent_req_create ( mem_ctx , & state ,
struct xattr_tdb_getxattrat_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > xattr_size = - 1 ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , state , & db ) ) {
tevent_req_error ( req , EIO ) ;
return tevent_req_post ( req , ev ) ;
} ) ;
cwd = SMB_VFS_GETWD ( dir_fsp - > conn , state ) ;
if ( tevent_req_nomem ( cwd , req ) ) {
return tevent_req_post ( req , ev ) ;
}
ret = SMB_VFS_CHDIR ( dir_fsp - > conn , dir_fsp - > fsp_name ) ;
if ( ret ! = 0 ) {
tevent_req_error ( req , errno ) ;
return tevent_req_post ( req , ev ) ;
}
ret = xattr_tdb_get_file_id ( handle , smb_fname - > base_name , & id ) ;
error = errno ;
cwd_ret = SMB_VFS_CHDIR ( dir_fsp - > conn , cwd ) ;
SMB_ASSERT ( cwd_ret = = 0 ) ;
if ( ret = = - 1 ) {
tevent_req_error ( req , error ) ;
return tevent_req_post ( req , ev ) ;
}
state - > xattr_size = xattr_tdb_getattr ( db ,
state ,
& id ,
xattr_name ,
& xattr_blob ) ;
if ( state - > xattr_size = = - 1 ) {
tevent_req_error ( req , errno ) ;
return tevent_req_post ( req , ev ) ;
}
if ( alloc_hint = = 0 ) {
/*
* The caller only wants to know the size .
*/
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
if ( state - > xattr_size = = 0 ) {
/*
* There ' s no data .
*/
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
if ( xattr_blob . length > alloc_hint ) {
/*
* The data doesn ' t fit .
*/
state - > xattr_size = - 1 ;
tevent_req_error ( req , ERANGE ) ;
return tevent_req_post ( req , ev ) ;
}
/*
* take the whole blob .
*/
state - > xattr_value = xattr_blob . data ;
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
static ssize_t xattr_tdb_getxattrat_recv ( struct tevent_req * req ,
struct vfs_aio_state * aio_state ,
TALLOC_CTX * mem_ctx ,
uint8_t * * xattr_value )
{
struct xattr_tdb_getxattrat_state * state = tevent_req_data (
req , struct xattr_tdb_getxattrat_state ) ;
ssize_t xattr_size ;
if ( tevent_req_is_unix_error ( req , & aio_state - > error ) ) {
tevent_req_received ( req ) ;
return - 1 ;
}
* aio_state = state - > vfs_aio_state ;
xattr_size = state - > xattr_size ;
if ( xattr_value ! = NULL ) {
* xattr_value = talloc_move ( mem_ctx , & state - > xattr_value ) ;
}
tevent_req_received ( req ) ;
return xattr_size ;
}
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 ;
2012-04-16 11:14:06 +04:00
ssize_t xattr_size ;
DATA_BLOB blob ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2007-10-22 20:14:57 +04:00
2012-08-15 16:21:48 +04:00
if ( SMB_VFS_NEXT_FSTAT ( handle , fsp , & sbuf ) = = - 1 ) {
2012-04-16 11:14:06 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2012-08-16 04:02:44 +04:00
id = SMB_VFS_NEXT_FILE_ID_CREATE ( handle , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2012-04-16 11:14:06 +04:00
xattr_size = xattr_tdb_getattr ( db , frame , & id , name , & blob ) ;
if ( xattr_size < 0 ) {
2012-08-15 16:22:26 +04:00
errno = ENOATTR ;
2012-04-16 11:14:06 +04:00
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2017-04-13 12:50:47 +03:00
if ( size = = 0 ) {
TALLOC_FREE ( frame ) ;
return xattr_size ;
}
2012-04-16 11:14:06 +04:00
if ( blob . length > size ) {
TALLOC_FREE ( frame ) ;
errno = ERANGE ;
return - 1 ;
}
2012-06-01 12:32:54 +04:00
memcpy ( value , blob . data , xattr_size ) ;
2012-04-16 11:14:06 +04:00
TALLOC_FREE ( frame ) ;
return xattr_size ;
2007-10-22 20:14:57 +04:00
}
2008-01-15 19:06:12 +03:00
static int xattr_tdb_setxattr ( struct vfs_handle_struct * handle ,
2017-05-25 22:41:31 +03:00
const struct smb_filename * smb_fname ,
const char * name ,
const void * value ,
size_t size ,
int flags )
2007-10-22 20:14:57 +04:00
{
struct file_id id ;
struct db_context * db ;
2012-08-16 04:02:44 +04:00
int ret ;
2012-08-20 13:20:19 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2007-10-22 20:14:57 +04:00
2017-05-25 22:41:31 +03:00
ret = xattr_tdb_get_file_id ( handle , smb_fname - > base_name , & id ) ;
2012-08-16 04:02:44 +04:00
if ( ret = = - 1 ) {
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2012-08-20 13:20:19 +04:00
ret = xattr_tdb_setattr ( db , & id , name , value , size , flags ) ;
TALLOC_FREE ( frame ) ;
return ret ;
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 ;
2012-08-20 13:20:19 +04:00
int ret ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2007-10-22 20:14:57 +04:00
2012-08-15 16:21:48 +04:00
if ( SMB_VFS_NEXT_FSTAT ( handle , fsp , & sbuf ) = = - 1 ) {
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2012-08-16 04:02:44 +04:00
id = SMB_VFS_NEXT_FILE_ID_CREATE ( handle , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
ret = xattr_tdb_setattr ( db , & id , name , value , size , flags ) ;
TALLOC_FREE ( frame ) ;
return ret ;
2007-10-22 20:14:57 +04:00
}
2008-01-15 19:06:12 +03:00
static ssize_t xattr_tdb_listxattr ( struct vfs_handle_struct * handle ,
2017-05-23 23:12:29 +03:00
const struct smb_filename * smb_fname ,
char * list ,
size_t size )
2007-10-22 20:14:57 +04:00
{
struct file_id id ;
struct db_context * db ;
2012-08-16 04:02:44 +04:00
int ret ;
2012-08-20 13:20:19 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2007-10-22 20:14:57 +04:00
2017-05-23 23:12:29 +03:00
ret = xattr_tdb_get_file_id ( handle , smb_fname - > base_name , & id ) ;
2012-08-16 04:02:44 +04:00
if ( ret = = - 1 ) {
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2012-08-20 13:20:19 +04:00
ret = xattr_tdb_listattr ( db , & id , list , size ) ;
TALLOC_FREE ( frame ) ;
return ret ;
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 ;
2012-08-20 13:20:19 +04:00
int ret ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2007-10-22 20:14:57 +04:00
2012-08-15 16:21:48 +04:00
if ( SMB_VFS_NEXT_FSTAT ( handle , fsp , & sbuf ) = = - 1 ) {
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2012-08-16 04:02:44 +04:00
id = SMB_VFS_NEXT_FILE_ID_CREATE ( handle , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
ret = xattr_tdb_listattr ( db , & id , list , size ) ;
TALLOC_FREE ( frame ) ;
return ret ;
2007-10-22 20:14:57 +04:00
}
2008-01-15 19:06:12 +03:00
static int xattr_tdb_removexattr ( struct vfs_handle_struct * handle ,
2017-05-24 21:35:50 +03:00
const struct smb_filename * smb_fname ,
const char * name )
2007-10-22 20:14:57 +04:00
{
struct file_id id ;
struct db_context * db ;
2012-08-16 04:02:44 +04:00
int ret ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2017-05-24 21:35:50 +03:00
ret = xattr_tdb_get_file_id ( handle , smb_fname - > base_name , & id ) ;
2012-08-16 04:02:44 +04:00
if ( ret = = - 1 ) {
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2012-08-16 04:02:44 +04:00
return ret ;
}
2007-10-22 20:14:57 +04:00
2012-08-16 04:02:44 +04:00
2012-08-20 13:20:19 +04:00
ret = xattr_tdb_removeattr ( db , & id , name ) ;
TALLOC_FREE ( frame ) ;
return ret ;
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 ;
2012-08-20 13:20:19 +04:00
int ret ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2007-10-22 20:14:57 +04:00
2012-08-15 16:21:48 +04:00
if ( SMB_VFS_NEXT_FSTAT ( handle , fsp , & sbuf ) = = - 1 ) {
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2012-08-16 04:02:44 +04:00
id = SMB_VFS_NEXT_FILE_ID_CREATE ( handle , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
ret = xattr_tdb_removeattr ( db , & id , name ) ;
TALLOC_FREE ( frame ) ;
return ret ;
2007-10-22 20:14:57 +04:00
}
/*
* Open the tdb file upon VFS_CONNECT
*/
2012-08-20 13:20:19 +04:00
static bool xattr_tdb_init ( int snum , TALLOC_CTX * mem_ctx , 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
2018-08-16 11:51:44 +03:00
def_dbname = state_path ( talloc_tos ( ) , " xattr.tdb " ) ;
2009-01-16 01:43:00 +03:00
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 ( ) ;
2012-01-06 20:19:54 +04:00
db = db_open ( NULL , dbname , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ,
2014-01-27 17:49:12 +04:00
DBWRAP_LOCK_ORDER_2 , DBWRAP_FLAG_NONE ) ;
2007-10-22 20:14:57 +04:00
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 ;
}
2016-07-21 02:40:53 +03:00
static int xattr_tdb_open ( vfs_handle_struct * handle ,
struct smb_filename * smb_fname ,
files_struct * fsp ,
int flags ,
mode_t mode )
{
struct db_context * db = NULL ;
TALLOC_CTX * frame = NULL ;
int ret ;
fsp - > fh - > fd = SMB_VFS_NEXT_OPEN ( handle ,
smb_fname , fsp ,
flags ,
mode ) ;
if ( fsp - > fh - > fd < 0 ) {
return fsp - > fh - > fd ;
}
if ( ( flags & ( O_CREAT | O_EXCL ) ) ! = ( O_CREAT | O_EXCL ) ) {
return fsp - > fh - > fd ;
}
/*
* We know we used O_CREAT | O_EXCL and it worked .
* We must have created the file .
*/
ret = SMB_VFS_FSTAT ( fsp , & smb_fname - > st ) ;
if ( ret = = - 1 ) {
/* Can't happen... */
DBG_WARNING ( " SMB_VFS_FSTAT failed on file %s (%s) \n " ,
smb_fname_str_dbg ( smb_fname ) ,
strerror ( errno ) ) ;
return - 1 ;
}
fsp - > file_id = SMB_VFS_FILE_ID_CREATE ( fsp - > conn , & smb_fname - > st ) ;
frame = talloc_stackframe ( ) ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
xattr_tdb_remove_all_attrs ( db , & fsp - > file_id ) ;
TALLOC_FREE ( frame ) ;
return fsp - > fh - > fd ;
}
static int xattr_tdb_mkdir ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
mode_t mode )
{
struct db_context * db = NULL ;
TALLOC_CTX * frame = NULL ;
struct file_id fileid ;
int ret ;
struct smb_filename * smb_fname_tmp = NULL ;
ret = SMB_VFS_NEXT_MKDIR ( handle , smb_fname , mode ) ;
if ( ret < 0 ) {
return ret ;
}
frame = talloc_stackframe ( ) ;
smb_fname_tmp = cp_smb_filename ( frame , smb_fname ) ;
if ( smb_fname_tmp = = NULL ) {
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
return - 1 ;
}
/* Always use LSTAT here - we just creaded the directory. */
ret = SMB_VFS_LSTAT ( handle - > conn , smb_fname_tmp ) ;
if ( ret = = - 1 ) {
/* Rename race. Let upper level take care of it. */
TALLOC_FREE ( frame ) ;
return - 1 ;
}
if ( ! S_ISDIR ( smb_fname_tmp - > st . st_ex_mode ) ) {
/* Rename race. Let upper level take care of it. */
TALLOC_FREE ( frame ) ;
return - 1 ;
}
fileid = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & smb_fname_tmp - > st ) ;
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
xattr_tdb_remove_all_attrs ( db , & fileid ) ;
TALLOC_FREE ( frame ) ;
return 0 ;
}
2007-10-22 20:14:57 +04:00
/*
* 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 ;
2009-07-02 20:27:44 +04:00
int ret = - 1 ;
2009-08-13 03:27:17 +04:00
bool remove_record = false ;
2012-08-20 13:20:19 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2007-10-22 20:14:57 +04:00
2013-04-11 17:35:02 +04:00
smb_fname_tmp = cp_smb_filename ( frame , smb_fname ) ;
if ( smb_fname_tmp = = NULL ) {
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2013-04-11 17:35:02 +04:00
errno = ENOMEM ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2016-03-19 07:58:20 +03:00
if ( smb_fname_tmp - > flags & SMB_FILENAME_POSIX_PATH ) {
2012-08-15 16:21:48 +04:00
ret = SMB_VFS_NEXT_LSTAT ( handle , smb_fname_tmp ) ;
2009-10-17 03:37:20 +04:00
} else {
2012-08-15 16:21:48 +04:00
ret = SMB_VFS_NEXT_STAT ( handle , smb_fname_tmp ) ;
2009-10-17 03:37:20 +04:00
}
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 ;
}
2012-08-16 04:02:44 +04:00
id = SMB_VFS_NEXT_FILE_ID_CREATE ( handle , & smb_fname_tmp - > st ) ;
2007-10-22 20:14:57 +04:00
2012-04-16 09:49:13 +04:00
xattr_tdb_remove_all_attrs ( db , & id ) ;
2007-10-22 20:14:57 +04:00
2009-07-02 20:27:44 +04:00
out :
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2009-07-02 20:27:44 +04:00
return ret ;
2007-10-22 20:14:57 +04:00
}
/*
* On rmdir we need to delete the tdb record
*/
2016-02-25 01:02:45 +03:00
static int xattr_tdb_rmdir ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname )
2007-10-22 20:14:57 +04:00
{
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
struct db_context * db ;
int ret ;
2012-08-20 13:20:19 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , db , struct db_context ,
if ( ! xattr_tdb_init ( - 1 , frame , & db ) )
{
TALLOC_FREE ( frame ) ; return - 1 ;
} ) ;
2007-10-22 20:14:57 +04:00
2016-03-12 03:07:20 +03:00
if ( vfs_stat_smb_basename ( handle - > conn ,
2016-03-19 08:17:30 +03:00
smb_fname ,
2016-03-12 03:07:20 +03:00
& sbuf ) = = - 1 ) {
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2016-02-25 01:02:45 +03:00
ret = SMB_VFS_NEXT_RMDIR ( handle , smb_fname ) ;
2007-10-22 20:14:57 +04:00
if ( ret = = - 1 ) {
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2012-08-16 04:02:44 +04:00
id = SMB_VFS_NEXT_FILE_ID_CREATE ( handle , & sbuf ) ;
2007-10-22 20:14:57 +04:00
2012-04-16 09:49:13 +04:00
xattr_tdb_remove_all_attrs ( db , & id ) ;
2007-10-22 20:14:57 +04:00
2012-08-20 13:20:19 +04:00
TALLOC_FREE ( frame ) ;
2007-10-22 20:14:57 +04:00
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 ;
}
2012-08-20 13:20:19 +04:00
if ( ! xattr_tdb_init ( snum , NULL , & 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 = {
2011-12-04 08:45:04 +04:00
. getxattr_fn = xattr_tdb_getxattr ,
2018-06-21 18:04:22 +03:00
. getxattrat_send_fn = xattr_tdb_getxattrat_send ,
. getxattrat_recv_fn = xattr_tdb_getxattrat_recv ,
2011-12-04 08:45:04 +04:00
. fgetxattr_fn = xattr_tdb_fgetxattr ,
. setxattr_fn = xattr_tdb_setxattr ,
. fsetxattr_fn = xattr_tdb_fsetxattr ,
. listxattr_fn = xattr_tdb_listxattr ,
. flistxattr_fn = xattr_tdb_flistxattr ,
. removexattr_fn = xattr_tdb_removexattr ,
. fremovexattr_fn = xattr_tdb_fremovexattr ,
2016-07-21 02:40:53 +03:00
. open_fn = xattr_tdb_open ,
. mkdir_fn = xattr_tdb_mkdir ,
2011-12-04 08:45:04 +04:00
. unlink_fn = xattr_tdb_unlink ,
. rmdir_fn = xattr_tdb_rmdir ,
2009-07-24 04:28:58 +04:00
. connect_fn = xattr_tdb_connect ,
2007-10-22 20:14:57 +04:00
} ;
2017-12-16 01:32:12 +03:00
static_decl_vfs ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_xattr_tdb_init ( TALLOC_CTX * ctx )
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
}