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
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config {
struct db_context * db ;
2022-07-27 13:47:21 +03:00
bool ignore_user_xattr ;
2022-07-27 12:59:54 +03:00
} ;
static bool xattr_tdb_init ( struct vfs_handle_struct * handle ,
struct xattr_tdb_config * * _config ) ;
2012-08-20 13:20:19 +04:00
2022-07-27 13:47:21 +03:00
static bool is_user_xattr ( const char * xattr_name )
{
int match ;
match = strncmp ( xattr_name , " user. " , strlen ( " user. " ) ) ;
return ( match = = 0 ) ;
}
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 ;
2020-05-03 16:06:12 +03:00
smb_fname = synthetic_smb_fname ( frame ,
path ,
NULL ,
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2020-05-03 16:06:12 +03:00
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 ;
}
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 ;
} ;
2022-07-27 13:47:21 +03:00
static void xattr_tdb_getxattrat_done ( struct tevent_req * subreq ) ;
2018-06-21 18:04:22 +03:00
static struct tevent_req * xattr_tdb_getxattrat_send (
TALLOC_CTX * mem_ctx ,
2018-12-27 18:32:46 +03:00
struct tevent_context * ev ,
2018-06-21 18:04:22 +03:00
struct vfs_handle_struct * handle ,
files_struct * dir_fsp ,
const struct smb_filename * smb_fname ,
const char * xattr_name ,
size_t alloc_hint )
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * config = NULL ;
2018-06-21 18:04:22 +03:00
struct tevent_req * req = NULL ;
2022-07-27 13:47:21 +03:00
struct tevent_req * subreq = NULL ;
2018-06-21 18:04:22 +03:00
struct xattr_tdb_getxattrat_state * state = NULL ;
struct smb_filename * cwd = NULL ;
struct file_id id ;
int ret ;
int error ;
int cwd_ret ;
DATA_BLOB xattr_blob ;
2022-07-27 12:59:54 +03:00
if ( ! xattr_tdb_init ( handle , & config ) ) {
return NULL ;
}
2018-06-21 18:04:22 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct xattr_tdb_getxattrat_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > xattr_size = - 1 ;
2022-07-27 13:47:21 +03:00
if ( config - > ignore_user_xattr & & is_user_xattr ( xattr_name ) ) {
subreq = SMB_VFS_NEXT_GETXATTRAT_SEND ( state ,
ev ,
handle ,
dir_fsp ,
smb_fname ,
xattr_name ,
alloc_hint ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , xattr_tdb_getxattrat_done , req ) ;
return req ;
}
2018-06-21 18:04:22 +03:00
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 ) ;
}
2022-07-27 12:59:54 +03:00
state - > xattr_size = xattr_tdb_getattr ( config - > db ,
2018-06-21 18:04:22 +03:00
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 ) ;
}
2022-07-27 13:47:21 +03:00
static void xattr_tdb_getxattrat_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct xattr_tdb_getxattrat_state * state = tevent_req_data (
req , struct xattr_tdb_getxattrat_state ) ;
state - > xattr_size = SMB_VFS_NEXT_GETXATTRAT_RECV ( subreq ,
& state - > vfs_aio_state ,
state ,
& state - > xattr_value ) ;
TALLOC_FREE ( subreq ) ;
if ( state - > xattr_size = = - 1 ) {
tevent_req_error ( req , state - > vfs_aio_state . error ) ;
return ;
}
tevent_req_done ( req ) ;
}
2018-06-21 18:04:22 +03:00
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
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * config = NULL ;
2007-10-22 20:14:57 +04:00
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
2012-04-16 11:14:06 +04:00
ssize_t xattr_size ;
DATA_BLOB blob ;
2022-07-27 12:59:54 +03:00
TALLOC_CTX * frame = NULL ;
if ( ! xattr_tdb_init ( handle , & config ) ) {
return - 1 ;
}
2007-10-22 20:14:57 +04:00
2022-07-27 13:47:21 +03:00
if ( config - > ignore_user_xattr & & is_user_xattr ( name ) ) {
return SMB_VFS_NEXT_FGETXATTR (
handle , fsp , name , value , size ) ;
}
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 ) {
2007-10-22 20:14:57 +04:00
return - 1 ;
}
2022-07-27 12:59:54 +03:00
frame = talloc_stackframe ( ) ;
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
2022-07-27 12:59:54 +03:00
xattr_size = xattr_tdb_getattr ( config - > db , frame , & id , name , & blob ) ;
2012-04-16 11:14:06 +04:00
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_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
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * config = NULL ;
2007-10-22 20:14:57 +04:00
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
2012-08-20 13:20:19 +04:00
int ret ;
2007-10-22 20:14:57 +04:00
2022-07-27 12:59:54 +03:00
if ( ! xattr_tdb_init ( handle , & config ) ) {
return - 1 ;
}
2007-10-22 20:14:57 +04:00
2022-07-27 13:47:21 +03:00
if ( config - > ignore_user_xattr & & is_user_xattr ( name ) ) {
return SMB_VFS_NEXT_FSETXATTR (
handle , fsp , name , value , size , flags ) ;
}
2012-08-15 16:21:48 +04:00
if ( SMB_VFS_NEXT_FSTAT ( handle , fsp , & sbuf ) = = - 1 ) {
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
2022-07-27 12:59:54 +03:00
ret = xattr_tdb_setattr ( config - > db , & id , name , value , size , flags ) ;
2012-08-20 13:20:19 +04:00
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
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * config = NULL ;
2007-10-22 20:14:57 +04:00
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
2022-07-27 13:47:21 +03:00
ssize_t backend_size ;
ssize_t ret ;
2007-10-22 20:14:57 +04:00
2022-07-27 12:59:54 +03:00
if ( ! xattr_tdb_init ( handle , & config ) ) {
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 ) {
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
2022-07-27 13:47:21 +03:00
ret = xattr_tdb_listattr ( config - > db , & id , list , size ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
if ( ret = = size ) {
return ret ;
}
if ( ! config - > ignore_user_xattr ) {
return ret ;
}
SMB_ASSERT ( ret < size ) ;
backend_size = SMB_VFS_NEXT_FLISTXATTR (
handle , fsp , list + ret , size - ret ) ;
if ( backend_size = = - 1 ) {
return - 1 ;
}
return ret + backend_size ;
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
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * config = NULL ;
2007-10-22 20:14:57 +04:00
SMB_STRUCT_STAT sbuf ;
struct file_id id ;
2022-07-27 12:59:54 +03:00
if ( ! xattr_tdb_init ( handle , & config ) ) {
return - 1 ;
}
2007-10-22 20:14:57 +04:00
2022-07-27 13:47:21 +03:00
if ( config - > ignore_user_xattr & & is_user_xattr ( name ) ) {
return SMB_VFS_NEXT_FREMOVEXATTR ( handle , fsp , name ) ;
}
2012-08-15 16:21:48 +04:00
if ( SMB_VFS_NEXT_FSTAT ( handle , fsp , & sbuf ) = = - 1 ) {
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
2022-07-27 12:59:54 +03:00
return xattr_tdb_removeattr ( config - > db , & id , name ) ;
2007-10-22 20:14:57 +04:00
}
2022-07-27 13:43:01 +03:00
/*
* Destructor for the VFS private data
*/
2022-07-27 12:59:54 +03:00
static void config_destructor ( void * * data )
2022-07-27 13:43:01 +03:00
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * * config = ( struct xattr_tdb_config * * ) data ;
TALLOC_FREE ( ( * config ) - > db ) ;
2022-07-27 13:43:01 +03:00
}
2007-10-22 20:14:57 +04:00
/*
* Open the tdb file upon VFS_CONNECT
*/
2022-07-27 12:59:54 +03:00
static bool xattr_tdb_init ( struct vfs_handle_struct * handle ,
struct xattr_tdb_config * * _config )
2007-10-22 20:14:57 +04:00
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * config = NULL ;
2007-10-22 20:14:57 +04:00
const char * dbname ;
2009-01-16 01:43:00 +03:00
char * def_dbname ;
2007-10-22 20:14:57 +04:00
2022-07-27 12:59:54 +03:00
if ( SMB_VFS_HANDLE_TEST_DATA ( handle ) ) {
SMB_VFS_HANDLE_GET_DATA ( handle , config , struct xattr_tdb_config ,
return false ) ;
if ( _config ! = NULL ) {
* _config = config ;
}
return true ;
}
config = talloc_zero ( handle - > conn , struct xattr_tdb_config ) ;
if ( config = = NULL ) {
errno = ENOMEM ;
goto error ;
}
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 ;
2022-07-27 12:59:54 +03:00
goto error ;
2007-10-22 20:14:57 +04:00
}
2022-07-27 12:59:54 +03:00
dbname = lp_parm_const_string ( SNUM ( handle - > conn ) ,
" xattr_tdb " ,
" file " ,
def_dbname ) ;
2009-01-16 01:43:00 +03:00
/* now we know dbname is not NULL */
2007-10-22 20:14:57 +04:00
become_root ( ) ;
2022-07-27 12:59:54 +03:00
config - > db = db_open ( handle , dbname , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ,
DBWRAP_LOCK_ORDER_2 , DBWRAP_FLAG_NONE ) ;
2007-10-22 20:14:57 +04:00
unbecome_root ( ) ;
2022-07-27 12:59:54 +03:00
if ( config - > 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 ) ;
2022-07-27 12:59:54 +03:00
goto error ;
2007-10-22 20:14:57 +04:00
}
2009-01-16 01:43:00 +03:00
TALLOC_FREE ( def_dbname ) ;
2022-07-27 12:59:54 +03:00
2022-07-27 13:47:21 +03:00
config - > ignore_user_xattr = lp_parm_bool (
SNUM ( handle - > conn ) , " xattr_tdb " , " ignore_user_xattr " , false ) ;
2022-07-27 12:59:54 +03:00
SMB_VFS_HANDLE_SET_DATA ( handle , config , config_destructor ,
struct xattr_tdb_config , return false ) ;
if ( _config ! = NULL ) {
* _config = config ;
}
2007-10-22 20:14:57 +04:00
return true ;
2022-07-27 12:59:54 +03:00
error :
DBG_WARNING ( " Failed to initialize config: %s \n " , strerror ( errno ) ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " ea support " , " False " ) ;
return false ;
2007-10-22 20:14:57 +04:00
}
2020-05-20 23:32:57 +03:00
static int xattr_tdb_openat ( struct vfs_handle_struct * handle ,
const struct files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
struct files_struct * fsp ,
int flags ,
mode_t mode )
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * config = NULL ;
2020-05-20 23:32:57 +03:00
SMB_STRUCT_STAT sbuf ;
2020-09-26 22:46:51 +03:00
int fd ;
2020-05-20 23:32:57 +03:00
int ret ;
2022-07-27 12:59:54 +03:00
if ( ! xattr_tdb_init ( handle , & config ) ) {
return - 1 ;
}
2020-09-26 22:46:51 +03:00
fd = SMB_VFS_NEXT_OPENAT ( handle ,
dirfsp ,
smb_fname ,
fsp ,
flags ,
mode ) ;
2020-05-20 23:32:57 +03:00
2020-09-26 22:46:51 +03:00
if ( fd = = - 1 ) {
return - 1 ;
2020-05-20 23:32:57 +03:00
}
if ( ( flags & ( O_CREAT | O_EXCL ) ) ! = ( O_CREAT | O_EXCL ) ) {
2020-09-26 22:46:51 +03:00
return fd ;
2020-05-20 23:32:57 +03:00
}
/*
* We know we used O_CREAT | O_EXCL and it worked .
* We must have created the file .
*/
2020-11-24 18:16:10 +03:00
fsp_set_fd ( fsp , fd ) ;
2020-05-20 23:32:57 +03:00
ret = SMB_VFS_FSTAT ( fsp , & sbuf ) ;
2020-11-24 18:16:10 +03:00
fsp_set_fd ( fsp , - 1 ) ;
2020-05-20 23:32:57 +03:00
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 , & sbuf ) ;
2022-07-27 12:59:54 +03:00
xattr_tdb_remove_all_attrs ( config - > db , & fsp - > file_id ) ;
2020-05-20 23:32:57 +03:00
2020-09-26 22:46:51 +03:00
return fd ;
2020-05-20 23:32:57 +03:00
}
2019-09-05 21:09:40 +03:00
static int xattr_tdb_mkdirat ( vfs_handle_struct * handle ,
struct files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
mode_t mode )
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * config = NULL ;
2019-09-05 21:09:40 +03:00
TALLOC_CTX * frame = NULL ;
struct file_id fileid ;
int ret ;
2020-12-14 17:38:07 +03:00
struct smb_filename * full_fname = NULL ;
2019-09-05 21:09:40 +03:00
2022-07-27 12:59:54 +03:00
if ( ! xattr_tdb_init ( handle , & config ) ) {
return - 1 ;
}
2019-09-05 21:09:40 +03:00
ret = SMB_VFS_NEXT_MKDIRAT ( handle ,
dirfsp ,
smb_fname ,
mode ) ;
if ( ret < 0 ) {
return ret ;
}
frame = talloc_stackframe ( ) ;
2020-12-14 17:38:07 +03:00
full_fname = full_path_from_dirfsp_atname ( talloc_tos ( ) ,
dirfsp ,
smb_fname ) ;
if ( full_fname = = NULL ) {
2019-09-05 21:09:40 +03:00
errno = ENOMEM ;
return - 1 ;
}
2020-09-29 13:56:26 +03:00
/* Always use LSTAT here - we just created the directory. */
2020-12-14 17:38:07 +03:00
ret = SMB_VFS_LSTAT ( handle - > conn , full_fname ) ;
2019-09-05 21:09:40 +03:00
if ( ret = = - 1 ) {
/* Rename race. Let upper level take care of it. */
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2020-12-14 17:38:07 +03:00
if ( ! S_ISDIR ( full_fname - > st . st_ex_mode ) ) {
2019-09-05 21:09:40 +03:00
/* Rename race. Let upper level take care of it. */
TALLOC_FREE ( frame ) ;
return - 1 ;
}
2020-12-14 17:38:07 +03:00
fileid = SMB_VFS_FILE_ID_CREATE ( handle - > conn , & full_fname - > st ) ;
2019-09-05 21:09:40 +03:00
2022-07-27 12:59:54 +03:00
xattr_tdb_remove_all_attrs ( config - > db , & fileid ) ;
2019-09-05 21:09:40 +03:00
TALLOC_FREE ( frame ) ;
return 0 ;
}
2019-09-13 20:12:38 +03:00
/*
* On unlink we need to delete the tdb record
*/
static int xattr_tdb_unlinkat ( vfs_handle_struct * handle ,
struct files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
int flags )
{
2022-07-27 12:59:54 +03:00
struct xattr_tdb_config * config = NULL ;
2019-09-13 20:12:38 +03:00
struct smb_filename * smb_fname_tmp = NULL ;
2021-01-20 17:22:52 +03:00
struct smb_filename * full_fname = NULL ;
2019-09-13 20:12:38 +03:00
struct file_id id ;
int ret = - 1 ;
bool remove_record = false ;
2022-07-27 12:59:54 +03:00
TALLOC_CTX * frame = NULL ;
if ( ! xattr_tdb_init ( handle , & config ) ) {
return - 1 ;
}
2019-09-13 20:12:38 +03:00
2022-07-27 12:59:54 +03:00
frame = talloc_stackframe ( ) ;
2019-09-13 20:12:38 +03:00
smb_fname_tmp = cp_smb_filename ( frame , smb_fname ) ;
if ( smb_fname_tmp = = NULL ) {
TALLOC_FREE ( frame ) ;
errno = ENOMEM ;
return - 1 ;
}
2021-01-20 17:22:52 +03:00
/*
* TODO : use SMB_VFS_STATX ( ) once we have that
*/
full_fname = full_path_from_dirfsp_atname ( frame ,
dirfsp ,
smb_fname ) ;
if ( full_fname = = NULL ) {
goto out ;
}
if ( full_fname - > flags & SMB_FILENAME_POSIX_PATH ) {
ret = SMB_VFS_NEXT_LSTAT ( handle , full_fname ) ;
2019-09-13 20:12:38 +03:00
} else {
2021-01-20 17:22:52 +03:00
ret = SMB_VFS_NEXT_STAT ( handle , full_fname ) ;
2021-10-25 22:02:43 +03:00
if ( ret = = - 1 & & ( errno = = ENOENT | | errno = = ELOOP ) ) {
if ( VALID_STAT ( smb_fname - > st ) & &
S_ISLNK ( smb_fname - > st . st_ex_mode ) ) {
/*
* Original name was a link - Could be
* trying to remove a dangling symlink .
*/
ret = SMB_VFS_NEXT_LSTAT ( handle , full_fname ) ;
}
}
2019-09-13 20:12:38 +03:00
}
if ( ret = = - 1 ) {
goto out ;
}
2021-01-20 17:22:52 +03:00
smb_fname_tmp - > st = full_fname - > st ;
2019-09-13 20:12:38 +03:00
if ( flags & AT_REMOVEDIR ) {
/* Always remove record when removing a directory succeeds. */
remove_record = true ;
} else {
if ( smb_fname_tmp - > st . st_ex_nlink = = 1 ) {
/* Only remove record on last link to file. */
remove_record = true ;
}
}
ret = SMB_VFS_NEXT_UNLINKAT ( handle ,
dirfsp ,
smb_fname_tmp ,
flags ) ;
if ( ret = = - 1 ) {
goto out ;
}
if ( ! remove_record ) {
goto out ;
}
id = SMB_VFS_NEXT_FILE_ID_CREATE ( handle , & smb_fname_tmp - > st ) ;
2022-07-27 12:59:54 +03:00
xattr_tdb_remove_all_attrs ( config - > db , & id ) ;
2019-09-13 20:12:38 +03:00
out :
TALLOC_FREE ( frame ) ;
return ret ;
}
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 ;
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 ;
}
2022-07-27 12:59:54 +03:00
if ( ! xattr_tdb_init ( handle , NULL ) ) {
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 " ) ;
return 0 ;
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_xattr_tdb_fns = {
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 ,
. fsetxattr_fn = xattr_tdb_fsetxattr ,
. flistxattr_fn = xattr_tdb_flistxattr ,
. fremovexattr_fn = xattr_tdb_fremovexattr ,
2020-05-20 23:32:57 +03:00
. openat_fn = xattr_tdb_openat ,
2019-09-05 21:09:40 +03:00
. mkdirat_fn = xattr_tdb_mkdirat ,
2019-09-13 20:12:38 +03:00
. unlinkat_fn = xattr_tdb_unlinkat ,
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
}