2012-02-01 17:42:39 +04:00
/*
2002-08-18 22:04:00 +04:00
Unix SMB / CIFS implementation .
VFS module functions
Copyright ( C ) Simo Sorce 2002
Copyright ( C ) Eric Lorimer 2002
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2002-08-18 22:04:00 +04:00
( at your option ) any later version .
2012-02-01 17:42:39 +04:00
2002-08-18 22:04:00 +04:00
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 .
2012-02-01 17:42:39 +04:00
2002-08-18 22:04:00 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2002-08-18 22:04:00 +04:00
*/
# include "includes.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2011-02-25 19:14:22 +03:00
# include "system/passwd.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2002-08-18 22:04:00 +04:00
# include "vfstest.h"
2011-03-02 18:06:32 +03:00
# include "../lib/util/util_pw.h"
2012-08-16 07:44:48 +04:00
# include "libcli/security/security.h"
# include "passdb/machine_sid.h"
2023-11-27 16:53:07 +03:00
# include "source3/smbd/dir.h"
2002-08-18 22:04:00 +04:00
2003-05-12 03:34:18 +04:00
static const char * null_string = " " ;
2002-08-18 22:04:00 +04:00
2016-03-19 07:19:38 +03:00
static uint32_t ssf_flags ( void )
{
return lp_posix_pathnames ( ) ? SMB_FILENAME_POSIX_PATH : 0 ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_load_module ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2003-05-12 03:34:18 +04:00
int i ;
2012-02-01 17:42:39 +04:00
2003-05-12 03:34:18 +04:00
if ( argc < 2 ) {
printf ( " Usage: load <modules> \n " ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2002-08-21 06:34:49 +04:00
2003-05-12 03:34:18 +04:00
for ( i = argc - 1 ; i > 0 ; i - - ) {
if ( ! vfs_init_custom ( vfs - > conn , argv [ i ] ) ) {
DEBUG ( 0 , ( " load: (vfs_init_custom failed for %s) \n " , argv [ i ] ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2002-08-18 22:04:00 +04:00
}
printf ( " load: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_populate ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
char c ;
size_t size ;
if ( argc ! = 3 ) {
printf ( " Usage: populate <char> <size> \n " ) ;
return NT_STATUS_OK ;
}
c = argv [ 1 ] [ 0 ] ;
size = atoi ( argv [ 2 ] ) ;
2011-06-07 05:30:12 +04:00
vfs - > data = talloc_array ( mem_ctx , char , size ) ;
2002-08-18 22:04:00 +04:00
if ( vfs - > data = = NULL ) {
2002-08-18 23:22:10 +04:00
printf ( " populate: error=-1 (not enough memory) " ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
memset ( vfs - > data , c , size ) ;
vfs - > data_size = size ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_show_data ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
size_t offset ;
size_t len ;
if ( argc ! = 1 & & argc ! = 3 ) {
printf ( " Usage: showdata [<offset> <len>] \n " ) ;
return NT_STATUS_OK ;
}
if ( vfs - > data = = NULL | | vfs - > data_size = = 0 ) {
printf ( " show_data: error=-1 (buffer empty) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
if ( argc = = 3 ) {
offset = atoi ( argv [ 1 ] ) ;
len = atoi ( argv [ 2 ] ) ;
} else {
offset = 0 ;
len = vfs - > data_size ;
}
if ( ( offset + len ) > vfs - > data_size ) {
printf ( " show_data: error=-1 (not enough data in buffer) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2015-05-09 06:10:12 +03:00
dump_data ( 0 , ( uint8_t * ) ( vfs - > data ) + offset , len ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_connect ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2019-11-07 13:01:05 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
SMB_VFS_CONNECT ( vfs - > conn , lp_servicename ( talloc_tos ( ) , lp_sub , SNUM ( vfs - > conn ) ) , " vfstest " ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_disconnect ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2003-05-14 14:59:01 +04:00
SMB_VFS_DISCONNECT ( vfs - > conn ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_disk_free ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2017-05-23 20:40:47 +03:00
struct smb_filename * smb_fname = NULL ;
2008-10-14 03:59:36 +04:00
uint64_t diskfree , bsize , dfree , dsize ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: disk_free <path> \n " ) ;
return NT_STATUS_OK ;
}
2017-05-23 20:40:47 +03:00
smb_fname = synthetic_smb_fname ( talloc_tos ( ) ,
argv [ 1 ] ,
NULL ,
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2017-05-23 20:40:47 +03:00
ssf_flags ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
diskfree = SMB_VFS_DISK_FREE ( vfs - > conn , smb_fname ,
& bsize , & dfree , & dsize ) ;
2002-11-23 05:58:31 +03:00
printf ( " disk_free: %lu, bsize = %lu, dfree = %lu, dsize = %lu \n " ,
( unsigned long ) diskfree ,
( unsigned long ) bsize ,
( unsigned long ) dfree ,
( unsigned long ) dsize ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_opendir ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2016-02-27 01:53:12 +03:00
struct smb_filename * smb_fname = NULL ;
2022-03-01 01:28:19 +03:00
NTSTATUS status ;
2016-02-27 01:53:12 +03:00
2002-08-18 22:04:00 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: opendir <fname> \n " ) ;
return NT_STATUS_OK ;
}
2016-02-27 01:53:12 +03:00
smb_fname = synthetic_smb_fname ( talloc_tos ( ) ,
argv [ 1 ] ,
NULL ,
2016-03-19 07:19:38 +03:00
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2016-03-19 07:19:38 +03:00
ssf_flags ( ) ) ;
2016-02-27 01:53:12 +03:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2022-03-01 01:34:48 +03:00
status = OpenDir ( vfs - > conn ,
vfs - > conn ,
smb_fname ,
NULL ,
0 ,
& vfs - > currentdir ) ;
2022-03-01 01:28:19 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
int err = map_errno_from_nt_status ( status ) ;
printf ( " opendir error=%d (%s) \n " , err , strerror ( err ) ) ;
2016-02-27 01:53:12 +03:00
TALLOC_FREE ( smb_fname ) ;
2022-03-01 01:28:19 +03:00
errno = err ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
2016-02-27 01:53:12 +03:00
TALLOC_FREE ( smb_fname ) ;
2002-08-18 22:04:00 +04:00
printf ( " opendir: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_readdir ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2022-09-06 11:43:29 +03:00
struct smb_Dir * currentdir = vfs - > currentdir ;
files_struct * dirfsp = dir_hnd_fetch_fsp ( currentdir ) ;
connection_struct * conn = dirfsp - > conn ;
2009-01-23 07:14:38 +03:00
SMB_STRUCT_STAT st ;
2020-03-18 19:40:29 +03:00
const char * dname = NULL ;
2022-09-06 11:43:29 +03:00
struct smb_filename * fname = NULL ;
2020-03-18 19:40:29 +03:00
char * talloced = NULL ;
2022-09-06 11:43:29 +03:00
int ret ;
2002-08-18 22:04:00 +04:00
if ( vfs - > currentdir = = NULL ) {
printf ( " readdir: error=-1 (no open directory) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2023-06-20 13:25:45 +03:00
dname = ReadDirName ( vfs - > currentdir , & talloced ) ;
2020-03-18 19:40:29 +03:00
if ( dname = = NULL ) {
2002-08-18 22:04:00 +04:00
printf ( " readdir: NULL \n " ) ;
return NT_STATUS_OK ;
}
2022-09-06 11:43:29 +03:00
fname = synthetic_smb_fname (
talloc_tos ( ) , dname , NULL , 0 , 0 , ssf_flags ( ) ) ;
if ( fname = = NULL ) {
printf ( " readdir: no memory \n " ) ;
return NT_STATUS_OK ;
}
2020-03-18 19:40:29 +03:00
printf ( " readdir: %s \n " , dname ) ;
2022-09-06 11:43:29 +03:00
ret = SMB_VFS_FSTATAT ( conn , dirfsp , fname , & st , AT_SYMLINK_NOFOLLOW ) ;
if ( ( ret = = 0 ) & & VALID_STAT ( st ) ) {
2009-05-14 17:34:42 +04:00
time_t tmp_time ;
2009-01-23 07:14:38 +03:00
printf ( " stat available " ) ;
2009-05-14 17:34:42 +04:00
if ( S_ISREG ( st . st_ex_mode ) ) printf ( " Regular File \n " ) ;
else if ( S_ISDIR ( st . st_ex_mode ) ) printf ( " Directory \n " ) ;
else if ( S_ISCHR ( st . st_ex_mode ) ) printf ( " Character Device \n " ) ;
else if ( S_ISBLK ( st . st_ex_mode ) ) printf ( " Block Device \n " ) ;
else if ( S_ISFIFO ( st . st_ex_mode ) ) printf ( " Fifo \n " ) ;
else if ( S_ISLNK ( st . st_ex_mode ) ) printf ( " Symbolic Link \n " ) ;
else if ( S_ISSOCK ( st . st_ex_mode ) ) printf ( " Socket \n " ) ;
printf ( " Size: %10u " , ( unsigned int ) st . st_ex_size ) ;
2009-01-23 07:14:38 +03:00
# ifdef HAVE_STAT_ST_BLOCKS
2009-05-14 17:34:42 +04:00
printf ( " Blocks: %9u " , ( unsigned int ) st . st_ex_blocks ) ;
2009-01-23 07:14:38 +03:00
# endif
# ifdef HAVE_STAT_ST_BLKSIZE
2009-05-14 17:34:42 +04:00
printf ( " IO Block: %u \n " , ( unsigned int ) st . st_ex_blksize ) ;
2009-01-23 07:14:38 +03:00
# endif
2009-05-14 17:34:42 +04:00
printf ( " Device: 0x%10x " , ( unsigned int ) st . st_ex_dev ) ;
printf ( " Inode: %10u " , ( unsigned int ) st . st_ex_ino ) ;
printf ( " Links: %10u \n " , ( unsigned int ) st . st_ex_nlink ) ;
printf ( " Access: %05o " , ( int ) ( ( st . st_ex_mode ) & 007777 ) ) ;
2009-02-11 09:16:26 +03:00
printf ( " Uid: %5lu Gid: %5lu \n " ,
2009-05-14 17:34:42 +04:00
( unsigned long ) st . st_ex_uid ,
( unsigned long ) st . st_ex_gid ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_atime ) ;
printf ( " Access: %s " , ctime ( & tmp_time ) ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_mtime ) ;
printf ( " Modify: %s " , ctime ( & tmp_time ) ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_ctime ) ;
printf ( " Change: %s " , ctime ( & tmp_time ) ) ;
2009-01-23 07:14:38 +03:00
}
2020-03-18 19:40:29 +03:00
TALLOC_FREE ( talloced ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_mkdir ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2016-02-24 00:14:03 +03:00
struct smb_filename * smb_fname = NULL ;
2019-09-05 21:27:42 +03:00
int ret ;
2016-02-24 00:14:03 +03:00
2002-08-18 22:04:00 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: mkdir <path> \n " ) ;
return NT_STATUS_OK ;
}
2016-02-24 00:14:03 +03:00
smb_fname = synthetic_smb_fname ( talloc_tos ( ) ,
argv [ 1 ] ,
NULL ,
2016-03-19 07:19:38 +03:00
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2016-03-19 07:19:38 +03:00
ssf_flags ( ) ) ;
2016-02-24 00:14:03 +03:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2019-09-05 21:27:42 +03:00
ret = SMB_VFS_MKDIRAT ( vfs - > conn ,
vfs - > conn - > cwd_fsp ,
smb_fname ,
00755 ) ;
if ( ret = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " mkdir error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2012-02-01 17:42:39 +04:00
2002-08-18 22:04:00 +04:00
printf ( " mkdir: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_closedir ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
if ( vfs - > currentdir = = NULL ) {
printf ( " closedir: failure (no directory open) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2020-03-18 19:40:29 +03:00
TALLOC_FREE ( vfs - > currentdir ) ;
2002-08-18 22:04:00 +04:00
printf ( " closedir: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_open ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2022-06-03 16:53:29 +03:00
struct vfs_open_how how = { . mode = 0400 , } ;
2003-05-12 03:34:18 +04:00
const char * flagstr ;
2006-07-11 22:01:26 +04:00
files_struct * fsp ;
2020-05-19 22:34:26 +03:00
struct files_struct * fspcwd = NULL ;
2009-06-16 23:01:13 +04:00
struct smb_filename * smb_fname = NULL ;
NTSTATUS status ;
2020-09-26 22:46:51 +03:00
int fd ;
2002-08-18 22:04:00 +04:00
2002-08-18 23:22:10 +04:00
if ( argc < 3 | | argc > 5 ) {
printf ( " Usage: open <filename> <flags> <mode> \n " ) ;
printf ( " flags: O = O_RDONLY \n " ) ;
printf ( " R = O_RDWR \n " ) ;
printf ( " W = O_WRONLY \n " ) ;
printf ( " C = O_CREAT \n " ) ;
printf ( " E = O_EXCL \n " ) ;
printf ( " T = O_TRUNC \n " ) ;
printf ( " A = O_APPEND \n " ) ;
printf ( " N = O_NONBLOCK/O_NDELAY \n " ) ;
2002-08-19 20:54:06 +04:00
# ifdef O_SYNC
2002-08-18 23:22:10 +04:00
printf ( " S = O_SYNC \n " ) ;
2002-08-19 20:54:06 +04:00
# endif
2002-08-19 00:28:16 +04:00
# ifdef O_NOFOLLOW
2002-08-18 23:22:10 +04:00
printf ( " F = O_NOFOLLOW \n " ) ;
2002-08-19 00:28:16 +04:00
# endif
2002-08-18 23:22:10 +04:00
printf ( " mode: see open.2 \n " ) ;
printf ( " mode is ignored if C flag not present \n " ) ;
printf ( " mode defaults to 00400 \n " ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2002-08-18 23:22:10 +04:00
flagstr = argv [ 2 ] ;
while ( * flagstr ) {
switch ( * flagstr ) {
case ' O ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_RDONLY ;
2002-08-18 23:22:10 +04:00
break ;
case ' R ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_RDWR ;
2002-08-18 23:22:10 +04:00
break ;
case ' W ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_WRONLY ;
2002-08-18 23:22:10 +04:00
break ;
case ' C ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_CREAT ;
2002-08-18 23:22:10 +04:00
break ;
case ' E ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_EXCL ;
2002-08-18 23:22:10 +04:00
break ;
case ' T ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_TRUNC ;
2002-08-18 23:22:10 +04:00
break ;
case ' A ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_APPEND ;
2002-08-18 23:22:10 +04:00
break ;
case ' N ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_NONBLOCK ;
2002-08-18 23:22:10 +04:00
break ;
2002-08-19 20:54:06 +04:00
# ifdef O_SYNC
2002-08-18 23:22:10 +04:00
case ' S ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_SYNC ;
2002-08-18 23:22:10 +04:00
break ;
2002-08-19 20:54:06 +04:00
# endif
2002-08-19 00:28:16 +04:00
# ifdef O_NOFOLLOW
2002-08-18 23:22:10 +04:00
case ' F ' :
2022-06-03 16:53:29 +03:00
how . flags | = O_NOFOLLOW ;
2002-08-18 23:22:10 +04:00
break ;
2002-08-19 00:28:16 +04:00
# endif
2002-08-18 23:22:10 +04:00
default :
printf ( " open: error=-1 (invalid flag!) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
flagstr + + ;
}
2022-06-03 16:53:29 +03:00
if ( ( how . flags & O_CREAT ) & & argc = = 4 ) {
2022-08-21 21:47:13 +03:00
short _mode = 0 ;
if ( sscanf ( argv [ 3 ] , " %ho " , & _mode ) = = 0 ) {
2002-08-18 23:22:10 +04:00
printf ( " open: error=-1 (invalid mode!) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2022-08-21 21:47:13 +03:00
how . mode = _mode ;
2002-08-18 23:22:10 +04:00
}
2002-08-18 22:04:00 +04:00
2012-08-16 09:16:01 +04:00
fsp = talloc_zero ( vfs , struct files_struct ) ;
2008-01-09 13:22:29 +03:00
if ( fsp = = NULL ) {
2022-02-22 14:38:27 +03:00
goto nomem ;
2008-01-09 13:22:29 +03:00
}
2020-09-27 22:16:03 +03:00
fsp - > fh = fd_handle_create ( fsp ) ;
2008-01-09 13:22:29 +03:00
if ( fsp - > fh = = NULL ) {
2022-02-22 14:38:27 +03:00
goto nomem ;
2008-01-09 13:22:29 +03:00
}
2006-07-11 22:01:26 +04:00
fsp - > conn = vfs - > conn ;
2016-03-10 03:00:47 +03:00
smb_fname = synthetic_smb_fname_split ( NULL ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
2013-04-15 13:43:38 +04:00
if ( smb_fname = = NULL ) {
2022-02-22 14:38:27 +03:00
goto nomem ;
2009-06-16 23:01:13 +04:00
}
2009-07-11 05:11:32 +04:00
fsp - > fsp_name = smb_fname ;
2020-05-19 22:34:26 +03:00
status = vfs_at_fspcwd ( fsp , vfs - > conn , & fspcwd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2022-02-22 14:38:27 +03:00
goto fail ;
2020-05-19 22:34:26 +03:00
}
2022-02-22 15:15:02 +03:00
if ( is_named_stream ( smb_fname ) ) {
struct smb_filename * base_name = NULL ;
base_name = cp_smb_filename_nostream ( NULL , smb_fname ) ;
if ( base_name = = NULL ) {
goto nomem ;
}
status = openat_pathref_fsp ( fspcwd , base_name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
2022-06-14 17:33:57 +03:00
TALLOC_FREE ( fspcwd ) ;
2022-02-22 15:15:02 +03:00
fsp - > base_fsp = base_name - > fsp ;
}
2020-09-26 22:46:51 +03:00
fd = SMB_VFS_OPENAT ( vfs - > conn ,
fspcwd ,
smb_fname ,
fsp ,
2022-06-03 16:53:29 +03:00
& how ) ;
2020-09-26 22:46:51 +03:00
if ( fd = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " open: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
2022-02-22 14:38:27 +03:00
status = map_nt_error_from_unix ( errno ) ;
goto fail ;
2002-08-18 22:04:00 +04:00
}
2020-09-26 22:46:51 +03:00
fsp_set_fd ( fsp , fd ) ;
2002-08-18 22:04:00 +04:00
2022-03-19 01:01:52 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-08-16 08:37:42 +04:00
/* If we have an fd, this stat should succeed. */
DEBUG ( 0 , ( " Error doing fstat on open file %s "
" (%s) \n " ,
smb_fname_str_dbg ( smb_fname ) ,
2022-03-19 01:01:52 +03:00
nt_errstr ( status ) ) ) ;
2012-08-16 08:37:42 +04:00
} else if ( S_ISDIR ( smb_fname - > st . st_ex_mode ) ) {
errno = EISDIR ;
status = NT_STATUS_FILE_IS_A_DIRECTORY ;
}
2013-11-08 16:56:23 +04:00
2012-08-16 08:37:42 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2021-12-28 14:25:59 +03:00
fd_close ( fsp ) ;
2022-02-22 14:38:27 +03:00
goto fail ;
2012-08-16 08:37:42 +04:00
}
fsp - > file_id = vfs_file_id_from_sbuf ( vfs - > conn , & smb_fname - > st ) ;
fsp - > vuid = UID_FIELD_INVALID ;
fsp - > file_pid = 0 ;
2020-04-02 18:09:36 +03:00
fsp - > fsp_flags . can_lock = true ;
2020-04-02 18:18:43 +03:00
fsp - > fsp_flags . can_read = true ;
2020-04-02 18:28:32 +03:00
fsp - > fsp_flags . can_write = CAN_WRITE ( vfs - > conn ) ;
2012-08-16 08:37:42 +04:00
fsp - > print_file = NULL ;
2020-04-02 18:37:02 +03:00
fsp - > fsp_flags . modified = false ;
2012-08-16 08:37:42 +04:00
fsp - > sent_oplock_break = NO_BREAK_SENT ;
2020-04-02 19:21:11 +03:00
fsp - > fsp_flags . is_directory = false ;
2012-08-16 08:37:42 +04:00
2020-10-05 08:51:50 +03:00
vfs - > files [ fsp_get_pathref_fd ( fsp ) ] = fsp ;
printf ( " open: fd=%d \n " , fsp_get_pathref_fd ( fsp ) ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
2022-02-22 14:38:27 +03:00
nomem :
status = NT_STATUS_NO_MEMORY ;
fail :
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( fsp ) ;
return status ;
2002-08-18 22:04:00 +04:00
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_pathfunc ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2016-02-25 01:02:45 +03:00
struct smb_filename * smb_fname = NULL ;
2002-08-18 22:04:00 +04:00
int ret = - 1 ;
if ( argc ! = 2 ) {
printf ( " Usage: %s <path> \n " , argv [ 0 ] ) ;
return NT_STATUS_OK ;
}
2016-02-25 01:02:45 +03:00
smb_fname = synthetic_smb_fname ( talloc_tos ( ) ,
argv [ 1 ] ,
NULL ,
2016-03-19 07:19:38 +03:00
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2016-03-19 07:19:38 +03:00
ssf_flags ( ) ) ;
2009-07-02 20:27:44 +04:00
2016-02-25 01:02:45 +03:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2009-07-02 20:27:44 +04:00
2016-02-25 01:02:45 +03:00
if ( strcmp ( " rmdir " , argv [ 0 ] ) = = 0 ) {
2019-10-04 22:51:06 +03:00
ret = SMB_VFS_UNLINKAT ( vfs - > conn ,
vfs - > conn - > cwd_fsp ,
smb_fname ,
AT_REMOVEDIR ) ;
2016-02-25 01:02:45 +03:00
TALLOC_FREE ( smb_fname ) ;
} else if ( strcmp ( " unlink " , argv [ 0 ] ) = = 0 ) {
2016-10-20 23:33:09 +03:00
TALLOC_FREE ( smb_fname ) ;
/* unlink can be a stream:name */
smb_fname = synthetic_smb_fname_split ( talloc_tos ( ) ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2019-09-13 20:56:30 +03:00
ret = SMB_VFS_UNLINKAT ( vfs - > conn ,
vfs - > conn - > cwd_fsp ,
smb_fname ,
0 ) ;
2009-07-02 20:27:44 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-08-19 20:54:06 +04:00
} else if ( strcmp ( " chdir " , argv [ 0 ] ) = = 0 ) {
2017-06-29 21:29:33 +03:00
ret = SMB_VFS_CHDIR ( vfs - > conn , smb_fname ) ;
TALLOC_FREE ( smb_fname ) ;
2002-08-19 20:54:06 +04:00
} else {
printf ( " %s: error=%d (invalid function name!) \n " , argv [ 0 ] , errno ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2002-08-18 22:04:00 +04:00
if ( ret = = - 1 ) {
printf ( " %s: error=%d (%s) \n " , argv [ 0 ] , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " %s: ok \n " , argv [ 0 ] ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_close ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2021-12-28 14:25:59 +03:00
int fd ;
NTSTATUS status ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: close <fd> \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
if ( vfs - > files [ fd ] = = NULL ) {
printf ( " close: error=-1 (invalid file descriptor) \n " ) ;
return NT_STATUS_OK ;
}
2021-12-28 14:25:59 +03:00
status = fd_close ( vfs - > files [ fd ] ) ;
if ( ! NT_STATUS_IS_OK ( status ) )
printf ( " close: error=%s \n " , nt_errstr ( status ) ) ;
2002-08-18 22:04:00 +04:00
else
printf ( " close: ok \n " ) ;
2012-08-16 09:16:01 +04:00
TALLOC_FREE ( vfs - > files [ fd ] ) ;
2002-08-18 22:04:00 +04:00
vfs - > files [ fd ] = NULL ;
2021-12-28 14:25:59 +03:00
return status ;
2002-08-18 22:04:00 +04:00
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_read ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
int fd ;
2022-02-03 17:23:45 +03:00
size_t size ;
ssize_t rsize ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: read <fd> <size> \n " ) ;
return NT_STATUS_OK ;
}
/* do some error checking on these */
fd = atoi ( argv [ 1 ] ) ;
size = atoi ( argv [ 2 ] ) ;
2011-06-07 05:30:12 +04:00
vfs - > data = talloc_array ( mem_ctx , char , size ) ;
2002-08-18 22:04:00 +04:00
if ( vfs - > data = = NULL ) {
printf ( " read: error=-1 (not enough memory) " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
vfs - > data_size = size ;
2012-02-01 17:42:39 +04:00
2018-05-01 21:53:10 +03:00
rsize = read_file ( vfs - > files [ fd ] , vfs - > data , 0 , size ) ;
2002-08-18 23:22:10 +04:00
if ( rsize = = - 1 ) {
printf ( " read: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
2002-08-18 22:04:00 +04:00
}
printf ( " read: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_write ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2022-02-03 17:23:45 +03:00
int fd , wsize ;
size_t size ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: write <fd> <size> \n " ) ;
return NT_STATUS_OK ;
}
/* some error checking should go here */
fd = atoi ( argv [ 1 ] ) ;
size = atoi ( argv [ 2 ] ) ;
if ( vfs - > data = = NULL ) {
printf ( " write: error=-1 (buffer empty, please populate it before writing) " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
if ( vfs - > data_size < size ) {
printf ( " write: error=-1 (buffer too small, please put some more data in) " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2018-05-03 02:49:56 +03:00
wsize = write_file ( NULL , vfs - > files [ fd ] , vfs - > data , 0 , size ) ;
2002-08-18 22:04:00 +04:00
if ( wsize = = - 1 ) {
printf ( " write: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " write: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_lseek ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
int fd , offset , whence ;
2012-04-05 08:53:08 +04:00
off_t pos ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 4 ) {
printf ( " Usage: lseek <fd> <offset> <whence> \n ...where whence is 1 => SEEK_SET, 2 => SEEK_CUR, 3 => SEEK_END \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
offset = atoi ( argv [ 2 ] ) ;
whence = atoi ( argv [ 3 ] ) ;
switch ( whence ) {
case 1 : whence = SEEK_SET ; break ;
case 2 : whence = SEEK_CUR ; break ;
default : whence = SEEK_END ;
}
2008-01-07 12:15:08 +03:00
pos = SMB_VFS_LSEEK ( vfs - > files [ fd ] , offset , whence ) ;
2012-04-05 08:53:08 +04:00
if ( pos = = ( off_t ) - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " lseek: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " lseek: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_rename ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
int ret ;
2009-07-01 04:04:38 +04:00
struct smb_filename * smb_fname_src = NULL ;
struct smb_filename * smb_fname_dst = NULL ;
2024-08-06 14:21:34 +03:00
struct vfs_rename_how rhow = { . flags = 0 , } ;
2009-07-01 04:04:38 +04:00
2002-08-18 22:04:00 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: rename <old> <new> \n " ) ;
return NT_STATUS_OK ;
}
2016-03-10 03:00:47 +03:00
smb_fname_src = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
2013-04-15 13:46:24 +04:00
if ( smb_fname_src = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2009-07-01 04:04:38 +04:00
}
2016-03-10 03:00:47 +03:00
smb_fname_dst = synthetic_smb_fname_split ( mem_ctx ,
argv [ 2 ] ,
lp_posix_pathnames ( ) ) ;
2013-04-15 13:46:24 +04:00
if ( smb_fname_dst = = NULL ) {
2009-07-01 04:04:38 +04:00
TALLOC_FREE ( smb_fname_src ) ;
2013-04-15 13:46:24 +04:00
return NT_STATUS_NO_MEMORY ;
2009-07-01 04:04:38 +04:00
}
2019-08-10 01:40:47 +03:00
ret = SMB_VFS_RENAMEAT ( vfs - > conn ,
vfs - > conn - > cwd_fsp ,
smb_fname_src ,
vfs - > conn - > cwd_fsp ,
2024-08-06 14:21:34 +03:00
smb_fname_dst ,
& rhow ) ;
2019-08-10 01:40:47 +03:00
2009-07-01 04:04:38 +04:00
TALLOC_FREE ( smb_fname_src ) ;
TALLOC_FREE ( smb_fname_dst ) ;
2002-08-18 22:04:00 +04:00
if ( ret = = - 1 ) {
printf ( " rename: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " rename: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_fsync ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
int ret , fd ;
if ( argc ! = 2 ) {
printf ( " Usage: fsync <fd> \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
2018-04-28 02:59:42 +03:00
ret = smb_vfs_fsync_sync ( vfs - > files [ fd ] ) ;
2002-08-18 22:04:00 +04:00
if ( ret = = - 1 ) {
printf ( " fsync: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " fsync: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_stat ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
int ret ;
2003-05-12 03:34:18 +04:00
const char * user ;
const char * group ;
2003-08-28 00:04:23 +04:00
struct passwd * pwd = NULL ;
struct group * grp = NULL ;
2009-06-23 02:26:56 +04:00
struct smb_filename * smb_fname = NULL ;
2002-08-18 22:04:00 +04:00
SMB_STRUCT_STAT st ;
2009-05-14 17:34:42 +04:00
time_t tmp_time ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: stat <fname> \n " ) ;
return NT_STATUS_OK ;
}
2016-03-10 03:00:47 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
2013-04-15 13:47:17 +04:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2009-06-23 02:26:56 +04:00
}
ret = SMB_VFS_STAT ( vfs - > conn , smb_fname ) ;
2002-08-18 22:04:00 +04:00
if ( ret = = - 1 ) {
printf ( " stat: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
2009-06-23 02:26:56 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
2009-06-23 02:26:56 +04:00
st = smb_fname - > st ;
TALLOC_FREE ( smb_fname ) ;
2002-08-18 22:04:00 +04:00
2012-03-24 18:25:05 +04:00
pwd = getpwuid ( st . st_ex_uid ) ;
2003-05-12 03:34:18 +04:00
if ( pwd ! = NULL ) user = pwd - > pw_name ;
2002-08-18 22:04:00 +04:00
else user = null_string ;
2012-03-24 18:26:36 +04:00
grp = getgrgid ( st . st_ex_gid ) ;
2003-05-12 03:34:18 +04:00
if ( grp ! = NULL ) group = grp - > gr_name ;
2002-08-18 22:04:00 +04:00
else group = null_string ;
printf ( " stat: ok \n " ) ;
printf ( " File: %s " , argv [ 1 ] ) ;
2009-05-14 17:34:42 +04:00
if ( S_ISREG ( st . st_ex_mode ) ) printf ( " Regular File \n " ) ;
else if ( S_ISDIR ( st . st_ex_mode ) ) printf ( " Directory \n " ) ;
else if ( S_ISCHR ( st . st_ex_mode ) ) printf ( " Character Device \n " ) ;
else if ( S_ISBLK ( st . st_ex_mode ) ) printf ( " Block Device \n " ) ;
else if ( S_ISFIFO ( st . st_ex_mode ) ) printf ( " Fifo \n " ) ;
else if ( S_ISLNK ( st . st_ex_mode ) ) printf ( " Symbolic Link \n " ) ;
else if ( S_ISSOCK ( st . st_ex_mode ) ) printf ( " Socket \n " ) ;
printf ( " Size: %10u " , ( unsigned int ) st . st_ex_size ) ;
2003-10-14 07:56:42 +04:00
# ifdef HAVE_STAT_ST_BLOCKS
2009-05-14 17:34:42 +04:00
printf ( " Blocks: %9u " , ( unsigned int ) st . st_ex_blocks ) ;
2003-10-14 07:56:42 +04:00
# endif
# ifdef HAVE_STAT_ST_BLKSIZE
2009-05-14 17:34:42 +04:00
printf ( " IO Block: %u \n " , ( unsigned int ) st . st_ex_blksize ) ;
2003-10-14 07:56:42 +04:00
# endif
2009-05-14 17:34:42 +04:00
printf ( " Device: 0x%10x " , ( unsigned int ) st . st_ex_dev ) ;
printf ( " Inode: %10u " , ( unsigned int ) st . st_ex_ino ) ;
printf ( " Links: %10u \n " , ( unsigned int ) st . st_ex_nlink ) ;
printf ( " Access: %05o " , ( int ) ( ( st . st_ex_mode ) & 007777 ) ) ;
printf ( " Uid: %5lu/%.16s Gid: %5lu/%.16s \n " , ( unsigned long ) st . st_ex_uid , user ,
( unsigned long ) st . st_ex_gid , group ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_atime ) ;
printf ( " Access: %s " , ctime ( & tmp_time ) ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_mtime ) ;
printf ( " Modify: %s " , ctime ( & tmp_time ) ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_ctime ) ;
printf ( " Change: %s " , ctime ( & tmp_time ) ) ;
2003-08-28 00:04:23 +04:00
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_fstat ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
int fd ;
2003-05-12 03:34:18 +04:00
const char * user ;
const char * group ;
2003-08-28 00:04:23 +04:00
struct passwd * pwd = NULL ;
struct group * grp = NULL ;
2002-08-18 22:04:00 +04:00
SMB_STRUCT_STAT st ;
2009-05-14 17:34:42 +04:00
time_t tmp_time ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: fstat <fd> \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
2008-01-30 21:56:05 +03:00
if ( fd < 0 | | fd > = 1024 ) {
2002-08-18 22:04:00 +04:00
printf ( " fstat: error=%d (file descriptor out of range) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
if ( vfs - > files [ fd ] = = NULL ) {
printf ( " fstat: error=%d (invalid file descriptor) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
2008-01-07 15:21:26 +03:00
if ( SMB_VFS_FSTAT ( vfs - > files [ fd ] , & st ) = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " fstat: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2012-03-24 18:25:05 +04:00
pwd = getpwuid ( st . st_ex_uid ) ;
2003-05-12 03:34:18 +04:00
if ( pwd ! = NULL ) user = pwd - > pw_name ;
2002-08-18 22:04:00 +04:00
else user = null_string ;
2012-03-24 18:26:36 +04:00
grp = getgrgid ( st . st_ex_gid ) ;
2003-05-12 03:34:18 +04:00
if ( grp ! = NULL ) group = grp - > gr_name ;
2002-08-18 22:04:00 +04:00
else group = null_string ;
printf ( " fstat: ok \n " ) ;
2009-05-14 17:34:42 +04:00
if ( S_ISREG ( st . st_ex_mode ) ) printf ( " Regular File \n " ) ;
else if ( S_ISDIR ( st . st_ex_mode ) ) printf ( " Directory \n " ) ;
else if ( S_ISCHR ( st . st_ex_mode ) ) printf ( " Character Device \n " ) ;
else if ( S_ISBLK ( st . st_ex_mode ) ) printf ( " Block Device \n " ) ;
else if ( S_ISFIFO ( st . st_ex_mode ) ) printf ( " Fifo \n " ) ;
else if ( S_ISLNK ( st . st_ex_mode ) ) printf ( " Symbolic Link \n " ) ;
else if ( S_ISSOCK ( st . st_ex_mode ) ) printf ( " Socket \n " ) ;
printf ( " Size: %10u " , ( unsigned int ) st . st_ex_size ) ;
2003-10-14 07:56:42 +04:00
# ifdef HAVE_STAT_ST_BLOCKS
2009-05-14 17:34:42 +04:00
printf ( " Blocks: %9u " , ( unsigned int ) st . st_ex_blocks ) ;
2003-10-14 07:56:42 +04:00
# endif
# ifdef HAVE_STAT_ST_BLKSIZE
2009-05-14 17:34:42 +04:00
printf ( " IO Block: %u \n " , ( unsigned int ) st . st_ex_blksize ) ;
2003-10-14 07:56:42 +04:00
# endif
2009-05-14 17:34:42 +04:00
printf ( " Device: 0x%10x " , ( unsigned int ) st . st_ex_dev ) ;
printf ( " Inode: %10u " , ( unsigned int ) st . st_ex_ino ) ;
printf ( " Links: %10u \n " , ( unsigned int ) st . st_ex_nlink ) ;
printf ( " Access: %05o " , ( int ) ( ( st . st_ex_mode ) & 007777 ) ) ;
printf ( " Uid: %5lu/%.16s Gid: %5lu/%.16s \n " , ( unsigned long ) st . st_ex_uid , user ,
( unsigned long ) st . st_ex_gid , group ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_atime ) ;
printf ( " Access: %s " , ctime ( & tmp_time ) ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_mtime ) ;
printf ( " Modify: %s " , ctime ( & tmp_time ) ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_ctime ) ;
printf ( " Change: %s " , ctime ( & tmp_time ) ) ;
2003-08-28 00:04:23 +04:00
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_lstat ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2003-05-12 03:34:18 +04:00
const char * user ;
const char * group ;
2003-08-28 00:04:23 +04:00
struct passwd * pwd = NULL ;
struct group * grp = NULL ;
2009-06-23 02:26:56 +04:00
struct smb_filename * smb_fname = NULL ;
2002-08-18 22:04:00 +04:00
SMB_STRUCT_STAT st ;
2009-05-14 17:34:42 +04:00
time_t tmp_time ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: lstat <path> \n " ) ;
return NT_STATUS_OK ;
}
2016-03-10 03:00:47 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
2013-04-15 13:48:05 +04:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2009-06-23 02:26:56 +04:00
}
if ( SMB_VFS_LSTAT ( vfs - > conn , smb_fname ) = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " lstat: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
2009-06-23 02:26:56 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
2009-06-23 02:26:56 +04:00
st = smb_fname - > st ;
TALLOC_FREE ( smb_fname ) ;
2002-08-18 22:04:00 +04:00
2012-03-24 18:25:05 +04:00
pwd = getpwuid ( st . st_ex_uid ) ;
2003-05-12 03:34:18 +04:00
if ( pwd ! = NULL ) user = pwd - > pw_name ;
2002-08-18 22:04:00 +04:00
else user = null_string ;
2012-03-24 18:26:36 +04:00
grp = getgrgid ( st . st_ex_gid ) ;
2003-05-12 03:34:18 +04:00
if ( grp ! = NULL ) group = grp - > gr_name ;
2002-08-18 22:04:00 +04:00
else group = null_string ;
printf ( " lstat: ok \n " ) ;
2009-05-14 17:34:42 +04:00
if ( S_ISREG ( st . st_ex_mode ) ) printf ( " Regular File \n " ) ;
else if ( S_ISDIR ( st . st_ex_mode ) ) printf ( " Directory \n " ) ;
else if ( S_ISCHR ( st . st_ex_mode ) ) printf ( " Character Device \n " ) ;
else if ( S_ISBLK ( st . st_ex_mode ) ) printf ( " Block Device \n " ) ;
else if ( S_ISFIFO ( st . st_ex_mode ) ) printf ( " Fifo \n " ) ;
else if ( S_ISLNK ( st . st_ex_mode ) ) printf ( " Symbolic Link \n " ) ;
else if ( S_ISSOCK ( st . st_ex_mode ) ) printf ( " Socket \n " ) ;
printf ( " Size: %10u " , ( unsigned int ) st . st_ex_size ) ;
2003-10-14 07:56:42 +04:00
# ifdef HAVE_STAT_ST_BLOCKS
2009-05-14 17:34:42 +04:00
printf ( " Blocks: %9u " , ( unsigned int ) st . st_ex_blocks ) ;
2003-10-14 07:56:42 +04:00
# endif
# ifdef HAVE_STAT_ST_BLKSIZE
2009-05-14 17:34:42 +04:00
printf ( " IO Block: %u \n " , ( unsigned int ) st . st_ex_blksize ) ;
2003-10-14 07:56:42 +04:00
# endif
2009-05-14 17:34:42 +04:00
printf ( " Device: 0x%10x " , ( unsigned int ) st . st_ex_dev ) ;
printf ( " Inode: %10u " , ( unsigned int ) st . st_ex_ino ) ;
printf ( " Links: %10u \n " , ( unsigned int ) st . st_ex_nlink ) ;
printf ( " Access: %05o " , ( int ) ( ( st . st_ex_mode ) & 007777 ) ) ;
printf ( " Uid: %5lu/%.16s Gid: %5lu/%.16s \n " , ( unsigned long ) st . st_ex_uid , user ,
( unsigned long ) st . st_ex_gid , group ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_atime ) ;
printf ( " Access: %s " , ctime ( & tmp_time ) ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_mtime ) ;
printf ( " Modify: %s " , ctime ( & tmp_time ) ) ;
tmp_time = convert_timespec_to_time_t ( st . st_ex_ctime ) ;
printf ( " Change: %s " , ctime ( & tmp_time ) ) ;
2012-02-01 17:42:39 +04:00
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_chmod ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2016-03-02 03:20:25 +03:00
struct smb_filename * smb_fname = NULL ;
2002-08-18 22:04:00 +04:00
mode_t mode ;
2021-04-08 15:02:09 +03:00
struct smb_filename * pathref_fname = NULL ;
NTSTATUS status ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: chmod <path> <mode> \n " ) ;
return NT_STATUS_OK ;
}
mode = atoi ( argv [ 2 ] ) ;
2016-03-02 03:20:25 +03:00
2021-04-08 15:02:09 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
2016-03-02 03:20:25 +03:00
argv [ 1 ] ,
2021-04-08 15:02:09 +03:00
lp_posix_pathnames ( ) ) ;
2016-03-02 03:20:25 +03:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-04-08 15:02:09 +03:00
status = synthetic_pathref ( mem_ctx ,
vfs - > conn - > cwd_fsp ,
smb_fname - > base_name ,
NULL ,
NULL ,
smb_fname - > twrp ,
smb_fname - > flags ,
& pathref_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( SMB_VFS_FCHMOD ( pathref_fname - > fsp , mode ) = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " chmod: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " chmod: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_fchmod ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
int fd ;
mode_t mode ;
if ( argc ! = 3 ) {
printf ( " Usage: fchmod <fd> <mode> \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
mode = atoi ( argv [ 2 ] ) ;
2008-01-30 21:56:05 +03:00
if ( fd < 0 | | fd > = 1024 ) {
2002-08-18 22:04:00 +04:00
printf ( " fchmod: error=%d (file descriptor out of range) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
if ( vfs - > files [ fd ] = = NULL ) {
printf ( " fchmod: error=%d (invalid file descriptor) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
2008-01-07 15:44:37 +03:00
if ( SMB_VFS_FCHMOD ( vfs - > files [ fd ] , mode ) = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " fchmod: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " fchmod: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_fchown ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
uid_t uid ;
gid_t gid ;
int fd ;
if ( argc ! = 4 ) {
printf ( " Usage: fchown <fd> <uid> <gid> \n " ) ;
return NT_STATUS_OK ;
}
uid = atoi ( argv [ 2 ] ) ;
gid = atoi ( argv [ 3 ] ) ;
fd = atoi ( argv [ 1 ] ) ;
2008-01-30 21:56:05 +03:00
if ( fd < 0 | | fd > = 1024 ) {
2023-07-18 12:35:22 +03:00
printf ( " fchown: failure=%d (file descriptor out of range) \n " , EBADF ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
if ( vfs - > files [ fd ] = = NULL ) {
printf ( " fchown: error=%d (invalid file descriptor) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
2008-01-07 16:26:00 +03:00
if ( SMB_VFS_FCHOWN ( vfs - > files [ fd ] , uid , gid ) = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " fchown error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " fchown: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_getwd ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2017-06-30 00:32:47 +03:00
struct smb_filename * smb_fname = SMB_VFS_GETWD ( vfs - > conn , talloc_tos ( ) ) ;
if ( smb_fname = = NULL ) {
2002-08-18 22:04:00 +04:00
printf ( " getwd: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2017-06-30 00:32:47 +03:00
printf ( " getwd: %s \n " , smb_fname - > base_name ) ;
TALLOC_FREE ( smb_fname ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_utime ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2009-01-24 01:40:19 +03:00
struct smb_file_time ft ;
2022-07-28 20:56:28 +03:00
struct files_struct * dirfsp = NULL ;
2009-07-03 00:39:20 +04:00
struct smb_filename * smb_fname = NULL ;
2020-10-28 13:31:46 +03:00
NTSTATUS status ;
2009-07-03 00:39:20 +04:00
2002-08-18 22:04:00 +04:00
if ( argc ! = 4 ) {
printf ( " Usage: utime <path> <access> <modify> \n " ) ;
return NT_STATUS_OK ;
}
2009-01-24 01:40:19 +03:00
2019-12-02 18:30:50 +03:00
init_smb_file_time ( & ft ) ;
2009-01-24 01:40:19 +03:00
2019-12-02 18:30:50 +03:00
ft . atime = time_t_to_full_timespec ( atoi ( argv [ 2 ] ) ) ;
ft . mtime = time_t_to_full_timespec ( atoi ( argv [ 3 ] ) ) ;
2009-07-03 00:39:20 +04:00
2022-07-28 20:56:28 +03:00
status = filename_convert_dirfsp ( mem_ctx ,
vfs - > conn ,
argv [ 1 ] ,
0 , /* ucf_flags */
0 , /* twrp */
& dirfsp ,
& smb_fname ) ;
2020-10-28 13:31:46 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " utime: %s \n " , nt_errstr ( status ) ) ;
return status ;
2009-07-03 00:39:20 +04:00
}
2021-04-14 15:21:41 +03:00
if ( SMB_VFS_FNTIMES ( smb_fname - > fsp , & ft ) ! = 0 ) {
2002-08-18 22:04:00 +04:00
printf ( " utime: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
2009-07-03 00:39:20 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
2009-07-03 00:39:20 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-08-18 22:04:00 +04:00
printf ( " utime: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_ftruncate ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
int fd ;
2012-04-05 08:53:08 +04:00
off_t off ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: ftruncate <fd> <length> \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
off = atoi ( argv [ 2 ] ) ;
2008-01-30 21:56:05 +03:00
if ( fd < 0 | | fd > = 1024 ) {
2002-08-18 22:04:00 +04:00
printf ( " ftruncate: error=%d (file descriptor out of range) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
if ( vfs - > files [ fd ] = = NULL ) {
printf ( " ftruncate: error=%d (invalid file descriptor) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
2008-01-07 17:55:09 +03:00
if ( SMB_VFS_FTRUNCATE ( vfs - > files [ fd ] , off ) = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " ftruncate: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " ftruncate: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_lock ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2002-08-21 06:34:49 +04:00
int fd ;
int op ;
long offset ;
long count ;
int type ;
2003-05-12 03:34:18 +04:00
const char * typestr ;
2012-02-01 17:42:39 +04:00
2002-08-21 06:34:49 +04:00
if ( argc ! = 6 ) {
printf ( " Usage: lock <fd> <op> <offset> <count> <type> \n " ) ;
printf ( " ops: G = F_GETLK \n " ) ;
printf ( " S = F_SETLK \n " ) ;
printf ( " W = F_SETLKW \n " ) ;
printf ( " type: R = F_RDLCK \n " ) ;
printf ( " W = F_WRLCK \n " ) ;
printf ( " U = F_UNLCK \n " ) ;
return NT_STATUS_OK ;
}
if ( sscanf ( argv [ 1 ] , " %d " , & fd ) = = 0 ) {
printf ( " lock: error=-1 (error parsing fd) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
op = 0 ;
switch ( * argv [ 2 ] ) {
case ' G ' :
op = F_GETLK ;
break ;
case ' S ' :
op = F_SETLK ;
break ;
case ' W ' :
op = F_SETLKW ;
break ;
default :
printf ( " lock: error=-1 (invalid op flag!) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
if ( sscanf ( argv [ 3 ] , " %ld " , & offset ) = = 0 ) {
printf ( " lock: error=-1 (error parsing fd) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
if ( sscanf ( argv [ 4 ] , " %ld " , & count ) = = 0 ) {
printf ( " lock: error=-1 (error parsing fd) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
type = 0 ;
typestr = argv [ 5 ] ;
while ( * typestr ) {
switch ( * typestr ) {
case ' R ' :
type | = F_RDLCK ;
break ;
case ' W ' :
type | = F_WRLCK ;
break ;
case ' U ' :
type | = F_UNLCK ;
break ;
default :
printf ( " lock: error=-1 (invalid type flag!) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
typestr + + ;
}
printf ( " lock: debug lock(fd=%d, op=%d, offset=%ld, count=%ld, type=%d)) \n " , fd , op , offset , count , type ) ;
2008-02-28 13:31:20 +03:00
if ( SMB_VFS_LOCK ( vfs - > files [ fd ] , op , offset , count , type ) = = False ) {
2002-08-21 06:34:49 +04:00
printf ( " lock: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " lock: ok \n " ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_symlink ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2019-08-31 00:10:47 +03:00
int ret ;
2020-04-30 18:46:31 +03:00
char * target = NULL ;
struct smb_filename target_fname ;
2017-06-09 02:25:58 +03:00
struct smb_filename * new_smb_fname = NULL ;
2020-04-30 18:46:31 +03:00
NTSTATUS status ;
2017-06-09 02:25:58 +03:00
2002-08-18 22:04:00 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: symlink <path> <link> \n " ) ;
return NT_STATUS_OK ;
}
2017-06-09 02:25:58 +03:00
new_smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 2 ] ,
lp_posix_pathnames ( ) ) ;
if ( new_smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2020-04-30 18:46:31 +03:00
target = talloc_strdup ( mem_ctx , argv [ 1 ] ) ;
if ( target = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
target_fname = ( struct smb_filename ) {
. base_name = target ,
} ;
/* Removes @GMT tokens if any */
2020-05-04 14:51:37 +03:00
status = canonicalize_snapshot_path ( & target_fname , UCF_GMT_PATHNAME , 0 ) ;
2020-04-30 18:46:31 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2019-08-31 00:10:47 +03:00
ret = SMB_VFS_SYMLINKAT ( vfs - > conn ,
2020-04-30 20:30:50 +03:00
& target_fname ,
2019-08-31 00:10:47 +03:00
vfs - > conn - > cwd_fsp ,
new_smb_fname ) ;
if ( ret = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " symlink: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " symlink: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_readlink ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
char buffer [ PATH_MAX ] ;
2017-06-08 01:03:37 +03:00
struct smb_filename * smb_fname = NULL ;
2002-08-18 22:04:00 +04:00
int size ;
if ( argc ! = 2 ) {
printf ( " Usage: readlink <path> \n " ) ;
return NT_STATUS_OK ;
}
2017-06-08 01:03:37 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2019-08-23 00:34:13 +03:00
size = SMB_VFS_READLINKAT ( vfs - > conn ,
vfs - > conn - > cwd_fsp ,
smb_fname ,
buffer ,
PATH_MAX ) ;
if ( size = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " readlink: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
buffer [ size ] = ' \0 ' ;
printf ( " readlink: %s \n " , buffer ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_link ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2017-06-03 00:21:54 +03:00
struct smb_filename * old_smb_fname = NULL ;
struct smb_filename * new_smb_fname = NULL ;
2019-08-17 02:14:03 +03:00
int ret ;
2017-06-03 00:21:54 +03:00
2002-08-18 22:04:00 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: link <path> <link> \n " ) ;
return NT_STATUS_OK ;
}
2017-06-03 00:21:54 +03:00
old_smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( old_smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
new_smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 2 ] ,
lp_posix_pathnames ( ) ) ;
if ( new_smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2019-08-17 02:14:03 +03:00
ret = SMB_VFS_LINKAT ( vfs - > conn ,
vfs - > conn - > cwd_fsp ,
old_smb_fname ,
vfs - > conn - > cwd_fsp ,
new_smb_fname ,
0 ) ;
if ( ret = = - 1 ) {
2002-08-18 22:04:00 +04:00
printf ( " link: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " link: ok \n " ) ;
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_mknod ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2022-08-21 21:47:13 +03:00
short _mode = 0 ;
2002-08-21 06:34:49 +04:00
mode_t mode ;
2002-11-23 05:58:31 +03:00
unsigned int dev_val ;
2002-08-21 06:34:49 +04:00
SMB_DEV_T dev ;
2017-05-20 01:01:52 +03:00
struct smb_filename * smb_fname = NULL ;
2019-08-21 22:11:44 +03:00
int ret ;
2012-02-01 17:42:39 +04:00
2002-08-21 06:34:49 +04:00
if ( argc ! = 4 ) {
printf ( " Usage: mknod <path> <mode> <dev> \n " ) ;
printf ( " mode is octal \n " ) ;
printf ( " dev is hex \n " ) ;
return NT_STATUS_OK ;
}
2022-08-21 21:47:13 +03:00
if ( sscanf ( argv [ 2 ] , " %ho " , & _mode ) = = 0 ) {
2002-08-21 06:34:49 +04:00
printf ( " open: error=-1 (invalid mode!) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2022-08-21 21:47:13 +03:00
mode = _mode ;
2002-08-21 06:34:49 +04:00
2002-11-23 05:58:31 +03:00
if ( sscanf ( argv [ 3 ] , " %x " , & dev_val ) = = 0 ) {
2002-08-21 06:34:49 +04:00
printf ( " open: error=-1 (invalid dev!) \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2002-11-23 05:58:31 +03:00
dev = ( SMB_DEV_T ) dev_val ;
2002-08-21 06:34:49 +04:00
2017-05-20 01:01:52 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2019-08-21 22:11:44 +03:00
ret = SMB_VFS_MKNODAT ( vfs - > conn ,
vfs - > conn - > cwd_fsp ,
smb_fname ,
mode ,
dev ) ;
if ( ret = = - 1 ) {
2002-08-21 06:34:49 +04:00
printf ( " mknod: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " mknod: ok \n " ) ;
2002-08-18 22:04:00 +04:00
return NT_STATUS_OK ;
}
2003-05-12 03:34:18 +04:00
static NTSTATUS cmd_realpath ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
2002-08-18 22:04:00 +04:00
{
2017-06-30 21:32:59 +03:00
struct smb_filename * smb_fname = NULL ;
2002-08-18 22:04:00 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: realpath <path> \n " ) ;
return NT_STATUS_OK ;
}
2017-06-30 21:32:59 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
if ( SMB_VFS_REALPATH ( vfs - > conn , mem_ctx , smb_fname ) = = NULL ) {
2002-08-18 22:04:00 +04:00
printf ( " realpath: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
printf ( " realpath: ok \n " ) ;
return NT_STATUS_OK ;
}
2012-02-02 19:36:18 +04:00
static NTSTATUS cmd_getxattr ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
uint8_t * buf ;
ssize_t ret ;
2017-05-26 02:42:04 +03:00
struct smb_filename * smb_fname = NULL ;
2021-06-22 21:47:25 +03:00
struct smb_filename * pathref_fname = NULL ;
NTSTATUS status ;
2012-02-02 19:36:18 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: getxattr <path> <xattr> \n " ) ;
return NT_STATUS_OK ;
}
buf = NULL ;
2017-05-26 02:42:04 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-06-22 21:47:25 +03:00
status = synthetic_pathref ( mem_ctx ,
vfs - > conn - > cwd_fsp ,
smb_fname - > base_name ,
NULL ,
NULL ,
smb_fname - > twrp ,
smb_fname - > flags ,
& pathref_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
ret = SMB_VFS_FGETXATTR ( pathref_fname - > fsp ,
argv [ 2 ] ,
buf ,
talloc_get_size ( buf ) ) ;
2012-02-02 19:36:18 +04:00
if ( ret = = - 1 ) {
int err = errno ;
printf ( " getxattr returned (%s) \n " , strerror ( err ) ) ;
return map_nt_error_from_unix ( err ) ;
}
buf = talloc_array ( mem_ctx , uint8_t , ret ) ;
if ( buf = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-06-22 21:47:25 +03:00
ret = SMB_VFS_FGETXATTR ( pathref_fname - > fsp ,
argv [ 2 ] ,
buf ,
talloc_get_size ( buf ) ) ;
2012-02-02 19:36:18 +04:00
if ( ret = = - 1 ) {
int err = errno ;
printf ( " getxattr returned (%s) \n " , strerror ( err ) ) ;
return map_nt_error_from_unix ( err ) ;
}
dump_data_file ( buf , talloc_get_size ( buf ) , false , stdout ) ;
return NT_STATUS_OK ;
}
2012-02-02 20:45:09 +04:00
static NTSTATUS cmd_listxattr ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
char * buf , * p ;
ssize_t ret ;
2017-05-23 23:12:29 +03:00
struct smb_filename * smb_fname = NULL ;
2021-02-05 20:10:20 +03:00
struct smb_filename * pathref_fname = NULL ;
NTSTATUS status ;
2012-02-02 20:45:09 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: listxattr <path> \n " ) ;
return NT_STATUS_OK ;
}
buf = NULL ;
2017-05-23 23:12:29 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-02-05 20:10:20 +03:00
status = synthetic_pathref ( mem_ctx ,
vfs - > conn - > cwd_fsp ,
smb_fname - > base_name ,
NULL ,
NULL ,
smb_fname - > twrp ,
smb_fname - > flags ,
& pathref_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
ret = SMB_VFS_FLISTXATTR ( pathref_fname - > fsp ,
2017-05-23 23:12:29 +03:00
buf , talloc_get_size ( buf ) ) ;
2012-02-02 20:45:09 +04:00
if ( ret = = - 1 ) {
int err = errno ;
printf ( " listxattr returned (%s) \n " , strerror ( err ) ) ;
return map_nt_error_from_unix ( err ) ;
}
buf = talloc_array ( mem_ctx , char , ret ) ;
if ( buf = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-02-05 20:10:20 +03:00
ret = SMB_VFS_FLISTXATTR ( pathref_fname - > fsp ,
2017-05-23 23:12:29 +03:00
buf , talloc_get_size ( buf ) ) ;
2012-02-02 20:45:09 +04:00
if ( ret = = - 1 ) {
int err = errno ;
printf ( " listxattr returned (%s) \n " , strerror ( err ) ) ;
return map_nt_error_from_unix ( err ) ;
}
if ( ret = = 0 ) {
return NT_STATUS_OK ;
}
if ( buf [ ret - 1 ] ! = ' \0 ' ) {
printf ( " listxattr returned non 0-terminated strings \n " ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
p = buf ;
while ( p < buf + ret ) {
printf ( " %s \n " , p ) ;
p = strchr ( p , 0 ) ;
p + = 1 ;
}
return NT_STATUS_OK ;
}
2021-02-19 12:17:57 +03:00
static NTSTATUS cmd_fsetxattr ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
2012-02-02 22:36:00 +04:00
int argc , const char * * argv )
{
ssize_t ret ;
int flags = 0 ;
2017-05-25 22:41:31 +03:00
struct smb_filename * smb_fname = NULL ;
2021-02-19 12:17:57 +03:00
struct smb_filename * pathref_fname = NULL ;
NTSTATUS status ;
2012-02-02 22:36:00 +04:00
if ( ( argc < 4 ) | | ( argc > 5 ) ) {
printf ( " Usage: setxattr <path> <xattr> <value> [flags] \n " ) ;
return NT_STATUS_OK ;
}
if ( argc = = 5 ) {
flags = atoi ( argv [ 4 ] ) ;
}
2017-05-25 22:41:31 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-02-19 12:17:57 +03:00
status = synthetic_pathref ( mem_ctx ,
vfs - > conn - > cwd_fsp ,
smb_fname - > base_name ,
NULL ,
NULL ,
smb_fname - > twrp ,
smb_fname - > flags ,
& pathref_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
ret = SMB_VFS_FSETXATTR ( pathref_fname - > fsp , argv [ 2 ] ,
2012-02-02 22:36:00 +04:00
argv [ 3 ] , strlen ( argv [ 3 ] ) , flags ) ;
if ( ret = = - 1 ) {
int err = errno ;
2021-02-19 12:17:57 +03:00
printf ( " fsetxattr returned (%s) \n " , strerror ( err ) ) ;
2012-02-02 22:36:00 +04:00
return map_nt_error_from_unix ( err ) ;
}
return NT_STATUS_OK ;
}
2012-02-02 22:41:56 +04:00
static NTSTATUS cmd_removexattr ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
ssize_t ret ;
2017-05-24 21:35:50 +03:00
struct smb_filename * smb_fname = NULL ;
2021-03-19 23:12:12 +03:00
struct smb_filename * pathref_fname = NULL ;
NTSTATUS status ;
2012-02-02 22:41:56 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: removexattr <path> <xattr> \n " ) ;
return NT_STATUS_OK ;
}
2021-03-19 23:12:12 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
2017-05-24 21:35:50 +03:00
argv [ 1 ] ,
2021-03-19 23:12:12 +03:00
lp_posix_pathnames ( ) ) ;
2017-05-24 21:35:50 +03:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-03-19 23:12:12 +03:00
status = synthetic_pathref ( mem_ctx ,
vfs - > conn - > cwd_fsp ,
smb_fname - > base_name ,
NULL ,
NULL ,
smb_fname - > twrp ,
smb_fname - > flags ,
& pathref_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
ret = SMB_VFS_FREMOVEXATTR ( pathref_fname - > fsp , argv [ 2 ] ) ;
2012-02-02 22:41:56 +04:00
if ( ret = = - 1 ) {
int err = errno ;
printf ( " removexattr returned (%s) \n " , strerror ( err ) ) ;
return map_nt_error_from_unix ( err ) ;
}
return NT_STATUS_OK ;
}
2012-08-16 07:44:48 +04:00
static NTSTATUS cmd_fget_nt_acl ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
int fd ;
NTSTATUS status ;
struct security_descriptor * sd ;
if ( argc ! = 2 ) {
printf ( " Usage: fget_nt_acl <fd> \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
if ( fd < 0 | | fd > = 1024 ) {
printf ( " fget_nt_acl: error=%d (file descriptor out of range) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
if ( vfs - > files [ fd ] = = NULL ) {
printf ( " fget_nt_acl: error=%d (invalid file descriptor) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
2022-07-29 15:49:56 +03:00
status = SMB_VFS_FGET_NT_ACL ( metadata_fsp ( vfs - > files [ fd ] ) ,
2012-10-10 04:50:27 +04:00
SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL ,
talloc_tos ( ) , & sd ) ;
2012-08-16 07:44:48 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " fget_nt_acl returned (%s) \n " , nt_errstr ( status ) ) ;
return status ;
}
printf ( " %s \n " , sddl_encode ( talloc_tos ( ) , sd , get_global_sam_sid ( ) ) ) ;
TALLOC_FREE ( sd ) ;
return NT_STATUS_OK ;
}
static NTSTATUS cmd_get_nt_acl ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
NTSTATUS status ;
struct security_descriptor * sd ;
2016-02-12 21:30:10 +03:00
struct smb_filename * smb_fname = NULL ;
2021-06-02 23:32:28 +03:00
struct smb_filename * pathref_fname = NULL ;
2012-08-16 07:44:48 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: get_nt_acl <path> \n " ) ;
return NT_STATUS_OK ;
}
2016-02-12 21:30:10 +03:00
smb_fname = synthetic_smb_fname ( talloc_tos ( ) ,
argv [ 1 ] ,
NULL ,
2016-03-19 07:19:38 +03:00
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2016-03-19 07:19:38 +03:00
ssf_flags ( ) ) ;
2016-02-12 21:30:10 +03:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-06-02 23:32:28 +03:00
status = synthetic_pathref ( mem_ctx ,
2020-04-14 01:26:05 +03:00
vfs - > conn - > cwd_fsp ,
2021-06-02 23:32:28 +03:00
smb_fname - > base_name ,
NULL ,
NULL ,
smb_fname - > twrp ,
smb_fname - > flags ,
& pathref_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb_fname ) ;
return status ;
}
status = SMB_VFS_FGET_NT_ACL ( pathref_fname - > fsp ,
2020-04-14 01:26:05 +03:00
SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL ,
talloc_tos ( ) ,
& sd ) ;
2012-08-16 07:44:48 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " get_nt_acl returned (%s) \n " , nt_errstr ( status ) ) ;
2021-06-02 23:32:28 +03:00
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( pathref_fname ) ;
2012-08-16 07:44:48 +04:00
return status ;
}
printf ( " %s \n " , sddl_encode ( talloc_tos ( ) , sd , get_global_sam_sid ( ) ) ) ;
TALLOC_FREE ( sd ) ;
2021-06-02 23:32:28 +03:00
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( pathref_fname ) ;
2012-08-16 07:44:48 +04:00
return NT_STATUS_OK ;
}
static NTSTATUS cmd_fset_nt_acl ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
int fd ;
NTSTATUS status ;
struct security_descriptor * sd ;
if ( argc ! = 3 ) {
printf ( " Usage: fset_nt_acl <fd> <sddl> \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
if ( fd < 0 | | fd > = 1024 ) {
printf ( " fset_nt_acl: error=%d (file descriptor out of range) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
if ( vfs - > files [ fd ] = = NULL ) {
printf ( " fset_nt_acl: error=%d (invalid file descriptor) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
sd = sddl_decode ( talloc_tos ( ) , argv [ 2 ] , get_global_sam_sid ( ) ) ;
if ( ! sd ) {
printf ( " sddl_decode failed to parse %s as SDDL \n " , argv [ 2 ] ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2022-07-29 15:54:07 +03:00
status = SMB_VFS_FSET_NT_ACL (
metadata_fsp ( vfs - > files [ fd ] ) ,
SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL ,
sd ) ;
2012-08-16 07:44:48 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " fset_nt_acl returned (%s) \n " , nt_errstr ( status ) ) ;
return status ;
}
TALLOC_FREE ( sd ) ;
return NT_STATUS_OK ;
}
static NTSTATUS cmd_set_nt_acl ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
2022-06-03 16:53:29 +03:00
struct vfs_open_how how = { . mode = 0400 , } ;
2012-08-16 07:44:48 +04:00
files_struct * fsp ;
2020-05-19 22:35:56 +03:00
struct files_struct * fspcwd = NULL ;
2012-08-16 07:44:48 +04:00
struct smb_filename * smb_fname = NULL ;
NTSTATUS status ;
struct security_descriptor * sd = NULL ;
2020-09-26 22:46:51 +03:00
int fd ;
2012-08-16 07:44:48 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: set_nt_acl <file> <sddl> \n " ) ;
return NT_STATUS_OK ;
}
2012-08-16 07:46:02 +04:00
fsp = talloc_zero ( vfs , struct files_struct ) ;
2012-08-16 07:44:48 +04:00
if ( fsp = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2020-09-27 22:16:03 +03:00
fsp - > fh = fd_handle_create ( fsp ) ;
2012-08-16 07:44:48 +04:00
if ( fsp - > fh = = NULL ) {
2012-08-16 07:46:02 +04:00
TALLOC_FREE ( fsp ) ;
2012-08-16 07:44:48 +04:00
return NT_STATUS_NO_MEMORY ;
}
fsp - > conn = vfs - > conn ;
2016-03-10 03:00:47 +03:00
smb_fname = synthetic_smb_fname_split ( NULL ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
2013-04-15 13:49:54 +04:00
if ( smb_fname = = NULL ) {
2012-08-16 07:46:02 +04:00
TALLOC_FREE ( fsp ) ;
2013-04-15 13:49:54 +04:00
return NT_STATUS_NO_MEMORY ;
2012-08-16 07:44:48 +04:00
}
fsp - > fsp_name = smb_fname ;
2020-05-19 22:35:56 +03:00
status = vfs_at_fspcwd ( fsp , vfs - > conn , & fspcwd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2022-06-03 16:53:29 +03:00
how . flags = O_RDWR ;
2020-09-26 22:46:51 +03:00
fd = SMB_VFS_OPENAT ( vfs - > conn ,
fspcwd ,
smb_fname ,
fsp ,
2022-06-03 16:53:29 +03:00
& how ) ;
2020-09-26 22:46:51 +03:00
if ( fd = = - 1 & & errno = = EISDIR ) {
2022-06-03 16:53:29 +03:00
# ifdef O_DIRECTORY
how . flags = O_RDONLY | O_DIRECTORY ;
# else
/* POSIX allows us to open a directory with O_RDONLY. */
how . flags = O_RDONLY ;
# endif
2020-09-26 22:46:51 +03:00
fd = SMB_VFS_OPENAT ( vfs - > conn ,
fspcwd ,
smb_fname ,
fsp ,
2022-06-03 16:53:29 +03:00
& how ) ;
2020-09-26 22:46:51 +03:00
}
if ( fd = = - 1 ) {
2012-08-16 07:44:48 +04:00
printf ( " open: error=%d (%s) \n " , errno , strerror ( errno ) ) ;
2012-08-16 07:46:02 +04:00
TALLOC_FREE ( fsp ) ;
2012-08-16 07:44:48 +04:00
TALLOC_FREE ( smb_fname ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2020-09-26 22:46:51 +03:00
fsp_set_fd ( fsp , fd ) ;
2012-08-16 07:44:48 +04:00
2022-03-19 01:04:34 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-08-16 07:46:02 +04:00
/* If we have an fd, this stat should succeed. */
DEBUG ( 0 , ( " Error doing fstat on open file %s "
" (%s) \n " ,
smb_fname_str_dbg ( smb_fname ) ,
2022-03-19 01:04:34 +03:00
nt_errstr ( status ) ) ) ;
2012-08-16 07:46:02 +04:00
goto out ;
}
fsp - > file_id = vfs_file_id_from_sbuf ( vfs - > conn , & smb_fname - > st ) ;
fsp - > vuid = UID_FIELD_INVALID ;
fsp - > file_pid = 0 ;
2020-04-02 18:09:36 +03:00
fsp - > fsp_flags . can_lock = true ;
2020-04-02 18:18:43 +03:00
fsp - > fsp_flags . can_read = true ;
2020-04-02 18:28:32 +03:00
fsp - > fsp_flags . can_write = true ;
2012-08-16 07:46:02 +04:00
fsp - > print_file = NULL ;
2020-04-02 18:37:02 +03:00
fsp - > fsp_flags . modified = false ;
2012-08-16 07:46:02 +04:00
fsp - > sent_oplock_break = NO_BREAK_SENT ;
2020-04-02 19:21:11 +03:00
fsp - > fsp_flags . is_directory = S_ISDIR ( smb_fname - > st . st_ex_mode ) ;
2012-08-16 07:46:02 +04:00
2012-08-16 07:44:48 +04:00
sd = sddl_decode ( talloc_tos ( ) , argv [ 2 ] , get_global_sam_sid ( ) ) ;
if ( ! sd ) {
printf ( " sddl_decode failed to parse %s as SDDL \n " , argv [ 2 ] ) ;
status = NT_STATUS_INVALID_PARAMETER ;
goto out ;
}
2022-07-29 15:54:07 +03:00
status = SMB_VFS_FSET_NT_ACL (
metadata_fsp ( fsp ) ,
SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL ,
sd ) ;
2012-08-16 07:44:48 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " fset_nt_acl returned (%s) \n " , nt_errstr ( status ) ) ;
goto out ;
}
out :
TALLOC_FREE ( sd ) ;
2021-12-28 14:25:59 +03:00
status = fd_close ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) )
printf ( " close: error= (%s) \n " , nt_errstr ( status ) ) ;
2012-08-16 07:44:48 +04:00
2012-08-16 07:46:02 +04:00
TALLOC_FREE ( fsp ) ;
2012-08-16 07:44:48 +04:00
return status ;
}
static NTSTATUS cmd_sys_acl_get_fd ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
int fd ;
SMB_ACL_T acl ;
char * acl_text ;
if ( argc ! = 2 ) {
printf ( " Usage: sys_acl_get_fd <fd> \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
if ( fd < 0 | | fd > = 1024 ) {
printf ( " sys_acl_get_fd: error=%d (file descriptor out of range) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
if ( vfs - > files [ fd ] = = NULL ) {
printf ( " sys_acl_get_fd: error=%d (invalid file descriptor) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
2021-05-14 17:26:46 +03:00
acl = SMB_VFS_SYS_ACL_GET_FD ( vfs - > files [ fd ] ,
SMB_ACL_TYPE_ACCESS ,
talloc_tos ( ) ) ;
2012-08-16 07:44:48 +04:00
if ( ! acl ) {
printf ( " sys_acl_get_fd failed (%s) \n " , strerror ( errno ) ) ;
2013-12-04 17:01:57 +04:00
return NT_STATUS_UNSUCCESSFUL ;
2012-08-16 07:44:48 +04:00
}
acl_text = sys_acl_to_text ( acl , NULL ) ;
printf ( " %s " , acl_text ) ;
TALLOC_FREE ( acl ) ;
SAFE_FREE ( acl_text ) ;
return NT_STATUS_OK ;
}
static NTSTATUS cmd_sys_acl_get_file ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
SMB_ACL_T acl ;
char * acl_text ;
int type ;
2017-05-24 03:11:18 +03:00
struct smb_filename * smb_fname = NULL ;
2021-06-02 20:52:47 +03:00
struct smb_filename * pathref_fname = NULL ;
NTSTATUS status ;
2017-05-24 03:11:18 +03:00
2012-08-16 07:44:48 +04:00
if ( argc ! = 3 ) {
printf ( " Usage: sys_acl_get_file <path> <type> \n " ) ;
return NT_STATUS_OK ;
}
2017-05-24 03:11:18 +03:00
smb_fname = synthetic_smb_fname_split ( talloc_tos ( ) ,
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2012-08-16 07:44:48 +04:00
type = atoi ( argv [ 2 ] ) ;
2021-06-02 20:52:47 +03:00
status = synthetic_pathref ( mem_ctx ,
vfs - > conn - > cwd_fsp ,
smb_fname - > base_name ,
NULL ,
NULL ,
smb_fname - > twrp ,
smb_fname - > flags ,
& pathref_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb_fname ) ;
return status ;
}
acl = SMB_VFS_SYS_ACL_GET_FD ( pathref_fname - > fsp ,
2017-05-24 03:11:18 +03:00
type , talloc_tos ( ) ) ;
2012-08-16 07:44:48 +04:00
if ( ! acl ) {
2021-06-02 20:52:47 +03:00
printf ( " sys_acl_get_fd failed (%s) \n " , strerror ( errno ) ) ;
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( pathref_fname ) ;
2013-12-04 17:01:57 +04:00
return NT_STATUS_UNSUCCESSFUL ;
2012-08-16 07:44:48 +04:00
}
acl_text = sys_acl_to_text ( acl , NULL ) ;
printf ( " %s " , acl_text ) ;
TALLOC_FREE ( acl ) ;
2021-06-02 20:52:47 +03:00
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( pathref_fname ) ;
2012-08-16 07:44:48 +04:00
SAFE_FREE ( acl_text ) ;
return NT_STATUS_OK ;
}
2012-11-15 18:19:07 +04:00
static NTSTATUS cmd_sys_acl_blob_get_file ( struct vfs_state * vfs ,
TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
char * description ;
DATA_BLOB blob ;
int ret ;
size_t i ;
2017-05-24 03:35:59 +03:00
struct smb_filename * smb_fname = NULL ;
2021-06-09 01:53:57 +03:00
struct smb_filename * pathref_fname = NULL ;
NTSTATUS status ;
2012-11-15 18:19:07 +04:00
if ( argc ! = 2 ) {
2021-06-09 01:53:57 +03:00
printf ( " Usage: sys_acl_blob_get_file <path> \n " ) ;
2012-11-15 18:19:07 +04:00
return NT_STATUS_OK ;
}
2021-06-09 01:53:57 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
2017-05-24 03:35:59 +03:00
argv [ 1 ] ,
lp_posix_pathnames ( ) ) ;
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-06-09 01:53:57 +03:00
status = synthetic_pathref ( mem_ctx ,
vfs - > conn - > cwd_fsp ,
smb_fname - > base_name ,
NULL ,
NULL ,
smb_fname - > twrp ,
smb_fname - > flags ,
& pathref_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb_fname ) ;
return status ;
}
ret = SMB_VFS_SYS_ACL_BLOB_GET_FD ( pathref_fname - > fsp ,
talloc_tos ( ) ,
& description ,
& blob ) ;
2012-11-15 18:19:07 +04:00
if ( ret ! = 0 ) {
2021-06-09 01:53:57 +03:00
status = map_nt_error_from_unix ( errno ) ;
2012-11-15 18:19:07 +04:00
printf ( " sys_acl_blob_get_file failed (%s) \n " , strerror ( errno ) ) ;
2021-06-09 01:53:57 +03:00
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( pathref_fname ) ;
return status ;
2012-11-15 18:19:07 +04:00
}
printf ( " Description: %s \n " , description ) ;
for ( i = 0 ; i < blob . length ; i + + ) {
printf ( " %.2x " , blob . data [ i ] ) ;
}
printf ( " \n " ) ;
2021-06-09 01:53:57 +03:00
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( pathref_fname ) ;
2012-11-15 18:19:07 +04:00
return NT_STATUS_OK ;
}
2012-11-15 18:25:52 +04:00
static NTSTATUS cmd_sys_acl_blob_get_fd ( struct vfs_state * vfs ,
TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
int fd ;
char * description ;
DATA_BLOB blob ;
int ret ;
size_t i ;
if ( argc ! = 2 ) {
printf ( " Usage: sys_acl_blob_get_fd <fd> \n " ) ;
return NT_STATUS_OK ;
}
fd = atoi ( argv [ 1 ] ) ;
if ( fd < 0 | | fd > = 1024 ) {
printf ( " sys_acl_blob_get_fd: error=%d "
" (file descriptor out of range) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
if ( vfs - > files [ fd ] = = NULL ) {
printf ( " sys_acl_blob_get_fd: error=%d "
" (invalid file descriptor) \n " , EBADF ) ;
return NT_STATUS_OK ;
}
ret = SMB_VFS_SYS_ACL_BLOB_GET_FD ( vfs - > files [ fd ] , talloc_tos ( ) ,
& description , & blob ) ;
if ( ret ! = 0 ) {
printf ( " sys_acl_blob_get_fd failed (%s) \n " , strerror ( errno ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
printf ( " Description: %s \n " , description ) ;
for ( i = 0 ; i < blob . length ; i + + ) {
printf ( " %.2x " , blob . data [ i ] ) ;
}
printf ( " \n " ) ;
return NT_STATUS_OK ;
}
2012-11-15 18:19:07 +04:00
2012-08-16 07:44:48 +04:00
static NTSTATUS cmd_sys_acl_delete_def_file ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
int ret ;
2017-05-24 01:33:31 +03:00
struct smb_filename * smb_fname = NULL ;
2021-05-15 02:09:58 +03:00
struct smb_filename * pathref_fname = NULL ;
NTSTATUS status ;
2012-08-16 07:44:48 +04:00
if ( argc ! = 2 ) {
printf ( " Usage: sys_acl_delete_def_file <path> \n " ) ;
return NT_STATUS_OK ;
}
2021-05-15 02:09:58 +03:00
smb_fname = synthetic_smb_fname_split ( mem_ctx ,
2017-05-24 01:33:31 +03:00
argv [ 1 ] ,
2021-05-15 02:09:58 +03:00
lp_posix_pathnames ( ) ) ;
2017-05-24 01:33:31 +03:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2021-05-15 02:09:58 +03:00
status = synthetic_pathref ( mem_ctx ,
vfs - > conn - > cwd_fsp ,
smb_fname - > base_name ,
NULL ,
NULL ,
smb_fname - > twrp ,
smb_fname - > flags ,
& pathref_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb_fname ) ;
return status ;
}
if ( ! pathref_fname - > fsp - > fsp_flags . is_directory ) {
printf ( " sys_acl_delete_def_file - %s is not a directory \n " ,
smb_fname - > base_name ) ;
TALLOC_FREE ( smb_fname ) ;
TALLOC_FREE ( pathref_fname ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
ret = SMB_VFS_SYS_ACL_DELETE_DEF_FD ( pathref_fname - > fsp ) ;
2012-08-16 07:44:48 +04:00
if ( ret = = - 1 ) {
2021-05-15 02:09:58 +03:00
int err = errno ;
printf ( " sys_acl_delete_def_file failed (%s) \n " , strerror ( err ) ) ;
2017-05-24 01:33:31 +03:00
TALLOC_FREE ( smb_fname ) ;
2021-05-15 02:09:58 +03:00
TALLOC_FREE ( pathref_fname ) ;
return map_nt_error_from_unix ( err ) ;
2012-08-16 07:44:48 +04:00
}
2017-05-24 01:33:31 +03:00
TALLOC_FREE ( smb_fname ) ;
2021-05-15 02:09:58 +03:00
TALLOC_FREE ( pathref_fname ) ;
2012-08-16 07:44:48 +04:00
return NT_STATUS_OK ;
}
2013-03-10 08:43:24 +04:00
/* Afaik translate name was first introduced with vfs_catia, to be able
to translate unix file / dir - names , containing invalid windows characters ,
to valid windows names .
The used translation direction is always unix - - > windows
*/
static NTSTATUS cmd_translate_name ( struct vfs_state * vfs , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
2020-03-18 19:40:29 +03:00
const char * dname = NULL ;
char * dname_talloced = NULL ;
2013-03-10 08:43:24 +04:00
bool found = false ;
char * translated = NULL ;
2016-02-27 01:53:12 +03:00
struct smb_filename * smb_fname = NULL ;
2013-03-10 08:43:24 +04:00
NTSTATUS status ;
if ( argc ! = 2 ) {
DEBUG ( 0 , ( " Usage: translate_name unix_filename \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2016-02-27 01:53:12 +03:00
smb_fname = synthetic_smb_fname ( talloc_tos ( ) ,
" . " ,
NULL ,
2016-03-19 07:19:38 +03:00
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2016-03-19 07:19:38 +03:00
ssf_flags ( ) ) ;
2016-02-27 01:53:12 +03:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2022-03-01 01:34:48 +03:00
status = OpenDir ( vfs - > conn ,
vfs - > conn ,
smb_fname ,
NULL ,
0 ,
& vfs - > currentdir ) ;
2022-03-01 01:28:19 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
int err = map_errno_from_nt_status ( status ) ;
2013-03-10 08:43:24 +04:00
DEBUG ( 0 , ( " cmd_translate_name: opendir error=%d (%s) \n " ,
2022-03-01 01:28:19 +03:00
err , strerror ( err ) ) ) ;
2016-02-27 01:53:12 +03:00
TALLOC_FREE ( smb_fname ) ;
2022-03-01 01:28:19 +03:00
errno = err ;
2013-03-10 08:43:24 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
while ( true ) {
2020-03-18 19:40:29 +03:00
/* ReadDirName() returns Windows "encoding" */
2023-06-20 13:25:45 +03:00
dname = ReadDirName ( vfs - > currentdir , & dname_talloced ) ;
2020-03-18 19:40:29 +03:00
if ( dname = = NULL ) {
2013-03-10 08:43:24 +04:00
break ;
}
2020-03-18 19:40:29 +03:00
/* Convert Windows "encoding" from ReadDirName() to UNIX */
status = SMB_VFS_TRANSLATE_NAME ( vfs - > conn ,
dname ,
vfs_translate_to_unix ,
talloc_tos ( ) ,
& translated ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " file '%s' cannot be translated \n " , argv [ 1 ] ) ;
goto cleanup ;
}
/*
* argv [ 1 ] uses UNIX " encoding " , so compare with translation
* result .
*/
if ( strcmp ( translated , argv [ 1 ] ) = = 0 ) {
2013-03-10 08:43:24 +04:00
found = true ;
break ;
}
2020-03-18 19:40:29 +03:00
TALLOC_FREE ( dname_talloced ) ;
TALLOC_FREE ( translated ) ;
2013-03-10 08:43:24 +04:00
} ;
if ( ! found ) {
DEBUG ( 0 , ( " cmd_translate_name: file '%s' not found. \n " ,
argv [ 1 ] ) ) ;
status = NT_STATUS_UNSUCCESSFUL ;
goto cleanup ;
}
2020-03-18 19:40:29 +03:00
2013-03-10 08:43:24 +04:00
/* translation success. But that could also mean
that translating " aaa " to " aaa " was successful : - (
*/
2020-03-18 19:40:29 +03:00
DBG_ERR ( " file '%s' --> '%s' \n " , argv [ 1 ] , dname ) ;
status = NT_STATUS_OK ;
2013-03-10 08:43:24 +04:00
cleanup :
2020-03-18 19:40:29 +03:00
TALLOC_FREE ( dname_talloced ) ;
TALLOC_FREE ( translated ) ;
2016-02-27 01:53:12 +03:00
TALLOC_FREE ( smb_fname ) ;
2020-03-18 19:40:29 +03:00
TALLOC_FREE ( vfs - > currentdir ) ;
return status ;
2013-03-10 08:43:24 +04:00
}
2022-02-03 17:25:11 +03:00
/*
* This is a quick hack to demonstrate a crash in the full_audit
* module when passing fsp - > smb_fname into SMB_VFS_CREATE_FILE leading
* to an error .
*
* Feel free to expand with more options as needed
*/
static NTSTATUS cmd_create_file (
struct vfs_state * vfs ,
TALLOC_CTX * mem_ctx ,
int argc ,
const char * * argv )
{
struct smb_filename * fname = NULL ;
struct files_struct * fsp = NULL ;
int info , ret ;
NTSTATUS status ;
if ( argc ! = 2 ) {
DBG_ERR ( " Usage: create_file filename \n " ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
fname = synthetic_smb_fname (
talloc_tos ( ) , argv [ 1 ] , NULL , NULL , 0 , 0 ) ;
if ( fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
ret = vfs_stat ( vfs - > conn , fname ) ;
if ( ret ! = 0 ) {
status = map_nt_error_from_unix ( errno ) ;
DBG_DEBUG ( " vfs_stat() failed: %s \n " , strerror ( errno ) ) ;
TALLOC_FREE ( fname ) ;
return status ;
}
status = openat_pathref_fsp ( vfs - > conn - > cwd_fsp , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " Could not open %s: %s \n " ,
fname - > base_name ,
nt_errstr ( status ) ) ;
TALLOC_FREE ( fname ) ;
return status ;
}
status = SMB_VFS_CREATE_FILE (
vfs - > conn ,
NULL ,
2021-11-23 14:29:17 +03:00
NULL ,
2022-02-03 17:25:11 +03:00
/*
* Using fname - > fsp - > fsp_name seems to be legal ,
* there ' s code to handle this in
* create_file_unixpath ( ) . And it is actually very
* worthwhile re - using the fsp_name , we can save quite
* a few copies of smb_filename with that .
*/
fname - > fsp - > fsp_name ,
SEC_FILE_ALL ,
FILE_SHARE_NONE ,
FILE_OPEN ,
FILE_NON_DIRECTORY_FILE ,
0 ,
0 ,
NULL ,
0 ,
0 ,
NULL ,
NULL ,
& fsp ,
& info ,
NULL ,
NULL
) ;
DBG_DEBUG ( " create_file returned %s \n " , nt_errstr ( status ) ) ;
TALLOC_FREE ( fname ) ;
return NT_STATUS_OK ;
}
2013-03-10 08:43:24 +04:00
2002-08-18 22:04:00 +04:00
struct cmd_set vfs_commands [ ] = {
2019-01-08 19:09:11 +03:00
{ . name = " VFS Commands " } ,
2002-08-18 22:04:00 +04:00
{ " load " , cmd_load_module , " Load a module " , " load <module.so> " } ,
{ " populate " , cmd_populate , " Populate a data buffer " , " populate <char> <size> " } ,
{ " showdata " , cmd_show_data , " Show data currently in data buffer " , " show_data [<offset> <len>] " } ,
{ " connect " , cmd_connect , " VFS connect() " , " connect " } ,
{ " disconnect " , cmd_disconnect , " VFS disconnect() " , " disconnect " } ,
{ " disk_free " , cmd_disk_free , " VFS disk_free() " , " disk_free <path> " } ,
{ " opendir " , cmd_opendir , " VFS opendir() " , " opendir <fname> " } ,
{ " readdir " , cmd_readdir , " VFS readdir() " , " readdir " } ,
{ " mkdir " , cmd_mkdir , " VFS mkdir() " , " mkdir <path> " } ,
{ " rmdir " , cmd_pathfunc , " VFS rmdir() " , " rmdir <path> " } ,
{ " closedir " , cmd_closedir , " VFS closedir() " , " closedir " } ,
2013-11-08 16:56:23 +04:00
{ " open " , cmd_open , " VFS open() " , " open <fname> <flags> <mode> " } ,
2002-08-18 22:04:00 +04:00
{ " close " , cmd_close , " VFS close() " , " close <fd> " } ,
{ " read " , cmd_read , " VFS read() " , " read <fd> <size> " } ,
{ " write " , cmd_write , " VFS write() " , " write <fd> <size> " } ,
{ " lseek " , cmd_lseek , " VFS lseek() " , " lseek <fd> <offset> <whence> " } ,
{ " rename " , cmd_rename , " VFS rename() " , " rename <old> <new> " } ,
{ " fsync " , cmd_fsync , " VFS fsync() " , " fsync <fd> " } ,
{ " stat " , cmd_stat , " VFS stat() " , " stat <fname> " } ,
{ " fstat " , cmd_fstat , " VFS fstat() " , " fstat <fd> " } ,
{ " lstat " , cmd_lstat , " VFS lstat() " , " lstat <fname> " } ,
{ " unlink " , cmd_pathfunc , " VFS unlink() " , " unlink <fname> " } ,
{ " chmod " , cmd_chmod , " VFS chmod() " , " chmod <path> <mode> " } ,
{ " fchmod " , cmd_fchmod , " VFS fchmod() " , " fchmod <fd> <mode> " } ,
{ " fchown " , cmd_fchown , " VFS fchown() " , " fchown <fd> <uid> <gid> " } ,
{ " chdir " , cmd_pathfunc , " VFS chdir() " , " chdir <path> " } ,
{ " getwd " , cmd_getwd , " VFS getwd() " , " getwd " } ,
{ " utime " , cmd_utime , " VFS utime() " , " utime <path> <access> <modify> " } ,
{ " ftruncate " , cmd_ftruncate , " VFS ftruncate() " , " ftruncate <fd> <length> " } ,
2002-08-21 06:34:49 +04:00
{ " lock " , cmd_lock , " VFS lock() " , " lock <f> <op> <offset> <count> <type> " } ,
2002-08-18 22:04:00 +04:00
{ " symlink " , cmd_symlink , " VFS symlink() " , " symlink <old> <new> " } ,
{ " readlink " , cmd_readlink , " VFS readlink() " , " readlink <path> " } ,
{ " link " , cmd_link , " VFS link() " , " link <oldpath> <newpath> " } ,
2002-08-21 06:34:49 +04:00
{ " mknod " , cmd_mknod , " VFS mknod() " , " mknod <path> <mode> <dev> " } ,
2002-08-18 22:04:00 +04:00
{ " realpath " , cmd_realpath , " VFS realpath() " , " realpath <path> " } ,
2012-02-02 19:36:18 +04:00
{ " getxattr " , cmd_getxattr , " VFS getxattr() " ,
" getxattr <path> <name> " } ,
2012-02-02 20:45:09 +04:00
{ " listxattr " , cmd_listxattr , " VFS listxattr() " ,
" listxattr <path> " } ,
2021-02-19 12:17:57 +03:00
{ " fsetxattr " , cmd_fsetxattr , " VFS fsetxattr() " ,
" fsetxattr <path> <name> <value> [<flags>] " } ,
2012-02-02 22:41:56 +04:00
{ " removexattr " , cmd_removexattr , " VFS removexattr() " ,
" removexattr <path> <name> \n " } ,
2012-08-16 07:44:48 +04:00
{ " fget_nt_acl " , cmd_fget_nt_acl , " VFS fget_nt_acl() " ,
" fget_nt_acl <fd> \n " } ,
{ " get_nt_acl " , cmd_get_nt_acl , " VFS get_nt_acl() " ,
" get_nt_acl <path> \n " } ,
{ " fset_nt_acl " , cmd_fset_nt_acl , " VFS fset_nt_acl() " ,
" fset_nt_acl <fd> \n " } ,
{ " set_nt_acl " , cmd_set_nt_acl , " VFS open() and fset_nt_acl() " ,
" set_nt_acl <file> \n " } ,
{ " sys_acl_get_file " , cmd_sys_acl_get_file , " VFS sys_acl_get_file() " , " sys_acl_get_file <path> " } ,
{ " sys_acl_get_fd " , cmd_sys_acl_get_fd , " VFS sys_acl_get_fd() " , " sys_acl_get_fd <fd> " } ,
2012-11-15 18:19:07 +04:00
{ " sys_acl_blob_get_file " , cmd_sys_acl_blob_get_file ,
" VFS sys_acl_blob_get_file() " , " sys_acl_blob_get_file <path> " } ,
2012-11-15 18:25:52 +04:00
{ " sys_acl_blob_get_fd " , cmd_sys_acl_blob_get_fd ,
" VFS sys_acl_blob_get_fd() " , " sys_acl_blob_get_fd <path> " } ,
2012-08-16 07:44:48 +04:00
{ " sys_acl_delete_def_file " , cmd_sys_acl_delete_def_file , " VFS sys_acl_delete_def_file() " , " sys_acl_delete_def_file <path> " } ,
2022-03-11 00:54:35 +03:00
# if defined(WITH_SMB1SERVER)
2012-02-28 03:19:48 +04:00
{ " test_chain " , cmd_test_chain , " test chain code " ,
" test_chain " } ,
2022-03-11 00:54:35 +03:00
# endif
2013-03-10 08:43:24 +04:00
{ " translate_name " , cmd_translate_name , " VFS translate_name() " , " translate_name unix_filename " } ,
2022-02-03 17:25:11 +03:00
{ " create_file " ,
cmd_create_file ,
" VFS create_file() " ,
" create_file <filename> "
} ,
2020-05-05 04:47:39 +03:00
{ 0 }
2002-08-18 22:04:00 +04:00
} ;