summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/include/smb.h29
-rw-r--r--source4/librpc/idl/xattr.idl18
-rw-r--r--source4/ntvfs/posix/pvfs_fileinfo.c1
-rw-r--r--source4/ntvfs/posix/pvfs_open.c56
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c2
-rw-r--r--source4/ntvfs/posix/pvfs_xattr.c43
-rw-r--r--source4/ntvfs/posix/vfs_posix.c4
-rw-r--r--source4/ntvfs/posix/vfs_posix.h6
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;