From b2ce2441a35ed68c39791168217d159352b5143c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 May 2014 21:31:49 -0700 Subject: [PATCH] s3: libsmbclient: Work around bugs in SLES cifsd and Apple smbx SMB1 servers. SLES's cifsd and Apple's smbx do not correctly handle FILE_NON_DIRECTORY_FILE which prevents recursive copies in gvfs from working correctly [1] since GVFS tries to open the directory, expecting ENOTDIR, but it suceeds and appears as a zero byte file. This fix adds code to the cli_open() open code that checks if CreateOptions was requested with FILE_NON_DIRECTORY_FILE set, and if the attributes returned include FILE_ATTRIBUTE_DIRECTORY we synchronously close the file handle just opened, and return NT_STATUS_FILE_IS_A_DIRECTORY to the caller. Depends on the previous API update to cli_ntcreate() to add returned attributes. Fixes bug #10587 - Opening directories on SLES's cifsd and Apple's smbx succeeds. https://bugzilla.samba.org/show_bug.cgi?id=10587 Signed-off-by: Jeremy Allison Reviewed-by: Stefan Metzmacher --- source3/libsmb/clifile.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 7f562a8061a..70b769d1bd8 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -2387,6 +2387,7 @@ NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags, unsigned int openfn = 0; unsigned int dos_deny = 0; uint32_t access_mask, share_mode, create_disposition, create_options; + struct smb_create_returns cr; /* Do the initial mapping into OpenX parameters. */ if (flags & O_CREAT) { @@ -2468,7 +2469,7 @@ NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags, create_options, 0, pfnum, - NULL); + &cr); /* Try and cope will all varients of "we don't do this call" and fall back to openX. */ @@ -2485,6 +2486,25 @@ NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags, goto try_openx; } + if (NT_STATUS_IS_OK(status) && + (create_options & FILE_NON_DIRECTORY_FILE) && + (cr.file_attributes & FILE_ATTRIBUTE_DIRECTORY)) + { + /* + * Some (broken) servers return a valid handle + * for directories even if FILE_NON_DIRECTORY_FILE + * is set. Just close the handle and set the + * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY. + */ + status = cli_close(cli, *pfnum); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = NT_STATUS_FILE_IS_A_DIRECTORY; + /* Set this so libsmbclient can retrieve it. */ + cli->raw_status = status; + } + return status; try_openx: -- 2.11.4.GIT