[PATCH] Add a "deltree" command to smbclient.

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[PATCH] Add a "deltree" command to smbclient.

Samba - samba-technical mailing list
Works over SMB1/2/3 and also in "posix" mode.

Once this is in we can use it to fix the flapping
symlink tests.

Includes test case + docs.

Please review and push if happy !

Cheers,

        Jeremy.

deltree (12K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Add a "deltree" command to smbclient.

Samba - samba-technical mailing list
On to, 06 heinä 2017, Jeremy Allison via samba-technical wrote:

> Works over SMB1/2/3 and also in "posix" mode.
>
> Once this is in we can use it to fix the flapping
> symlink tests.
>
> Includes test case + docs.
>
> Please review and push if happy !
>
> Cheers,
>
> Jeremy.

> From 960b509d2fc7138ebe4da8c897258cc7344df926 Mon Sep 17 00:00:00 2001
> From: Jeremy Allison <[hidden email]>
> Date: Wed, 5 Jul 2017 15:53:07 -0700
> Subject: [PATCH 1/4] s3: client: Move struct file_list code to using talloc
>  from malloc.
>
> Signed-off-by: Jeremy Allison <[hidden email]>
> ---
>  source3/client/client.c | 29 ++++++++++++++++++-----------
>  1 file changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/source3/client/client.c b/source3/client/client.c
> index c431a011466..82b31b9829d 100644
> --- a/source3/client/client.c
> +++ b/source3/client/client.c
> @@ -2061,8 +2061,7 @@ static void free_file_list (struct file_list *l_head)
>   for (list = l_head; list; list = next) {
>   next = list->next;
>   DLIST_REMOVE(l_head, list);
> - SAFE_FREE(list->file_path);
> - SAFE_FREE(list);
> + TALLOC_FREE(list);
>   }
>  }
>  
> @@ -2107,8 +2106,11 @@ static int cmd_select(void)
>    match must be always set to true when calling this function
>  ****************************************************************************/
>  
> -static int file_find(struct file_list **list, const char *directory,
> -      const char *expression, bool match)
> +static int file_find(TALLOC_CTX *ctx,
> + struct file_list **list,
> + const char *directory,
> + const char *expression,
> + bool match)
>  {
>   DIR *dir;
>   struct file_list *entry;
> @@ -2128,7 +2130,8 @@ static int file_find(struct file_list **list, const char *directory,
>   if (!strcmp(".", dname))
>   continue;
>  
> - if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
> + path = talloc_asprintf("%s/%s", directory, dname);
you missed talloc context for talloc_asprintf()

> + if (path == NULL) {
>   continue;
>   }
>  
> @@ -2139,29 +2142,33 @@ static int file_find(struct file_list **list, const char *directory,
>   if (ret == 0) {
>   if (S_ISDIR(statbuf.st_mode)) {
>   isdir = true;
> - ret = file_find(list, path, expression, false);
> + ret = file_find(ctx,
> + list,
> + path,
> + expression,
> + false);
>   }
>   } else {
>   d_printf("file_find: cannot stat file %s\n", path);
>   }
>  
>   if (ret == -1) {
> - SAFE_FREE(path);
> + TALLOC_FREE(path);
>   closedir(dir);
>   return -1;
>   }
>   }
> - entry = SMB_MALLOC_P(struct file_list);
> + entry = talloc_zero(ctx, struct file_list);
>   if (!entry) {
>   d_printf("Out of memory in file_find\n");
>   closedir(dir);
>   return -1;
>   }
> - entry->file_path = path;
> + entry->file_path = talloc_move(entry, &path);
>   entry->isdir = isdir;
>                          DLIST_ADD(*list, entry);
>   } else {
> - SAFE_FREE(path);
> + TALLOC_FREE(path);
>   }
>          }
>  
> @@ -2185,7 +2192,7 @@ static int cmd_mput(void)
>  
>   file_list = NULL;
>  
> - ret = file_find(&file_list, ".", p, true);
> + ret = file_find(ctx, &file_list, ".", p, true);
>   if (ret) {
>   free_file_list(file_list);
>   continue;
> --
> 2.13.2.725.g09c95d1e9-goog
>
>
> From b6ecfca6b05de85ea8b6d5b6dcbf2fecd8f6e603 Mon Sep 17 00:00:00 2001
> From: Jeremy Allison <[hidden email]>
> Date: Wed, 5 Jul 2017 17:21:18 -0700
> Subject: [PATCH 2/4] s3: smbclient: Add new command deltree.
>
> Signed-off-by: Jeremy Allison <[hidden email]>
> ---
>  source3/client/client.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 175 insertions(+)
>
> diff --git a/source3/client/client.c b/source3/client/client.c
> index 82b31b9829d..d8c1a933970 100644
> --- a/source3/client/client.c
> +++ b/source3/client/client.c
> @@ -2438,6 +2438,180 @@ static int cmd_del(void)
>   return 0;
>  }
>  
> +/****************************************************************************
> + Delete some files.
> +****************************************************************************/
> +
> +static NTSTATUS delete_remote_files_list(struct cli_state *cli_state,
> + struct file_list *flist)
> +{
> + NTSTATUS status = NT_STATUS_OK;
> + struct file_list *deltree_list_iter = NULL;
> +
> + for (deltree_list_iter = flist;
> + deltree_list_iter != NULL;
> + deltree_list_iter = deltree_list_iter->next) {
> + if (CLI_DIRSEP_CHAR == '/') {
> + /* POSIX. */
> + status = cli_posix_unlink(cli_state,
> + deltree_list_iter->file_path);
> + } else if (deltree_list_iter->isdir) {
> + status = cli_rmdir(cli_state,
> + deltree_list_iter->file_path);
> + } else {
> + status = cli_unlink(cli_state,
> + deltree_list_iter->file_path,
> + FILE_ATTRIBUTE_SYSTEM |
> + FILE_ATTRIBUTE_HIDDEN);
> + }
> + if (!NT_STATUS_IS_OK(status)) {
> + d_printf("%s deleting remote %s %s\n",
> + nt_errstr(status),
> + deltree_list_iter->isdir ?
> + "directory" : "file",
> + deltree_list_iter->file_path);
> + return status;
> + }
> + }
> + return NT_STATUS_OK;
> +}
> +
> +/****************************************************************************
> + Save a list of files to delete.
> +****************************************************************************/
> +
> +static struct file_list *deltree_list_head;
> +
> +static NTSTATUS do_deltree_list(struct cli_state *cli_state,
> + struct file_info *finfo,
> + const char *dir)
> +{
> + struct file_list **file_list_head_pp = &deltree_list_head;
> + struct file_list *dt = NULL;
> +
> + if (!do_this_one(finfo)) {
> + return NT_STATUS_OK;
> + }
> +
> + /* skip if this is . or .. */
> + if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
> + return NT_STATUS_OK;
> + }
> +
> + dt = talloc_zero(NULL, struct file_list);
> + if (dt == NULL) {
> + return NT_STATUS_NO_MEMORY;
> + }
> +
> + /* create absolute filename for cli_ntcreate() */
> + dt->file_path = talloc_asprintf(dt,
> + "%s%s%s",
> + dir,
> + CLI_DIRSEP_STR,
> + finfo->name);
> + if (dt->file_path == NULL) {
> + return NT_STATUS_NO_MEMORY;
> + }
> +
> + if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
> + dt->isdir = true;
> + }
> +
> + DLIST_ADD(*file_list_head_pp, dt);
> + return NT_STATUS_OK;
> +}
> +
> +static int cmd_deltree(void)
> +{
> + TALLOC_CTX *ctx = talloc_tos();
> + char *buf = NULL;
> + NTSTATUS status = NT_STATUS_OK;
> + struct file_list *deltree_list_norecurse = NULL;
> + struct file_list *deltree_list_iter = NULL;
> + uint16_t attribute = FILE_ATTRIBUTE_SYSTEM |
> + FILE_ATTRIBUTE_HIDDEN |
> + FILE_ATTRIBUTE_DIRECTORY;
> + char *mask = talloc_strdup(ctx, client_get_cur_dir());
> + if (!mask) {
> + return 1;
> + }
> + if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
> + d_printf("deltree <filename>\n");
> + return 1;
> + }
> + mask = talloc_asprintf_append(mask, "%s", buf);
> + if (!mask) {
> + return 1;
> + }
> +
> + deltree_list_head = NULL;
> +
> + /*
> + * Get the list of directories to
> + * delete (in case mask has a wildcard).
> + */
> + status = do_list(mask,attribute,do_deltree_list,false,true);
> + if (!NT_STATUS_IS_OK(status)) {
> + goto err;
> + }
> + deltree_list_norecurse = deltree_list_head;
> + deltree_list_head = NULL;
> +
> + for (deltree_list_iter = deltree_list_norecurse;
> + deltree_list_iter != NULL;
> + deltree_list_iter = deltree_list_iter->next) {
> +
> + if (deltree_list_iter->isdir == false) {
> + /* Just a regular file. */
> + if (CLI_DIRSEP_CHAR == '/') {
> + /* POSIX. */
> + status = cli_posix_unlink(cli,
> + deltree_list_iter->file_path);
> + } else {
> + status = cli_unlink(cli,
> + deltree_list_iter->file_path,
> + FILE_ATTRIBUTE_SYSTEM |
> + FILE_ATTRIBUTE_HIDDEN);
> + }
> + if (!NT_STATUS_IS_OK(status)) {
> + goto err;
> + }
> + continue;
> + }
> +
> + /*
> + * Get the list of files or directories to
> + * delete in depth order.
> + */
> + status = do_list(deltree_list_iter->file_path,
> + attribute,
> + do_deltree_list,
> + true,
> + true);
> + if (!NT_STATUS_IS_OK(status)) {
> + goto err;
> + }
> + status = delete_remote_files_list(cli, deltree_list_head);
> + free_file_list(deltree_list_head);
> + deltree_list_head = NULL;
> + if (!NT_STATUS_IS_OK(status)) {
> + goto err;
> + }
> + }
> +
> + free_file_list(deltree_list_norecurse);
> + free_file_list(deltree_list_head);
> + return 0;
> +
> +  err:
> +
> + free_file_list(deltree_list_norecurse);
> + free_file_list(deltree_list_head);
> + deltree_list_head = NULL;
> + return 1;
> +}
> +
> +
>  /****************************************************************************
>   Wildcard delete some files.
>  ****************************************************************************/
> @@ -5005,6 +5179,7 @@ static struct {
>    {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_NONE}},
>    {"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_NONE}},
>    {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
> +  {"deltree",cmd_deltree,"<mask> recursively delete all matching files and directories",{COMPL_REMOTE,COMPL_NONE}},
>    {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
>    {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
>    {"echo",cmd_echo,"ping the server",{COMPL_NONE,COMPL_NONE}},
> --
> 2.13.2.725.g09c95d1e9-goog
>
>
> From a0d4269b2cc416d5b900c006d23937237f181266 Mon Sep 17 00:00:00 2001
> From: Jeremy Allison <[hidden email]>
> Date: Wed, 5 Jul 2017 17:23:48 -0700
> Subject: [PATCH 3/4] docs: Document new smbclient deltree command.
>
> Signed-off-by: Jeremy Allison <[hidden email]>
> ---
>  docs-xml/manpages/smbclient.1.xml | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/docs-xml/manpages/smbclient.1.xml b/docs-xml/manpages/smbclient.1.xml
> index 2b712fe18e6..432f60da78a 100644
> --- a/docs-xml/manpages/smbclient.1.xml
> +++ b/docs-xml/manpages/smbclient.1.xml
> @@ -654,6 +654,16 @@
>   directory on the server. </para></listitem>
>   </varlistentry>
>  
> + <varlistentry>
> + <term>deltree &lt;mask&gt;</term>
> + <listitem><para>The client will request that the server attempt
> + to delete all files and directories matching <replaceable>mask</replaceable> from the current working
> + directory on the server. Note this will recursively delete files and directories within
> + the directories selected even without the recurse command being set. If any of the delete
> + requests fail the command will stop processing at that point, leaving files and directories
> + not yet processed untouched. This is by design.</para></listitem>
> + </varlistentry>
> +
>   <varlistentry>
>   <term>dir &lt;mask&gt;</term>
>   <listitem><para>A list of the files matching <replaceable>mask</replaceable> in the current
> --
> 2.13.2.725.g09c95d1e9-goog
>
>
> From d5162f6d9e078ebf6d86a2865800a0ca291b7fc7 Mon Sep 17 00:00:00 2001
> From: Jeremy Allison <[hidden email]>
> Date: Thu, 6 Jul 2017 10:52:45 -0700
> Subject: [PATCH 4/4] s3: tests: Add test for new smbclient "deltree" command.
>
> Signed-off-by: Jeremy Allison <[hidden email]>
> ---
>  source3/script/tests/test_smbclient_s3.sh | 47 +++++++++++++++++++++++++++++++
>  1 file changed, 47 insertions(+)
>
> diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh
> index 4cfd054b018..6a022370205 100755
> --- a/source3/script/tests/test_smbclient_s3.sh
> +++ b/source3/script/tests/test_smbclient_s3.sh
> @@ -1189,6 +1189,49 @@ EOF
>      fi
>  }
>  
> +# Test smbclient deltree command
> +test_deltree()
> +{
> +    tmpfile=$PREFIX/smbclient_interactive_prompt_commands
> +    deltree_dir=$PREFIX/deltree_dir
> +
> +    rm -f $deltree_dir
> +    cat > $tmpfile <<EOF
> +mkdir deltree_dir
> +mkdir deltree_dir/foo
> +mkdir deltree_dir/foo/bar
> +put ${SMBCLIENT} deltree_dir/foo/bar/client
> +deltree deltree_dir
> +quit
> +EOF
> +    cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/tmp -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
> +    eval echo "$cmd"
> +    out=`eval $cmd`
> +    ret=$?
> +
> +    if [ $ret != 0 ] ; then
> + echo "$out"
> + echo "failed deltree test with output $ret"
> + false
> + return
> +    fi
> +
> +    echo "$out" | grep 'NT_STATUS_'
> +    ret=$?
> +    if [ $ret -eq 0 ] ; then
> +       echo "$out"
> +       echo "failed - got an NT_STATUS error"
> +       false
> +       return
> +    fi
> +
> +    if [ -d $deltree_dir ] ; then
> + echo "deltree did not delete everything"
> + false
> + return
> +    fi
> +}
> +
>  test_server_os_message()
>  {
>      tmpfile=$PREFIX/smbclient_interactive_prompt_commands
> @@ -1326,6 +1369,10 @@ testit "follow local symlinks" \
>      test_local_symlinks || \
>      failed=`expr $failed + 1`
>  
> +testit "smbclient deltree command" \
> +    test_deltree || \
> +    failed=`expr $failed + 1`
> +
>  testit "server os message" \
>      test_server_os_message || \
>      failed=`expr $failed + 1`
> --
> 2.13.2.725.g09c95d1e9-goog
>


--
/ Alexander Bokovoy

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Add a "deltree" command to smbclient.

Samba - samba-technical mailing list
On Thu, Jul 06, 2017 at 10:05:46PM +0300, Alexander Bokovoy wrote:

> On to, 06 heinä 2017, Jeremy Allison via samba-technical wrote:
> > Works over SMB1/2/3 and also in "posix" mode.
> >
> > Once this is in we can use it to fix the flapping
> > symlink tests.
> >
> > Includes test case + docs.
> >
> > Please review and push if happy !
> >
> > Cheers,
> >
> > Jeremy.
>
> > From 960b509d2fc7138ebe4da8c897258cc7344df926 Mon Sep 17 00:00:00 2001
> > From: Jeremy Allison <[hidden email]>
> > Date: Wed, 5 Jul 2017 15:53:07 -0700
> > Subject: [PATCH 1/4] s3: client: Move struct file_list code to using talloc
> >  from malloc.
> >
> > Signed-off-by: Jeremy Allison <[hidden email]>
> > ---
> >  source3/client/client.c | 29 ++++++++++++++++++-----------
> >  1 file changed, 18 insertions(+), 11 deletions(-)
> >
> > diff --git a/source3/client/client.c b/source3/client/client.c
> > index c431a011466..82b31b9829d 100644
> > --- a/source3/client/client.c
> > +++ b/source3/client/client.c
> > @@ -2061,8 +2061,7 @@ static void free_file_list (struct file_list *l_head)
> >   for (list = l_head; list; list = next) {
> >   next = list->next;
> >   DLIST_REMOVE(l_head, list);
> > - SAFE_FREE(list->file_path);
> > - SAFE_FREE(list);
> > + TALLOC_FREE(list);
> >   }
> >  }
> >  
> > @@ -2107,8 +2106,11 @@ static int cmd_select(void)
> >    match must be always set to true when calling this function
> >  ****************************************************************************/
> >  
> > -static int file_find(struct file_list **list, const char *directory,
> > -      const char *expression, bool match)
> > +static int file_find(TALLOC_CTX *ctx,
> > + struct file_list **list,
> > + const char *directory,
> > + const char *expression,
> > + bool match)
> >  {
> >   DIR *dir;
> >   struct file_list *entry;
> > @@ -2128,7 +2130,8 @@ static int file_find(struct file_list **list, const char *directory,
> >   if (!strcmp(".", dname))
> >   continue;
> >  
> > - if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
> > + path = talloc_asprintf("%s/%s", directory, dname);
> you missed talloc context for talloc_asprintf()
Thanks :-). How did that even compile (and it was passing 'make test' :-).

Updated version attached.

Jeremy

deltree1 (12K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Add a "deltree" command to smbclient.

Samba - samba-technical mailing list
In reply to this post by Samba - samba-technical mailing list
On Thursday, 6 July 2017 21:05:46 CEST Alexander Bokovoy wrote:

> +       dt = talloc_zero(NULL, struct file_list);
> +       if (dt == NULL) {
> +               return NT_STATUS_NO_MEMORY;
> +       }
> +
> +       /* create absolute filename for cli_ntcreate() */
> +       dt->file_path = talloc_asprintf(dt,
> +                               "%s%s%s",
> +                               dir,
> +                               CLI_DIRSEP_STR,
> +                               finfo->name);
> +       if (dt->file_path == NULL) {

TALLOC_FREE(dt);

missing, I've added it and pushed the patchset upstream

> +               return NT_STATUS_NO_MEMORY;
> +       }


> +# Test smbclient deltree command
> +test_deltree()
> +{
> +    tmpfile=$PREFIX/smbclient_interactive_prompt_commands
> +    deltree_dir=$PREFIX/deltree_dir
> +
> +    rm -f $deltree_dir

And as this is a directory I think we want 'rm -rf'

> +    cat > $tmpfile <<EOF
> +mkdir deltree_dir
> +mkdir deltree_dir/foo
> +mkdir deltree_dir/foo/bar
> +put ${SMBCLIENT} deltree_dir/foo/bar/client
> +deltree deltree_dir
> +quit
> +EOF



        Andreas

--
Andreas Schneider                   GPG-ID: CC014E3D
Samba Team                             [hidden email]
www.samba.org

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Add a "deltree" command to smbclient.

Samba - samba-technical mailing list
On Fri, 2017-07-07 at 09:14 +0200, Andreas Schneider via samba-
technical wrote:

> On Thursday, 6 July 2017 21:05:46 CEST Alexander Bokovoy wrote:
> > +       dt = talloc_zero(NULL, struct file_list);
> > +       if (dt == NULL) {
> > +               return NT_STATUS_NO_MEMORY;
> > +       }
> > +
> > +       /* create absolute filename for cli_ntcreate() */
> > +       dt->file_path = talloc_asprintf(dt,
> > +                               "%s%s%s",
> > +                               dir,
> > +                               CLI_DIRSEP_STR,
> > +                               finfo->name);
> > +       if (dt->file_path == NULL) {
>
> TALLOC_FREE(dt);
>
> missing, I've added it and pushed the patchset upstream
>
> > +               return NT_STATUS_NO_MEMORY;
> > +       }
>
>
> > +# Test smbclient deltree command
> > +test_deltree()
> > +{
> > +    tmpfile=$PREFIX/smbclient_interactive_prompt_commands
> > +    deltree_dir=$PREFIX/deltree_dir
> > +
> > +    rm -f $deltree_dir
>
> And as this is a directory I think we want 'rm -rf'
>
> > +    cat > $tmpfile <<EOF
> > +mkdir deltree_dir
> > +mkdir deltree_dir/foo
> > +mkdir deltree_dir/foo/bar
> > +put ${SMBCLIENT} deltree_dir/foo/bar/client
> > +deltree deltree_dir
> > +quit
> > +EOF
>

Nice!  Thanks for doing the mkdir side remotely, that should avoid this
flapping with the same issue as the symlink test.

Andrew Bartlett
--
Andrew Bartlett                       http://samba.org/~abartlet/
Authentication Developer, Samba Team  http://samba.org
Samba Developer, Catalyst IT          http://catalyst.net.nz/services/samba


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [PATCH] Add a "deltree" command to smbclient.

Samba - samba-technical mailing list
In reply to this post by Samba - samba-technical mailing list
On Fri, Jul 07, 2017 at 09:14:37AM +0200, Andreas Schneider wrote:

> On Thursday, 6 July 2017 21:05:46 CEST Alexander Bokovoy wrote:
> > +       dt = talloc_zero(NULL, struct file_list);
> > +       if (dt == NULL) {
> > +               return NT_STATUS_NO_MEMORY;
> > +       }
> > +
> > +       /* create absolute filename for cli_ntcreate() */
> > +       dt->file_path = talloc_asprintf(dt,
> > +                               "%s%s%s",
> > +                               dir,
> > +                               CLI_DIRSEP_STR,
> > +                               finfo->name);
> > +       if (dt->file_path == NULL) {
>
> TALLOC_FREE(dt);
>
> missing, I've added it and pushed the patchset upstream

Thanks !

> > +               return NT_STATUS_NO_MEMORY;
> > +       }
>
>
> > +# Test smbclient deltree command
> > +test_deltree()
> > +{
> > +    tmpfile=$PREFIX/smbclient_interactive_prompt_commands
> > +    deltree_dir=$PREFIX/deltree_dir
> > +
> > +    rm -f $deltree_dir
>
> And as this is a directory I think we want 'rm -rf'

Yes, that change is correct also.

Thanks a *LOT* for the review !

Jeremy.

Loading...