1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-22 05:57:43 +03:00

s3:net: add 'vfs' hierarchy with 'stream2adouble' command

This adds a new top-level command hierarchy 'vfs' that can be used to add
commands that access the smbd VFS stack.

The first command to be implemented is 'stream2adouble' which can be used to
convert stream metadata to AppleDouble files.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
Ralph Boehme 2019-07-10 16:03:17 +02:00 committed by Jeremy Allison
parent a331b15e2b
commit 17496a39b1
6 changed files with 439 additions and 0 deletions

View File

@ -392,6 +392,26 @@
</para></listitem>
</varlistentry>
<!-- Options for net vfs stream2abouble -->
<varlistentry>
<term>--recursive</term>
<listitem><para>Traverse a directory
hierarchy.</para></listitem>
</varlistentry>
<varlistentry>
<term>--continue</term>
<listitem><para>Continue traversing a directory hierarchy in
case conversion of one file fails.</para></listitem>
</varlistentry>
<varlistentry>
<term>--follow-symlinks</term>
<listitem><para>Follow symlinks encountered while traversing a
directory.</para></listitem>
</varlistentry>
&stdarg.encrypt;
&popt.common.samba.client;
@ -2889,6 +2909,52 @@ Dump the locking table of a certain global lock.
</refsect3>
</refsect2>
<refsect2>
<title>vfs</title>
<para>Access shared filesystem through the VFS.</para>
<refsect3>
<title>vfs stream2abouble [--recursive] [--verbose] [--continue] [--follow-symlinks] <replaceable>share</replaceable> <replaceable>path</replaceable></title>
<para>Convert file streams to AppleDouble files.</para>
<itemizedlist>
<listitem>
<para><replaceable>share</replaceable>
A Samba share.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para><replaceable>path</replaceable> A relative path of something in
the Samba share. "." can be used for the root directory of the
share.</para>
</listitem>
</itemizedlist>
<para>Options:</para>
<variablelist>
<varlistentry>
<term>--recursive</term>
<listitem><para>Traverse a directory hierarchy.</para></listitem>
</varlistentry>
<varlistentry>
<term>--verbose</term>
<listitem><para>Verbose output.</para></listitem>
</varlistentry>
<varlistentry>
<term>--continue</term>
<listitem><para>Continue traversing a directory hierarchy if a single
conversion fails.</para></listitem>
</varlistentry>
<varlistentry>
<term>--follow-symlinks</term>
<listitem><para>Follow symlinks encountered while traversing a
directory.</para></listitem>
</varlistentry>
</variablelist>
</refsect3>
</refsect2>
<refsect2>
<title>HELP [COMMAND]</title>

View File

@ -892,6 +892,14 @@ static struct functable net_func[] = {
"'net tdb' commands.")
},
{ "vfs",
net_vfs,
NET_TRANSPORT_LOCAL,
N_("Filesystem operation through the VFS stack"),
N_(" Use 'net help vfs' to get more information about "
"'net vfs' commands.")
},
#ifdef WITH_FAKE_KASERVER
{ "afs",
net_afs,
@ -1257,6 +1265,25 @@ static void get_credentials_file(struct net_context *c,
.argInfo = POPT_ARG_NONE,
.arg = &c->opt_json,
},
/* Options for 'net vfs' */
{
.longName = "continue",
.argInfo = POPT_ARG_NONE,
.arg = &c->opt_continue_on_error,
.descrip = "Continue on errors",
},
{
.longName = "recursive",
.argInfo = POPT_ARG_NONE,
.arg = &c->opt_recursive,
.descrip = "Traverse directory hierarchy",
},
{
.longName = "follow-symlinks",
.argInfo = POPT_ARG_NONE,
.arg = &c->opt_follow_symlink,
.descrip = "follow symlinks",
},
POPT_COMMON_SAMBA
POPT_TABLEEND
};

View File

