From bb7d041ff1dc563f747efabff473f25ee14fc491 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 13 Jul 2017 13:57:53 -0500 Subject: [PATCH] s3:smbclient: Allow last dos attribute to be cleared With the upgrade to SMB3.1.1 from cifs for smbclient, setmode no longer works when removing attributes, if the resultant attribute is 0 it is skipped (unlike for the old cifs setpathinfo). When clearing the final attribute, pass in ATTRIBUTE_NORMAL instead of zero. This also removes a redundant cli_setatr call when clearing attributes (cli_setatr was being called twice). BUG: https://bugzilla.samba.org/show_bug.cgi?id=12899 Signed-off-by: Steve French Reviewed-by: Anne Marie Merritt Reviewed-by: Richard Sharpe Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Fri Jul 14 02:43:47 CEST 2017 on sn-devel-144 (cherry picked from commit a4c3ee6767d768365a47bfda32a26cb7994b3787) --- source3/client/client.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index c431a011466..02948bc3fe2 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -4777,11 +4777,21 @@ int set_remote_attr(const char *filename, uint16_t new_attr, int mode) } if (mode == ATTR_SET) { + if (new_attr == old_attr) { + d_printf("attributes unchanged, cli_setatr skipped\n"); + return 0; + } new_attr |= old_attr; } else { new_attr = old_attr & ~new_attr; } - + /* + * if we are clearing attributes - can't pass 0 in + * since that means "skip this field. See MS-FSCC section 2.6 + */ + if (new_attr == 0) { + new_attr = FILE_ATTRIBUTE_NORMAL; + } status = cli_setatr(cli, filename, new_attr, 0); if (!NT_STATUS_IS_OK(status)) { d_printf("cli_setatr failed: %s\n", nt_errstr(status)); @@ -4806,6 +4816,8 @@ int cmd_setmode(void) int mode = ATTR_SET; int err = 0; bool ok; + bool set = false; + bool unset = false; TALLOC_CTX *ctx = talloc_new(NULL); if (ctx == NULL) { return 1; @@ -4833,9 +4845,11 @@ int cmd_setmode(void) while (*s) { switch (*s++) { case '+': + set = true; mode = ATTR_SET; break; case '-': + unset = true; mode = ATTR_UNSET; break; case 'r': @@ -4867,8 +4881,12 @@ int cmd_setmode(void) DEBUG(2, ("perm set %d %d\n", attr[ATTR_SET], attr[ATTR_UNSET])); /* ignore return value: server might not store DOS attributes */ - set_remote_attr(fname, attr[ATTR_SET], ATTR_SET); - set_remote_attr(fname, attr[ATTR_UNSET], ATTR_UNSET); + if (set) { + set_remote_attr(fname, attr[ATTR_SET], ATTR_SET); + } + if (unset) { + set_remote_attr(fname, attr[ATTR_UNSET], ATTR_UNSET); + } out: talloc_free(ctx); return err; -- 2.13.2.932.g7449e964c-goog