2013-05-29 15:21:46 +04:00
/*
Unix SMB / CIFS implementation .
Wrap GlusterFS GFAPI calls in vfs functions .
Copyright ( c ) 2013 Anand Avati < avati @ redhat . com >
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/>.
*/
2013-12-12 22:27:10 +04:00
/**
* @ file vfs_glusterfs . c
* @ author Anand Avati < avati @ redhat . com >
* @ date May 2013
* @ brief Samba VFS module for glusterfs
*
* @ todo
* - AIO support \ n
* See , for example \ c vfs_aio_linux . c in the \ c sourc3 / modules directory
* - sendfile / recvfile support
*
* A Samba VFS module for GlusterFS , based on Gluster ' s libgfapi .
* This is a " bottom " vfs module ( not something to be stacked on top of
* another module ) , and translates ( most ) calls to the closest actions
* available in libgfapi .
*
*/
2013-05-29 15:21:46 +04:00
# include "includes.h"
# include "smbd/smbd.h"
# include <stdio.h>
# include "api/glfs.h"
# include "lib/util/dlinklist.h"
# define DEFAULT_VOLFILE_SERVER "localhost"
2013-12-12 22:29:20 +04:00
/**
* Helper to convert struct stat to struct stat_ex .
*/
2013-05-29 15:21:46 +04:00
static void smb_stat_ex_from_stat ( struct stat_ex * dst , const struct stat * src )
{
ZERO_STRUCTP ( dst ) ;
dst - > st_ex_dev = src - > st_dev ;
dst - > st_ex_ino = src - > st_ino ;
dst - > st_ex_mode = src - > st_mode ;
dst - > st_ex_nlink = src - > st_nlink ;
dst - > st_ex_uid = src - > st_uid ;
dst - > st_ex_gid = src - > st_gid ;
dst - > st_ex_rdev = src - > st_rdev ;
dst - > st_ex_size = src - > st_size ;
dst - > st_ex_atime . tv_sec = src - > st_atime ;
dst - > st_ex_mtime . tv_sec = src - > st_mtime ;
dst - > st_ex_ctime . tv_sec = src - > st_ctime ;
dst - > st_ex_btime . tv_sec = src - > st_mtime ;
2013-12-12 22:29:20 +04:00
dst - > st_ex_blksize = src - > st_blksize ;
dst - > st_ex_blocks = src - > st_blocks ;
2013-05-29 15:21:46 +04:00
# ifdef STAT_HAVE_NSEC
2013-12-12 22:29:20 +04:00
dst - > st_ex_atime . tv_nsec = src - > st_atime_nsec ;
dst - > st_ex_mtime . tv_nsec = src - > st_mtime_nsec ;
dst - > st_ex_ctime . tv_nsec = src - > st_ctime_nsec ;
2013-05-29 15:21:46 +04:00
dst - > st_ex_btime . tv_nsec = src - > st_mtime_nsec ;
# endif
}
/* pre-opened glfs_t */
static struct glfs_preopened {
char * volume ;
2014-12-10 09:56:34 +03:00
char * connectpath ;
2013-05-29 15:21:46 +04:00
glfs_t * fs ;
int ref ;
struct glfs_preopened * next , * prev ;
} * glfs_preopened ;
2014-12-10 09:56:34 +03:00
static int glfs_set_preopened ( const char * volume , const char * connectpath , glfs_t * fs )
2013-05-29 15:21:46 +04:00
{
struct glfs_preopened * entry = NULL ;
entry = talloc_zero ( NULL , struct glfs_preopened ) ;
if ( ! entry ) {
errno = ENOMEM ;
return - 1 ;
}
entry - > volume = talloc_strdup ( entry , volume ) ;
if ( ! entry - > volume ) {
talloc_free ( entry ) ;
errno = ENOMEM ;
return - 1 ;
}
2014-12-10 09:56:34 +03:00
entry - > connectpath = talloc_strdup ( entry , connectpath ) ;
if ( entry - > connectpath = = NULL ) {
talloc_free ( entry ) ;
errno = ENOMEM ;
return - 1 ;
}
2013-05-29 15:21:46 +04:00
entry - > fs = fs ;
entry - > ref = 1 ;
DLIST_ADD ( glfs_preopened , entry ) ;
return 0 ;
}
2014-12-10 09:56:34 +03:00
static glfs_t * glfs_find_preopened ( const char * volume , const char * connectpath )
2013-05-29 15:21:46 +04:00
{
struct glfs_preopened * entry = NULL ;
for ( entry = glfs_preopened ; entry ; entry = entry - > next ) {
2014-12-10 09:56:34 +03:00
if ( strcmp ( entry - > volume , volume ) = = 0 & &
strcmp ( entry - > connectpath , connectpath ) = = 0 )
{
2013-05-29 15:21:46 +04:00
entry - > ref + + ;
return entry - > fs ;
}
}
return NULL ;
}
static void glfs_clear_preopened ( glfs_t * fs )
{
struct glfs_preopened * entry = NULL ;
for ( entry = glfs_preopened ; entry ; entry = entry - > next ) {
if ( entry - > fs = = fs ) {
if ( - - entry - > ref )
return ;
DLIST_REMOVE ( glfs_preopened , entry ) ;
glfs_fini ( entry - > fs ) ;
talloc_free ( entry ) ;
}
}
}
/* Disk Operations */
static int vfs_gluster_connect ( struct vfs_handle_struct * handle ,
const char * service ,
const char * user )
{
const char * volfile_server ;
const char * volume ;
2013-11-22 09:04:11 +04:00
char * logfile ;
2013-05-29 15:21:46 +04:00
int loglevel ;
2013-11-22 09:04:11 +04:00
glfs_t * fs = NULL ;
TALLOC_CTX * tmp_ctx ;
int ret = 0 ;
2013-05-29 15:21:46 +04:00
2013-11-22 09:04:11 +04:00
tmp_ctx = talloc_new ( NULL ) ;
if ( tmp_ctx = = NULL ) {
ret = - 1 ;
goto done ;
}
logfile = lp_parm_talloc_string ( tmp_ctx , SNUM ( handle - > conn ) , " glusterfs " ,
2013-05-29 15:21:46 +04:00
" logfile " , NULL ) ;
loglevel = lp_parm_int ( SNUM ( handle - > conn ) , " glusterfs " , " loglevel " , - 1 ) ;
volfile_server = lp_parm_const_string ( SNUM ( handle - > conn ) , " glusterfs " ,
" volfile_server " , NULL ) ;
if ( volfile_server = = NULL ) {
volfile_server = DEFAULT_VOLFILE_SERVER ;
}
volume = lp_parm_const_string ( SNUM ( handle - > conn ) , " glusterfs " , " volume " ,
NULL ) ;
if ( volume = = NULL ) {
volume = service ;
}
2014-12-10 09:56:34 +03:00
fs = glfs_find_preopened ( volume , handle - > conn - > connectpath ) ;
2013-05-29 15:21:46 +04:00
if ( fs ) {
2013-11-22 09:04:11 +04:00
goto done ;
2013-05-29 15:21:46 +04:00
}
fs = glfs_new ( volume ) ;
if ( fs = = NULL ) {
2013-11-22 09:04:11 +04:00
ret = - 1 ;
goto done ;
2013-05-29 15:21:46 +04:00
}
ret = glfs_set_volfile_server ( fs , " tcp " , volfile_server , 0 ) ;
if ( ret < 0 ) {
DEBUG ( 0 , ( " Failed to set volfile_server %s \n " , volfile_server ) ) ;
2013-11-22 09:04:11 +04:00
goto done ;
2013-05-29 15:21:46 +04:00
}
ret = glfs_set_xlator_option ( fs , " *-md-cache " , " cache-posix-acl " ,
" true " ) ;
if ( ret < 0 ) {
DEBUG ( 0 , ( " %s: Failed to set xlator options \n " , volume ) ) ;
2013-11-22 09:04:11 +04:00
goto done ;
2013-05-29 15:21:46 +04:00
}
ret = glfs_set_logging ( fs , logfile , loglevel ) ;
if ( ret < 0 ) {
DEBUG ( 0 , ( " %s: Failed to set logfile %s loglevel %d \n " ,
volume , logfile , loglevel ) ) ;
2013-11-22 09:04:11 +04:00
goto done ;
2013-05-29 15:21:46 +04:00
}
ret = glfs_init ( fs ) ;
if ( ret < 0 ) {
DEBUG ( 0 , ( " %s: Failed to initialize volume (%s) \n " ,
volume , strerror ( errno ) ) ) ;
2013-11-22 09:04:11 +04:00
goto done ;
2013-05-29 15:21:46 +04:00
}
2014-12-10 09:56:34 +03:00
ret = glfs_set_preopened ( volume , handle - > conn - > connectpath , fs ) ;
2013-05-29 15:21:46 +04:00
if ( ret < 0 ) {
DEBUG ( 0 , ( " %s: Failed to register volume (%s) \n " ,
volume , strerror ( errno ) ) ) ;
2013-11-22 09:04:11 +04:00
goto done ;
}
done :
talloc_free ( tmp_ctx ) ;
if ( ret < 0 ) {
if ( fs )
glfs_fini ( fs ) ;
2013-05-29 15:21:46 +04:00
return - 1 ;
2013-11-22 09:04:11 +04:00
} else {
DEBUG ( 0 , ( " %s: Initialized volume from server %s \n " ,
volume , volfile_server ) ) ;
handle - > data = fs ;
return 0 ;
2013-05-29 15:21:46 +04:00
}
}
static void vfs_gluster_disconnect ( struct vfs_handle_struct * handle )
{
glfs_t * fs = NULL ;
fs = handle - > data ;
glfs_clear_preopened ( fs ) ;
}
static uint64_t vfs_gluster_disk_free ( struct vfs_handle_struct * handle ,
const char * path , bool small_query ,
uint64_t * bsize_p , uint64_t * dfree_p ,
uint64_t * dsize_p )
{
struct statvfs statvfs = { 0 , } ;
int ret ;
ret = glfs_statvfs ( handle - > data , path , & statvfs ) ;
if ( ret < 0 ) {
return - 1 ;
}
if ( bsize_p ! = NULL ) {
2013-08-07 01:45:06 +04:00
* bsize_p = ( uint64_t ) statvfs . f_bsize ; /* Block size */
2013-05-29 15:21:46 +04:00
}
if ( dfree_p ! = NULL ) {
2013-08-07 01:45:06 +04:00
* dfree_p = ( uint64_t ) statvfs . f_bavail ; /* Available Block units */
2013-05-29 15:21:46 +04:00
}
if ( dsize_p ! = NULL ) {
2013-08-07 01:45:06 +04:00
* dsize_p = ( uint64_t ) statvfs . f_blocks ; /* Total Block units */
2013-05-29 15:21:46 +04:00
}
2013-08-07 01:45:06 +04:00
return ( uint64_t ) statvfs . f_bavail ;
2013-05-29 15:21:46 +04:00
}
static int vfs_gluster_get_quota ( struct vfs_handle_struct * handle ,
enum SMB_QUOTA_TYPE qtype , unid_t id ,
SMB_DISK_QUOTA * qt )
{
errno = ENOSYS ;
return - 1 ;
}
static int
vfs_gluster_set_quota ( struct vfs_handle_struct * handle ,
enum SMB_QUOTA_TYPE qtype , unid_t id , SMB_DISK_QUOTA * qt )
{
errno = ENOSYS ;
return - 1 ;
}
static int vfs_gluster_statvfs ( struct vfs_handle_struct * handle ,
const char * path ,
struct vfs_statvfs_struct * vfs_statvfs )
{
struct statvfs statvfs = { 0 , } ;
int ret ;
ret = glfs_statvfs ( handle - > data , path , & statvfs ) ;
if ( ret < 0 ) {
DEBUG ( 0 , ( " glfs_statvfs(%s) failed: %s \n " ,
path , strerror ( errno ) ) ) ;
return - 1 ;
}
ZERO_STRUCTP ( vfs_statvfs ) ;
vfs_statvfs - > OptimalTransferSize = statvfs . f_frsize ;
vfs_statvfs - > BlockSize = statvfs . f_bsize ;
vfs_statvfs - > TotalBlocks = statvfs . f_blocks ;
vfs_statvfs - > BlocksAvail = statvfs . f_bfree ;
vfs_statvfs - > UserBlocksAvail = statvfs . f_bavail ;
vfs_statvfs - > TotalFileNodes = statvfs . f_files ;
vfs_statvfs - > FreeFileNodes = statvfs . f_ffree ;
vfs_statvfs - > FsIdentifier = statvfs . f_fsid ;
vfs_statvfs - > FsCapabilities =
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES ;
return ret ;
}
static uint32_t vfs_gluster_fs_capabilities ( struct vfs_handle_struct * handle ,
enum timestamp_set_resolution * p_ts_res )
{
uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES ;
# ifdef STAT_HAVE_NSEC
* p_ts_res = TIMESTAMP_SET_NT_OR_BETTER ;
# endif
return caps ;
}
static DIR * vfs_gluster_opendir ( struct vfs_handle_struct * handle ,
const char * path , const char * mask ,
uint32 attributes )
{
glfs_fd_t * fd ;
fd = glfs_opendir ( handle - > data , path ) ;
if ( fd = = NULL ) {
DEBUG ( 0 , ( " glfs_opendir(%s) failed: %s \n " ,
path , strerror ( errno ) ) ) ;
}
return ( DIR * ) fd ;
}
static DIR * vfs_gluster_fdopendir ( struct vfs_handle_struct * handle ,
files_struct * fsp , const char * mask ,
uint32 attributes )
{
2013-12-13 02:06:36 +04:00
return ( DIR * ) * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) ;
2013-05-29 15:21:46 +04:00
}
static int vfs_gluster_closedir ( struct vfs_handle_struct * handle , DIR * dirp )
{
return glfs_closedir ( ( void * ) dirp ) ;
}
static struct dirent * vfs_gluster_readdir ( struct vfs_handle_struct * handle ,
DIR * dirp , SMB_STRUCT_STAT * sbuf )
{
static char direntbuf [ 512 ] ;
int ret ;
struct stat stat ;
struct dirent * dirent = 0 ;
if ( sbuf ! = NULL ) {
ret = glfs_readdirplus_r ( ( void * ) dirp , & stat , ( void * ) direntbuf ,
& dirent ) ;
} else {
ret = glfs_readdir_r ( ( void * ) dirp , ( void * ) direntbuf , & dirent ) ;
}
if ( ( ret < 0 ) | | ( dirent = = NULL ) ) {
return NULL ;
}
if ( sbuf ! = NULL ) {
smb_stat_ex_from_stat ( sbuf , & stat ) ;
}
return dirent ;
}
static long vfs_gluster_telldir ( struct vfs_handle_struct * handle , DIR * dirp )
{
return glfs_telldir ( ( void * ) dirp ) ;
}
static void vfs_gluster_seekdir ( struct vfs_handle_struct * handle , DIR * dirp ,
long offset )
{
glfs_seekdir ( ( void * ) dirp , offset ) ;
}
static void vfs_gluster_rewinddir ( struct vfs_handle_struct * handle , DIR * dirp )
{
glfs_seekdir ( ( void * ) dirp , 0 ) ;
}
static void vfs_gluster_init_search_op ( struct vfs_handle_struct * handle ,
DIR * dirp )
{
return ;
}
static int vfs_gluster_mkdir ( struct vfs_handle_struct * handle , const char * path ,
mode_t mode )
{
return glfs_mkdir ( handle - > data , path , mode ) ;
}
static int vfs_gluster_rmdir ( struct vfs_handle_struct * handle , const char * path )
{
return glfs_rmdir ( handle - > data , path ) ;
}
static int vfs_gluster_open ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname , files_struct * fsp ,
int flags , mode_t mode )
{
glfs_fd_t * glfd ;
2013-12-13 02:06:36 +04:00
glfs_fd_t * * p_tmp ;
2013-05-29 15:21:46 +04:00
if ( flags & O_DIRECTORY ) {
glfd = glfs_opendir ( handle - > data , smb_fname - > base_name ) ;
} else if ( flags & O_CREAT ) {
glfd = glfs_creat ( handle - > data , smb_fname - > base_name , flags ,
mode ) ;
} else {
glfd = glfs_open ( handle - > data , smb_fname - > base_name , flags ) ;
}
if ( glfd = = NULL ) {
return - 1 ;
}
2013-12-13 02:06:36 +04:00
p_tmp = ( glfs_fd_t * * ) VFS_ADD_FSP_EXTENSION ( handle , fsp ,
glfs_fd_t * , NULL ) ;
* p_tmp = glfd ;
/* An arbitrary value for error reporting, so you know its us. */
return 13371337 ;
2013-05-29 15:21:46 +04:00
}
static int vfs_gluster_close ( struct vfs_handle_struct * handle ,
files_struct * fsp )
{
2013-12-13 02:06:36 +04:00
glfs_fd_t * glfd ;
glfd = * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) ;
VFS_REMOVE_FSP_EXTENSION ( handle , fsp ) ;
return glfs_close ( glfd ) ;
2013-05-29 15:21:46 +04:00
}
static ssize_t vfs_gluster_read ( struct vfs_handle_struct * handle ,
files_struct * fsp , void * data , size_t n )
{
2013-12-13 02:06:36 +04:00
return glfs_read ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , data , n , 0 ) ;
2013-05-29 15:21:46 +04:00
}
static ssize_t vfs_gluster_pread ( struct vfs_handle_struct * handle ,
files_struct * fsp , void * data , size_t n ,
off_t offset )
{
2013-12-13 02:06:36 +04:00
return glfs_pread ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , data , n , offset , 0 ) ;
2013-05-29 15:21:46 +04:00
}
static struct tevent_req * vfs_gluster_pread_send ( struct vfs_handle_struct
* handle , TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
files_struct * fsp , void * data ,
size_t n , off_t offset )
{
errno = ENOTSUP ;
return NULL ;
}
static ssize_t vfs_gluster_pread_recv ( struct tevent_req * req , int * err )
{
errno = ENOTSUP ;
return - 1 ;
}
static ssize_t vfs_gluster_write ( struct vfs_handle_struct * handle ,
files_struct * fsp , const void * data , size_t n )
{
2013-12-13 02:06:36 +04:00
return glfs_write ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , data , n , 0 ) ;
2013-05-29 15:21:46 +04:00
}
static ssize_t vfs_gluster_pwrite ( struct vfs_handle_struct * handle ,
files_struct * fsp , const void * data ,
size_t n , off_t offset )
{
2013-12-13 02:06:36 +04:00
return glfs_pwrite ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , data , n , offset , 0 ) ;
2013-05-29 15:21:46 +04:00
}
static struct tevent_req * vfs_gluster_pwrite_send ( struct vfs_handle_struct
* handle , TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
files_struct * fsp ,
const void * data , size_t n ,
off_t offset )
{
errno = ENOTSUP ;
return NULL ;
}
static ssize_t vfs_gluster_pwrite_recv ( struct tevent_req * req , int * err )
{
errno = ENOTSUP ;
return - 1 ;
}
static off_t vfs_gluster_lseek ( struct vfs_handle_struct * handle ,
files_struct * fsp , off_t offset , int whence )
{
2013-12-13 02:06:36 +04:00
return glfs_lseek ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , offset , whence ) ;
2013-05-29 15:21:46 +04:00
}
static ssize_t vfs_gluster_sendfile ( struct vfs_handle_struct * handle , int tofd ,
files_struct * fromfsp ,
const DATA_BLOB * hdr ,
off_t offset , size_t n )
{
errno = ENOTSUP ;
return - 1 ;
}
static ssize_t vfs_gluster_recvfile ( struct vfs_handle_struct * handle ,
int fromfd , files_struct * tofsp ,
off_t offset , size_t n )
{
errno = ENOTSUP ;
return - 1 ;
}
static int vfs_gluster_rename ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname_src ,
const struct smb_filename * smb_fname_dst )
{
return glfs_rename ( handle - > data , smb_fname_src - > base_name ,
smb_fname_dst - > base_name ) ;
}
static int vfs_gluster_fsync ( struct vfs_handle_struct * handle ,
files_struct * fsp )
{
2013-12-13 02:06:36 +04:00
return glfs_fsync ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) ) ;
2013-05-29 15:21:46 +04:00
}
static struct tevent_req * vfs_gluster_fsync_send ( struct vfs_handle_struct
* handle , TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
files_struct * fsp )
{
errno = ENOTSUP ;
return NULL ;
}
static int vfs_gluster_fsync_recv ( struct tevent_req * req , int * err )
{
errno = ENOTSUP ;
return - 1 ;
}
static int vfs_gluster_stat ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
{
struct stat st ;
int ret ;
ret = glfs_stat ( handle - > data , smb_fname - > base_name , & st ) ;
if ( ret = = 0 ) {
smb_stat_ex_from_stat ( & smb_fname - > st , & st ) ;
}
if ( ret < 0 & & errno ! = ENOENT ) {
DEBUG ( 0 , ( " glfs_stat(%s) failed: %s \n " ,
smb_fname - > base_name , strerror ( errno ) ) ) ;
}
return ret ;
}
static int vfs_gluster_fstat ( struct vfs_handle_struct * handle ,
files_struct * fsp , SMB_STRUCT_STAT * sbuf )
{
struct stat st ;
int ret ;
2013-12-13 02:06:36 +04:00
ret = glfs_fstat ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , & st ) ;
2013-05-29 15:21:46 +04:00
if ( ret = = 0 ) {
smb_stat_ex_from_stat ( sbuf , & st ) ;
}
if ( ret < 0 ) {
DEBUG ( 0 , ( " glfs_fstat(%d) failed: %s \n " ,
fsp - > fh - > fd , strerror ( errno ) ) ) ;
}
return ret ;
}
static int vfs_gluster_lstat ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
{
struct stat st ;
int ret ;
ret = glfs_lstat ( handle - > data , smb_fname - > base_name , & st ) ;
if ( ret = = 0 ) {
smb_stat_ex_from_stat ( & smb_fname - > st , & st ) ;
}
if ( ret < 0 & & errno ! = ENOENT ) {
DEBUG ( 0 , ( " glfs_lstat(%s) failed: %s \n " ,
smb_fname - > base_name , strerror ( errno ) ) ) ;
}
return ret ;
}
static uint64_t vfs_gluster_get_alloc_size ( struct vfs_handle_struct * handle ,
files_struct * fsp ,
const SMB_STRUCT_STAT * sbuf )
{
return sbuf - > st_ex_blocks * 512 ;
}
static int vfs_gluster_unlink ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname )
{
return glfs_unlink ( handle - > data , smb_fname - > base_name ) ;
}
static int vfs_gluster_chmod ( struct vfs_handle_struct * handle ,
const char * path , mode_t mode )
{
return glfs_chmod ( handle - > data , path , mode ) ;
}
static int vfs_gluster_fchmod ( struct vfs_handle_struct * handle ,
files_struct * fsp , mode_t mode )
{
2013-12-13 02:06:36 +04:00
return glfs_fchmod ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , mode ) ;
2013-05-29 15:21:46 +04:00
}
static int vfs_gluster_chown ( struct vfs_handle_struct * handle ,
const char * path , uid_t uid , gid_t gid )
{
return glfs_chown ( handle - > data , path , uid , gid ) ;
}
static int vfs_gluster_fchown ( struct vfs_handle_struct * handle ,
files_struct * fsp , uid_t uid , gid_t gid )
{
2013-12-13 02:06:36 +04:00
return glfs_fchown ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , uid , gid ) ;
2013-05-29 15:21:46 +04:00
}
static int vfs_gluster_lchown ( struct vfs_handle_struct * handle ,
const char * path , uid_t uid , gid_t gid )
{
return glfs_lchown ( handle - > data , path , uid , gid ) ;
}
static int vfs_gluster_chdir ( struct vfs_handle_struct * handle , const char * path )
{
return glfs_chdir ( handle - > data , path ) ;
}
static char * vfs_gluster_getwd ( struct vfs_handle_struct * handle )
{
char * cwd ;
char * ret ;
2013-11-04 15:32:04 +04:00
cwd = SMB_CALLOC_ARRAY ( char , PATH_MAX ) ;
2013-05-29 15:21:46 +04:00
if ( cwd = = NULL ) {
return NULL ;
}
2013-11-04 15:32:04 +04:00
ret = glfs_getcwd ( handle - > data , cwd , PATH_MAX - 1 ) ;
2013-05-29 15:21:46 +04:00
if ( ret = = 0 ) {
free ( cwd ) ;
}
return ret ;
}
static int vfs_gluster_ntimes ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
struct smb_file_time * ft )
{
struct timespec times [ 2 ] ;
2014-01-10 19:26:18 +04:00
if ( null_timespec ( ft - > atime ) ) {
times [ 0 ] . tv_sec = smb_fname - > st . st_ex_atime . tv_sec ;
times [ 0 ] . tv_nsec = smb_fname - > st . st_ex_atime . tv_nsec ;
} else {
times [ 0 ] . tv_sec = ft - > atime . tv_sec ;
times [ 0 ] . tv_nsec = ft - > atime . tv_nsec ;
}
if ( null_timespec ( ft - > mtime ) ) {
times [ 1 ] . tv_sec = smb_fname - > st . st_ex_mtime . tv_sec ;
times [ 1 ] . tv_nsec = smb_fname - > st . st_ex_mtime . tv_nsec ;
} else {
times [ 1 ] . tv_sec = ft - > mtime . tv_sec ;
times [ 1 ] . tv_nsec = ft - > mtime . tv_nsec ;
}
if ( ( timespec_compare ( & times [ 0 ] ,
& smb_fname - > st . st_ex_atime ) = = 0 ) & &
( timespec_compare ( & times [ 1 ] ,
& smb_fname - > st . st_ex_mtime ) = = 0 ) ) {
return 0 ;
}
2013-05-29 15:21:46 +04:00
return glfs_utimens ( handle - > data , smb_fname - > base_name , times ) ;
}
static int vfs_gluster_ftruncate ( struct vfs_handle_struct * handle ,
files_struct * fsp , off_t offset )
{
2013-12-13 02:06:36 +04:00
return glfs_ftruncate ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , offset ) ;
2013-05-29 15:21:46 +04:00
}
static int vfs_gluster_fallocate ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
enum vfs_fallocate_mode mode ,
off_t offset , off_t len )
{
errno = ENOTSUP ;
return - 1 ;
}
static char * vfs_gluster_realpath ( struct vfs_handle_struct * handle ,
const char * path )
{
return glfs_realpath ( handle - > data , path , 0 ) ;
}
static bool vfs_gluster_lock ( struct vfs_handle_struct * handle ,
files_struct * fsp , int op , off_t offset ,
off_t count , int type )
{
struct flock flock = { 0 , } ;
int ret ;
flock . l_type = type ;
flock . l_whence = SEEK_SET ;
flock . l_start = offset ;
flock . l_len = count ;
flock . l_pid = 0 ;
2013-12-13 02:06:36 +04:00
ret = glfs_posix_lock ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , op , & flock ) ;
2013-05-29 15:21:46 +04:00
if ( op = = F_GETLK ) {
/* lock query, true if someone else has locked */
if ( ( ret ! = - 1 ) & &
( flock . l_type ! = F_UNLCK ) & &
( flock . l_pid ! = 0 ) & & ( flock . l_pid ! = getpid ( ) ) )
return true ;
/* not me */
return false ;
}
if ( ret = = - 1 ) {
return false ;
}
return true ;
}
static int vfs_gluster_kernel_flock ( struct vfs_handle_struct * handle ,
files_struct * fsp , uint32 share_mode ,
uint32_t access_mask )
{
errno = ENOSYS ;
return - 1 ;
}
static int vfs_gluster_linux_setlease ( struct vfs_handle_struct * handle ,
files_struct * fsp , int leasetype )
{
errno = ENOSYS ;
return - 1 ;
}
static bool vfs_gluster_getlock ( struct vfs_handle_struct * handle ,
files_struct * fsp , off_t * poffset ,
off_t * pcount , int * ptype , pid_t * ppid )
{
struct flock flock = { 0 , } ;
int ret ;
flock . l_type = * ptype ;
flock . l_whence = SEEK_SET ;
flock . l_start = * poffset ;
flock . l_len = * pcount ;
flock . l_pid = 0 ;
2013-12-13 02:06:36 +04:00
ret = glfs_posix_lock ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , F_GETLK , & flock ) ;
2013-05-29 15:21:46 +04:00
if ( ret = = - 1 ) {
return false ;
}
* ptype = flock . l_type ;
* poffset = flock . l_start ;
* pcount = flock . l_len ;
* ppid = flock . l_pid ;
return true ;
}
static int vfs_gluster_symlink ( struct vfs_handle_struct * handle ,
const char * oldpath , const char * newpath )
{
return glfs_symlink ( handle - > data , oldpath , newpath ) ;
}
static int vfs_gluster_readlink ( struct vfs_handle_struct * handle ,
const char * path , char * buf , size_t bufsiz )
{
return glfs_readlink ( handle - > data , path , buf , bufsiz ) ;
}
static int vfs_gluster_link ( struct vfs_handle_struct * handle ,
const char * oldpath , const char * newpath )
{
return glfs_link ( handle - > data , oldpath , newpath ) ;
}
static int vfs_gluster_mknod ( struct vfs_handle_struct * handle , const char * path ,
mode_t mode , SMB_DEV_T dev )
{
return glfs_mknod ( handle - > data , path , mode , dev ) ;
}
static NTSTATUS vfs_gluster_notify_watch ( struct vfs_handle_struct * handle ,
struct sys_notify_context * ctx ,
const char * path , uint32_t * filter ,
uint32_t * subdir_filter ,
void ( * callback ) ( struct sys_notify_context * ctx ,
void * private_data ,
struct notify_event * ev ) ,
void * private_data , void * handle_p )
{
return NT_STATUS_NOT_IMPLEMENTED ;
}
static int vfs_gluster_chflags ( struct vfs_handle_struct * handle ,
const char * path , unsigned int flags )
{
errno = ENOSYS ;
return - 1 ;
}
static int vfs_gluster_get_real_filename ( struct vfs_handle_struct * handle ,
const char * path , const char * name ,
TALLOC_CTX * mem_ctx , char * * found_name )
{
int ret ;
char key_buf [ NAME_MAX + 64 ] ;
char val_buf [ NAME_MAX + 1 ] ;
if ( strlen ( name ) > = NAME_MAX ) {
errno = ENAMETOOLONG ;
return - 1 ;
}
snprintf ( key_buf , NAME_MAX + 64 ,
" user.glusterfs.get_real_filename:%s " , name ) ;
ret = glfs_getxattr ( handle - > data , path , key_buf , val_buf , NAME_MAX + 1 ) ;
2013-06-21 20:56:22 +04:00
if ( ret = = - 1 ) {
if ( errno = = ENODATA ) {
errno = EOPNOTSUPP ;
}
2013-05-29 15:21:46 +04:00
return - 1 ;
}
* found_name = talloc_strdup ( mem_ctx , val_buf ) ;
if ( found_name [ 0 ] = = NULL ) {
errno = ENOMEM ;
return - 1 ;
}
return 0 ;
}
static const char * vfs_gluster_connectpath ( struct vfs_handle_struct * handle ,
const char * filename )
{
return handle - > conn - > connectpath ;
}
/* EA Operations */
static ssize_t vfs_gluster_getxattr ( struct vfs_handle_struct * handle ,
const char * path , const char * name ,
void * value , size_t size )
{
return glfs_getxattr ( handle - > data , path , name , value , size ) ;
}
static ssize_t vfs_gluster_fgetxattr ( struct vfs_handle_struct * handle ,
files_struct * fsp , const char * name ,
void * value , size_t size )
{
2013-12-13 02:06:36 +04:00
return glfs_fgetxattr ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , name , value , size ) ;
2013-05-29 15:21:46 +04:00
}
static ssize_t vfs_gluster_listxattr ( struct vfs_handle_struct * handle ,
const char * path , char * list , size_t size )
{
return glfs_listxattr ( handle - > data , path , list , size ) ;
}
static ssize_t vfs_gluster_flistxattr ( struct vfs_handle_struct * handle ,
files_struct * fsp , char * list ,
size_t size )
{
2013-12-13 02:06:36 +04:00
return glfs_flistxattr ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , list , size ) ;
2013-05-29 15:21:46 +04:00
}
static int vfs_gluster_removexattr ( struct vfs_handle_struct * handle ,
const char * path , const char * name )
{
return glfs_removexattr ( handle - > data , path , name ) ;
}
static int vfs_gluster_fremovexattr ( struct vfs_handle_struct * handle ,
files_struct * fsp , const char * name )
{
2013-12-13 02:06:36 +04:00
return glfs_fremovexattr ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , name ) ;
2013-05-29 15:21:46 +04:00
}
static int vfs_gluster_setxattr ( struct vfs_handle_struct * handle ,
const char * path , const char * name ,
const void * value , size_t size , int flags )
{
return glfs_setxattr ( handle - > data , path , name , value , size , flags ) ;
}
static int vfs_gluster_fsetxattr ( struct vfs_handle_struct * handle ,
files_struct * fsp , const char * name ,
const void * value , size_t size , int flags )
{
2013-12-13 02:06:36 +04:00
return glfs_fsetxattr ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) , name , value , size ,
2013-05-29 15:21:46 +04:00
flags ) ;
}
/* AIO Operations */
static bool vfs_gluster_aio_force ( struct vfs_handle_struct * handle ,
files_struct * fsp )
{
return false ;
}
/* Offline Operations */
static bool vfs_gluster_is_offline ( struct vfs_handle_struct * handle ,
const struct smb_filename * fname ,
SMB_STRUCT_STAT * sbuf )
{
return false ;
}
static int vfs_gluster_set_offline ( struct vfs_handle_struct * handle ,
const struct smb_filename * fname )
{
errno = ENOTSUP ;
return - 1 ;
}
2013-08-11 23:59:29 +04:00
/*
Gluster ACL Format :
Size = 4 ( header ) + N * 8 ( entry )
Offset Size Field ( Little Endian )
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0 - 3 4 - byte Version
4 - 5 2 - byte Entry - 1 tag
6 - 7 2 - byte Entry - 1 perm
8 - 11 4 - byte Entry - 1 id
12 - 13 2 - byte Entry - 2 tag
14 - 15 2 - byte Entry - 2 perm
16 - 19 4 - byte Entry - 2 id
2013-05-29 15:21:46 +04:00
2013-08-11 23:59:29 +04:00
. . .
*/
/* header version */
2013-05-29 15:21:46 +04:00
# define GLUSTER_ACL_VERSION 2
2013-08-11 23:59:29 +04:00
/* perm bits */
2013-05-29 15:21:46 +04:00
# define GLUSTER_ACL_READ 0x04
# define GLUSTER_ACL_WRITE 0x02
# define GLUSTER_ACL_EXECUTE 0x01
2013-08-11 23:59:29 +04:00
/* tag values */
2013-05-29 15:21:46 +04:00
# define GLUSTER_ACL_UNDEFINED_TAG 0x00
# define GLUSTER_ACL_USER_OBJ 0x01
# define GLUSTER_ACL_USER 0x02
# define GLUSTER_ACL_GROUP_OBJ 0x04
# define GLUSTER_ACL_GROUP 0x08
# define GLUSTER_ACL_MASK 0x10
# define GLUSTER_ACL_OTHER 0x20
# define GLUSTER_ACL_UNDEFINED_ID (-1)
2013-08-11 23:59:29 +04:00
# define GLUSTER_ACL_HEADER_SIZE 4
# define GLUSTER_ACL_ENTRY_SIZE 8
2013-05-29 15:21:46 +04:00
2014-10-30 14:44:51 +03:00
# define GLUSTER_ACL_SIZE(n) (GLUSTER_ACL_HEADER_SIZE + (n * GLUSTER_ACL_ENTRY_SIZE))
2013-05-29 15:21:46 +04:00
static SMB_ACL_T gluster_to_smb_acl ( const char * buf , size_t xattr_size ,
TALLOC_CTX * mem_ctx )
{
int count ;
size_t size ;
struct smb_acl_entry * smb_ace ;
struct smb_acl_t * result ;
int i ;
2013-08-11 23:59:29 +04:00
int offset ;
2013-05-29 15:21:46 +04:00
uint16_t tag ;
uint16_t perm ;
uint32_t id ;
size = xattr_size ;
2013-08-11 23:59:29 +04:00
if ( size < GLUSTER_ACL_HEADER_SIZE ) {
/* ACL should be at least as big as the header (4 bytes) */
2013-05-29 15:21:46 +04:00
errno = EINVAL ;
return NULL ;
}
2013-08-11 23:59:29 +04:00
size - = GLUSTER_ACL_HEADER_SIZE ; /* size of header = 4 bytes */
2013-05-29 15:21:46 +04:00
2013-08-11 23:59:29 +04:00
if ( size % GLUSTER_ACL_ENTRY_SIZE ) {
2013-05-29 15:21:46 +04:00
/* Size of entries must strictly be a multiple of
2013-08-11 23:59:29 +04:00
size of an ACE ( 8 bytes )
2013-05-29 15:21:46 +04:00
*/
errno = EINVAL ;
return NULL ;
}
2013-08-11 23:59:29 +04:00
count = size / GLUSTER_ACL_ENTRY_SIZE ;
2013-05-29 15:21:46 +04:00
2013-08-11 23:59:29 +04:00
/* Version is the first 4 bytes of the ACL */
if ( IVAL ( buf , 0 ) ! = GLUSTER_ACL_VERSION ) {
2013-05-29 15:21:46 +04:00
DEBUG ( 0 , ( " Unknown gluster ACL version: %d \n " ,
2013-08-11 23:59:29 +04:00
IVAL ( buf , 0 ) ) ) ;
2013-05-29 15:21:46 +04:00
return NULL ;
}
2013-08-11 23:59:29 +04:00
offset = GLUSTER_ACL_HEADER_SIZE ;
2013-05-29 15:21:46 +04:00
result = sys_acl_init ( mem_ctx ) ;
if ( ! result ) {
errno = ENOMEM ;
return NULL ;
}
result - > acl = talloc_array ( result , struct smb_acl_entry , count ) ;
if ( ! result - > acl ) {
errno = ENOMEM ;
talloc_free ( result ) ;
return NULL ;
}
result - > count = count ;
smb_ace = result - > acl ;
for ( i = 0 ; i < count ; i + + ) {
2013-08-11 23:59:29 +04:00
/* TAG is the first 2 bytes of an entry */
tag = SVAL ( buf , offset ) ;
offset + = 2 ;
/* PERM is the next 2 bytes of an entry */
perm = SVAL ( buf , offset ) ;
offset + = 2 ;
/* ID is the last 4 bytes of an entry */
id = IVAL ( buf , offset ) ;
offset + = 4 ;
2013-05-29 15:21:46 +04:00
switch ( tag ) {
case GLUSTER_ACL_USER :
smb_ace - > a_type = SMB_ACL_USER ;
break ;
case GLUSTER_ACL_USER_OBJ :
smb_ace - > a_type = SMB_ACL_USER_OBJ ;
break ;
case GLUSTER_ACL_GROUP :
smb_ace - > a_type = SMB_ACL_GROUP ;
break ;
case GLUSTER_ACL_GROUP_OBJ :
smb_ace - > a_type = SMB_ACL_GROUP_OBJ ;
break ;
case GLUSTER_ACL_OTHER :
smb_ace - > a_type = SMB_ACL_OTHER ;
break ;
case GLUSTER_ACL_MASK :
smb_ace - > a_type = SMB_ACL_MASK ;
break ;
default :
DEBUG ( 0 , ( " unknown tag type %d \n " , ( unsigned int ) tag ) ) ;
return NULL ;
}
switch ( smb_ace - > a_type ) {
case SMB_ACL_USER :
smb_ace - > info . user . uid = id ;
break ;
case SMB_ACL_GROUP :
smb_ace - > info . group . gid = id ;
break ;
default :
break ;
}
smb_ace - > a_perm = 0 ;
smb_ace - > a_perm | =
( ( perm & GLUSTER_ACL_READ ) ? SMB_ACL_READ : 0 ) ;
smb_ace - > a_perm | =
( ( perm & GLUSTER_ACL_WRITE ) ? SMB_ACL_WRITE : 0 ) ;
smb_ace - > a_perm | =
( ( perm & GLUSTER_ACL_EXECUTE ) ? SMB_ACL_EXECUTE : 0 ) ;
smb_ace + + ;
}
return result ;
}
2013-08-11 23:59:29 +04:00
static int gluster_ace_cmp ( const void * left , const void * right )
{
int ret = 0 ;
uint16_t tag_left , tag_right ;
uint32_t id_left , id_right ;
/*
Sorting precedence :
- Smaller TAG values must be earlier .
- Within same TAG , smaller identifiers must be earlier , E . g :
UID 0 entry must be earlier than UID 200
GID 17 entry must be earlier than GID 19
*/
/* TAG is the first element in the entry */
tag_left = SVAL ( left , 0 ) ;
tag_right = SVAL ( right , 0 ) ;
ret = ( tag_left - tag_right ) ;
if ( ! ret ) {
/* ID is the third element in the entry, after two short
integers ( tag and perm ) , i . e at offset 4.
*/
id_left = IVAL ( left , 4 ) ;
id_right = IVAL ( right , 4 ) ;
ret = id_left - id_right ;
}
return ret ;
}
2013-05-29 15:21:46 +04:00
static ssize_t smb_to_gluster_acl ( SMB_ACL_T theacl , char * buf , size_t len )
{
ssize_t size ;
struct smb_acl_entry * smb_ace ;
int i ;
int count ;
uint16_t tag ;
uint16_t perm ;
uint32_t id ;
2013-08-11 23:59:29 +04:00
int offset ;
2013-05-29 15:21:46 +04:00
count = theacl - > count ;
2013-08-11 23:59:29 +04:00
size = GLUSTER_ACL_HEADER_SIZE + ( count * GLUSTER_ACL_ENTRY_SIZE ) ;
2013-05-29 15:21:46 +04:00
if ( ! buf ) {
return size ;
}
if ( len < size ) {
errno = ERANGE ;
return - 1 ;
}
smb_ace = theacl - > acl ;
2013-08-11 23:59:29 +04:00
/* Version is the first 4 bytes of the ACL */
SIVAL ( buf , 0 , GLUSTER_ACL_VERSION ) ;
offset = GLUSTER_ACL_HEADER_SIZE ;
2013-05-29 15:21:46 +04:00
for ( i = 0 ; i < count ; i + + ) {
2013-08-11 23:59:29 +04:00
/* Calculate tag */
2013-05-29 15:21:46 +04:00
switch ( smb_ace - > a_type ) {
case SMB_ACL_USER :
tag = GLUSTER_ACL_USER ;
break ;
case SMB_ACL_USER_OBJ :
tag = GLUSTER_ACL_USER_OBJ ;
break ;
case SMB_ACL_GROUP :
tag = GLUSTER_ACL_GROUP ;
break ;
case SMB_ACL_GROUP_OBJ :
tag = GLUSTER_ACL_GROUP_OBJ ;
break ;
case SMB_ACL_OTHER :
tag = GLUSTER_ACL_OTHER ;
break ;
case SMB_ACL_MASK :
tag = GLUSTER_ACL_MASK ;
break ;
default :
DEBUG ( 0 , ( " Unknown tag value %d \n " ,
smb_ace - > a_type ) ) ;
errno = EINVAL ;
return - 1 ;
}
2013-08-11 23:59:29 +04:00
/* Calculate id */
2013-05-29 15:21:46 +04:00
switch ( smb_ace - > a_type ) {
case SMB_ACL_USER :
id = smb_ace - > info . user . uid ;
break ;
case SMB_ACL_GROUP :
id = smb_ace - > info . group . gid ;
break ;
default :
id = GLUSTER_ACL_UNDEFINED_ID ;
break ;
}
2013-08-11 23:59:29 +04:00
/* Calculate perm */
perm = 0 ;
2013-05-29 15:21:46 +04:00
2013-08-11 23:59:29 +04:00
perm | =
2013-05-29 15:21:46 +04:00
( ( smb_ace - > a_perm & SMB_ACL_READ ) ? GLUSTER_ACL_READ : 0 ) ;
2013-08-11 23:59:29 +04:00
perm | =
2013-05-29 15:21:46 +04:00
( ( smb_ace - > a_perm & SMB_ACL_WRITE ) ? GLUSTER_ACL_WRITE : 0 ) ;
2013-08-11 23:59:29 +04:00
perm | =
2013-05-29 15:21:46 +04:00
( ( smb_ace - > a_perm & SMB_ACL_EXECUTE ) ? GLUSTER_ACL_EXECUTE : 0 ) ;
2013-08-11 23:59:29 +04:00
/* TAG is the first 2 bytes of an entry */
SSVAL ( buf , offset , tag ) ;
offset + = 2 ;
/* PERM is the next 2 bytes of an entry */
SSVAL ( buf , offset , perm ) ;
offset + = 2 ;
/* ID is the last 4 bytes of an entry */
SIVAL ( buf , offset , id ) ;
offset + = 4 ;
2013-05-29 15:21:46 +04:00
smb_ace + + ;
}
2013-08-11 23:59:29 +04:00
/* Skip the header, sort @count number of 8-byte entries */
qsort ( buf + GLUSTER_ACL_HEADER_SIZE , count , GLUSTER_ACL_ENTRY_SIZE ,
gluster_ace_cmp ) ;
2013-05-29 15:21:46 +04:00
return size ;
}
static SMB_ACL_T vfs_gluster_sys_acl_get_file ( struct vfs_handle_struct * handle ,
const char * path_p ,
SMB_ACL_TYPE_T type ,
TALLOC_CTX * mem_ctx )
{
struct smb_acl_t * result ;
char * buf ;
2013-11-04 15:32:05 +04:00
const char * key ;
2014-10-30 14:44:51 +03:00
ssize_t ret , size = GLUSTER_ACL_SIZE ( 20 ) ;
2013-05-29 15:21:46 +04:00
switch ( type ) {
case SMB_ACL_TYPE_ACCESS :
key = " system.posix_acl_access " ;
break ;
case SMB_ACL_TYPE_DEFAULT :
key = " system.posix_acl_default " ;
break ;
default :
errno = EINVAL ;
return NULL ;
}
2014-10-30 14:44:51 +03:00
buf = alloca ( size ) ;
if ( ! buf ) {
2013-05-29 15:21:46 +04:00
return NULL ;
}
2014-10-30 14:44:51 +03:00
ret = glfs_getxattr ( handle - > data , path_p , key , buf , size ) ;
if ( ret = = - 1 & & errno = = ERANGE ) {
ret = glfs_getxattr ( handle - > data , path_p , key , 0 , 0 ) ;
if ( ret > 0 ) {
buf = alloca ( ret ) ;
if ( ! buf ) {
return NULL ;
}
ret = glfs_getxattr ( handle - > data , path_p , key , buf , ret ) ;
}
}
2013-05-29 15:21:46 +04:00
if ( ret < = 0 ) {
return NULL ;
}
result = gluster_to_smb_acl ( buf , ret , mem_ctx ) ;
return result ;
}
static SMB_ACL_T vfs_gluster_sys_acl_get_fd ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
TALLOC_CTX * mem_ctx )
{
struct smb_acl_t * result ;
2014-10-30 14:44:51 +03:00
ssize_t ret , size = GLUSTER_ACL_SIZE ( 20 ) ;
2013-05-29 15:21:46 +04:00
char * buf ;
2013-12-13 02:06:36 +04:00
glfs_fd_t * glfd ;
2013-05-29 15:21:46 +04:00
2013-12-13 02:06:36 +04:00
glfd = * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) ;
2014-10-30 14:44:51 +03:00
buf = alloca ( size ) ;
if ( ! buf ) {
2013-05-29 15:21:46 +04:00
return NULL ;
}
2014-10-30 14:44:51 +03:00
ret = glfs_fgetxattr ( glfd , " system.posix_acl_access " , buf , size ) ;
if ( ret = = - 1 & & errno = = ERANGE ) {
ret = glfs_fgetxattr ( glfd , " system.posix_acl_access " , 0 , 0 ) ;
if ( ret > 0 ) {
buf = alloca ( ret ) ;
if ( ! buf ) {
return NULL ;
}
ret = glfs_fgetxattr ( glfd , " system.posix_acl_access " ,
buf , ret ) ;
}
}
2013-05-29 15:21:46 +04:00
if ( ret < = 0 ) {
return NULL ;
}
result = gluster_to_smb_acl ( buf , ret , mem_ctx ) ;
return result ;
}
static int vfs_gluster_sys_acl_set_file ( struct vfs_handle_struct * handle ,
const char * name ,
SMB_ACL_TYPE_T acltype ,
SMB_ACL_T theacl )
{
int ret ;
2013-11-04 15:32:05 +04:00
const char * key ;
2013-05-29 15:21:46 +04:00
char * buf ;
ssize_t size ;
switch ( acltype ) {
case SMB_ACL_TYPE_ACCESS :
key = " system.posix_acl_access " ;
break ;
case SMB_ACL_TYPE_DEFAULT :
key = " system.posix_acl_default " ;
break ;
default :
errno = EINVAL ;
return - 1 ;
}
size = smb_to_gluster_acl ( theacl , 0 , 0 ) ;
buf = alloca ( size ) ;
size = smb_to_gluster_acl ( theacl , buf , size ) ;
if ( size = = - 1 ) {
return - 1 ;
}
ret = glfs_setxattr ( handle - > data , name , key , buf , size , 0 ) ;
return ret ;
}
static int vfs_gluster_sys_acl_set_fd ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
SMB_ACL_T theacl )
{
int ret ;
char * buf ;
ssize_t size ;
size = smb_to_gluster_acl ( theacl , 0 , 0 ) ;
buf = alloca ( size ) ;
size = smb_to_gluster_acl ( theacl , buf , size ) ;
if ( size = = - 1 ) {
return - 1 ;
}
2013-12-13 02:06:36 +04:00
ret = glfs_fsetxattr ( * ( glfs_fd_t * * ) VFS_FETCH_FSP_EXTENSION ( handle , fsp ) ,
2013-05-29 15:21:46 +04:00
" system.posix_acl_access " , buf , size , 0 ) ;
return ret ;
}
static int vfs_gluster_sys_acl_delete_def_file ( struct vfs_handle_struct * handle ,
const char * path )
{
return glfs_removexattr ( handle - > data , path , " system.posix_acl_default " ) ;
}
static struct vfs_fn_pointers glusterfs_fns = {
/* Disk Operations */
. connect_fn = vfs_gluster_connect ,
. disconnect_fn = vfs_gluster_disconnect ,
. disk_free_fn = vfs_gluster_disk_free ,
. get_quota_fn = vfs_gluster_get_quota ,
. set_quota_fn = vfs_gluster_set_quota ,
. statvfs_fn = vfs_gluster_statvfs ,
. fs_capabilities_fn = vfs_gluster_fs_capabilities ,
. get_dfs_referrals_fn = NULL ,
/* Directory Operations */
. opendir_fn = vfs_gluster_opendir ,
. fdopendir_fn = vfs_gluster_fdopendir ,
. readdir_fn = vfs_gluster_readdir ,
. seekdir_fn = vfs_gluster_seekdir ,
. telldir_fn = vfs_gluster_telldir ,
. rewind_dir_fn = vfs_gluster_rewinddir ,
. mkdir_fn = vfs_gluster_mkdir ,
. rmdir_fn = vfs_gluster_rmdir ,
. closedir_fn = vfs_gluster_closedir ,
. init_search_op_fn = vfs_gluster_init_search_op ,
/* File Operations */
. open_fn = vfs_gluster_open ,
. create_file_fn = NULL ,
. close_fn = vfs_gluster_close ,
. read_fn = vfs_gluster_read ,
. pread_fn = vfs_gluster_pread ,
. pread_send_fn = vfs_gluster_pread_send ,
. pread_recv_fn = vfs_gluster_pread_recv ,
. write_fn = vfs_gluster_write ,
. pwrite_fn = vfs_gluster_pwrite ,
. pwrite_send_fn = vfs_gluster_pwrite_send ,
. pwrite_recv_fn = vfs_gluster_pwrite_recv ,
. lseek_fn = vfs_gluster_lseek ,
. sendfile_fn = vfs_gluster_sendfile ,
. recvfile_fn = vfs_gluster_recvfile ,
. rename_fn = vfs_gluster_rename ,
. fsync_fn = vfs_gluster_fsync ,
. fsync_send_fn = vfs_gluster_fsync_send ,
. fsync_recv_fn = vfs_gluster_fsync_recv ,
. stat_fn = vfs_gluster_stat ,
. fstat_fn = vfs_gluster_fstat ,
. lstat_fn = vfs_gluster_lstat ,
. get_alloc_size_fn = vfs_gluster_get_alloc_size ,
. unlink_fn = vfs_gluster_unlink ,
. chmod_fn = vfs_gluster_chmod ,
. fchmod_fn = vfs_gluster_fchmod ,
. chown_fn = vfs_gluster_chown ,
. fchown_fn = vfs_gluster_fchown ,
. lchown_fn = vfs_gluster_lchown ,
. chdir_fn = vfs_gluster_chdir ,
. getwd_fn = vfs_gluster_getwd ,
. ntimes_fn = vfs_gluster_ntimes ,
. ftruncate_fn = vfs_gluster_ftruncate ,
. fallocate_fn = vfs_gluster_fallocate ,
. lock_fn = vfs_gluster_lock ,
. kernel_flock_fn = vfs_gluster_kernel_flock ,
. linux_setlease_fn = vfs_gluster_linux_setlease ,
. getlock_fn = vfs_gluster_getlock ,
. symlink_fn = vfs_gluster_symlink ,
. readlink_fn = vfs_gluster_readlink ,
. link_fn = vfs_gluster_link ,
. mknod_fn = vfs_gluster_mknod ,
. realpath_fn = vfs_gluster_realpath ,
. notify_watch_fn = vfs_gluster_notify_watch ,
. chflags_fn = vfs_gluster_chflags ,
. file_id_create_fn = NULL ,
. copy_chunk_send_fn = NULL ,
. copy_chunk_recv_fn = NULL ,
. streaminfo_fn = NULL ,
. get_real_filename_fn = vfs_gluster_get_real_filename ,
. connectpath_fn = vfs_gluster_connectpath ,
. brl_lock_windows_fn = NULL ,
. brl_unlock_windows_fn = NULL ,
. brl_cancel_windows_fn = NULL ,
. strict_lock_fn = NULL ,
. strict_unlock_fn = NULL ,
. translate_name_fn = NULL ,
. fsctl_fn = NULL ,
/* NT ACL Operations */
. fget_nt_acl_fn = NULL ,
. get_nt_acl_fn = NULL ,
. fset_nt_acl_fn = NULL ,
. audit_file_fn = NULL ,
/* Posix ACL Operations */
. chmod_acl_fn = NULL , /* passthrough to default */
. fchmod_acl_fn = NULL , /* passthrough to default */
. sys_acl_get_file_fn = vfs_gluster_sys_acl_get_file ,
. sys_acl_get_fd_fn = vfs_gluster_sys_acl_get_fd ,
. sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file ,
. sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd ,
. sys_acl_set_file_fn = vfs_gluster_sys_acl_set_file ,
. sys_acl_set_fd_fn = vfs_gluster_sys_acl_set_fd ,
. sys_acl_delete_def_file_fn = vfs_gluster_sys_acl_delete_def_file ,
/* EA Operations */
. getxattr_fn = vfs_gluster_getxattr ,
. fgetxattr_fn = vfs_gluster_fgetxattr ,
. listxattr_fn = vfs_gluster_listxattr ,
. flistxattr_fn = vfs_gluster_flistxattr ,
. removexattr_fn = vfs_gluster_removexattr ,
. fremovexattr_fn = vfs_gluster_fremovexattr ,
. setxattr_fn = vfs_gluster_setxattr ,
. fsetxattr_fn = vfs_gluster_fsetxattr ,
/* AIO Operations */
. aio_force_fn = vfs_gluster_aio_force ,
/* Offline Operations */
. is_offline_fn = vfs_gluster_is_offline ,
. set_offline_fn = vfs_gluster_set_offline ,
/* Durable handle Operations */
. durable_cookie_fn = NULL ,
. durable_disconnect_fn = NULL ,
. durable_reconnect_fn = NULL ,
} ;
NTSTATUS vfs_glusterfs_init ( void ) ;
NTSTATUS vfs_glusterfs_init ( void )
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION ,
" glusterfs " , & glusterfs_fns ) ;
}