2013-01-30 17:42:46 +04:00
/*
* Module for snapshot management using shell callouts
*
* Copyright ( C ) David Disseldorp 2013 - 2015
*
* 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"
# include "include/ntioctl.h"
# include "system/filesys.h"
# include "smbd/smbd.h"
/*
* Check whether a path can be shadow copied . Return the base volume , allowing
* the caller to determine if multiple paths lie on the same base volume .
*/
static NTSTATUS shell_snap_check_path ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
const char * service_path ,
char * * base_volume )
{
NTSTATUS status ;
const char * cmd ;
char * cmd_run ;
int ret ;
TALLOC_CTX * tmp_ctx ;
cmd = lp_parm_const_string ( handle - > conn - > params - > service ,
" shell_snap " , " check path command " , " " ) ;
if ( ( cmd = = NULL ) | | ( strlen ( cmd ) = = 0 ) ) {
DEBUG ( 0 ,
( " \" shell_snap:check path command \" not configured \n " ) ) ;
status = NT_STATUS_NOT_SUPPORTED ;
goto err_out ;
}
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( tmp_ctx = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err_out ;
}
/* add service path argument */
cmd_run = talloc_asprintf ( tmp_ctx , " %s %s " , cmd , service_path ) ;
if ( cmd_run = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err_tmp_free ;
}
2016-10-12 18:55:15 +03:00
ret = smbrun ( cmd_run , NULL , NULL ) ;
2013-01-30 17:42:46 +04:00
if ( ret ! = 0 ) {
DEBUG ( 0 , ( " %s failed with %d \n " , cmd_run , ret ) ) ;
status = NT_STATUS_NOT_SUPPORTED ;
goto err_tmp_free ;
}
/* assume the service path is the base volume */
* base_volume = talloc_strdup ( mem_ctx , service_path ) ;
if ( * base_volume = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err_tmp_free ;
}
status = NT_STATUS_OK ;
err_tmp_free :
talloc_free ( tmp_ctx ) ;
err_out :
return status ;
}
static NTSTATUS shell_snap_create ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
const char * base_volume ,
time_t * tstamp ,
bool rw ,
char * * base_path ,
char * * snap_path )
{
const char * cmd ;
char * cmd_run ;
char * * qlines ;
int numlines , ret ;
int fd = - 1 ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
cmd = lp_parm_const_string ( handle - > conn - > params - > service ,
" shell_snap " , " create command " , " " ) ;
if ( ( cmd = = NULL ) | | ( strlen ( cmd ) = = 0 ) ) {
DEBUG ( 1 , ( " \" shell_snap:create command \" not configured \n " ) ) ;
status = NT_STATUS_NOT_SUPPORTED ;
goto err_out ;
}
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( tmp_ctx = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err_out ;
}
/* add base vol argument */
cmd_run = talloc_asprintf ( tmp_ctx , " %s %s " , cmd , base_volume ) ;
if ( cmd_run = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err_tmp_free ;
}
2016-10-12 18:55:15 +03:00
ret = smbrun ( cmd_run , & fd , NULL ) ;
2013-01-30 17:42:46 +04:00
talloc_free ( cmd_run ) ;
if ( ret ! = 0 ) {
if ( fd ! = - 1 ) {
close ( fd ) ;
}
status = NT_STATUS_UNSUCCESSFUL ;
goto err_tmp_free ;
}
numlines = 0 ;
qlines = fd_lines_load ( fd , & numlines , PATH_MAX + 1 , tmp_ctx ) ;
close ( fd ) ;
/* script must return the snapshot path as a single line */
if ( ( numlines = = 0 ) | | ( qlines = = NULL ) | | ( qlines [ 0 ] = = NULL ) ) {
status = NT_STATUS_UNSUCCESSFUL ;
goto err_tmp_free ;
}
* base_path = talloc_strdup ( mem_ctx , base_volume ) ;
if ( * base_path = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err_tmp_free ;
}
* snap_path = talloc_strdup ( mem_ctx , qlines [ 0 ] ) ;
if ( * snap_path = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
talloc_free ( * base_path ) ;
goto err_tmp_free ;
}
status = NT_STATUS_OK ;
err_tmp_free :
talloc_free ( tmp_ctx ) ;
err_out :
return status ;
}
static NTSTATUS shell_snap_delete ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
char * base_path ,
char * snap_path )
{
const char * cmd ;
char * cmd_run ;
int ret ;
cmd = lp_parm_const_string ( handle - > conn - > params - > service ,
" shell_snap " , " delete command " , " " ) ;
if ( ( cmd = = NULL ) | | ( strlen ( cmd ) = = 0 ) ) {
DEBUG ( 1 , ( " \" shell_snap:delete command \" not configured \n " ) ) ;
return NT_STATUS_NOT_SUPPORTED ;
}
/* add base path and snap path arguments */
cmd_run = talloc_asprintf ( mem_ctx , " %s %s %s " ,
cmd , base_path , snap_path ) ;
if ( cmd_run = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2016-10-12 18:55:15 +03:00
ret = smbrun ( cmd_run , NULL , NULL ) ;
2013-01-30 17:42:46 +04:00
talloc_free ( cmd_run ) ;
if ( ret ! = 0 ) {
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
}
static struct vfs_fn_pointers shell_snap_fns = {
. snap_check_path_fn = shell_snap_check_path ,
. snap_create_fn = shell_snap_create ,
. snap_delete_fn = shell_snap_delete ,
} ;
NTSTATUS vfs_shell_snap_init ( void ) ;
NTSTATUS vfs_shell_snap_init ( void )
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION ,
" shell_snap " , & shell_snap_fns ) ;
}