From 7fa912e708331e729d5e4ffad28646d294d4745a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 07:03:15 +0000 Subject: r3200: - improved the accuracy of openx emulation. We now nearly pass the openx portion of RAW-OPEN - fixed directory size reporting to make it consistent. we now pass the ntcreatex portion of RAW-OPEN (This used to be commit 6282e5811b8d4f1c17152d86875ac60d1323779d) --- source4/ntvfs/ntvfs_generic.c | 56 ++++++++++++++++++++++++++++++------- source4/ntvfs/posix/pvfs_fileinfo.c | 11 ++++---- source4/ntvfs/posix/pvfs_open.c | 7 ++--- 3 files changed, 53 insertions(+), 21 deletions(-) (limited to 'source4') diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index ceb7900935..452273cbdb 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -90,14 +90,20 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io, switch (io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) { case OPENX_MODE_ACCESS_READ: io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ; + io->openx.out.access = OPENX_MODE_ACCESS_READ; break; case OPENX_MODE_ACCESS_WRITE: io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE; + io->openx.out.access = OPENX_MODE_ACCESS_WRITE; break; case OPENX_MODE_ACCESS_RDWR: case OPENX_MODE_ACCESS_FCB: + case OPENX_MODE_ACCESS_EXEC: io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE; + io->openx.out.access = OPENX_MODE_ACCESS_RDWR; break; + default: + return NT_STATUS_INVALID_LOCK_SEQUENCE; } switch (io->openx.in.open_mode & OPENX_MODE_DENY_MASK) { @@ -129,12 +135,11 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io, case OPENX_MODE_DENY_FCB: io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; break; + default: + return NT_STATUS_INVALID_LOCK_SEQUENCE; } switch (io->openx.in.open_func) { - case (OPENX_OPEN_FUNC_FAIL): - io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE; - break; case (OPENX_OPEN_FUNC_OPEN): io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN; break; @@ -150,8 +155,17 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io, case (OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE): io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF; break; + default: + /* this one is very strange */ + if ((io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) == + OPENX_MODE_ACCESS_EXEC) { + io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE; + break; + } + return NT_STATUS_INVALID_LOCK_SEQUENCE; } - io2->generic.in.alloc_size = io->openx.in.size; + + io2->generic.in.alloc_size = 0; io2->generic.in.file_attr = io->openx.in.file_attrs; io2->generic.in.fname = io->openx.in.fname; @@ -159,13 +173,35 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io, if (!NT_STATUS_IS_OK(status)) { return status; } + + io->openx.out.fnum = io2->generic.out.fnum; + io->openx.out.attrib = io2->generic.out.attrib; + io->openx.out.write_time = nt_time_to_unix(io2->generic.out.write_time); + io->openx.out.size = io2->generic.out.size; + io->openx.out.ftype = 0; + io->openx.out.devstate = 0; + io->openx.out.action = io2->generic.out.create_action; + io->openx.out.unique_fid = 0; + io->openx.out.access_mask = io2->generic.in.access_mask; + io->openx.out.unknown = 0; - ZERO_STRUCT(io->openx.out); - io->openx.out.fnum = io2->generic.out.fnum; - io->openx.out.attrib = io2->generic.out.attrib; - io->openx.out.write_time = nt_time_to_unix(io2->generic.out.write_time); - io->openx.out.size = io2->generic.out.size; - + /* we need to extend the file to the requested size if + it was newly created */ + if (io2->generic.out.create_action == NTCREATEX_ACTION_CREATED && + io->openx.in.size != 0) { + union smb_setfileinfo *sf; + sf = talloc_p(req, union smb_setfileinfo); + if (sf != NULL) { + sf->generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; + sf->generic.file.fnum = io2->generic.out.fnum; + sf->end_of_file_info.in.size = io->openx.in.size; + status = ntvfs->ops->setfileinfo(ntvfs, req, sf); + if (NT_STATUS_IS_OK(status)) { + io->openx.out.size = io->openx.in.size; + } + } + } + return NT_STATUS_OK; diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c index 4fa2c1601b..2e2acb2c82 100644 --- a/source4/ntvfs/posix/pvfs_fileinfo.c +++ b/source4/ntvfs/posix/pvfs_fileinfo.c @@ -57,12 +57,6 @@ static uint32_t dos_mode_from_stat(struct pvfs_state *pvfs, struct stat *st) if (S_ISDIR(st->st_mode)) result = FILE_ATTRIBUTE_DIRECTORY | (result & FILE_ATTRIBUTE_READONLY); -#if defined (HAVE_STAT_ST_BLOCKS) && defined (HAVE_STAT_ST_BLKSIZE) - if (st->st_size > st->st_blocks * (off_t)st->st_blksize) { - result |= FILE_ATTRIBUTE_SPARSE; - } -#endif - if (!(result & (FILE_ATTRIBUTE_READONLY| FILE_ATTRIBUTE_ARCHIVE| @@ -82,6 +76,11 @@ static uint32_t dos_mode_from_stat(struct pvfs_state *pvfs, struct stat *st) */ NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name) { + /* make directories appear as size 0 */ + if (S_ISDIR(name->st.st_mode)) { + name->st.st_size = 0; + } + /* for now just use the simple samba mapping */ unix_to_nt_time(&name->dos.create_time, name->st.st_ctime); unix_to_nt_time(&name->dos.access_time, name->st.st_atime); diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 4844521c45..5e162ad147 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -180,8 +180,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, io->generic.out.write_time = name->dos.write_time; io->generic.out.change_time = name->dos.change_time; io->generic.out.attrib = name->dos.attrib; - io->generic.out.alloc_size = 0; - io->generic.out.size = 0; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; io->generic.out.file_type = FILE_TYPE_DISK; io->generic.out.ipc_state = 0; io->generic.out.is_directory = 1; @@ -457,9 +457,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_SUPERSEDE: - if (!name->exists) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } flags = O_TRUNC; break; -- cgit