@ -87,6 +87,9 @@ struct net_context {
int opt_no_dns_updates;
int opt_keep_account;
int opt_json;
int opt_continue_on_error;
int opt_recursive;
int opt_follow_symlink;
int opt_have_ip;
struct sockaddr_storage opt_dest_ip;

View File

@ -457,4 +457,6 @@ int net_notify(struct net_context *c, int argc, const char **argv);
int net_tdb(struct net_context *c, int argc, const char **argv);
int net_vfs(struct net_context *c, int argc, const char **argv);
#endif /* _NET_PROTO_H_ */

339
source3/utils/net_vfs.c Normal file
View File

@ -0,0 +1,339 @@
/*
* Samba Unix/Linux SMB client library
* Distributed SMB/CIFS Server Management Utility
* Copyright (C) 2019 Ralph Boehme <slow@samba.org>
*
* 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 <talloc.h>
#include <tevent.h>
#include <ftw.h>
#include "system/filesys.h"
#include "system/passwd.h"
#include "popt_common.h"
#include "lib/param/loadparm.h"
#include "lib/param/param.h"
#include "libcli/security/security.h"
#include "smbd/proto.h"
#include "locking/proto.h"
#include "auth.h"
#include "lib/adouble.h"
#include "lib/string_replace.h"
#include "utils/net.h"
#define NET_VFS_CMD_STREAM_TO_ADOUBLE "stream2adouble"
static struct net_vfs_state {
TALLOC_CTX *mem_ctx;
struct net_context *c;
struct auth_session_info *session_info;
struct conn_struct_tos *conn_tos;
} state;
static void net_vfs_usage(void)
{
fprintf(stderr,
"Usage:\n"
"net vfs [OPTIONS] <share> ....\n");
}
static void net_vfs_stream_to_appledouble_usage(void)
{
fprintf(stderr,
"Usage:\n"
"net vfs " NET_VFS_CMD_STREAM_TO_ADOUBLE
" [OPTIONS] <share> <path> [<path> ...]\n"
"Options:\n"
" --verbose verbose output\n"
" --continue continue on error\n"
" --recursive traverse directory hierarchy\n"
" --follow-symlinks follow symlinks\n");
}
static bool net_vfs_make_session_info(struct auth_session_info **session_info)
{
NTSTATUS status;
if (non_root_mode()) {
struct passwd *p = NULL;
p = getpwuid(geteuid());
if (p == NULL) {
fprintf(stderr, "getpwuid(%d) failed\n", geteuid());
return false;
}
status = make_session_info_from_username(state.mem_ctx,
p->pw_name,
false,
session_info);
if (!NT_STATUS_IS_OK(status)) {
fprintf(stderr, "session_info from username failed\n");
return false;
}
return true;
}
status = init_system_session_info(state.mem_ctx);
if (!NT_STATUS_IS_OK(status)) {
fprintf(stderr, "init_system_session_info failed\n");
return false;
}
status = make_session_info_system(state.mem_ctx, session_info);
if (!NT_STATUS_IS_OK(status)) {
fprintf(stderr, "make_session_info_system failed\n");
return false;
}
return true;
}
static int net_vfs_init(struct net_context *c, int argc, const char **argv)
{
const char *service = NULL;
char *share_root = NULL;
int snum;
NTSTATUS status;
bool ok;
int rc = 1;
state = (struct net_vfs_state) {
.c = c,
.mem_ctx = c,
};
if (argc < 1) {
net_vfs_usage();
goto done;
}
if (geteuid() != 0 && !uid_wrapper_enabled()) {
fprintf(stderr, "'net vfs' must be run as root.\n");
goto done;
}
smb_init_locale();
umask(0);
sec_init();
setup_logging("net", DEBUG_STDOUT);
lp_set_cmdline("log level", "0");
ok = lp_load_with_shares(get_dyn_CONFIGFILE());
if (!ok) {
fprintf(stderr, "lp_load_with_shares failed\n");
goto done;
}
ok = locking_init();
if (!ok) {
fprintf(stderr, "locking init failed\n");
goto done;
}
ok = net_vfs_make_session_info(&state.session_info);
if (!ok) {
goto done;
}
service = argv[0];
snum = lp_servicenumber(service);
if (snum == -1) {
fprintf(stderr, "unknown service: %s\n", service);
goto done;
}
share_root = lp_path(state.mem_ctx, snum);
if (share_root == NULL) {
fprintf(stderr, "Failed to find share root for service: %s\n",
service);
goto done;
}
status = create_conn_struct_tos_cwd(global_messaging_context(),
snum,
share_root,
state.session_info,
&state.conn_tos);
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
state.conn_tos->conn->share_access = FILE_GENERIC_ALL;
state.conn_tos->conn->read_only = false;
file_init(state.conn_tos->conn->sconn);
ok = become_user_by_session(state.conn_tos->conn, state.session_info);
if (!ok) {
fprintf(stderr, "become_user_by_session failed\n");
goto done;
}
rc = 0;
done:
return rc;
}
static bool do_unfruit(const char *path)
{
struct smb_filename *smb_fname = NULL;
char *p = NULL;
bool converted;
int ret;
bool ok;
p = strrchr_m(path, '/');
if (p != NULL) {
if (p[1] == '.' && p[2] == '_') {
return true;
}
}
smb_fname = synthetic_smb_fname(state.mem_ctx,
path,
NULL,
NULL,
0);
if (smb_fname == NULL) {
return false;
}
ret = SMB_VFS_STAT(state.conn_tos->conn, smb_fname);
if (ret != 0) {
fprintf(stderr, "%s: %s\n", path, strerror(errno));
if (state.c->opt_continue_on_error) {
return true;
}
return false;
}
ok = ad_unconvert(state.mem_ctx,
state.conn_tos->conn->vfs_handles,
macos_string_replace_map,
smb_fname,
&converted);
if (!ok) {
fprintf(stderr, "Converting failed: %s\n", path);
if (state.c->opt_continue_on_error) {
return true;
}
return false;
}
if (converted) {
fprintf(stdout, "Converted: %s\n", path);
} else if (state.c->opt_verbose) {
fprintf(stdout, "%s\n", path);
}
return true;
}
static int nftw_cb(const char *path,
const struct stat *sb,
int typeflag,
struct FTW *ftwbuf)
{
bool ok;
if (typeflag == FTW_SL) {
if (state.c->opt_verbose) {
fprintf(stdout, "Ignoring symlink: %s\n", path);
}
return 0;
}
ok = do_unfruit(path);
if (!ok) {
return -1;
}
return 0;
}
static int net_vfs_stream_to_appledouble(struct net_context *net,
int argc,
const char **argv)
{
int i;
int ret;
bool ok;
int rc = 1;
if (argc < 2 || net->display_usage) {
net_vfs_stream_to_appledouble_usage();
goto done;
}
ret = net_vfs_init(net, argc, argv);
if (ret != 0) {
goto done;
}
for (i = 1; i < argc; i++) {
const char *path = argv[i];
if (path[0] == '/') {
fprintf(stderr, "ignoring absolute path: %s\n", path);
if (state.c->opt_continue_on_error) {
continue;
}
goto done;
}
if (!state.c->opt_recursive) {
ok = do_unfruit(path);
if (!ok) {
if (!state.c->opt_continue_on_error) {
goto done;
}
}
continue;
}
ret = nftw(path,
nftw_cb,
256,
state.c->opt_follow_symlink ? 0 : FTW_PHYS);
if (ret != 0) {
fprintf(stderr, "%s: %s\n", path, strerror(errno));
if (!state.c->opt_continue_on_error) {
goto done;
}
}
}
rc = 0;
done:
return rc;
}
static struct functable func[] = {
{
NET_VFS_CMD_STREAM_TO_ADOUBLE,
net_vfs_stream_to_appledouble,
NET_TRANSPORT_LOCAL,
N_("Convert streams to AppleDouble files"),
N_("net vfs " NET_VFS_CMD_STREAM_TO_ADOUBLE " [OPTIONS] <share> <path> [<path> ...]")
},
{NULL, NULL, 0, NULL, NULL}
};
int net_vfs(struct net_context *c, int argc, const char **argv)
{
return net_run_function(c, argc, argv, "net vfs", func);
}

View File

@ -224,6 +224,7 @@ bld.SAMBA3_BINARY('net',
net_afs.c
net_notify.c
net_tdb.c
net_vfs.c
../registry/reg_parse.c
../registry/reg_format.c
../registry/reg_import.c
@ -269,6 +270,7 @@ bld.SAMBA3_BINARY('net',
CONN_TDB
jansson
common_auth
ADOUBLE
''')
bld.SAMBA3_BINARY('mvxattr',