[PATCH] s3:client: Add "scopy" cmd to perform Server Side copy using smbclient.

Jeremy Allison jra at samba.org
Mon Jul 13 17:03:09 UTC 2015


On Fri, Jul 10, 2015 at 10:34:22AM -0700, Jeremy Allison wrote:
> On Thu, Jun 25, 2015 at 11:37:18AM +0530, Anubhav Rakshit wrote:
> > 
> > 
> > Signed-off-by: Anubhav Rakshit <anubhav.rakshit at gmail.com>
> 
> Thanks Anubhav - this looks really good ! Here is a slightly
> updated version with a few changes.
> 
> 1). Raised the debug level from 1 to 5 of the splice messages
> (doesnt' flood client console).
> 
> 2). Added missing cli_close of src fd if open of dest file fails.
> 
> 3). Added xml-docs for new command.
> 
> Can I get a second Team reviewer ?

Ralph, do you have time to look at this ?

Cheers,

	Jeremy.

> From c487b08307b383c6f54344cb176b978802fd101f Mon Sep 17 00:00:00 2001
> From: Anubhav Rakshit <anubhav.rakshit at gmail.com>
> Date: Thu, 25 Jun 2015 11:37:18 +0530
> Subject: [PATCH 1/2] s3:client: Add "scopy" cmd to perform Server Side copy
>  using smbclient.
> 
> Signed-off-by: Anubhav Rakshit <anubhav.rakshit at gmail.com>
> Reviewed-by: Jeremy Allison <jra at samba.org>
> ---
>  source3/client/client.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 135 insertions(+)
> 
> diff --git a/source3/client/client.c b/source3/client/client.c
> index fde5b49..d0da6bc 100644
> --- a/source3/client/client.c
> +++ b/source3/client/client.c
> @@ -3806,6 +3806,140 @@ static int cmd_rename(void)
>  	return 0;
>  }
>  
> +struct scopy_timing {
> +	struct timespec tp_start;
> +};
> +
> +static int scopy_status(off_t written, void *priv)
> +{
> +	struct timespec tp_end;
> +	unsigned int scopy_total_time_ms;
> +	struct scopy_timing *st = priv;
> +
> +	clock_gettime_mono(&tp_end);
> +	scopy_total_time_ms = nsec_time_diff(&tp_end,&st->tp_start)/1000000;
> +
> +	DEBUG(5,("Copied ""%" PRIu64 " bytes at an ", written));
> +	DEBUG(5,("average %3.1f kb/s\n",
> +				written / (1.024*scopy_total_time_ms)));
> +
> +	return true;
> +}
> +
> +/****************************************************************************
> + Server-Side copy some file.
> +****************************************************************************/
> +
> +static int cmd_scopy(void)
> +{
> +	TALLOC_CTX *ctx = talloc_tos();
> +	char *src, *dest;
> +	char *buf, *buf2;
> +	struct cli_state *targetcli;
> +	char *targetsrc;
> +	char *targetdest;
> +	uint32_t DesiredAccess, ShareAccess, CreateDisposition, CreateOptions;
> +	struct smb_create_returns cr;
> +	uint16_t destfnum = (uint16_t)-1;
> +	uint16_t srcfnum = (uint16_t)-1;
> +	off_t written = 0;
> +	struct scopy_timing st;
> +	int rc = 0;
> +	NTSTATUS status;
> +
> +	if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
> +			!next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
> +		d_printf("scopy <src> <dest>\n");
> +		return 1;
> +	}
> +
> +	src = talloc_asprintf(ctx,
> +			"%s%s",
> +			client_get_cur_dir(),
> +			buf);
> +	if (!src) {
> +		return 1;
> +	}
> +
> +	dest = talloc_asprintf(ctx,
> +			"%s%s",
> +			client_get_cur_dir(),
> +			buf2);
> +	if (!dest) {
> +		return 1;
> +	}
> +
> +	status = cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli,
> +			&targetsrc);
> +	if (!NT_STATUS_IS_OK(status)) {
> +		d_printf("scopy %s: %s\n", src, nt_errstr(status));
> +		return 1;
> +	}
> +
> +	status = cli_resolve_path(ctx, "", auth_info, cli, dest, &targetcli,
> +			&targetdest);
> +	if (!NT_STATUS_IS_OK(status)) {
> +		d_printf("scopy %s: %s\n", dest, nt_errstr(status));
> +		return 1;
> +	}
> +
> +
> +	DesiredAccess = (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES|
> +			READ_CONTROL_ACCESS|SYNCHRONIZE_ACCESS);
> +	ShareAccess = FILE_SHARE_READ|FILE_SHARE_DELETE;
> +	CreateDisposition = FILE_OPEN;
> +	CreateOptions = (FILE_SEQUENTIAL_ONLY|FILE_NON_DIRECTORY_FILE|
> +			FILE_OPEN_REPARSE_POINT);
> +	status = cli_ntcreate(targetcli, targetsrc, 0, DesiredAccess, 0,
> +			ShareAccess, CreateDisposition, CreateOptions, 0x0,
> +			&srcfnum, &cr);
> +	if (!NT_STATUS_IS_OK(status)) {
> +		d_printf("Failed to open file %s. %s\n",
> +				targetsrc, nt_errstr(status));
> +		return 1;
> +	}
> +
> +	DesiredAccess = (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_READ_EA|
> +			FILE_WRITE_EA|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES|
> +			DELETE_ACCESS|READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|SYNCHRONIZE_ACCESS);
> +	ShareAccess = FILE_SHARE_NONE;
> +	CreateDisposition = FILE_CREATE;
> +	CreateOptions = FILE_SEQUENTIAL_ONLY|FILE_NON_DIRECTORY_FILE;
> +	status = cli_ntcreate(targetcli, targetdest, 0, DesiredAccess,
> +			FILE_ATTRIBUTE_ARCHIVE, ShareAccess, CreateDisposition,
> +			CreateOptions, 0x0, &destfnum, NULL);
> +	if (!NT_STATUS_IS_OK(status)) {
> +		d_printf("Failed to create file %s. %s\n",
> +				targetdest, nt_errstr(status));
> +		cli_close(targetcli, srcfnum);
> +		return 1;
> +	}
> +
> +	clock_gettime_mono(&st.tp_start);
> +	status = cli_splice(targetcli, targetcli, srcfnum, destfnum,
> +			cr.end_of_file, 0, 0, &written, scopy_status, &st);
> +	if (!NT_STATUS_IS_OK(status)) {
> +		d_printf("%s copying file %s -> %s \n",
> +				nt_errstr(status),
> +				targetsrc,
> +				targetdest);
> +		rc = 1;
> +	}
> +
> +	status = cli_close(targetcli, srcfnum);
> +	if (!NT_STATUS_IS_OK(status)) {
> +		d_printf("Error %s closing remote source file\n", nt_errstr(status));
> +		rc = 1;
> +	}
> +	status = cli_close(targetcli, destfnum);
> +	if (!NT_STATUS_IS_OK(status)) {
> +		d_printf("Error %s closing remote dest file\n", nt_errstr(status));
> +		rc = 1;
> +	}
> +
> +	return rc;
> +}
> +
>  /****************************************************************************
>   Print the volume name.
>  ****************************************************************************/
> @@ -4699,6 +4833,7 @@ static struct {
>    {"setea", cmd_setea, "<file name> <eaname> <eaval> Set an EA of a file",
>     {COMPL_REMOTE, COMPL_LOCAL}},
>    {"setmode",cmd_setmode,"<file name> <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
> +  {"scopy",cmd_scopy,"<src> <dest> server-side copy file",{COMPL_REMOTE,COMPL_REMOTE}},
>    {"stat",cmd_stat,"<file name> Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_NONE}},
>    {"symlink",cmd_symlink,"<oldname> <newname> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
>    {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
> -- 
> 2.4.3.573.g4eafbef
> 
> 
> From a0199e19fec56827fd13530d70d08f56deadee9c Mon Sep 17 00:00:00 2001
> From: Jeremy Allison <jra at samba.org>
> Date: Fri, 10 Jul 2015 10:29:01 -0700
> Subject: [PATCH 2/2] docs: Document new scopy command.
> 
> Signed-off-by: Jeremy Allison <jra at samba.org>
> ---
>  docs-xml/manpages/smbclient.1.xml | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/docs-xml/manpages/smbclient.1.xml b/docs-xml/manpages/smbclient.1.xml
> index 8b166d1..e1d805a 100644
> --- a/docs-xml/manpages/smbclient.1.xml
> +++ b/docs-xml/manpages/smbclient.1.xml
> @@ -1011,6 +1011,14 @@
>  		</varlistentry>
>  
>  		<varlistentry>
> +		<term>scopy <source filename> <destination filename></term>
> +		<listitem><para>Attempt to copy a file on the server using the
> +		most efficient server-side copy calls. Falls back to using
> +		read then write if server doesn't support server-side copy.
> +		</para></listitem>
> +		</varlistentry>
> +
> +		<varlistentry>
>  		<term>setmode <filename> <perm=[+|\-]rsha></term>
>  		<listitem><para>A version of the DOS attrib command to set
>  		file permissions. For example: </para>
> -- 
> 2.4.3.573.g4eafbef
> 




More information about the samba-technical mailing list