The branch, master has been updated via 440d71f torture test for bug #8111 - CIFS VFS: unexpected error on SMB posix open. via 7673943 Fix bug 8111 - CIFS VFS: unexpected error on SMB posix open from bbacaec s3-proto: move more headers to rpc_server/rpc_ncacn_np.h where they origin from.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 440d71f6c76a4363f69eaf70cada69bdcb98c7bf Author: Jeremy Allison <j...@samba.org> Date: Fri Apr 29 14:27:45 2011 -0700 torture test for bug #8111 - CIFS VFS: unexpected error on SMB posix open. Autobuild-User: Jeremy Allison <j...@samba.org> Autobuild-Date: Sat Apr 30 00:33:40 CEST 2011 on sn-devel-104 commit 76739435fc8abf1f47193ec4db35a567b564c785 Author: Jeremy Allison <j...@samba.org> Date: Fri Apr 29 14:27:32 2011 -0700 Fix bug 8111 - CIFS VFS: unexpected error on SMB posix open We are conflating the O_CREAT|O_EXCL with the O_TRUNC processing, they need to be separate. We need to chose using (O_CREAT|O_EXCL) first, then modify if O_TRUNC is set. This needs two separate switch statements. Jeremy ----------------------------------------------------------------------- Summary of changes: source3/smbd/trans2.c | 61 ++++++++++++++++++++++++++++++++++++--------- source3/torture/torture.c | 55 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 12 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index abab387..028d318 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7286,18 +7286,55 @@ static NTSTATUS smb_posix_open(connection_struct *conn, wire_open_mode &= ~SMB_ACCMODE; - if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) { - create_disp = FILE_CREATE; - } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) { - create_disp = FILE_OVERWRITE_IF; - } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) { - create_disp = FILE_OPEN_IF; - } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) { - create_disp = FILE_OPEN; - } else { - DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n", - (unsigned int)wire_open_mode )); - return NT_STATUS_INVALID_PARAMETER; + /* First take care of O_CREAT|O_EXCL interactions. */ + switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) { + case (SMB_O_CREAT | SMB_O_EXCL): + /* File exists fail. File not exist create. */ + create_disp = FILE_CREATE; + break; + case SMB_O_CREAT: + /* File exists open. File not exist create. */ + create_disp = FILE_OPEN_IF; + break; + case 0: + /* File exists open. File not exist fail. */ + create_disp = FILE_OPEN; + break; + case SMB_O_EXCL: + /* O_EXCL on its own without O_CREAT is undefined. */ + default: + DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n", + (unsigned int)wire_open_mode )); + return NT_STATUS_INVALID_PARAMETER; + } + + /* Next factor in the effects of O_TRUNC. */ + wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL); + + if (wire_open_mode & SMB_O_TRUNC) { + switch (create_disp) { + case FILE_CREATE: + /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */ + /* Leave create_disp alone as + (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL) + */ + /* File exists fail. File not exist create. */ + break; + case FILE_OPEN_IF: + /* SMB_O_CREAT | SMB_O_TRUNC */ + /* File exists overwrite. File not exist create. */ + create_disp = FILE_OVERWRITE_IF; + break; + case FILE_OPEN: + /* SMB_O_TRUNC */ + /* File exists overwrite. File not exist fail. */ + create_disp = FILE_OVERWRITE; + break; + default: + /* Cannot get here. */ + smb_panic("smb_posix_open: logic error"); + return NT_STATUS_INVALID_PARAMETER; + } } raw_unixmode = IVAL(pdata,8); diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 3c5de28..61af238 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -5018,6 +5018,61 @@ static bool run_simple_posix_open_test(int dummy) goto out; } + /* Create again to test open with O_TRUNC. */ + if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) { + printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1)); + goto out; + } + + /* Test ftruncate - set file size. */ + if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 1000))) { + printf("ftruncate failed (%s)\n", cli_errstr(cli1)); + goto out; + } + + /* Ensure st_size == 1000 */ + if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) { + printf("stat failed (%s)\n", cli_errstr(cli1)); + goto out; + } + + if (sbuf.st_ex_size != 1000) { + printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size); + goto out; + } + + if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) { + printf("close(2) failed (%s)\n", cli_errstr(cli1)); + goto out; + } + + /* Re-open with O_TRUNC. */ + if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1))) { + printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1)); + goto out; + } + + /* Ensure st_size == 0 */ + if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) { + printf("stat failed (%s)\n", cli_errstr(cli1)); + goto out; + } + + if (sbuf.st_ex_size != 0) { + printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size); + goto out; + } + + if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) { + printf("close failed (%s)\n", cli_errstr(cli1)); + goto out; + } + + if (!NT_STATUS_IS_OK(cli_posix_unlink(cli1, fname))) { + printf("POSIX unlink of %s failed (%s)\n", fname, cli_errstr(cli1)); + goto out; + } + /* What happens when we try and POSIX open a directory ? */ if (NT_STATUS_IS_OK(cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1))) { printf("POSIX open of directory %s succeeded, should have failed.\n", fname); -- Samba Shared Repository