diff options
-rw-r--r-- | source4/include/smb.h | 29 | ||||
-rw-r--r-- | source4/librpc/idl/xattr.idl | 18 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_fileinfo.c | 1 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_open.c | 56 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_setfileinfo.c | 2 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_xattr.c | 43 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.c | 4 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.h | 6 |
8 files changed, 116 insertions, 43 deletions
diff --git a/source4/include/smb.h b/source4/include/smb.h index 1fc43fd2f3..fb30ad1c67 100644 --- a/source4/include/smb.h +++ b/source4/include/smb.h @@ -518,7 +518,6 @@ typedef uint64_t HYPER_T; #define NEGOTIATE_SECURITY_SIGNATURES_REQUIRED 0x08 /* NT Flags2 bits - cifs6.txt section 3.1.2 */ - #define FLAGS2_LONG_PATH_COMPONENTS 0x0001 #define FLAGS2_EXTENDED_ATTRIBUTES 0x0002 #define FLAGS2_SMB_SECURITY_SIGNATURES 0x0004 @@ -529,10 +528,8 @@ typedef uint64_t HYPER_T; #define FLAGS2_32_BIT_ERROR_CODES 0x4000 #define FLAGS2_UNICODE_STRINGS 0x8000 -#define FLAGS2_WIN2K_SIGNATURE 0xC852 /* Hack alert ! For now... JRA. */ - -/* Capabilities. see ftp.microsoft.com/developr/drg/cifs/cifs/cifs4.txt */ +/* CIFS protocol capabilities */ #define CAP_RAW_MODE 0x00000001 #define CAP_MPX_MODE 0x00000002 #define CAP_UNICODE 0x00000004 @@ -551,7 +548,7 @@ typedef uint64_t HYPER_T; #define CAP_EXTENDED_SECURITY 0x80000000 /* - * Global value meaing that the smb_uid field should be + * Global value meaning that the smb_uid field should be * ingored (in share level security and protocol level == CORE) */ @@ -559,24 +556,20 @@ typedef uint64_t HYPER_T; #define VUID_OFFSET 100 /* Amount to bias returned vuid numbers */ /* Lock types. */ -#define LOCKING_ANDX_SHARED_LOCK 0x1 -#define LOCKING_ANDX_OPLOCK_RELEASE 0x2 -#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x4 -#define LOCKING_ANDX_CANCEL_LOCK 0x8 -#define LOCKING_ANDX_LARGE_FILES 0x10 - -/* Oplock levels */ -#define OPLOCKLEVEL_NONE 0 -#define OPLOCKLEVEL_II 1 +#define LOCKING_ANDX_SHARED_LOCK 0x01 +#define LOCKING_ANDX_OPLOCK_RELEASE 0x02 +#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 +#define LOCKING_ANDX_CANCEL_LOCK 0x08 +#define LOCKING_ANDX_LARGE_FILES 0x10 /* * Bits we test with. */ -#define NO_OPLOCK 0 -#define EXCLUSIVE_OPLOCK 1 -#define BATCH_OPLOCK 2 -#define LEVEL_II_OPLOCK 4 +#define OPLOCK_NONE 0 +#define OPLOCK_EXCLUSIVE 1 +#define OPLOCK_BATCH 2 +#define OPLOCK_LEVEL_II 4 #define CORE_OPLOCK_GRANTED (1<<5) #define EXTENDED_OPLOCK_GRANTED (1<<15) diff --git a/source4/librpc/idl/xattr.idl b/source4/librpc/idl/xattr.idl index f7bc38605f..501ac2ab7d 100644 --- a/source4/librpc/idl/xattr.idl +++ b/source4/librpc/idl/xattr.idl @@ -19,6 +19,7 @@ interface xattr /* we store basic dos attributes in a DosAttrib xattr. By using a union we can cope with new version of this structure more easily */ + typedef struct { uint32 attrib; uint32 ea_size; @@ -28,8 +29,23 @@ interface xattr NTTIME change_time; } xattr_DosInfo1; + const int XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME = 0x1; + + typedef struct { + uint32 flags; + uint32 attrib; + uint32 ea_size; + uint64 size; + uint64 alloc_size; + NTTIME create_time; + NTTIME change_time; + NTTIME write_time; /* only used when sticky write time is set */ + utf8string name; /* will be used for case-insensitive speedup */ + } xattr_DosInfo2; + typedef union { [case(1)] xattr_DosInfo1 info1; + [case(2)] xattr_DosInfo2 info2; } xattr_DosInfo; typedef [public] struct { @@ -77,7 +93,7 @@ interface xattr } xattr_DosStreams; - /* we store the NT ACL a NTAcl xattr. It is versioned so we + /* we store the NT ACL a NTACL xattr. It is versioned so we can later add other acl attribs (such as posix acl mapping) we put this xattr in the security namespace to ensure that diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c index 32c7ae34fa..fa45444159 100644 --- a/source4/ntvfs/posix/pvfs_fileinfo.c +++ b/source4/ntvfs/posix/pvfs_fileinfo.c @@ -97,6 +97,7 @@ NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, name->dos.nlink = name->st.st_nlink; name->dos.ea_size = 0; name->dos.file_id = (((uint64_t)name->st.st_dev)<<32) | name->st.st_ino; + name->dos.flags = 0; return pvfs_dosattrib_load(pvfs, name, fd); } diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5a23ffaa67..3d0e444d29 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -26,6 +26,7 @@ #include "system/filesys.h" #include "dlinklist.h" #include "messages.h" +#include "librpc/gen_ndr/ndr_xattr.h" /* create file handles with convenient numbers for sniffers @@ -160,15 +161,16 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->share_access = io->generic.in.share_access; f->impersonation = io->generic.in.impersonation; - f->handle->pvfs = pvfs; - f->handle->name = talloc_steal(f->handle, name); - f->handle->fd = -1; - f->handle->odb_locking_key = data_blob(NULL, 0); - f->handle->brl_locking_key = data_blob(NULL, 0); - f->handle->create_options = io->generic.in.create_options; - f->handle->seek_offset = 0; - f->handle->position = 0; - f->handle->mode = 0; + f->handle->pvfs = pvfs; + f->handle->name = talloc_steal(f->handle, name); + f->handle->fd = -1; + f->handle->odb_locking_key = data_blob(NULL, 0); + f->handle->brl_locking_key = data_blob(NULL, 0); + f->handle->create_options = io->generic.in.create_options; + f->handle->seek_offset = 0; + f->handle->position = 0; + f->handle->mode = 0; + f->handle->sticky_write_time = False; DLIST_ADD(pvfs->open_files, f); @@ -201,7 +203,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* the open succeeded, keep this handle permanently */ talloc_steal(pvfs, f); - io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.oplock_level = OPLOCK_NONE; io->generic.out.fnum = f->fnum; io->generic.out.create_action = create_action; io->generic.out.create_time = name->dos.create_time; @@ -225,6 +227,16 @@ static int pvfs_handle_destructor(void *p) { struct pvfs_file_handle *h = p; + /* the write time is no longer sticky */ + if (h->sticky_write_time) { + NTSTATUS status; + status = pvfs_dosattrib_load(h->pvfs, h->name, h->fd); + if (NT_STATUS_IS_OK(status)) { + h->name->dos.flags &= ~XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME; + pvfs_dosattrib_save(h->pvfs, h->name, h->fd); + } + } + if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && h->name->stream_name) { NTSTATUS status; @@ -515,6 +527,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->position = 0; f->handle->mode = 0; f->handle->have_opendb_entry = True; + f->handle->sticky_write_time = False; DLIST_ADD(pvfs->open_files, f); @@ -523,7 +536,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, talloc_set_destructor(f, pvfs_fnum_destructor); talloc_set_destructor(f->handle, pvfs_handle_destructor); - io->generic.out.oplock_level = NO_OPLOCK; + + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + io->generic.out.oplock_level = OPLOCK_EXCLUSIVE; + } else { + io->generic.out.oplock_level = OPLOCK_NONE; + } io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; @@ -685,7 +703,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, name = f->handle->name; - io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.oplock_level = OPLOCK_NONE; io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; io->generic.out.create_time = name->dos.create_time; @@ -963,7 +981,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->create_options = io->generic.in.create_options; f->handle->seek_offset = 0; f->handle->position = 0; + f->handle->mode = 0; f->handle->have_opendb_entry = False; + f->handle->sticky_write_time = False; /* form the lock context used for byte range locking and opendb locking */ @@ -1063,7 +1083,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); - io->generic.out.oplock_level = NO_OPLOCK; + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + io->generic.out.oplock_level = OPLOCK_EXCLUSIVE; + } else { + io->generic.out.oplock_level = OPLOCK_NONE; + } io->generic.out.fnum = f->fnum; io->generic.out.create_action = stream_existed? NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; @@ -1112,8 +1136,12 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, unix_times.actime = 0; unix_times.modtime = io->close.in.write_time; utime(f->handle->name->full_name, &unix_times); + } else if (f->handle->sticky_write_time) { + unix_times.actime = 0; + unix_times.modtime = nt_time_to_unix(f->handle->name->dos.write_time); + utime(f->handle->name->full_name, &unix_times); } - + talloc_free(f); return NT_STATUS_OK; diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index cc1b69b8ea..5a758a6b70 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -245,6 +245,8 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, } if (info->basic_info.in.write_time) { newstats.dos.write_time = info->basic_info.in.write_time; + newstats.dos.flags |= XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME; + h->sticky_write_time = True; } if (info->basic_info.in.change_time) { newstats.dos.change_time = info->basic_info.in.change_time; diff --git a/source4/ntvfs/posix/pvfs_xattr.c b/source4/ntvfs/posix/pvfs_xattr.c index fda15a2e92..47549499e6 100644 --- a/source4/ntvfs/posix/pvfs_xattr.c +++ b/source4/ntvfs/posix/pvfs_xattr.c @@ -183,6 +183,7 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name struct xattr_DosAttrib attrib; TALLOC_CTX *mem_ctx = talloc(name, 0); struct xattr_DosInfo1 *info1; + struct xattr_DosInfo2 *info2; if (name->stream_name != NULL) { name->stream_exists = False; @@ -233,6 +234,27 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name if (info1->change_time != 0) { name->dos.change_time = info1->change_time; } + name->dos.flags = 0; + break; + + case 2: + info2 = &attrib.info.info2; + name->dos.attrib = pvfs_attrib_normalise(info2->attrib); + name->dos.ea_size = info2->ea_size; + if (name->st.st_size == info2->size) { + name->dos.alloc_size = + pvfs_round_alloc_size(pvfs, info2->alloc_size); + } + if (info2->create_time != 0) { + name->dos.create_time = info2->create_time; + } + if (info2->change_time != 0) { + name->dos.change_time = info2->change_time; + } + name->dos.flags = info2->flags; + if (name->dos.flags & XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME) { + name->dos.write_time = info2->write_time; + } break; default: @@ -255,23 +277,26 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name NTSTATUS pvfs_dosattrib_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd) { struct xattr_DosAttrib attrib; - struct xattr_DosInfo1 *info1; + struct xattr_DosInfo2 *info2; if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) { return NT_STATUS_OK; } - attrib.version = 1; - info1 = &attrib.info.info1; + attrib.version = 2; + info2 = &attrib.info.info2; name->dos.attrib = pvfs_attrib_normalise(name->dos.attrib); - info1->attrib = name->dos.attrib; - info1->ea_size = name->dos.ea_size; - info1->size = name->st.st_size; - info1->alloc_size = name->dos.alloc_size; - info1->create_time = name->dos.create_time; - info1->change_time = name->dos.change_time; + info2->attrib = name->dos.attrib; + info2->ea_size = name->dos.ea_size; + info2->size = name->st.st_size; + info2->alloc_size = name->dos.alloc_size; + info2->create_time = name->dos.create_time; + info2->change_time = name->dos.change_time; + info2->write_time = name->dos.write_time; + info2->flags = name->dos.flags; + info2->name = ""; return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, XATTR_DOSATTRIB_NAME, &attrib, diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index e19b0739c7..95b4c20551 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -44,6 +44,10 @@ static void pvfs_setup_options(struct pvfs_state *pvfs) if (lp_strict_locking(snum)) pvfs->flags |= PVFS_FLAG_STRICT_LOCKING; if (lp_ci_filesystem(snum)) pvfs->flags |= PVFS_FLAG_CI_FILESYSTEM; + if (lp_parm_bool(snum, "posix", "fakeoplocks", True)) { + pvfs->flags |= PVFS_FLAG_FAKE_OPLOCKS; + } + #if HAVE_XATTR_SUPPORT if (lp_parm_bool(snum, "posix", "xattr", True)) pvfs->flags |= PVFS_FLAG_XATTR_ENABLE; #endif diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index a79c53ca2e..1ae552b116 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -58,7 +58,6 @@ struct pvfs_state { uint32_t fs_attribs; }; - /* this is the basic information needed about a file from the filesystem */ struct pvfs_dos_fileinfo { NTTIME create_time; @@ -70,6 +69,7 @@ struct pvfs_dos_fileinfo { uint32_t nlink; uint32_t ea_size; uint64_t file_id; + uint32_t flags; }; /* @@ -120,6 +120,9 @@ struct pvfs_file_handle { /* we need this hook back to our parent for lock destruction */ struct pvfs_state *pvfs; + + /* have we set a sticky write time that we should remove on close */ + BOOL sticky_write_time; }; /* open file state */ @@ -189,6 +192,7 @@ struct pvfs_mangle_context { #define PVFS_FLAG_STRICT_SYNC (1<<5) #define PVFS_FLAG_STRICT_LOCKING (1<<6) #define PVFS_FLAG_XATTR_ENABLE (1<<7) +#define PVFS_FLAG_FAKE_OPLOCKS (1<<8) /* forward declare some anonymous structures */ struct pvfs_dir; |