r8219: Merge the new open code from HEAD to 3.0. Haven't yet run the torture
authorJeremy Allison <jra@samba.org>
Fri, 8 Jul 2005 04:51:27 +0000 (04:51 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:58:18 +0000 (10:58 -0500)
tests on this as it's very late NY time (just wanted to get this work
into the tree). I'll test this over the weekend....
Jerry - in looking at the difference between the two trees there
seem to be some printing/ntprinting.c and registry changes we might
want to examine to try keep in sync.
Jeremy.
(This used to be commit c7fe18761e2c753afbffd3a78abff46472a9b8eb)

35 files changed:
source3/include/doserr.h
source3/include/ntlmssp.h
source3/include/smb.h
source3/include/smb_macros.h
source3/include/vfs.h
source3/lib/util.c
source3/libsmb/clifile.c
source3/libsmb/errormap.c
source3/locking/locking.c
source3/locking/posix.c
source3/modules/vfs_afsacl.c
source3/printing/nt_printing.c
source3/printing/printfsp.c
source3/rpc_server/srv_srvsvc_nt.c
source3/smbd/close.c
source3/smbd/dir.c
source3/smbd/dosmode.c
source3/smbd/fake_file.c
source3/smbd/fileio.c
source3/smbd/files.c
source3/smbd/ntquotas.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/oplock.c
source3/smbd/oplock_linux.c
source3/smbd/pipes.c
source3/smbd/posix_acls.c
source3/smbd/reply.c
source3/smbd/trans2.c
source3/smbd/vfs-wrap.c
source3/smbd/vfs.c
source3/torture/cmd_vfs.c
source3/utils/status.c
source3/web/cgi.c
source3/web/statuspage.c

index 77255ee4c112c15d83959560b0118f3de5de9788..647f11527b7d0efe6fb70f15321c4bcee301b706 100644 (file)
@@ -63,6 +63,9 @@
 #define ERRinvalidname 123 /* Invalid name */
 #define ERRunknownlevel 124
 #define ERRnotlocked 158 /* This region is not locked by this locking context. */
+#define ERRinvalidpath 161
+#define ERRcancelviolation 173
+#define ERRnoatomiclocks 174
 #define ERRrename 183
 #define ERRbadpipe 230 /* Named pipe invalid */
 #define ERRpipebusy 231 /* All instances of pipe are busy */
index 8ab6265673c227f248d9c53679a79a780143fe06..267779c434d462334e40a9673fb40edc00edd4ae 100644 (file)
@@ -124,7 +124,6 @@ typedef struct ntlmssp_state
         *
         * @param ntlmssp_state This structure
         * @param challenge 8 bytes of data, agreed by the client and server to be the effective challenge for NTLM2 authentication
-        * @param challange 8 bytes of data, agreed by the client and server to be the effective challenge for NTLM2 authentication
         *
         */
        NTSTATUS (*set_challenge)(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge);
index 50bd233da76f6254da5c0a665011144286b09f85..55baf84531587e7835d3443d4adff97794a1a10d 100644 (file)
@@ -107,44 +107,32 @@ typedef int BOOL;
 #define DOS_OPEN_FCB 0xF
 
 /* define shifts and masks for share and open modes. */
-#define OPEN_MODE_MASK 0xF
-#define SHARE_MODE_SHIFT 4
-#define SHARE_MODE_MASK 0x7
-#define GET_OPEN_MODE(x) ((x) & OPEN_MODE_MASK)
-#define SET_OPEN_MODE(x) ((x) & OPEN_MODE_MASK)
-#define GET_DENY_MODE(x) (((x)>>SHARE_MODE_SHIFT) & SHARE_MODE_MASK)
-#define SET_DENY_MODE(x) (((x) & SHARE_MODE_MASK) <<SHARE_MODE_SHIFT)
+#define OPENX_MODE_MASK 0xF
+#define DENY_MODE_SHIFT 4
+#define DENY_MODE_MASK 0x7
+#define GET_OPENX_MODE(x) ((x) & OPENX_MODE_MASK)
+#define SET_OPENX_MODE(x) ((x) & OPENX_MODE_MASK)
+#define GET_DENY_MODE(x) (((x)>>DENY_MODE_SHIFT) & DENY_MODE_MASK)
+#define SET_DENY_MODE(x) (((x) & DENY_MODE_MASK) <<DENY_MODE_SHIFT)
 
 /* Sync on open file (not sure if used anymore... ?) */
 #define FILE_SYNC_OPENMODE (1<<14)
 #define GET_FILE_SYNC_OPENMODE(x) (((x) & FILE_SYNC_OPENMODE) ? True : False)
 
-/* allow delete on open file mode (used by NT SMB's). */
-#define ALLOW_SHARE_DELETE (1<<15)
-#define GET_ALLOW_SHARE_DELETE(x) (((x) & ALLOW_SHARE_DELETE) ? True : False)
-#define SET_ALLOW_SHARE_DELETE(x) ((x) ? ALLOW_SHARE_DELETE : 0)
-
-/* delete on close flag (used by NT SMB's). */
-#define DELETE_ON_CLOSE_FLAG (1<<16)
-#define GET_DELETE_ON_CLOSE_FLAG(x) (((x) & DELETE_ON_CLOSE_FLAG) ? True : False)
-#define SET_DELETE_ON_CLOSE_FLAG(x) ((x) ? DELETE_ON_CLOSE_FLAG : 0)
-
 /* open disposition values */
-#define FILE_EXISTS_FAIL 0
-#define FILE_EXISTS_OPEN 1
-#define FILE_EXISTS_TRUNCATE 2
+#define OPENX_FILE_EXISTS_FAIL 0
+#define OPENX_FILE_EXISTS_OPEN 1
+#define OPENX_FILE_EXISTS_TRUNCATE 2
 
 /* mask for open disposition. */
-#define FILE_OPEN_MASK 0x3
+#define OPENX_FILE_OPEN_MASK 0x3
 
-#define GET_FILE_OPEN_DISPOSITION(x) ((x) & FILE_OPEN_MASK)
-#define SET_FILE_OPEN_DISPOSITION(x) ((x) & FILE_OPEN_MASK)
+#define GET_FILE_OPENX_DISPOSITION(x) ((x) & FILE_OPEN_MASK)
+#define SET_FILE_OPENX_DISPOSITION(x) ((x) & FILE_OPEN_MASK)
 
 /* The above can be OR'ed with... */
-#define FILE_CREATE_IF_NOT_EXIST 0x10
-#define FILE_FAIL_IF_NOT_EXIST 0
-
-#define GET_FILE_CREATE_DISPOSITION(x) ((x) & (FILE_CREATE_IF_NOT_EXIST|FILE_FAIL_IF_NOT_EXIST))
+#define OPENX_FILE_CREATE_IF_NOT_EXIST 0x10
+#define OPENX_FILE_FAIL_IF_NOT_EXIST 0
 
 /* share types */
 #define STYPE_DISKTREE  0      /* Disk drive */
@@ -407,27 +395,38 @@ typedef struct
 
 #include "fake_file.h"
 
+struct fd_handle {
+       size_t ref_count;
+       int fd;
+       SMB_BIG_UINT position_information;
+       SMB_OFF_T pos;
+       uint32 private_options; /* NT Create options, but we only look at
+                                * NTCREATEX_OPTIONS_PRIVATE_DENY_DOS and
+                                * NTCREATEX_OPTIONS_PRIVATE_DENY_FCB (Except
+                                * for print files *only*, where
+                                * DELETE_ON_CLOSE is not stored in the share
+                                * mode database.
+                                */
+};
+
 typedef struct files_struct {
        struct files_struct *next, *prev;
        int fnum;
        struct connection_struct *conn;
-       int fd;
+       struct fd_handle *fh;
        unsigned int num_smb_operations;
        uint16 rap_print_jobid;
        SMB_DEV_T dev;
        SMB_INO_T inode;
-       BOOL delete_on_close;
-       SMB_OFF_T pos;
        SMB_BIG_UINT initial_allocation_size; /* Faked up initial allocation on disk. */
-       SMB_BIG_UINT position_information;
        mode_t mode;
        uint16 file_pid;
        uint16 vuid;
        write_bmpx_struct *wbmpx_ptr;
        write_cache *wcp;
        struct timeval open_time;
-       int share_mode;
-       uint32 desired_access;
+       uint32 access_mask;             /* NTCreateX access bits (FILE_READ_DATA etc.) */
+       uint32 share_access;            /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */
        BOOL pending_modtime_owner;
        time_t pending_modtime;
        time_t last_write_time;
@@ -441,7 +440,6 @@ typedef struct files_struct {
        BOOL modified;
        BOOL is_directory;
        BOOL is_stat;
-       BOOL directory_delete_on_close;
        BOOL aio_write_behind;
        char *fsp_name;
        FAKE_FILE_HANDLE *fake_file_handle;
@@ -639,8 +637,12 @@ typedef struct {
        pid_t pid;
        uint16 op_port;
        uint16 op_type;
-       int share_mode;
-       uint32 desired_access;
+       uint32 access_mask;             /* NTCreateX access bits (FILE_READ_DATA etc.) */
+       uint32 share_access;            /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */
+       uint32 private_options; /* NT Create options, but we only look at
+                                * NTCREATEX_OPTIONS_PRIVATE_DENY_DOS and
+                                * NTCREATEX_OPTIONS_PRIVATE_DENY_FCB for
+                                * smbstatus and swat */
        struct timeval time;
        SMB_DEV_T dev;
        SMB_INO_T inode;
@@ -1079,18 +1081,18 @@ struct bitmap {
 #define DESIRED_ACCESS_PIPE 0x2019f
  
 /* Generic access masks & rights. */
-#define DELETE_ACCESS        (1L<<16) /* 0x00010000 */
-#define READ_CONTROL_ACCESS  (1L<<17) /* 0x00020000 */
-#define WRITE_DAC_ACCESS     (1L<<18) /* 0x00040000 */
-#define WRITE_OWNER_ACCESS   (1L<<19) /* 0x00080000 */
-#define SYNCHRONIZE_ACCESS   (1L<<20) /* 0x00100000 */
-
-#define SYSTEM_SECURITY_ACCESS (1L<<24)           /* 0x01000000 */
-#define MAXIMUM_ALLOWED_ACCESS (1L<<25)           /* 0x02000000 */
-#define GENERIC_ALL_ACCESS     (1<<28)            /* 0x10000000 */
-#define GENERIC_EXECUTE_ACCESS (1<<29)            /* 0x20000000 */
-#define GENERIC_WRITE_ACCESS   (1<<30)            /* 0x40000000 */
-#define GENERIC_READ_ACCESS   (((unsigned)1)<<31) /* 0x80000000 */
+#define DELETE_ACCESS        0x00010000 /* (1L<<16) */
+#define READ_CONTROL_ACCESS  0x00020000 /* (1L<<17) */
+#define WRITE_DAC_ACCESS     0x00040000 /* (1L<<18) */
+#define WRITE_OWNER_ACCESS   0x00080000 /* (1L<<19) */
+#define SYNCHRONIZE_ACCESS   0x00100000 /* (1L<<20) */
+
+#define SYSTEM_SECURITY_ACCESS 0x01000000 /* (1L<<24) */
+#define MAXIMUM_ALLOWED_ACCESS 0x02000000 /* (1L<<25) */
+#define GENERIC_ALL_ACCESS     0x10000000 /* (1<<28) */
+#define GENERIC_EXECUTE_ACCESS 0x20000000 /* (1<<29) */
+#define GENERIC_WRITE_ACCESS   0x40000000 /* (1<<30) */
+#define GENERIC_READ_ACCESS    ((unsigned)0x80000000) /* (((unsigned)1)<<31) */
 
 /* Mapping of generic access rights for files to specific rights. */
 
@@ -1172,12 +1174,12 @@ struct bitmap {
 #define FILE_FLAG_POSIX_SEMANTICS  0x01000000L
 
 /* CreateDisposition field. */
-#define FILE_SUPERSEDE 0
-#define FILE_OPEN 1
-#define FILE_CREATE 2
-#define FILE_OPEN_IF 3
-#define FILE_OVERWRITE 4
-#define FILE_OVERWRITE_IF 5
+#define FILE_SUPERSEDE 0               /* File exists overwrite/supersede. File not exist create. */
+#define FILE_OPEN 1                    /* File exists open. File not exist fail. */
+#define FILE_CREATE 2                  /* File exists fail. File not exist create. */
+#define FILE_OPEN_IF 3                 /* File exists open. File not exist create. */
+#define FILE_OVERWRITE 4               /* File exists overwrite. File not exist fail. */
+#define FILE_OVERWRITE_IF 5            /* File exists overwrite. File not exist create. */
 
 /* CreateOptions field. */
 #define FILE_DIRECTORY_FILE       0x0001
@@ -1190,6 +1192,10 @@ struct bitmap {
 #define FILE_DELETE_ON_CLOSE      0x1000
 #define FILE_OPEN_BY_FILE_ID     0x2000
 
+/* Private create options used by the ntcreatex processing code. From Samba4. */
+#define NTCREATEX_OPTIONS_PRIVATE_DENY_DOS     0x01000000
+#define NTCREATEX_OPTIONS_PRIVATE_DENY_FCB     0x02000000
+
 /* Responses when opening a file. */
 #define FILE_WAS_SUPERSEDED 0
 #define FILE_WAS_OPENED 1
@@ -1335,7 +1341,7 @@ char *strdup(char *s);
 #define FLAGS2_IS_LONG_NAME            0x0040
 #define FLAGS2_EXTENDED_SECURITY       0x0800 
 #define FLAGS2_DFS_PATHNAMES           0x1000
-#define FLAGS2_READ_PERMIT_NO_EXECUTE  0x2000
+#define FLAGS2_READ_PERMIT_EXECUTE     0x2000
 #define FLAGS2_32_BIT_ERROR_CODES      0x4000 
 #define FLAGS2_UNICODE_STRINGS         0x8000
 
@@ -1442,36 +1448,36 @@ extern int chain_size;
 #define LOCKING_ANDX_CANCEL_LOCK 0x8
 #define LOCKING_ANDX_LARGE_FILES 0x10
 
-/* Oplock levels */
-#define OPLOCKLEVEL_NONE 0
-#define OPLOCKLEVEL_II 1
-
 /*
  * Bits we test with.
  */
-
+                                                                                                                              
 #define NO_OPLOCK 0
 #define EXCLUSIVE_OPLOCK 1
 #define BATCH_OPLOCK 2
 #define LEVEL_II_OPLOCK 4
 #define INTERNAL_OPEN_ONLY 8
 
-#define EXCLUSIVE_OPLOCK_TYPE(lck) ((lck) & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
-#define BATCH_OPLOCK_TYPE(lck) ((lck) & BATCH_OPLOCK)
-#define LEVEL_II_OPLOCK_TYPE(lck) ((lck) & LEVEL_II_OPLOCK)
-
-#define CORE_OPLOCK_GRANTED (1<<5)
-#define EXTENDED_OPLOCK_GRANTED (1<<15)
+#define EXCLUSIVE_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)EXCLUSIVE_OPLOCK|(unsigned int)BATCH_OPLOCK))
+#define BATCH_OPLOCK_TYPE(lck) ((lck) & (unsigned int)BATCH_OPLOCK)
+#define LEVEL_II_OPLOCK_TYPE(lck) ((lck) & (unsigned int)LEVEL_II_OPLOCK)
 
 /*
- * Return values for oplock types.
+ * On the wire return values for oplock types.
  */
 
+#define CORE_OPLOCK_GRANTED (1<<5)
+#define EXTENDED_OPLOCK_GRANTED (1<<15)
+
 #define NO_OPLOCK_RETURN 0
 #define EXCLUSIVE_OPLOCK_RETURN 1
 #define BATCH_OPLOCK_RETURN 2
 #define LEVEL_II_OPLOCK_RETURN 3
 
+/* Oplock levels */
+#define OPLOCKLEVEL_NONE 0
+#define OPLOCKLEVEL_II 1
+
 /*
  * Loopback command offsets.
  */
index b7e27d22667d1a76225f147509305ce43e5f89c5..7a0afdfc19294fa74c393bb45ee7770062c5fb7e 100644 (file)
                        extern struct current_user current_user;\
                        if (!FNUM_OK(fsp,conn)) \
                                return(ERROR_DOS(ERRDOS,ERRbadfid)); \
-                       else if((fsp)->fd == -1) \
+                       else if((fsp)->fh->fd == -1) \
                                return(ERROR_DOS(ERRDOS,ERRbadaccess));\
                        (fsp)->num_smb_operations++;\
                        } while(0)
 
-#define CHECK_READ(fsp) if (!(fsp)->can_read) \
-                               return(ERROR_DOS(ERRDOS,ERRbadaccess))
-#define CHECK_WRITE(fsp) if (!(fsp)->can_write) \
-                               return(ERROR_DOS(ERRDOS,ERRbadaccess))
+#define CHECK_READ(fsp,inbuf) (((fsp)->fh->fd != -1) && ((fsp)->can_read || \
+                       ((SVAL((inbuf),smb_flg2) & FLAGS2_READ_PERMIT_EXECUTE) && \
+                        (fsp->access_mask & FILE_EXECUTE))))
+
+#define CHECK_WRITE(fsp) ((fsp)->can_write && ((fsp)->fh->fd != -1))
 
 #define ERROR_WAS_LOCK_DENIED(status) (NT_STATUS_EQUAL((status), NT_STATUS_LOCK_NOT_GRANTED) || \
                                NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT) )
index 71b4f6562799545a65378628655b226e0d9fc660..7f6c94f6e99feadcaab9be1739b51de1ddc7cd6a 100644 (file)
@@ -58,7 +58,8 @@
 /* Changed to version 11 to include seekdir/telldir/rewinddir calls. JRA */
 /* Changed to version 12 to add mask and attributes to opendir(). JRA 
    Also include aio calls. JRA. */
-#define SMB_VFS_INTERFACE_VERSION 12
+/* Changed to version 13 as the internal structure of files_struct has changed. JRA */
+#define SMB_VFS_INTERFACE_VERSION 13
 
 
 /* to bug old modules which are trying to compile with the old functions */
index 42cbc7288f913c45be70e0d9c580ca6120dd5472..de366c604ffe688d0b9901e1ec22fbf91b47385a 100644 (file)
@@ -2735,3 +2735,25 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
        return ret;
 }
 #endif
+
+uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
+{
+       switch (share_access) {
+               case FILE_SHARE_NONE:
+                       return DENY_ALL;
+               case FILE_SHARE_READ:
+                       return DENY_WRITE;
+               case FILE_SHARE_WRITE:
+                       return DENY_READ;
+               case FILE_SHARE_READ|FILE_SHARE_WRITE:
+               case FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE:
+                       return DENY_NONE;
+       }
+       if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
+               return DENY_DOS;
+       } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
+               return DENY_FCB;
+       }
+
+       return (uint32)-1;
+}
index 2fb5b456cc4fe664bc12ec136b83922999410c94..87c6f2568b165005ea0e87ee1e2b5c987404298f 100644 (file)
@@ -705,7 +705,7 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname,
 int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess)
 {
        return cli_nt_create_full(cli, fname, 0, DesiredAccess, 0,
-                               FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_EXISTS_OPEN, 0x0, 0x0);
+                               FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0);
 }
 
 /****************************************************************************
index c79561bda87a54cebdfd1dc9a1b3811b6c60d771..8462fbee877d7cd7fe8f431b9f8fb976a44c6604 100644 (file)
@@ -124,9 +124,9 @@ static const struct {
        {ERRHRD,        ERRgeneral,     NT_STATUS_HANDLE_NOT_WAITABLE},
        {ERRDOS,        ERRbadfid,      NT_STATUS_PORT_DISCONNECTED},
        {ERRHRD,        ERRgeneral,     NT_STATUS_DEVICE_ALREADY_ATTACHED},
-       {ERRDOS,        161,    NT_STATUS_OBJECT_PATH_INVALID},
+       {ERRDOS,        ERRinvalidpath, NT_STATUS_OBJECT_PATH_INVALID},
        {ERRDOS,        ERRbadpath,     NT_STATUS_OBJECT_PATH_NOT_FOUND},
-       {ERRDOS,        161,    NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
+       {ERRDOS,        ERRinvalidpath, NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
        {ERRHRD,        ERRgeneral,     NT_STATUS_DATA_OVERRUN},
        {ERRHRD,        ERRgeneral,     NT_STATUS_DATA_LATE_ERROR},
        {ERRDOS,        23,     NT_STATUS_DATA_ERROR},
index 3c5ab63b4ab994100d20dedd3f268a90dbc5325f..5bcf7f2eda8ec480a6868259ba68f9781a63e142 100644 (file)
@@ -3,6 +3,7 @@
    Locking functions
    Copyright (C) Andrew Tridgell 1992-2000
    Copyright (C) Jeremy Allison 1992-2000
+   Copyright (C) Volker Lendecke 2005
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -46,7 +47,10 @@ static TDB_CONTEXT *deferred_open_tdb;
 
 struct locking_data {
         union {
-                int num_share_mode_entries;
+               struct {
+                       int num_share_mode_entries;
+                       BOOL delete_on_close;
+               } s;
                 share_mode_entry dummy; /* Needed for alignment. */
         } u;
         /* the following two entries are implicit
@@ -432,10 +436,14 @@ char *share_mode_str(int num, share_mode_entry *e)
 {
        static pstring share_str;
 
-       slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \
-pid = %lu, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f",
-       num, (unsigned long)e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id,
-       (unsigned int)e->dev, (double)e->inode );
+       slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: "
+                "pid = %lu, share_access = 0x%x, private_options = 0x%x, "
+                "access_mask = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, "
+                "dev = 0x%x, inode = %.0f",
+                num, (unsigned long)e->pid,
+                e->share_access, e->private_options,
+                e->access_mask, e->op_port, e->op_type, e->share_file_id,
+                (unsigned int)e->dev, (double)e->inode );
 
        return share_str;
 }
@@ -446,7 +454,7 @@ pid = %lu, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, fi
 
 static void print_share_mode_table(struct locking_data *data)
 {
-       int num_share_modes = data->u.num_share_mode_entries;
+       int num_share_modes = data->u.s.num_share_mode_entries;
        share_mode_entry *shares = (share_mode_entry *)(data + 1);
        int i;
 
@@ -460,9 +468,9 @@ static void print_share_mode_table(struct locking_data *data)
  Get all share mode entries for a dev/inode pair.
 ********************************************************************/
 
-int get_share_modes(connection_struct *conn
-                   SMB_DEV_T dev, SMB_INO_T inode, 
-                   share_mode_entry **pp_shares)
+int get_share_modes(SMB_DEV_T dev, SMB_INO_T inode
+                   share_mode_entry **pp_shares,
+                   BOOL *delete_on_close)
 {
        TDB_DATA dbuf;
        struct locking_data *data;
@@ -470,13 +478,18 @@ int get_share_modes(connection_struct *conn,
        share_mode_entry *shares = NULL;
        TDB_DATA key = locking_key(dev, inode);
        *pp_shares = NULL;
+       *delete_on_close = False;
 
        dbuf = tdb_fetch(tdb, key);
        if (!dbuf.dptr)
                return 0;
 
        data = (struct locking_data *)dbuf.dptr;
-       num_share_modes = data->u.num_share_mode_entries;
+
+       *delete_on_close = data->u.s.delete_on_close;
+       DEBUG(10, ("get_share_modes: delete_on_close: %d\n",
+                  *delete_on_close));
+       num_share_modes = data->u.s.num_share_mode_entries;
        if(num_share_modes) {
                pstring fname;
                int i;
@@ -515,7 +528,7 @@ int get_share_modes(connection_struct *conn,
 
                /* Did we delete any ? If so, re-store in tdb. */
                if (del_count) {
-                       data->u.num_share_mode_entries = num_share_modes;
+                       data->u.s.num_share_mode_entries = num_share_modes;
                        
                        if (num_share_modes) {
                                memcpy(dbuf.dptr + sizeof(*data), shares,
@@ -527,7 +540,7 @@ int get_share_modes(connection_struct *conn,
                        /* The record has shrunk a bit */
                        dbuf.dsize -= del_count * sizeof(share_mode_entry);
 
-                       if (data->u.num_share_mode_entries == 0) {
+                       if (data->u.s.num_share_mode_entries == 0) {
                                if (tdb_delete(tdb, key) == -1) {
                                        SAFE_FREE(shares);
                                        SAFE_FREE(dbuf.dptr);
@@ -548,6 +561,15 @@ int get_share_modes(connection_struct *conn,
        return num_share_modes;
 }
 
+BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
+{
+       share_mode_entry *shares;
+       BOOL result;
+       get_share_modes(dev, inode, &shares, &result);
+       SAFE_FREE(shares);
+       return result;
+}
+
 /*******************************************************************
  Fill a share mode entry.
 ********************************************************************/
@@ -559,8 +581,9 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t
 
        memset(e, '\0', sizeof(share_mode_entry));
        e->pid = sys_getpid();
-       e->share_mode = fsp->share_mode;
-       e->desired_access = fsp->desired_access;
+       e->share_access = fsp->share_access;
+       e->private_options = fsp->fh->private_options;
+       e->access_mask = fsp->access_mask;
        e->op_port = port;
        e->op_type = op_type;
        memcpy(x, &fsp->open_time, sizeof(struct timeval));
@@ -581,16 +604,17 @@ BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2)
                e1->share_file_id == e2->share_file_id &&
                e1->dev == e2->dev &&
                e1->inode == e2->inode &&
-               (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) != (e2->share_mode & ~DELETE_ON_CLOSE_FLAG)) {
-                       DEBUG(0,("PANIC: share_modes_identical: share_mode missmatch (e1 = %u, e2 = %u). Logic error.\n",
-                               (unsigned int)(e1->share_mode & ~DELETE_ON_CLOSE_FLAG),
-                               (unsigned int)(e2->share_mode & ~DELETE_ON_CLOSE_FLAG) ));
+               (e1->share_access) != (e2->share_access)) {
+                       DEBUG(0,("PANIC: share_modes_identical: share_mode "
+                                "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n",
+                                (unsigned int)e1->share_access,
+                                (unsigned int)e2->share_access ));
                smb_panic("PANIC: share_modes_identical logic error.\n");
        }
 #endif
 
        return (e1->pid == e2->pid &&
-               (e1->share_mode & ~DELETE_ON_CLOSE_FLAG) == (e2->share_mode & ~DELETE_ON_CLOSE_FLAG) &&
+               (e1->share_access) == (e2->share_access) &&
                e1->dev == e2->dev &&
                e1->inode == e2->inode &&
                e1->share_file_id == e2->share_file_id );
@@ -602,8 +626,9 @@ BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2)
  Ignore if no entry deleted.
 ********************************************************************/
 
-ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
-                       share_mode_entry *entry, share_mode_entry **ppse)
+ssize_t del_share_entry(SMB_DEV_T dev, SMB_INO_T inode,
+                       share_mode_entry *entry, share_mode_entry **ppse,
+                       BOOL *delete_on_close)
 {
        TDB_DATA dbuf;
        struct locking_data *data;
@@ -621,6 +646,7 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
                return -1;
 
        data = (struct locking_data *)dbuf.dptr;
+       *delete_on_close = data->u.s.delete_on_close;
        shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
 
        /*
@@ -629,15 +655,15 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
         * from the record.
         */
 
-       DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.num_share_mode_entries ));
+       DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.s.num_share_mode_entries ));
 
-       for (i=0;i<data->u.num_share_mode_entries;) {
+       for (i=0;i<data->u.s.num_share_mode_entries;) {
                if (share_modes_identical(&shares[i], entry)) {
                        DEBUG(10,("del_share_entry: deleted %s\n",
                                share_mode_str(i, &shares[i]) ));
                        if (ppse)
                                *ppse = memdup(&shares[i], sizeof(*shares));
-                       data->u.num_share_mode_entries--;
+                       data->u.s.num_share_mode_entries--;
                        if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))) > 0) {
                                memmove(&shares[i], &shares[i+1], 
                                        dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
@@ -655,10 +681,10 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
                /* the record may have shrunk a bit */
                dbuf.dsize -= del_count * sizeof(*shares);
 
-               count = (ssize_t)data->u.num_share_mode_entries;
+               count = (ssize_t)data->u.s.num_share_mode_entries;
 
                /* store it back in the database */
-               if (data->u.num_share_mode_entries == 0) {
+               if (data->u.s.num_share_mode_entries == 0) {
                        if (tdb_delete(tdb, key) == -1)
                                count = -1;
                } else {
@@ -677,7 +703,8 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
  of entries left, and a memdup'ed copy of the entry deleted.
 ********************************************************************/
 
-ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse)
+ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse,
+                      BOOL *delete_on_close)
 {
        share_mode_entry entry;
 
@@ -686,7 +713,8 @@ ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse)
         */
 
        fill_share_mode((char *)&entry, fsp, 0, 0);
-       return del_share_entry(fsp->dev, fsp->inode, &entry, ppse);
+       return del_share_entry(fsp->dev, fsp->inode, &entry, ppse,
+                              delete_on_close);
 }
 
 /*******************************************************************
@@ -718,7 +746,8 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
                if (!p)
                        return False;
                data = (struct locking_data *)p;
-               data->u.num_share_mode_entries = 1;
+               ZERO_STRUCT(data->u); /* Keep valgrind happy */
+               data->u.s.num_share_mode_entries = 1;
        
                DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n",
                        fsp->fsp_name ));
@@ -740,10 +769,10 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
        /* we're adding to an existing entry - this is a bit fiddly */
        data = (struct locking_data *)dbuf.dptr;
 
-       data->u.num_share_mode_entries++;
+       data->u.s.num_share_mode_entries++;
        
        DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n",
-               fsp->fsp_name, data->u.num_share_mode_entries ));
+               fsp->fsp_name, data->u.s.num_share_mode_entries ));
 
        size = dbuf.dsize + sizeof(share_mode_entry);
        p = SMB_MALLOC(size);
@@ -790,7 +819,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en
        shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
 
        /* find any with our pid and call the supplied function */
-       for (i=0;i<data->u.num_share_mode_entries;i++) {
+       for (i=0;i<data->u.s.num_share_mode_entries;i++) {
                if (share_modes_identical(entry, &shares[i])) {
                        mod_fn(&shares[i], dev, inode, param);
                        need_store=True;
@@ -799,7 +828,7 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en
 
        /* if the mod fn was called then store it back */
        if (need_store) {
-               if (data->u.num_share_mode_entries == 0) {
+               if (data->u.s.num_share_mode_entries == 0) {
                        if (tdb_delete(tdb, key) == -1)
                                ret = False;
                } else {
@@ -877,8 +906,7 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close)
 {
        TDB_DATA dbuf;
        struct locking_data *data;
-       int i;
-       share_mode_entry *shares;
+       BOOL res;
        TDB_DATA key = locking_key(dev, inode);
 
        /* read in the existing share modes */
@@ -887,25 +915,14 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close)
                return False;
 
        data = (struct locking_data *)dbuf.dptr;
-       shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
 
        /* Set/Unset the delete on close element. */
-       for (i=0;i<data->u.num_share_mode_entries;i++,shares++) {
-               shares->share_mode = (delete_on_close ?
-                            (shares->share_mode | DELETE_ON_CLOSE_FLAG) :
-                            (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) );
-       }
+       data->u.s.delete_on_close = delete_on_close;
 
-       /* store it back */
-       if (data->u.num_share_mode_entries) {
-               if (tdb_store(tdb, key, dbuf, TDB_REPLACE)==-1) {
-                       SAFE_FREE(dbuf.dptr);
-                       return False;
-               }
-       }
+       res = (tdb_store(tdb, key, dbuf, TDB_REPLACE)!=-1);
 
        SAFE_FREE(dbuf.dptr);
-       return True;
+       return res;
 }
 
 /*******************************************************************
@@ -1200,6 +1217,7 @@ BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T
                if (!p)
                        return False;
                data = (struct deferred_open_data *)p;
+               ZERO_STRUCT(data->u.dummy); /* Keep valgrind happy */
                data->u.num_deferred_open_entries = 1;
        
                DEBUG(10,("add_deferred_open: creating entry for file %s. num_deferred_open_entries = 1\n",
@@ -1268,9 +1286,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
 
        data = (struct locking_data *)dbuf.dptr;
        shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
-       name = dbuf.dptr + sizeof(*data) + data->u.num_share_mode_entries*sizeof(*shares);
+       name = dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares);
 
-       for (i=0;i<data->u.num_share_mode_entries;i++) {
+       for (i=0;i<data->u.s.num_share_mode_entries;i++) {
                traverse_callback(&shares[i], name);
        }
        return 0;
index 218c44102805429e4047cfc9e037e1d50f904715..c63992adc592a631e89ec665a3685a53e132aaf0 100644 (file)
@@ -114,7 +114,7 @@ static BOOL add_fd_to_close_entry(files_struct *fsp)
        } else
                dbuf.dptr = tp;
 
-       memcpy(dbuf.dptr + dbuf.dsize, &fsp->fd, sizeof(int));
+       memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
        dbuf.dsize += sizeof(int);
 
        if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
@@ -209,8 +209,8 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
                /*
                 * No POSIX to worry about, just close.
                 */
-               ret = SMB_VFS_CLOSE(fsp,fsp->fd);
-               fsp->fd = -1;
+               ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
+               fsp->fh->fd = -1;
                return ret;
        }
 
@@ -227,7 +227,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
         */
 
        for (i = 0; i < count; i++) {
-               if (entries[i].fd != fsp->fd) {
+               if (entries[i].fd != fsp->fh->fd) {
                        locks_on_other_fds = True;
                        break;
                }
@@ -237,7 +237,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
 
                /*
                 * There are outstanding locks on this dev/inode pair on other fds.
-                * Add our fd to the pending close tdb and set fsp->fd to -1.
+                * Add our fd to the pending close tdb and set fsp->fh->fd to -1.
                 */
 
                if (!add_fd_to_close_entry(fsp)) {
@@ -246,7 +246,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
                }
 
                SAFE_FREE(entries);
-               fsp->fd = -1;
+               fsp->fh->fd = -1;
                return 0;
        }
 
@@ -282,14 +282,14 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
         * Finally close the fd associated with this fsp.
         */
 
-       ret = SMB_VFS_CLOSE(fsp,fsp->fd);
+       ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
 
        if (saved_errno != 0) {
                errno = saved_errno;
                ret = -1;
        } 
 
-       fsp->fd = -1;
+       fsp->fh->fd = -1;
 
        return ret;
 }
@@ -371,7 +371,7 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s
         * Add new record.
         */
 
-       pl.fd = fsp->fd;
+       pl.fd = fsp->fh->fd;
        pl.start = start;
        pl.size = size;
        pl.lock_type = lock_type;
@@ -455,7 +455,7 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T
        for (i=0; i<count; i++) { 
                struct posix_lock *entry = &locks[i];
 
-               if (entry->fd == fsp->fd &&
+               if (entry->fd == fsp->fh->fd &&
                        entry->start == start &&
                        entry->size == size) {
 
@@ -490,7 +490,7 @@ static int delete_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T
        for (i = 0; i < count; i++) {
                struct posix_lock *entry = &locks[i];
 
-               if (fsp->fd == entry->fd &&
+               if (fsp->fh->fd == entry->fd &&
                        does_lock_overlap( start, size, entry->start, entry->size))
                                num_overlapping_records++;
        }
@@ -524,13 +524,17 @@ static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
                 */
                DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
                return F_RDLCK;
-       } else if((lock_type == READ_LOCK) && !fsp->can_read) {
+       }
+#if 0
+       /* We no longer open files write-only. */
+        else if((lock_type == READ_LOCK) && !fsp->can_read) {
                /*
                 * Ditto for read locks on write only files.
                 */
                DEBUG(10,("map_posix_lock_type: Changing read lock to write due to write-only file.\n"));
                return F_WRLCK;
        }
+#endif
 
        /*
         * This return should be the most normal, as we attempt
@@ -652,9 +656,9 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF
 {
        int ret;
 
-       DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type));
+       DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
 
-       ret = SMB_VFS_LOCK(fsp,fsp->fd,op,offset,count,type);
+       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
 
        if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
 
@@ -678,7 +682,7 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF
                        DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
                        errno = 0;
                        count &= 0x7fffffff;
-                       ret = SMB_VFS_LOCK(fsp,fsp->fd,op,offset,count,type);
+                       ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
                }
        }
 
@@ -1247,7 +1251,7 @@ void posix_locking_close_file(files_struct *fsp)
        }
 
        for (i = 0; i < count; i++) {
-               if (entries[i].fd != fsp->fd )
+               if (entries[i].fd != fsp->fh->fd )
                        break;
 
                dump_entry(&entries[i]);
@@ -1269,7 +1273,7 @@ void posix_locking_close_file(files_struct *fsp)
 
        for (i = 0; i < count; i++) {
                struct posix_lock *pl = &entries[i];
-               if (pl->fd == fsp->fd)
+               if (pl->fd == fsp->fh->fd)
                        release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size );
        }
        SAFE_FREE(entries);
index 3b54428f14c874ca6fd457757791fb8caed97fc2..731ddfa58364f95f5ea6989e19513aa370b670aa 100644 (file)
@@ -605,13 +605,13 @@ static size_t afs_to_nt_acl(struct afs_acl *afs_acl,
 
        struct afs_ace *afs_ace;
 
-       if (fsp->is_directory || fsp->fd == -1) {
+       if (fsp->is_directory || fsp->fh->fd == -1) {
                /* Get the stat struct for the owner info. */
                if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) {
                        return 0;
                }
        } else {
-               if(SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
+               if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
                        return 0;
                }
        }
index b3a2ca5893b7f019db511a02faa45f846ec867df..25083002c3112e98af2484cbbe59f9b9460bb9fc 100644 (file)
@@ -922,7 +922,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
        }
 
        /* Skip OEM header (if any) and the DOS stub to start of Windows header */
-       if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
+       if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
                DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
                                fname, errno));
                /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
@@ -988,7 +988,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
                                }
 
                                /* Seek to the start of the .rsrc section info */
-                               if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
+                               if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
                                        DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
                                                        fname, errno));
                                        goto error_exit;
@@ -1084,7 +1084,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
                                 * twice, as it is simpler to read the code. */
                                if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
                                        /* Compute skip alignment to next long address */
-                                       int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
+                                       int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
                                                                 sizeof(VS_SIGNATURE)) & 3;
                                        if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
 
@@ -1142,8 +1142,6 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        uint32 old_minor;
        time_t old_create_time;
 
-       int access_mode;
-       int action;
        files_struct    *fsp = NULL;
        SMB_STRUCT_STAT st;
        SMB_STRUCT_STAT stat_buf;
@@ -1159,10 +1157,15 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
 
        driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
 
-       fsp = open_file_shared(conn, filepath, &stat_buf,
-                                                  SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
-                                                  (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
-                                                  FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
+       fsp = open_file_ntcreate(conn, filepath, &stat_buf,
+                               FILE_GENERIC_READ,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE,
+                               FILE_OPEN,
+                               0,
+                               FILE_ATTRIBUTE_NORMAL,
+                               INTERNAL_OPEN_ONLY,
+                               NULL);
+
        if (!fsp) {
                /* Old file not found, so by definition new file is in fact newer */
                DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
@@ -1171,13 +1174,15 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
 
        } else {
                int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
-               if (ret == -1) goto error_exit;
+               if (ret == -1) {
+                       goto error_exit;
+               }
 
                if (!ret) {
                        DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
                                         old_file));
                        use_version = False;
-                       if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
+                       if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
                        old_create_time = st.st_mtime;
                        DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
                }
@@ -1188,10 +1193,15 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
        pstrcpy(filepath, new_file);
        driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
 
-       fsp = open_file_shared(conn, filepath, &stat_buf,
-                                                  SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
-                                                  (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
-                                                  FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
+       fsp = open_file_ntcreate(conn, filepath, &stat_buf,
+                               FILE_GENERIC_READ,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE,
+                               FILE_OPEN,
+                               0,
+                               FILE_ATTRIBUTE_NORMAL,
+                               INTERNAL_OPEN_ONLY,
+                               NULL);
+
        if (!fsp) {
                /* New file not found, this shouldn't occur if the caller did its job */
                DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
@@ -1200,13 +1210,15 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
 
        } else {
                int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
-               if (ret == -1) goto error_exit;
+               if (ret == -1) {
+                       goto error_exit;
+               }
 
                if (!ret) {
                        DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
                                         new_file));
                        use_version = False;
-                       if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
+                       if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
                        new_create_time = st.st_mtime;
                        DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
                }
@@ -1251,8 +1263,6 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
                                   struct current_user *user, WERROR *perr)
 {
        int               cversion;
-       int               access_mode;
-       int               action;
        NTSTATUS          nt_status;
        pstring           driverpath;
        DATA_BLOB         null_pw;
@@ -1309,18 +1319,21 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
                goto error_exit;
        }
 
-       fsp = open_file_shared(conn, driverpath, &st,
-               SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
-               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
-               FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
+       fsp = open_file_ntcreate(conn, driverpath, &st,
+                               FILE_GENERIC_READ,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE,
+                               FILE_OPEN,
+                               0,
+                               FILE_ATTRIBUTE_NORMAL,
+                               INTERNAL_OPEN_ONLY,
+                               NULL);
 
        if (!fsp) {
                DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
                                driverpath, errno));
                *perr = WERR_ACCESS_DENIED;
                goto error_exit;
-       }
-       else {
+       } else {
                uint32 major;
                uint32 minor;
                int    ret = get_file_version(fsp, driverpath, &major, &minor);
@@ -1660,7 +1673,8 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
                if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                        driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
-                       if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+                       if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                                               OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
                                DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                new_name, old_name));
                                *perr = WERR_ACCESS_DENIED;
@@ -1675,7 +1689,8 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
-                               if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+                               if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                                               OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
                                        *perr = WERR_ACCESS_DENIED;
@@ -1692,7 +1707,8 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
-                               if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+                               if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                                               OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
                                        *perr = WERR_ACCESS_DENIED;
@@ -1710,7 +1726,8 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
-                               if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+                               if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                                               OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
                                        *perr = WERR_ACCESS_DENIED;
@@ -1737,7 +1754,9 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                                slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
                                if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                        driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
-                                       if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
+                                       if ( !copy_file(new_name, old_name, conn,
+                                                       OPENX_FILE_EXISTS_TRUNCATE|
+                                                       OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
                                                DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                                new_name, old_name));
                                                *perr = WERR_ACCESS_DENIED;
index 863de9624e795a4c75ff4ffc141cdcc2f30f106d..eb81dc4536fb575dc5b617f1925741149f974404 100644 (file)
@@ -28,7 +28,7 @@ open a print file and setup a fsp for it. This is a wrapper around
 print_job_start().
 ***************************************************************************/
 
-files_struct *print_fsp_open(connection_struct *conn, char *fname)
+files_struct *print_fsp_open(connection_struct *conn, const char *fname)
 {
        int jobid;
        SMB_STRUCT_STAT sbuf;
@@ -40,10 +40,11 @@ files_struct *print_fsp_open(connection_struct *conn, char *fname)
 
        fstrcpy( name, "Remote Downlevel Document");
        if (fname) {
-               char *p = strrchr(fname, '/');
+               const char *p = strrchr(fname, '/');
                fstrcat(name, " ");
-               if (!p)
+               if (!p) {
                        p = fname;
+               }
                fstrcat(name, p);
        }
 
@@ -63,24 +64,23 @@ files_struct *print_fsp_open(connection_struct *conn, char *fname)
        }
 
        /* setup a full fsp */
-       fsp->fd = print_job_fd(lp_const_servicename(SNUM(conn)),jobid);
+       fsp->fh->fd = print_job_fd(lp_const_servicename(SNUM(conn)),jobid);
        GetTimeOfDay(&fsp->open_time);
        fsp->vuid = current_user.vuid;
-       fsp->pos = -1;
+       fsp->fh->pos = -1;
        fsp->can_lock = True;
        fsp->can_read = False;
+       fsp->access_mask = FILE_GENERIC_WRITE;
        fsp->can_write = True;
-       fsp->share_mode = 0;
        fsp->print_file = True;
        fsp->modified = False;
        fsp->oplock_type = NO_OPLOCK;
        fsp->sent_oplock_break = NO_BREAK_SENT;
        fsp->is_directory = False;
-       fsp->directory_delete_on_close = False;
        string_set(&fsp->fsp_name,print_job_fname(lp_const_servicename(SNUM(conn)),jobid));
        fsp->wbmpx_ptr = NULL;      
        fsp->wcp = NULL; 
-       SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf);
+       SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf);
        fsp->mode = sbuf.st_mode;
        fsp->inode = sbuf.st_ino;
        fsp->dev = sbuf.st_dev;
@@ -91,19 +91,20 @@ files_struct *print_fsp_open(connection_struct *conn, char *fname)
 }
 
 /****************************************************************************
-print a file - called on closing the file
+ Print a file - called on closing the file.
 ****************************************************************************/
+
 void print_fsp_end(files_struct *fsp, BOOL normal_close)
 {
        uint32 jobid;
        fstring sharename;
 
-       if (fsp->share_mode == FILE_DELETE_ON_CLOSE) {
+       if (fsp->fh->private_options & FILE_DELETE_ON_CLOSE) {
                /*
                 * Truncate the job. print_job_end will take
                 * care of deleting it for us. JRA.
                 */
-               sys_ftruncate(fsp->fd, 0);
+               sys_ftruncate(fsp->fh->fd, 0);
        }
 
        if (fsp->fsp_name) {
index f8124031ce038928d4a0a701980e7fb903ac9320..c3fd53a3844839f9f401246fa5440a2c1d164dd6 100644 (file)
@@ -1976,8 +1976,6 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
        files_struct *fsp = NULL;
        SMB_STRUCT_STAT st;
        BOOL bad_path;
-       int access_mode;
-       int action;
        NTSTATUS nt_status;
        struct current_user user;
        connection_struct *conn = NULL;
@@ -2025,15 +2023,16 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
                goto error_exit;
        }
 
-       fsp = open_file_shared(conn, filename, &st, SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
-                               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
-                               &access_mode, &action);
-
+       fsp = open_file_stat(conn, filename, &st);
        if (!fsp) {
                /* Perhaps it is a directory */
                if (errno == EISDIR)
-                       fsp = open_directory(conn, filename, &st,FILE_READ_ATTRIBUTES,0,
-                                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), &action);
+                       fsp = open_directory(conn, filename, &st,
+                                       READ_CONTROL_ACCESS,
+                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                       FILE_OPEN,
+                                       0,
+                                       NULL);
 
                if (!fsp) {
                        DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename));
@@ -2092,8 +2091,6 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
        files_struct *fsp = NULL;
        SMB_STRUCT_STAT st;
        BOOL bad_path;
-       int access_mode;
-       int action;
        NTSTATUS nt_status;
        struct current_user user;
        connection_struct *conn = NULL;
@@ -2142,15 +2139,17 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
        }
 
 
-       fsp = open_file_shared(conn, filename, &st, SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDWR),
-                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
-                       &access_mode, &action);
+       fsp = open_file_stat(conn, filename, &st);
 
        if (!fsp) {
                /* Perhaps it is a directory */
                if (errno == EISDIR)
-                       fsp = open_directory(conn, filename, &st,FILE_READ_ATTRIBUTES,0,
-                                               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), &action);
+                       fsp = open_directory(conn, filename, &st,
+                                               FILE_READ_ATTRIBUTES,
+                                               FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                               FILE_OPEN,
+                                               0,
+                                               NULL);
 
                if (!fsp) {
                        DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename));
@@ -2178,11 +2177,13 @@ error_exit:
                close_file(fsp, True);
        }
 
-       if (became_user)
+       if (became_user) {
                unbecome_user();
+       }
 
-       if (conn) 
+       if (conn) {
                close_cnum(conn, user.vuid);
+       }
 
        return r_u->status;
 }
index b7649bcce4f52a4ec536f21f48fd2a8cd7549024..3fc7fdb05998e2a2d0b98c24da3c6448ae1de2b6 100644 (file)
@@ -3,6 +3,7 @@
    file closing
    Copyright (C) Andrew Tridgell 1992-1998
    Copyright (C) Jeremy Allison 1992-2004.
+   Copyright (C) Volker Lendecke 2005
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -92,7 +93,7 @@ static int close_filestruct(files_struct *fsp)
        connection_struct *conn = fsp->conn;
        int ret = 0;
     
-       if (fsp->fd != -1) {
+       if (fsp->fh->fd != -1) {
                if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
                        ret = -1;
 
@@ -148,7 +149,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
 {
        share_mode_entry *share_entry = NULL;
        size_t share_entry_count = 0;
-       BOOL delete_on_close = False;
+       BOOL delete_file = False;
        connection_struct *conn = fsp->conn;
        int saved_errno = 0;
        int err = 0;
@@ -194,34 +195,16 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
 
        lock_share_entry_fsp(fsp);
 
-       if (fsp->delete_on_close) {
-
-               /*
-                * Modify the share mode entry for all files open
-                * on this device and inode to tell other smbds we have
-                * changed the delete on close flag. The last closer will delete the file
-                * if flag is set.
-                */
-
-               NTSTATUS status =set_delete_on_close_over_all(fsp, fsp->delete_on_close);
-               if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
-                       DEBUG(0,("close_normal_file: failed to change delete on close flag for file %s\n",
-                               fsp->fsp_name ));
-       }
-
-       share_entry_count = del_share_mode(fsp, &share_entry);
+       share_entry_count = del_share_mode(fsp, &share_entry,
+                                          &delete_file);
 
        DEBUG(10,("close_normal_file: share_entry_count = %lu for file %s\n",
                (unsigned long)share_entry_count, fsp->fsp_name ));
 
-       /*
-        * We delete on close if it's the last open, and the
-        * delete on close flag was set in the entry we just deleted.
-        */
-
-       if ((share_entry_count == 0) && share_entry && 
-                       GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) )
-               delete_on_close = True;
+       if (share_entry_count != 0) {
+               /* We're not the last ones -- don't delete */
+               delete_file = False;
+       }
 
        SAFE_FREE(share_entry);
 
@@ -233,7 +216,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
         * reference to a file.
         */
 
-       if (normal_close && delete_on_close) {
+       if (normal_close && delete_file) {
                DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
                        fsp->fsp_name));
                if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
@@ -311,7 +294,8 @@ static int close_directory(files_struct *fsp, BOOL normal_close)
         * reference to a directory also.
         */
 
-       if (normal_close && fsp->directory_delete_on_close) {
+       if (normal_close &&
+           get_delete_on_close_flag(fsp->dev, fsp->inode)) {
                BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
                DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
                        fsp->fsp_name, ok ? "succeeded" : "failed" ));
@@ -321,8 +305,9 @@ static int close_directory(files_struct *fsp, BOOL normal_close)
                 * now fail as the directory has been deleted.
                 */
 
-               if(ok)
+               if(ok) {
                        remove_pending_change_notify_requests_by_filename(fsp);
+               }
                process_pending_change_notify_queue((time_t)0);
        }
 
@@ -331,8 +316,9 @@ static int close_directory(files_struct *fsp, BOOL normal_close)
         */
        close_filestruct(fsp);
        
-       if (fsp->fsp_name)
+       if (fsp->fsp_name) {
                string_free(&fsp->fsp_name);
+       }
        
        file_free(fsp);
        return 0;
index fd0a30350449a27c33a73740d599bc6a80f63794..949e31210f6eda88fd74fb83d3a2893045f51181 100644 (file)
@@ -822,7 +822,6 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
        SEC_DESC *psd = NULL;
        size_t sd_size;
        files_struct *fsp;
-       int smb_action;
        NTSTATUS status;
        uint32 access_granted;
 
@@ -831,32 +830,41 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
         * we never hide files from them.
         */
 
-       if (conn->admin_user)
+       if (conn->admin_user) {
                return True;
+       }
 
        /* If we can't stat it does not show it */
-       if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
+       if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
                return False;
+       }
 
        /* Pseudo-open the file (note - no fd's created). */
 
-       if(S_ISDIR(pst->st_mode))       
-                fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
-                       &smb_action);
-       else
+       if(S_ISDIR(pst->st_mode)) {
+                fsp = open_directory(conn, name, pst,
+                       READ_CONTROL_ACCESS,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE,
+                       FILE_OPEN,
+                       0, /* no create options. */
+                       NULL);
+       } else {
                fsp = open_file_stat(conn, name, pst);
+       }
 
-       if (!fsp)
+       if (!fsp) {
                return False;
+       }
 
        /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
-       sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
+       sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
                        (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
        close_file(fsp, True);
 
        /* No access if SD get failed. */
-       if (!sd_size)
+       if (!sd_size) {
                return False;
+       }
 
        return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
                                  &access_granted, &status);
@@ -874,8 +882,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
        SEC_DESC *psd = NULL;
        size_t sd_size;
        files_struct *fsp;
-       int smb_action;
-       int access_mode;
+       int info;
        NTSTATUS status;
        uint32 access_granted;
 
@@ -884,27 +891,36 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
         * we never hide files from them.
         */
 
-       if (conn->admin_user)
+       if (conn->admin_user) {
                return True;
+       }
 
        /* If we can't stat it does not show it */
-       if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
+       if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
                return False;
+       }
 
-       /* Pseudo-open the file (note - no fd's created). */
+       /* Pseudo-open the file */
 
-       if(S_ISDIR(pst->st_mode))       
+       if(S_ISDIR(pst->st_mode)) {
                return True;
-       else
-               fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
-                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
-                       &access_mode, &smb_action);
+       } else {
+               fsp = open_file_ntcreate(conn, name, pst,
+                       FILE_WRITE_ATTRIBUTES,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE,
+                       FILE_OPEN,
+                       0,
+                       FILE_ATTRIBUTE_NORMAL,
+                       INTERNAL_OPEN_ONLY,
+                       &info);
+       }
 
-       if (!fsp)
+       if (!fsp) {
                return False;
+       }
 
        /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
-       sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
+       sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
                        (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
        close_file(fsp, False);
 
index 3602e3f908186476b503a430d0c1894443733c02..a2bc424b8e751734ed075146526973218ed3875d 100644 (file)
@@ -430,7 +430,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode,
                if (!fsp)
                        return -1;
                become_root();
-               ret = SMB_VFS_FCHMOD(fsp, fsp->fd, unixmode);
+               ret = SMB_VFS_FCHMOD(fsp, fsp->fh->fd, unixmode);
                unbecome_root();
                close_file_fchmod(fsp);
        }
index 59ddb60db5ee00cecbff19dd5bef48e22c17a39a..799725a7820975c2de979bba29c1412d4728ad69 100644 (file)
 
 extern struct current_user current_user;
 
-/****************************************************************************
- Open a file with a share mode.
-****************************************************************************/
-files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connection_struct *conn,char *fname,
-                               SMB_STRUCT_STAT *psbuf, 
-                               uint32 desired_access, 
-                               int share_mode,int ofun, uint32 new_dos_attr, int oplock_request, 
-                               int *Access,int *action)
-{
-       int flags=0;
-       files_struct *fsp = NULL;
-
-       if (fake_file_type == 0) {
-               return open_file_shared1(conn,fname,psbuf,desired_access,
-                                       share_mode,ofun,new_dos_attr,
-                                       oplock_request,Access,action);  
-       }
-
-       /* access check */
-       if (current_user.uid != 0) {
-               DEBUG(1,("access_denied to service[%s] file[%s] user[%s]\n",
-                       lp_servicename(SNUM(conn)),fname,conn->user));
-               errno = EACCES;
-               return NULL;
-       }
-
-       fsp = file_new(conn);
-       if(!fsp)
-               return NULL;
-
-       DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, oplock request = %d\n",
-               fname, fsp->fnum, share_mode, ofun, oplock_request ));
-
-       if (!check_name(fname,conn)) {
-               file_free(fsp);
-               return NULL;
-       } 
-
-       fsp->fd = -1;
-       fsp->mode = psbuf->st_mode;
-       fsp->inode = psbuf->st_ino;
-       fsp->dev = psbuf->st_dev;
-       fsp->vuid = current_user.vuid;
-       fsp->pos = -1;
-       fsp->can_lock = True;
-       fsp->can_read = ((flags & O_WRONLY)==0);
-       fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
-       fsp->share_mode = 0;
-       fsp->desired_access = desired_access;
-       fsp->print_file = False;
-       fsp->modified = False;
-       fsp->oplock_type = NO_OPLOCK;
-       fsp->sent_oplock_break = NO_BREAK_SENT;
-       fsp->is_directory = False;
-       fsp->is_stat = False;
-       fsp->directory_delete_on_close = False;
-       fsp->conn = conn;
-       string_set(&fsp->fsp_name,fname);
-       fsp->wcp = NULL; /* Write cache pointer. */
-       
-       fsp->fake_file_handle = init_fake_file_handle(fake_file_type);
-       
-       if (fsp->fake_file_handle==NULL) {
-               file_free(fsp);
-               return NULL;
-       }
-
-       conn->num_files_open++;
-       return fsp;
-}
-
 static FAKE_FILE fake_files[] = {
 #ifdef WITH_QUOTAS
        {FAKE_FILE_NAME_QUOTA_UNIX,     FAKE_FILE_TYPE_QUOTA,   init_quota_handle,      destroy_quota_handle},
@@ -100,24 +29,11 @@ static FAKE_FILE fake_files[] = {
        {NULL,                          FAKE_FILE_TYPE_NONE,    NULL,                   NULL }
 };
 
-int is_fake_file(char *fname)
-{
-       int i;
-
-       if (!fname)
-               return 0;
-
-       for (i=0;fake_files[i].name!=NULL;i++) {
-               if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) {
-                       DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname));
-                       return fake_files[i].type;
-               }
-       }
-
-       return FAKE_FILE_TYPE_NONE;
-}
+/****************************************************************************
+ Create a fake file handle
+****************************************************************************/
 
-struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type)
+static struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type)
 {
        TALLOC_CTX *mem_ctx = NULL;
        FAKE_FILE_HANDLE *fh = NULL;
@@ -141,8 +57,9 @@ struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type)
                        fh->type = type;
                        fh->mem_ctx = mem_ctx;
 
-                       if (fake_files[i].init_pd)
+                       if (fake_files[i].init_pd) {
                                fh->pd = fake_files[i].init_pd(fh->mem_ctx);
+                       }
 
                        fh->free_pd = fake_files[i].free_pd;
 
@@ -153,13 +70,88 @@ struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type)
        return NULL;    
 }
 
+/****************************************************************************
+ Does this name match a fake filename ?
+****************************************************************************/
+
+enum FAKE_FILE_TYPE is_fake_file(const char *fname)
+{
+#ifdef HAVE_SYS_QUOTAS
+       int i;
+#endif
+
+       if (!fname) {
+               return FAKE_FILE_TYPE_NONE;
+       }
+
+#ifdef HAVE_SYS_QUOTAS
+       for (i=0;fake_files[i].name!=NULL;i++) {
+               if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) {
+                       DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname));
+                       return fake_files[i].type;
+               }
+       }
+#endif
+
+       return FAKE_FILE_TYPE_NONE;
+}
+
+
+/****************************************************************************
+ Open a fake quota file with a share mode.
+****************************************************************************/
+
+files_struct *open_fake_file(connection_struct *conn,
+                               enum FAKE_FILE_TYPE fake_file_type,
+                               const char *fname,
+                               uint32 access_mask)
+{
+       files_struct *fsp = NULL;
+
+       /* access check */
+       if (current_user.uid != 0) {
+               DEBUG(1,("open_fake_file_shared: access_denied to service[%s] file[%s] user[%s]\n",
+                       lp_servicename(SNUM(conn)),fname,conn->user));
+               errno = EACCES;
+               return NULL;
+       }
+
+       fsp = file_new(conn);
+       if(!fsp) {
+               return NULL;
+       }
+
+       DEBUG(5,("open_fake_file_shared: fname = %s, FID = %d, access_mask = 0x%x\n",
+               fname, fsp->fnum, (unsigned int)access_mask));
+
+       fsp->conn = conn;
+       fsp->fh->fd = -1;
+       fsp->vuid = current_user.vuid;
+       fsp->fh->pos = -1;
+       fsp->can_lock = True; /* Should this be true ? */
+       fsp->access_mask = access_mask;
+       string_set(&fsp->fsp_name,fname);
+       
+       fsp->fake_file_handle = init_fake_file_handle(fake_file_type);
+       
+       if (fsp->fake_file_handle==NULL) {
+               file_free(fsp);
+               return NULL;
+       }
+
+       conn->num_files_open++;
+       return fsp;
+}
+
 void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
 {
-       if (!fh||!(*fh))
+       if (!fh||!(*fh)) {
                return;
+       }
 
-       if ((*fh)->free_pd)
+       if ((*fh)->free_pd) {
                (*fh)->free_pd(&(*fh)->pd);             
+       }
 
        talloc_destroy((*fh)->mem_ctx);
        (*fh) = NULL;
index ba0766c298671e2305b8ac61a232a99040c10a35..76189d114bb0dd85f7e58f6925c34693c010da81 100644 (file)
@@ -65,20 +65,20 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n)
         */
 
        if(read_from_write_cache(fsp, data, pos, n)) {
-               fsp->pos = pos + n;
-               fsp->position_information = fsp->pos;
+               fsp->fh->pos = pos + n;
+               fsp->fh->position_information = fsp->fh->pos;
                return n;
        }
 
        flush_write_cache(fsp, READ_FLUSH);
 
-       fsp->pos = pos;
+       fsp->fh->pos = pos;
 
        if (n > 0) {
 #ifdef DMF_FIX
                int numretries = 3;
 tryagain:
-               readret = SMB_VFS_PREAD(fsp,fsp->fd,data,n,pos);
+               readret = SMB_VFS_PREAD(fsp,fsp->fh->fd,data,n,pos);
 
                if (readret == -1) {
                        if ((errno == EAGAIN) && numretries) {
@@ -90,7 +90,7 @@ tryagain:
                        return -1;
                }
 #else /* NO DMF fix. */
-               readret = SMB_VFS_PREAD(fsp,fsp->fd,data,n,pos);
+               readret = SMB_VFS_PREAD(fsp,fsp->fh->fd,data,n,pos);
 
                if (readret == -1) {
                        return -1;
@@ -104,8 +104,8 @@ tryagain:
        DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n",
                fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
 
-       fsp->pos += ret;
-       fsp->position_information = fsp->pos;
+       fsp->fh->pos += ret;
+       fsp->fh->position_information = fsp->fh->pos;
 
        return(ret);
 }
@@ -124,7 +124,7 @@ static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos
         if (pos == -1) {
                 ret = vfs_write_data(fsp, data, n);
         } else {
-               fsp->pos = pos;
+               fsp->fh->pos = pos;
                if (pos && lp_strict_allocate(SNUM(fsp->conn))) {
                        if (vfs_fill_sparse(fsp, pos) == -1) {
                                return -1;
@@ -137,7 +137,7 @@ static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos
                fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
 
        if (ret != -1) {
-               fsp->pos += ret;
+               fsp->fh->pos += ret;
 
                /*
                 * It turns out that setting the last write time from a Windows
@@ -180,7 +180,7 @@ static int wcp_file_size_change(files_struct *fsp)
        write_cache *wcp = fsp->wcp;
 
        wcp->file_size = wcp->offset + wcp->data_size;
-       ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, wcp->file_size);
+       ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, wcp->file_size);
        if (ret == -1) {
                DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f error %s\n",
                        fsp->fsp_name, (double)wcp->file_size, strerror(errno) ));
@@ -221,7 +221,7 @@ ssize_t write_file(files_struct *fsp, const char *data, SMB_OFF_T pos, size_t n)
                SMB_STRUCT_STAT st;
                fsp->modified = True;
 
-               if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) {
+               if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
                        int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
                        if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) {
                                file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st, False);
@@ -288,9 +288,9 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
        }
 
        DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n",
-               fsp->fsp_name, fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size));
+               fsp->fsp_name, fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size));
 
-       fsp->pos = pos + n;
+       fsp->fh->pos = pos + n;
 
        /* 
         * If we have active cache and it isn't contiguous then we flush.
@@ -589,7 +589,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
                         */
 
                        DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \
-len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size ));
+len = %u\n",fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size ));
 
                        /*
                         * If write would fit in the cache, and is larger than
@@ -612,7 +612,7 @@ len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigne
                                if ((pos <= wcp->offset) &&
                                                (pos + n >= wcp->offset + wcp->data_size) ) {
                                        DEBUG(9,("write_file: discarding overwritten write \
-cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned int)wcp->data_size ));
+cache: fd = %d, off=%.0f, size=%u\n", fsp->fh->fd, (double)wcp->offset, (unsigned int)wcp->data_size ));
                                        wcp->data_size = 0;
                                }
 
@@ -635,7 +635,7 @@ cache: fd = %d, off=%.0f, size=%u\n", fsp->fd, (double)wcp->offset, (unsigned in
                if (cache_flush_needed) {
                        DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \
 n = %u, wcp->offset=%.0f, wcp->data_size=%u\n",
-                               write_path, fsp->fd, (double)wcp->file_size, (double)pos, (unsigned int)n,
+                               write_path, fsp->fh->fd, (double)wcp->file_size, (double)pos, (unsigned int)n,
                                (double)wcp->offset, (unsigned int)wcp->data_size ));
 
                        flush_write_cache(fsp, WRITE_FLUSH);
@@ -809,7 +809,7 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason)
        DO_PROFILE_DEC_INC(writecache_num_write_caches,writecache_flushed_writes[reason]);
 
        DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n",
-               fsp->fd, (double)wcp->offset, (unsigned int)data_size));
+               fsp->fh->fd, (double)wcp->offset, (unsigned int)data_size));
 
 #ifdef WITH_PROFILE
        if(data_size == wcp->alloc_size) {
@@ -836,9 +836,9 @@ sync a file
 
 void sync_file(connection_struct *conn, files_struct *fsp)
 {
-       if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) {
+       if(lp_strict_sync(SNUM(conn)) && fsp->fh->fd != -1) {
                flush_write_cache(fsp, SYNC_FLUSH);
-               SMB_VFS_FSYNC(fsp,fsp->fd);
+               SMB_VFS_FSYNC(fsp,fsp->fh->fd);
        }
 }
 
@@ -849,9 +849,9 @@ void sync_file(connection_struct *conn, files_struct *fsp)
 
 int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst)
 {
-       if (fsp->fd == -1) {
+       if (fsp->fh->fd == -1) {
                return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst);
        } else {
-               return SMB_VFS_FSTAT(fsp,fsp->fd, pst);
+               return SMB_VFS_FSTAT(fsp,fsp->fh->fd, pst);
        }
 }
index e893e9fefc1cc7df78a10357d5d85b8c9c063890..80e5b0f710fedd46b24a8239d07e83b0877d8bda 100644 (file)
@@ -106,7 +106,19 @@ files_struct *file_new(connection_struct *conn)
        }
 
        ZERO_STRUCTP(fsp);
-       fsp->fd = -1;
+
+       fsp->fh = SMB_MALLOC_P(struct fd_handle);
+       if (!fsp->fh) {
+               SAFE_FREE(fsp);
+               set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY);
+               return NULL;
+       }
+
+       ZERO_STRUCTP(fsp->fh);
+
+       fsp->fh->ref_count = 1;
+       fsp->fh->fd = -1;
+
        fsp->conn = conn;
        fsp->file_id = get_gen_count();
        GetTimeOfDay(&fsp->open_time);
@@ -233,7 +245,7 @@ void file_dump_open_table(void)
 
        for (fsp=Files;fsp;fsp=fsp->next,count++) {
                DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n",
-                       count, fsp->fnum, fsp->fsp_name, fsp->fd, (unsigned long)fsp->file_id,
+                       count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->file_id,
                        (unsigned int)fsp->dev, (double)fsp->inode ));
        }
 }
@@ -248,7 +260,7 @@ files_struct *file_find_fd(int fd)
        files_struct *fsp;
 
        for (fsp=Files;fsp;fsp=fsp->next,count++) {
-               if (fsp->fd == fd) {
+               if (fsp->fh->fd == fd) {
                        if (count > 10) {
                                DLIST_PROMOTE(Files, fsp);
                        }
@@ -269,7 +281,7 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i
        files_struct *fsp;
 
        for (fsp=Files;fsp;fsp=fsp->next,count++) {
-               /* We can have a fsp->fd == -1 here as it could be a stat open. */
+               /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
                if (fsp->dev == dev && 
                    fsp->inode == inode &&
                    fsp->file_id == file_id ) {
@@ -277,7 +289,7 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i
                                DLIST_PROMOTE(Files, fsp);
                        }
                        /* Paranoia check. */
-                       if (fsp->fd == -1 && fsp->oplock_type != NO_OPLOCK) {
+                       if (fsp->fh->fd == -1 && fsp->oplock_type != NO_OPLOCK) {
                                DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \
 oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev,
                                                (double)fsp->inode, (unsigned int)fsp->file_id,
@@ -326,7 +338,7 @@ files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
        fsp_fi_cache.inode = inode;
 
        for (fsp=Files;fsp;fsp=fsp->next) {
-               if ( fsp->fd != -1 &&
+               if ( fsp->fh->fd != -1 &&
                                fsp->dev == dev &&
                                fsp->inode == inode ) {
                        /* Setup positive cache. */
@@ -349,7 +361,7 @@ files_struct *file_find_di_next(files_struct *start_fsp)
        files_struct *fsp;
 
        for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
-               if ( fsp->fd != -1 &&
+               if ( fsp->fh->fd != -1 &&
                                fsp->dev == start_fsp->dev &&
                                fsp->inode == start_fsp->inode )
                        return fsp;
@@ -389,7 +401,7 @@ void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod)
        }
 
        for (fsp = Files;fsp;fsp=fsp->next) {
-               if ( fsp->fd != -1 &&
+               if ( fsp->fh->fd != -1 &&
                                fsp->dev == tfsp->dev &&
                                fsp->inode == tfsp->inode ) {
                        fsp->pending_modtime = pmod;
@@ -410,7 +422,7 @@ void file_sync_all(connection_struct *conn)
 
        for (fsp=Files;fsp;fsp=next) {
                next=fsp->next;
-               if ((conn == fsp->conn) && (fsp->fd != -1)) {
+               if ((conn == fsp->conn) && (fsp->fh->fd != -1)) {
                        sync_file(conn,fsp);
                }
        }
@@ -430,6 +442,12 @@ void file_free(files_struct *fsp)
                destroy_fake_file_handle(&fsp->fake_file_handle);
        }
 
+       if (fsp->fh->ref_count == 1) {
+               SAFE_FREE(fsp->fh);
+       } else {
+               fsp->fh->ref_count--;
+       }
+
        bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
        files_used--;
 
@@ -506,3 +524,49 @@ void file_chain_restore(void)
 {
        chain_fsp = oplock_save_chain_fsp;
 }
+
+files_struct *dup_file_fsp(files_struct *fsp,
+                               uint32 access_mask,
+                               uint32 share_access,
+                               uint32 create_options)
+{
+       files_struct *dup_fsp = file_new(fsp->conn);
+
+       if (!dup_fsp) {
+               return NULL;
+       }
+
+       SAFE_FREE(dup_fsp->fh);
+
+       dup_fsp->fh = fsp->fh;
+       dup_fsp->fh->ref_count++;
+
+       dup_fsp->dev = fsp->dev;
+       dup_fsp->inode = fsp->inode;
+       dup_fsp->initial_allocation_size = fsp->initial_allocation_size;
+       dup_fsp->mode = fsp->mode;
+       dup_fsp->file_pid = fsp->file_pid;
+       dup_fsp->vuid = fsp->vuid;
+       dup_fsp->open_time = fsp->open_time;
+       dup_fsp->access_mask = access_mask;
+       dup_fsp->share_access = share_access;
+       dup_fsp->pending_modtime_owner = fsp->pending_modtime_owner;
+       dup_fsp->pending_modtime = fsp->pending_modtime;
+       dup_fsp->last_write_time = fsp->last_write_time;
+       dup_fsp->oplock_type = fsp->oplock_type;
+       dup_fsp->can_lock = fsp->can_lock;
+       dup_fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
+       if (!CAN_WRITE(fsp->conn)) {
+               dup_fsp->can_write = False;
+       } else {
+               dup_fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
+       }
+       dup_fsp->print_file = fsp->print_file;
+       dup_fsp->modified = fsp->modified;
+       dup_fsp->is_directory = fsp->is_directory;
+       dup_fsp->is_stat = fsp->is_stat;
+       dup_fsp->aio_write_behind = fsp->aio_write_behind;
+        string_set(&dup_fsp->fsp_name,fsp->fsp_name);
+
+       return dup_fsp;
+}
index 8fbf858008b94763705356bcebbef799282691a1..9bc444d2536700327075bd69e221fa7c28421ef1 100644 (file)
@@ -259,4 +259,3 @@ void destroy_quota_handle(void **pqt_handle)
 
        return;
 }
-
index cc37d531f2485f00abec8d241919fc600113b087..f9b70de0ace3d3e17237cf73f0d64fa63b1bf078 100644 (file)
@@ -46,20 +46,12 @@ static const char *known_nt_pipes[] = {
        NULL
 };
 
-/* Map generic permissions to file object specific permissions */
-struct generic_mapping file_generic_mapping = {
-       FILE_GENERIC_READ,
-       FILE_GENERIC_WRITE,
-       FILE_GENERIC_EXECUTE,
-       FILE_GENERIC_ALL
-};
-
 static char *nttrans_realloc(char **ptr, size_t size)
 {
        char *tptr = NULL;
-       if (ptr==NULL)
+       if (ptr==NULL) {
                smb_panic("nttrans_realloc() called with NULL ptr\n");
+       }
                
        tptr = SMB_REALLOC(*ptr, size);
        if(tptr == NULL) {
@@ -99,8 +91,9 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e
 
        set_message(outbuf,18,0,True);
 
-       if (NT_STATUS_V(nt_error))
+       if (NT_STATUS_V(nt_error)) {
                ERROR_NT(nt_error);
+       }
 
        /* 
         * If there genuinely are no parameters or data to send just send
@@ -108,8 +101,10 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e
         */
 
        if(params_to_send == 0 && data_to_send == 0) {
-               if (!send_smb(smbd_server_fd(),outbuf))
+               show_msg(outbuf);
+               if (!send_smb(smbd_server_fd(),outbuf)) {
                        exit_server("send_nt_replies: send_smb failed.");
+               }
                return 0;
        }
 
@@ -119,8 +114,9 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e
         * can cause NT redirector problems.
         */
 
-       if (((params_to_send % 4) != 0) && (data_to_send != 0))
+       if (((params_to_send % 4) != 0) && (data_to_send != 0)) {
                data_alignment_offset = 4 - (params_to_send % 4);
+       }
 
        /* 
         * Space is bufsize minus Netbios over TCP header minus SMB header.
@@ -221,16 +217,18 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e
                 * Copy the param bytes into the packet.
                 */
 
-               if(params_sent_thistime)
+               if(params_sent_thistime) {
                        memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
+               }
 
                /*
                 * Copy in the data bytes
                 */
 
-               if(data_sent_thistime)
+               if(data_sent_thistime) {
                        memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
                                data_alignment_offset,pd,data_sent_thistime);
+               }
     
                DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
                        params_sent_thistime, data_sent_thistime, useable_space));
@@ -238,8 +236,10 @@ static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_e
                        params_to_send, data_to_send, paramsize, datasize));
     
                /* Send the packet */
-               if (!send_smb(smbd_server_fd(),outbuf))
+               show_msg(outbuf);
+               if (!send_smb(smbd_server_fd(),outbuf)) {
                        exit_server("send_nt_replies: send_smb failed.");
+               }
     
                pp += params_sent_thistime;
                pd += data_sent_thistime;
@@ -287,8 +287,9 @@ static BOOL saved_short_case_preserve;
 
 static void set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
 {
-       if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS))
+       if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
                return;
+       }
 
        saved_case_sensitive = conn->case_sensitive;
        saved_case_preserve = conn->case_preserve;
@@ -306,200 +307,15 @@ static void set_posix_case_semantics(connection_struct *conn, uint32 file_attrib
 
 static void restore_case_semantics(connection_struct *conn, uint32 file_attributes)
 {
-       if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS))
+       if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
                return;
+       }
 
        conn->case_sensitive = saved_case_sensitive;
        conn->case_preserve = saved_case_preserve;
        conn->short_case_preserve = saved_short_case_preserve;
 }
 
-/****************************************************************************
- Utility function to map create disposition.
-****************************************************************************/
-
-static int map_create_disposition( uint32 create_disposition)
-{
-       int ret;
-
-       switch( create_disposition ) {
-               case FILE_CREATE:
-                       /* create if not exist, fail if exist */
-                       ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL);
-                       break;
-               case FILE_SUPERSEDE:
-               case FILE_OVERWRITE_IF:
-                       /* create if not exist, trunc if exist */
-                       ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE);
-                       break;
-               case FILE_OPEN:
-                       /* fail if not exist, open if exists */
-                       ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN);
-                       break;
-               case FILE_OPEN_IF:
-                       /* create if not exist, open if exists */
-                       ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_OPEN);
-                       break;
-               case FILE_OVERWRITE:
-                       /* fail if not exist, truncate if exists */
-                       ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE);
-                       break;
-               default:
-                       DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n",
-                               create_disposition ));
-                       return -1;
-       }
-
-       DEBUG(10,("map_create_disposition: Mapped create_disposition 0x%lx to 0x%x\n",
-                       (unsigned long)create_disposition, ret ));
-
-       return ret;
-}
-
-/****************************************************************************
- Utility function to map share modes.
-****************************************************************************/
-
-static int map_share_mode( char *fname, uint32 create_options,
-                       uint32 *desired_access, uint32 share_access, uint32 file_attributes)
-{
-       int smb_open_mode = -1;
-       uint32 original_desired_access = *desired_access;
-
-       /* This is a nasty hack - must fix... JRA. */
-       if (*desired_access == MAXIMUM_ALLOWED_ACCESS) {
-               *desired_access = FILE_GENERIC_ALL;
-       }
-
-       /*
-        * Convert GENERIC bits to specific bits.
-        */
-
-       se_map_generic(desired_access, &file_generic_mapping);
-
-       switch( *desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA) ) {
-               case FILE_READ_DATA:
-                       smb_open_mode = DOS_OPEN_RDONLY;
-                       break;
-               case FILE_WRITE_DATA:
-               case FILE_APPEND_DATA:
-               case FILE_WRITE_DATA|FILE_APPEND_DATA:
-                       smb_open_mode = DOS_OPEN_WRONLY;
-                       break;
-               case FILE_READ_DATA|FILE_WRITE_DATA:
-               case FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA:
-               case FILE_READ_DATA|FILE_APPEND_DATA:
-                       smb_open_mode = DOS_OPEN_RDWR;
-                       break;
-       }
-
-       /*
-        * NB. For DELETE_ACCESS we should really check the
-        * directory permissions, as that is what controls
-        * delete, and for WRITE_DAC_ACCESS we should really
-        * check the ownership, as that is what controls the
-        * chmod. Note that this is *NOT* a security hole (this
-        * note is for you, Andrew) as we are not *allowing*
-        * the access at this point, the actual unlink or
-        * chown or chmod call would do this. We are just helping
-        * clients out by telling them if they have a hope
-        * of any of this succeeding. POSIX acls may still
-        * deny the real call. JRA.
-        */
-
-       if (smb_open_mode == -1) {
-
-               if(*desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS|
-                                       FILE_EXECUTE|FILE_READ_ATTRIBUTES|
-                                       FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS|
-                                       FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) {
-                       smb_open_mode = DOS_OPEN_RDONLY;
-               } else if(*desired_access == 0) {
-
-                       /* 
-                        * JRA - NT seems to sometimes send desired_access as zero. play it safe
-                        * and map to a stat open.
-                        */
-
-                       smb_open_mode = DOS_OPEN_RDONLY;
-
-               } else {
-                       DEBUG(0,("map_share_mode: Incorrect value 0x%lx for desired_access to file %s\n",
-                               (unsigned long)*desired_access, fname));
-                       return -1;
-               }
-       }
-
-       /*
-        * Set the special bit that means allow share delete.
-        * This is held outside the normal share mode bits at 1<<15.
-        * JRA.
-        */
-
-       if(share_access & FILE_SHARE_DELETE) {
-               smb_open_mode |= ALLOW_SHARE_DELETE;
-               DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = 0x%x\n", smb_open_mode));
-       }
-
-       if(*desired_access & DELETE_ACCESS) {
-               DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode));
-       }
-
-       /*
-        * We need to store the intent to open for Delete. This
-        * is what determines if a delete on close flag can be set.
-        * This is the wrong way (and place) to store this, but for 2.2 this
-        * is the only practical way. JRA.
-        */
-
-       if (create_options & FILE_DELETE_ON_CLOSE) {
-               /*
-                * W2K3 bug compatibility mode... To set delete on close
-                * the redirector must have *specifically* set DELETE_ACCESS
-                * in the desired_access field. Just asking for GENERIC_ALL won't do. JRA.
-                */
-
-               if (!(original_desired_access & DELETE_ACCESS)) {
-                       DEBUG(5,("map_share_mode: FILE_DELETE_ON_CLOSE requested without \
-DELETE_ACCESS for file %s. (desired_access = 0x%lx)\n",
-                               fname, (unsigned long)*desired_access));
-                       return -1;
-               }
-               /* Implicit delete access is *NOT* requested... */
-               smb_open_mode |= DELETE_ON_CLOSE_FLAG;
-               DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode));
-       }
-
-       /* Add in the requested share mode. */
-       switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) {
-               case FILE_SHARE_READ:
-                       smb_open_mode |= SET_DENY_MODE(DENY_WRITE);
-                       break;
-               case FILE_SHARE_WRITE:
-                       smb_open_mode |= SET_DENY_MODE(DENY_READ);
-                       break;
-               case (FILE_SHARE_READ|FILE_SHARE_WRITE):
-                       smb_open_mode |= SET_DENY_MODE(DENY_NONE);
-                       break;
-               case FILE_SHARE_NONE:
-                       smb_open_mode |= SET_DENY_MODE(DENY_ALL);
-                       break;
-       }
-
-       /*
-        * Handle an O_SYNC request.
-        */
-
-       if(file_attributes & FILE_FLAG_WRITE_THROUGH)
-               smb_open_mode |= FILE_SYNC_OPENMODE;
-
-       DEBUG(10,("map_share_mode: Mapped desired access 0x%lx, share access 0x%lx, file attributes 0x%lx \
-to open_mode 0x%x\n", (unsigned long)*desired_access, (unsigned long)share_access,
-               (unsigned long)file_attributes, smb_open_mode ));
-       return smb_open_mode;
-}
-
 /****************************************************************************
  Reply to an NT create and X call on a pipe.
 ****************************************************************************/
@@ -508,7 +324,6 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
                        char *inbuf, char *outbuf, int *ppnum)
 {
        smb_np_struct *p = NULL;
-
        uint16 vuid = SVAL(inbuf, smb_uid);
        int i;
 
@@ -516,15 +331,19 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
     
        /* See if it is one we want to handle. */
 
-       if (lp_disable_spoolss() && strequal(fname, "\\spoolss"))
+       if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) {
                return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe));
+       }
 
-       for( i = 0; known_nt_pipes[i]; i++ )
-               if( strequal(fname,known_nt_pipes[i]))
+       for( i = 0; known_nt_pipes[i]; i++ ) {
+               if( strequal(fname,known_nt_pipes[i])) {
                        break;
+               }
+       }
     
-       if ( known_nt_pipes[i] == NULL )
+       if ( known_nt_pipes[i] == NULL ) {
                return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe));
+       }
     
        /* Strip \\ off the name. */
        fname++;
@@ -532,11 +351,11 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
        DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname));
 
        p = open_rpc_pipe_p(fname, conn, vuid);
-       if (!p)
+       if (!p) {
                return(ERROR_DOS(ERRSRV,ERRnofids));
+       }
 
        *ppnum = p->pnum;
-
        return 0;
 }
 
@@ -554,8 +373,9 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
 
        srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
 
-       if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0)
+       if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) {
                return ret;
+       }
 
        /*
         * Deal with pipe return.
@@ -582,6 +402,66 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
        return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
+/****************************************************************************
+ Reply to an NT create and X call for a quota file.
+****************************************************************************/
+
+int reply_ntcreate_and_X_quota(connection_struct *conn,
+                               char *inbuf,
+                               char *outbuf,
+                               int length,
+                               int bufsize,
+                               enum FAKE_FILE_TYPE fake_file_type,
+                               const char *fname)
+{
+       int result;
+       char *p;
+       uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess);
+       files_struct *fsp = open_fake_file(conn, fake_file_type, fname, desired_access);
+
+       if (!fsp) {
+               return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+       }
+
+       set_message(outbuf,34,0,True);
+       
+       p = outbuf + smb_vwv2;
+       
+       /* SCVAL(p,0,NO_OPLOCK_RETURN); */
+       p++;
+       SSVAL(p,0,fsp->fnum);
+#if 0
+       p += 2;
+       SIVAL(p,0,smb_action);
+       p += 4;
+       
+       /* Create time. */  
+       put_long_date(p,c_time);
+       p += 8;
+       put_long_date(p,sbuf.st_atime); /* access time */
+       p += 8;
+       put_long_date(p,sbuf.st_mtime); /* write time */
+       p += 8;
+       put_long_date(p,sbuf.st_mtime); /* change time */
+       p += 8;
+       SIVAL(p,0,fattr); /* File Attributes. */
+       p += 4;
+       SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
+       p += 8;
+       SOFF_T(p,0,file_len);
+       p += 8;
+       if (flags & EXTENDED_RESPONSE_REQUIRED)
+               SSVAL(p,2,0x7);
+       p += 4;
+       SCVAL(p,0,fsp->is_directory ? 1 : 0);
+#endif
+
+       DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name));
+
+       result = chain_reply(inbuf,outbuf,length,bufsize);
+       return result;
+}
+
 /****************************************************************************
  Reply to an NT create and X call.
 ****************************************************************************/
@@ -591,23 +471,20 @@ int reply_ntcreate_and_X(connection_struct *conn,
 {  
        int result;
        pstring fname;
-       enum FAKE_FILE_TYPE fake_file_type = FAKE_FILE_TYPE_NONE;
        uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
-       uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess);
+       uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess);
        uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
        uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
        uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
        uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
        uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid);
-       int smb_ofun;
-       int smb_open_mode;
        /* Breakout the oplock request bits so we can set the
           reply bits separately. */
        int oplock_request = 0;
-       int fmode=0,rmode=0;
+       uint32 fattr=0;
        SMB_OFF_T file_len = 0;
        SMB_STRUCT_STAT sbuf;
-       int smb_action = 0;
+       int info = 0;
        BOOL bad_path = False;
        files_struct *fsp=NULL;
        char *p = NULL;
@@ -617,11 +494,16 @@ int reply_ntcreate_and_X(connection_struct *conn,
 
        START_PROFILE(SMBntcreateX);
 
-       DEBUG(10,("reply_ntcreateX: flags = 0x%x, desired_access = 0x%x \
+       DEBUG(10,("reply_ntcreateX: flags = 0x%x, access_mask = 0x%x \
 file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \
-create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attributes,
-                       share_access, create_disposition,
-                       create_options, root_dir_fid ));
+create_options = 0x%x root_dir_fid = 0x%x\n",
+                       (unsigned int)flags,
+                       (unsigned int)access_mask,
+                       (unsigned int)file_attributes,
+                       (unsigned int)share_access,
+                       (unsigned int)create_disposition,
+                       (unsigned int)create_options,
+                       (unsigned int)root_dir_fid ));
 
        /* If it's an IPC, use the pipe handler. */
 
@@ -640,16 +522,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
        }
 
-       /* 
-        * We need to construct the open_and_X ofun value from the
-        * NT values, as that's what our code is structured to accept.
-        */    
-       
-       if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
-               END_PROFILE(SMBntcreateX);
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-       }
-
        /*
         * Get the file name.
         */
@@ -729,25 +601,25 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                 */
 
                if( is_ntfs_stream_name(fname)) {
-                       
-#ifdef HAVE_SYS_QUOTAS
-                       if ((fake_file_type=is_fake_file(fname))!=FAKE_FILE_TYPE_NONE) {
+                       enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname);
+                       if (fake_file_type!=FAKE_FILE_TYPE_NONE) {
                                /*
-                                * here we go! support for changing the disk quotas --metze
+                                * Here we go! support for changing the disk quotas --metze
                                 *
-                                * we need to fake up to open this MAGIC QUOTA file 
-                                * and return a valid FID
+                                * We need to fake up to open this MAGIC QUOTA file 
+                                * and return a valid FID.
                                 *
                                 * w2k close this file directly after openening
                                 * xp also tries a QUERY_FILE_INFO on the file and then close it
                                 */
+                               result = reply_ntcreate_and_X_quota(conn, inbuf, outbuf, length, bufsize,
+                                                               fake_file_type, fname);
+                               END_PROFILE(SMBntcreateX);
+                               return result;
                        } else {
-#endif
                                END_PROFILE(SMBntcreateX);
                                return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
-#ifdef HAVE_SYS_QUOTAS
                        }
-#endif
                }
        }
        
@@ -757,13 +629,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
         */
        RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
 
-       if((smb_open_mode = map_share_mode(fname, create_options, &desired_access, 
-                                          share_access, 
-                                          file_attributes)) == -1) {
-               END_PROFILE(SMBntcreateX);
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-       }
-
        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
        if (oplock_request) {
                oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
@@ -781,20 +646,16 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                
        unix_convert(fname,conn,0,&bad_path,&sbuf);
 
-       /* FAKE_FILE is a special case */
-       if (fake_file_type == FAKE_FILE_TYPE_NONE) {
-               /* Normal file. */
-               if (bad_path) {
-                       restore_case_semantics(conn, file_attributes);
-                       END_PROFILE(SMBntcreateX);
-                       return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
-               }
-               /* All file access must go through check_name() */
-               if (!check_name(fname,conn)) {
-                       restore_case_semantics(conn, file_attributes);
-                       END_PROFILE(SMBntcreateX);
-                       return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
-               }
+       if (bad_path) {
+               restore_case_semantics(conn, file_attributes);
+               END_PROFILE(SMBntcreateX);
+               return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       }
+       /* All file access must go through check_name() */
+       if (!check_name(fname,conn)) {
+               restore_case_semantics(conn, file_attributes);
+               END_PROFILE(SMBntcreateX);
+               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
        }
 
 #if 0
@@ -805,7 +666,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
        if (desired_access & DELETE_ACCESS) {
 #else
        /* Setting FILE_SHARE_DELETE is the hint. */
-       if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) {
+       if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE)
+                               && (access_mask & DELETE_ACCESS)) {
 #endif
                status = can_delete(conn, fname, file_attributes, bad_path, True);
                /* We're only going to fail here if it's access denied, as that's the
@@ -814,7 +676,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                                                 NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) {
                        restore_case_semantics(conn, file_attributes);
                        END_PROFILE(SMBntcreateX);
-                       return ERROR_NT(status);
+                       return ERROR_NT(NT_STATUS_ACCESS_DENIED);
                }
        }
 
@@ -831,8 +693,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
                }
 
-               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
-                       
+               fsp = open_directory(conn, fname, &sbuf,
+                                       access_mask,
+                                       share_access,
+                                       create_disposition,
+                                       create_options,
+                                       &info);
+
                restore_case_semantics(conn, file_attributes);
 
                if(!fsp) {
@@ -857,21 +724,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                 * before issuing an oplock break request to
                 * our client. JRA.  */
 
-               if (fake_file_type==FAKE_FILE_TYPE_NONE) {
-                       fsp = open_file_shared1(conn,fname,&sbuf,
-                                       desired_access,
-                                       smb_open_mode,
-                                       smb_ofun,file_attributes,oplock_request,
-                                       &rmode,&smb_action);
-               } else {
-                       /* to open a fake_file --metze */
-                       fsp = open_fake_file_shared1(fake_file_type,conn,fname,&sbuf,
-                                       desired_access,
-                                       smb_open_mode,
-                                       smb_ofun,file_attributes, oplock_request,
-                                       &rmode,&smb_action);
-               }
-               
+               fsp = open_file_ntcreate(conn,fname,&sbuf,
+                                       access_mask,
+                                       share_access,
+                                       create_disposition,
+                                       create_options,
+                                       file_attributes,
+                                       oplock_request,
+                                       &info);
                if (!fsp) { 
                        /* We cheat here. There are two cases we
                         * care about. One is a directory rename,
@@ -905,8 +765,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
                                }
        
                                oplock_request = 0;
-                               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
-                               
+                               fsp = open_directory(conn, fname, &sbuf,
+                                                       access_mask,
+                                                       share_access,
+                                                       create_disposition,
+                                                       create_options,
+                                                       &info);
+
                                if(!fsp) {
                                        restore_case_semantics(conn, file_attributes);
                                        END_PROFILE(SMBntcreateX);
@@ -928,18 +793,18 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
        restore_case_semantics(conn, file_attributes);
                
        file_len = sbuf.st_size;
-       fmode = dos_mode(conn,fname,&sbuf);
-       if(fmode == 0) {
-               fmode = FILE_ATTRIBUTE_NORMAL;
+       fattr = dos_mode(conn,fname,&sbuf);
+       if(fattr == 0) {
+               fattr = FILE_ATTRIBUTE_NORMAL;
        }
-       if (!fsp->is_directory && (fmode & aDIR)) {
+       if (!fsp->is_directory && (fattr & aDIR)) {
                close_file(fsp,False);
                END_PROFILE(SMBntcreateX);
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        } 
        
        /* Save the requested allocation size. */
-       if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
+       if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
                SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize);
 #ifdef LARGE_SMB_OFF_T
                allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
@@ -1005,10 +870,11 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
        p++;
        SSVAL(p,0,fsp->fnum);
        p += 2;
-       if ((create_disposition == FILE_SUPERSEDE) && (smb_action == FILE_WAS_OVERWRITTEN))
+       if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) {
                SIVAL(p,0,FILE_WAS_SUPERSEDED);
-       else
-               SIVAL(p,0,smb_action);
+       } else {
+               SIVAL(p,0,info);
+       }
        p += 4;
        
        /* Create time. */  
@@ -1029,14 +895,15 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
        p += 8;
        put_long_date(p,sbuf.st_mtime); /* change time */
        p += 8;
-       SIVAL(p,0,fmode); /* File Attributes. */
+       SIVAL(p,0,fattr); /* File Attributes. */
        p += 4;
        SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
        p += 8;
        SOFF_T(p,0,file_len);
        p += 8;
-       if (flags & EXTENDED_RESPONSE_REQUIRED)
+       if (flags & EXTENDED_RESPONSE_REQUIRED) {
                SSVAL(p,2,0x7);
+       }
        p += 4;
        SCVAL(p,0,fsp->is_directory ? 1 : 0);
 
@@ -1077,13 +944,15 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
                return ERROR_NT(status);
        }
 
-       if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0)
+       if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) {
                return ret;
+       }
        
        /* Realloc the size of parameters and data we will return */
        params = nttrans_realloc(ppparams, 69);
-       if(params == NULL)
+       if(params == NULL) {
                return ERROR_DOS(ERRDOS,ERRnomem);
+       }
        
        p = params;
        SCVAL(p,0,NO_OPLOCK_RETURN);
@@ -1156,16 +1025,20 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
                return NT_STATUS_NO_MEMORY;
        }
        
-       if (psd->off_owner_sid==0)
+       if (psd->off_owner_sid==0) {
                security_info_sent &= ~OWNER_SECURITY_INFORMATION;
-       if (psd->off_grp_sid==0)
+       }
+       if (psd->off_grp_sid==0) {
                security_info_sent &= ~GROUP_SECURITY_INFORMATION;
-       if (psd->off_sacl==0)
+       }
+       if (psd->off_sacl==0) {
                security_info_sent &= ~SACL_SECURITY_INFORMATION;
-       if (psd->off_dacl==0)
+       }
+       if (psd->off_dacl==0) {
                security_info_sent &= ~DACL_SECURITY_INFORMATION;
+       }
        
-       ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fd, security_info_sent, psd);
+       ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd);
        
        if (!ret) {
                talloc_destroy(mem_ctx);
@@ -1219,16 +1092,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        char *data = *ppdata;
        /* Breakout the oplock request bits so we can set the reply bits separately. */
        int oplock_request = 0;
-       int fmode=0,rmode=0;
+       uint32 fattr=0;
        SMB_OFF_T file_len = 0;
        SMB_STRUCT_STAT sbuf;
-       int smb_action = 0;
+       int info = 0;
        BOOL bad_path = False;
        files_struct *fsp = NULL;
        char *p = NULL;
        BOOL extended_oplock_granted = False;
        uint32 flags;
-       uint32 desired_access;
+       uint32 access_mask;
        uint32 file_attributes;
        uint32 share_access;
        uint32 create_disposition;
@@ -1236,8 +1109,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        uint32 sd_len;
        uint32 ea_len;
        uint16 root_dir_fid;
-       int smb_ofun;
-       int smb_open_mode;
        time_t c_time;
        struct ea_list *ea_list = NULL;
        TALLOC_CTX *ctx = NULL;
@@ -1251,14 +1122,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
         */
 
        if (IS_IPC(conn)) {
-               if (lp_nt_pipe_support())
+               if (lp_nt_pipe_support()) {
                        return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, 
                                        bufsize,
                                        ppsetup, setup_count,
                                        ppparams, parameter_count,
                                        ppdata, data_count);
-               else
+               } else {
                        return ERROR_DOS(ERRDOS,ERRnoaccess);
+               }
        }
 
        /*
@@ -1271,7 +1143,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        }
 
        flags = IVAL(params,0);
-       desired_access = IVAL(params,8);
+       access_mask = IVAL(params,8);
        file_attributes = IVAL(params,20);
        share_access = IVAL(params,24);
        create_disposition = IVAL(params,28);
@@ -1307,15 +1179,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
        }
 
-       /* 
-        * We need to construct the open_and_X ofun value from the
-        * NT values, as that's what our code is structured to accept.
-        */    
-
-       if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-       }
-
        /*
         * Get the file name.
         */
@@ -1327,8 +1190,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                files_struct *dir_fsp = file_fsp(params,4);
                size_t dir_name_len;
 
-               if(!dir_fsp)
+               if(!dir_fsp) {
                        return ERROR_DOS(ERRDOS,ERRbadfid);
+               }
 
                if(!dir_fsp->is_directory) {
                        srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
@@ -1386,15 +1250,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                }
        }
 
-       /*
-        * Now contruct the smb_open_mode value from the desired access
-        * and the share access.
-        */
-
-       if((smb_open_mode = map_share_mode( fname, create_options, &desired_access,
-                                               share_access, file_attributes)) == -1)
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-
        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
        oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
 
@@ -1425,7 +1280,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        if (desired_access & DELETE_ACCESS) {
 #else
        /* Setting FILE_SHARE_DELETE is the hint. */
-       if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) {
+       if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS)) {
 #endif
                status = can_delete(conn, fname, file_attributes, bad_path, True);
                /* We're only going to fail here if it's access denied, as that's the
@@ -1478,8 +1333,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 * CreateDirectory() call.
                 */
 
-               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
-
+               fsp = open_directory(conn, fname, &sbuf,
+                                       access_mask,
+                                       share_access,
+                                       create_disposition,
+                                       create_options,
+                                       &info);
                if(!fsp) {
                        talloc_destroy(ctx);
                        restore_case_semantics(conn, file_attributes);
@@ -1492,9 +1351,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 * Ordinary file case.
                 */
 
-               fsp = open_file_shared1(conn,fname,&sbuf,desired_access,
-                                               smb_open_mode,smb_ofun,file_attributes,
-                                               oplock_request,&rmode,&smb_action);
+               fsp = open_file_ntcreate(conn,fname,&sbuf,
+                                       access_mask,
+                                       share_access,
+                                       create_disposition,
+                                       create_options,
+                                       file_attributes,
+                                       oplock_request,
+                                       &info);
 
                if (!fsp) { 
                        if(errno == EISDIR) {
@@ -1509,8 +1373,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                                }
        
                                oplock_request = 0;
-                               fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
-                               
+                               fsp = open_directory(conn, fname, &sbuf,
+                                                       access_mask,
+                                                       share_access,
+                                                       create_disposition,
+                                                       create_options,
+                                                       &info);
                                if(!fsp) {
                                        talloc_destroy(ctx);
                                        restore_case_semantics(conn, file_attributes);
@@ -1539,12 +1407,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
         * Patch for bug #2242 from Tom Lackemann <cessnatomny@yahoo.com>.
         */
 
-       if (lp_nt_acl_support(SNUM(conn)) && sd_len && smb_action == FILE_WAS_CREATED) {
-               uint32 saved_access = fsp->desired_access;
+       if (lp_nt_acl_support(SNUM(conn)) && sd_len && info == FILE_WAS_CREATED) {
+               uint32 saved_access_mask = fsp->access_mask;
 
                /* We have already checked that sd_len <= data_count here. */
 
-               fsp->desired_access = FILE_GENERIC_ALL;
+               fsp->access_mask = FILE_GENERIC_ALL;
 
                status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION);
                if (!NT_STATUS_IS_OK(status)) {
@@ -1553,10 +1421,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                        restore_case_semantics(conn, file_attributes);
                        return ERROR_NT(status);
                }
-               fsp->desired_access = saved_access;
+               fsp->access_mask = saved_access_mask;
        }
        
-       if (ea_len && (smb_action == FILE_WAS_CREATED)) {
+       if (ea_len && (info == FILE_WAS_CREATED)) {
                status = set_ea(conn, fsp, fname, ea_list);
                talloc_destroy(ctx);
                if (!NT_STATUS_IS_OK(status)) {
@@ -1569,17 +1437,17 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        restore_case_semantics(conn, file_attributes);
 
        file_len = sbuf.st_size;
-       fmode = dos_mode(conn,fname,&sbuf);
-       if(fmode == 0) {
-               fmode = FILE_ATTRIBUTE_NORMAL;
+       fattr = dos_mode(conn,fname,&sbuf);
+       if(fattr == 0) {
+               fattr = FILE_ATTRIBUTE_NORMAL;
        }
-       if (!fsp->is_directory && (fmode & aDIR)) {
+       if (!fsp->is_directory && (fattr & aDIR)) {
                close_file(fsp,False);
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        } 
        
        /* Save the requested allocation size. */
-       if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
+       if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
                SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12);
 #ifdef LARGE_SMB_OFF_T
                allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
@@ -1616,24 +1484,27 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
 
        /* Realloc the size of parameters and data we will return */
        params = nttrans_realloc(ppparams, 69);
-       if(params == NULL)
+       if(params == NULL) {
                return ERROR_DOS(ERRDOS,ERRnomem);
+       }
 
        p = params;
-       if (extended_oplock_granted)
+       if (extended_oplock_granted) {
                SCVAL(p,0, BATCH_OPLOCK_RETURN);
-       else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
+       } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) {
                SCVAL(p,0, LEVEL_II_OPLOCK_RETURN);
-       else
+       } else {
                SCVAL(p,0,NO_OPLOCK_RETURN);
+       }
        
        p += 2;
        SSVAL(p,0,fsp->fnum);
        p += 2;
-       if ((create_disposition == FILE_SUPERSEDE) && (smb_action == FILE_WAS_OVERWRITTEN))
+       if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) {
                SIVAL(p,0,FILE_WAS_SUPERSEDED);
-       else
-               SIVAL(p,0,smb_action);
+       } else {
+               SIVAL(p,0,info);
+       }
        p += 8;
 
        /* Create time. */
@@ -1654,14 +1525,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        p += 8;
        put_long_date(p,sbuf.st_mtime); /* change time */
        p += 8;
-       SIVAL(p,0,fmode); /* File Attributes. */
+       SIVAL(p,0,fattr); /* File Attributes. */
        p += 4;
        SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
        p += 8;
        SOFF_T(p,0,file_len);
        p += 8;
-       if (flags & EXTENDED_RESPONSE_REQUIRED)
+       if (flags & EXTENDED_RESPONSE_REQUIRED) {
                SSVAL(p,2,0x7);
+       }
        p += 4;
        SCVAL(p,0,fsp->is_directory ? 1 : 0);
 
@@ -1700,7 +1572,7 @@ int reply_ntcancel(connection_struct *conn,
  Copy a file.
 ****************************************************************************/
 
-static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint16 attrs)
+static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs)
 {
        BOOL bad_path_oldname = False;
        BOOL bad_path_newname = False;
@@ -1708,9 +1580,8 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
        pstring last_component_oldname;
        pstring last_component_newname;
        files_struct *fsp1,*fsp2;
-       uint16 fmode;
-       int access_mode;
-       int smb_action;
+       uint32 fattr;
+       int info;
        SMB_OFF_T ret=-1;
        int close_ret;
        NTSTATUS status = NT_STATUS_OK;
@@ -1747,9 +1618,10 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
        }
 
        /* Ensure attributes match. */
-       fmode = dos_mode(conn,oldname,&sbuf1);
-       if ((fmode & ~attrs) & (aHIDDEN | aSYSTEM))
+       fattr = dos_mode(conn,oldname,&sbuf1);
+       if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) {
                return NT_STATUS_NO_SUCH_FILE;
+       }
 
        unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
        if (bad_path_newname) {
@@ -1784,9 +1656,14 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
 
        DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
 
-        fsp1 = open_file_shared1(conn,oldname,&sbuf1,FILE_READ_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
-                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,
-                       &access_mode,&smb_action);
+        fsp1 = open_file_ntcreate(conn,oldname,&sbuf1,
+                       FILE_READ_DATA, /* Read-only. */
+                       0, /* No sharing. */
+                       FILE_OPEN,
+                       0, /* No create options. */
+                       FILE_ATTRIBUTE_NORMAL,
+                       INTERNAL_OPEN_ONLY,
+                       &info);
 
        if (!fsp1) {
                get_saved_error_triple(NULL, NULL, &status);
@@ -1797,9 +1674,14 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
                return status;
        }
 
-       fsp2 = open_file_shared1(conn,newname,&sbuf2,FILE_WRITE_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
-                       (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL),fmode,INTERNAL_OPEN_ONLY,
-                       &access_mode,&smb_action);
+        fsp2 = open_file_ntcreate(conn,newname,&sbuf2,
+                       FILE_WRITE_DATA, /* Read-only. */
+                       0, /* No sharing. */
+                       FILE_CREATE,
+                       0, /* No create options. */
+                       fattr,
+                       INTERNAL_OPEN_ONLY,
+                       &info);
 
        if (!fsp2) {
                get_saved_error_triple(NULL, NULL, &status);
@@ -1811,8 +1693,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
                return status;
        }
 
-       if (sbuf1.st_size)
+       if (sbuf1.st_size) {
                ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size);
+       }
 
        /*
         * As we are opening fsp1 read-only we only expect
@@ -1829,7 +1712,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
 
        /* Grrr. We have to do this as open_file_shared1 adds aARCH when it
           creates the file. This isn't the correct thing to do in the copy case. JRA */
-       file_set_dosmode(conn, newname, fmode, &sbuf2, True);
+       file_set_dosmode(conn, newname, fattr, &sbuf2, True);
 
        if (ret < (SMB_OFF_T)sbuf1.st_size) {
                return NT_STATUS_DISK_FULL;
@@ -1855,7 +1738,7 @@ int reply_ntrename(connection_struct *conn,
        pstring newname;
        char *p;
        NTSTATUS status;
-       uint16 attrs = SVAL(inbuf,smb_vwv0);
+       uint32 attrs = SVAL(inbuf,smb_vwv0);
        uint16 rename_type = SVAL(inbuf,smb_vwv1);
 
        START_PROFILE(SMBntrename);
@@ -1955,22 +1838,26 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
        files_struct *fsp;
        uint32 flags;
 
-        if(setup_count < 6)
+       if(setup_count < 6) {
                return ERROR_DOS(ERRDOS,ERRbadfunc);
+       }
 
        fsp = file_fsp(setup,4);
        flags = IVAL(setup, 0);
 
        DEBUG(3,("call_nt_transact_notify_change\n"));
 
-       if(!fsp)
+       if(!fsp) {
                return ERROR_DOS(ERRDOS,ERRbadfid);
+       }
 
-       if((!fsp->is_directory) || (conn != fsp->conn))
+       if((!fsp->is_directory) || (conn != fsp->conn)) {
                return ERROR_DOS(ERRDOS,ERRbadfid);
+       }
 
-       if (!change_notify_set(inbuf, fsp, conn, flags))
+       if (!change_notify_set(inbuf, fsp, conn, flags)) {
                return(UNIXERROR(ERRDOS,ERRbadfid));
+       }
 
        DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \
 name = %s\n", fsp->fsp_name ));
@@ -1993,8 +1880,9 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
        BOOL replace_if_exists = False;
        NTSTATUS status;
 
-        if(parameter_count < 4)
+        if(parameter_count < 4) {
                return ERROR_DOS(ERRDOS,ERRbadfunc);
+       }
 
        fsp = file_fsp(params, 0);
        replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
@@ -2062,12 +1950,14 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i
        TALLOC_CTX *mem_ctx;
        files_struct *fsp = NULL;
 
-        if(parameter_count < 8)
+        if(parameter_count < 8) {
                return ERROR_DOS(ERRDOS,ERRbadfunc);
+       }
 
        fsp = file_fsp(params,0);
-       if(!fsp)
+       if(!fsp) {
                return ERROR_DOS(ERRDOS,ERRbadfid);
+       }
 
        security_info_wanted = IVAL(params,4);
 
@@ -2075,8 +1965,9 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i
                        (unsigned int)security_info_wanted ));
 
        params = nttrans_realloc(ppparams, 4);
-       if(params == NULL)
+       if(params == NULL) {
                return ERROR_DOS(ERRDOS,ERRnomem);
+       }
 
        if ((mem_ctx = talloc_init("call_nt_transact_query_security_desc")) == NULL) {
                DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n"));
@@ -2087,10 +1978,11 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i
         * Get the permissions to return.
         */
 
-       if (!lp_nt_acl_support(SNUM(conn)))
+       if (!lp_nt_acl_support(SNUM(conn))) {
                sd_size = get_null_nt_acl(mem_ctx, &psd);
-       else
-               sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, security_info_wanted, &psd);
+       } else {
+               sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, security_info_wanted, &psd);
+       }
 
        if (sd_size == 0) {
                talloc_destroy(mem_ctx);
@@ -2171,25 +2063,30 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb
        uint32 security_info_sent = 0;
        NTSTATUS nt_status;
 
-       if(parameter_count < 8)
+       if(parameter_count < 8) {
                return ERROR_DOS(ERRDOS,ERRbadfunc);
+       }
 
-       if((fsp = file_fsp(params,0)) == NULL)
+       if((fsp = file_fsp(params,0)) == NULL) {
                return ERROR_DOS(ERRDOS,ERRbadfid);
+       }
 
-       if(!lp_nt_acl_support(SNUM(conn)))
+       if(!lp_nt_acl_support(SNUM(conn))) {
                goto done;
+       }
 
        security_info_sent = IVAL(params,4);
 
        DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name,
                (unsigned int)security_info_sent ));
 
-       if (data_count == 0)
+       if (data_count == 0) {
                return ERROR_DOS(ERRDOS, ERRnoaccess);
+       }
 
-       if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, data_count, security_info_sent)))
+       if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, data_count, security_info_sent))) {
                return ERROR_NT(nt_status);
+       }
 
   done:
 
@@ -2520,8 +2417,9 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
                                /* Realloc the size of parameters and data we will return */
                                param_len = 4;
                                params = nttrans_realloc(ppparams, param_len);
-                               if(params == NULL)
+                               if(params == NULL) {
                                        return ERROR_DOS(ERRDOS,ERRnomem);
+                               }
 
                                data_len = 0;
                                SIVAL(params,0,data_len);
@@ -2544,19 +2442,20 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
                        /* Realloc the size of parameters and data we will return */
                        param_len = 4;
                        params = nttrans_realloc(ppparams, param_len);
-                       if(params == NULL)
+                       if(params == NULL) {
                                return ERROR_DOS(ERRDOS,ERRnomem);
+                       }
 
                        /* we should not trust the value in max_data_count*/
                        max_data_count = MIN(max_data_count,2048);
                        
                        pdata = nttrans_realloc(ppdata, max_data_count);/* should be max data count from client*/
-                       if(pdata == NULL)
+                       if(pdata == NULL) {
                                return ERROR_DOS(ERRDOS,ERRnomem);
+                       }
 
                        entry = pdata;
 
-
                        /* set params Size of returned Quota Data 4 bytes*/
                        /* but set it later when we know it */
                
@@ -2641,7 +2540,6 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
 
                        sid_parse(pdata+8,sid_len,&sid);
                
-
                        if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) {
                                ZERO_STRUCT(qt);
                                /* 
@@ -2654,12 +2552,14 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
                        /* Realloc the size of parameters and data we will return */
                        param_len = 4;
                        params = nttrans_realloc(ppparams, param_len);
-                       if(params == NULL)
+                       if(params == NULL) {
                                return ERROR_DOS(ERRDOS,ERRnomem);
+                       }
 
                        pdata = nttrans_realloc(ppdata, data_len);
-                       if(pdata == NULL)
+                       if(pdata == NULL) {
                                return ERROR_DOS(ERRDOS,ERRnomem);
+                       }
 
                        entry = pdata;
 
@@ -2884,12 +2784,15 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
 
        /* Allocate the space for the setup, the maximum needed parameters and data */
 
-       if(setup_count > 0)
+       if(setup_count > 0) {
                setup = (char *)SMB_MALLOC(setup_count);
-       if (total_parameter_count > 0)
+       }
+       if (total_parameter_count > 0) {
                params = (char *)SMB_MALLOC(total_parameter_count);
-       if (total_data_count > 0)
+       }
+       if (total_data_count > 0) {
                data = (char *)SMB_MALLOC(total_data_count);
+       }
  
        if ((total_parameter_count && !params)  || (total_data_count && !data) ||
                                (setup_count && !setup)) {
@@ -2911,10 +2814,12 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
        if(setup) {
                DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count));
                if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) ||
-                               (smb_nt_SetupStart + setup_count < setup_count))
+                               (smb_nt_SetupStart + setup_count < setup_count)) {
                        goto bad_param;
-               if (smb_nt_SetupStart + setup_count > length)
+               }
+               if (smb_nt_SetupStart + setup_count > length) {
                        goto bad_param;
+               }
 
                memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
                dump_data(10, setup, setup_count);
@@ -2922,22 +2827,26 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
        if(params) {
                DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count));
                if ((parameter_offset + parameter_count < parameter_offset) ||
-                               (parameter_offset + parameter_count < parameter_count))
+                               (parameter_offset + parameter_count < parameter_count)) {
                        goto bad_param;
+               }
                if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)||
-                               (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf)))
+                               (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) {
                        goto bad_param;
+               }
 
                memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
                dump_data(10, params, parameter_count);
        }
        if(data) {
                DEBUG(10,("reply_nttrans: data_count = %d\n",data_count));
-               if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count))
+               if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) {
                        goto bad_param;
+               }
                if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) ||
-                               (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf)))
+                               (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) {
                        goto bad_param;
+               }
 
                memcpy( data, smb_base(inbuf) + data_offset, data_count);
                dump_data(10, data, data_count);
@@ -2950,8 +2859,10 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                        of the parameter/data bytes */
                outsize = set_message(outbuf,0,0,True);
                srv_signing_trans_stop();
-               if (!send_smb(smbd_server_fd(),outbuf))
+               show_msg(outbuf);
+               if (!send_smb(smbd_server_fd(),outbuf)) {
                        exit_server("reply_nttrans: send_smb failed.");
+               }
 
                while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
                        BOOL ret;
@@ -2982,10 +2893,12 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                        }
       
                        /* Revise total_params and total_data in case they have changed downwards */
-                       if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count)
+                       if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count) {
                                total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
-                       if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count)
+                       }
+                       if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count) {
                                total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
+                       }
 
                        parameter_count = IVAL(inbuf,smb_nts_ParameterCount);
                        parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset);
@@ -3003,43 +2916,54 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
                        }
 
                        if (parameter_count) {
-                               if (parameter_displacement + parameter_count > total_parameter_count)
+                               if (parameter_displacement + parameter_count > total_parameter_count) {
                                        goto bad_param;
+                               }
                                if ((parameter_displacement + parameter_count < parameter_displacement) ||
-                                               (parameter_displacement + parameter_count < parameter_count))
+                                               (parameter_displacement + parameter_count < parameter_count)) {
                                        goto bad_param;
-                               if (parameter_displacement > total_parameter_count)
+                               }
+                               if (parameter_displacement > total_parameter_count) {
                                        goto bad_param;
+                               }
                                if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) ||
-                                               (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf)))
+                                               (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) {
                                        goto bad_param;
-                               if (parameter_displacement + params < params)
+                               }
+                               if (parameter_displacement + params < params) {
                                        goto bad_param;
+                               }
 
                                memcpy( &params[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count);
                        }
 
                        if (data_count) {
-                               if (data_displacement + data_count > total_data_count)
+                               if (data_displacement + data_count > total_data_count) {
                                        goto bad_param;
+                               }
                                if ((data_displacement + data_count < data_displacement) ||
-                                               (data_displacement + data_count < data_count))
+                                               (data_displacement + data_count < data_count)) {
                                        goto bad_param;
-                               if (data_displacement > total_data_count)
+                               }
+                               if (data_displacement > total_data_count) {
                                        goto bad_param;
+                               }
                                if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) ||
-                                               (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf)))
+                                               (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) {
                                        goto bad_param;
-                               if (data_displacement + data < data)
+                               }
+                               if (data_displacement + data < data) {
                                        goto bad_param;
+                               }
 
                                memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count);
                        }
                }
        }
 
-       if (Protocol >= PROTOCOL_NT1)
+       if (Protocol >= PROTOCOL_NT1) {
                SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME);
+       }
 
        /* Now we must call the relevant NT_TRANS function */
        switch(function_code) {
index 9da53a5057a96116e457157010bfbd7cb6ff5c4d..810913c025d83294ee21d9e59158a1285bfb76e6 100644 (file)
@@ -3,6 +3,7 @@
    file opening and share modes
    Copyright (C) Andrew Tridgell 1992-1998
    Copyright (C) Jeremy Allison 2001-2004
+   Copyright (C) Volker Lendecke 2005
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -36,13 +37,16 @@ struct dev_inode_bundle {
  fd support routines - attempt to do a dos_open.
 ****************************************************************************/
 
-static int fd_open(struct connection_struct *conn, const char *fname, 
-                  int flags, mode_t mode)
+static int fd_open(struct connection_struct *conn,
+                       const char *fname, 
+                       int flags,
+                       mode_t mode)
 {
        int fd;
 #ifdef O_NOFOLLOW
-       if (!lp_symlinks(SNUM(conn)))
+       if (!lp_symlinks(SNUM(conn))) {
                flags |= O_NOFOLLOW;
+       }
 #endif
 
        fd = SMB_VFS_OPEN(conn,fname,flags,mode);
@@ -57,10 +61,15 @@ static int fd_open(struct connection_struct *conn, const char *fname,
  Close the file associated with a fsp.
 ****************************************************************************/
 
-int fd_close(struct connection_struct *conn, files_struct *fsp)
+int fd_close(struct connection_struct *conn,
+               files_struct *fsp)
 {
-       if (fsp->fd == -1)
-               return 0; /* what we used to call a stat open. */
+       if (fsp->fh->fd == -1) {
+               return 0; /* What we used to call a stat open. */
+       }
+       if (fsp->fh->ref_count > 1) {
+               return 0; /* Shared handle. Only close last reference. */
+       }
        return fd_close_posix(conn, fsp);
 }
 
@@ -86,7 +95,10 @@ static void check_for_pipe(const char *fname)
  Do this by fd if possible.
 ****************************************************************************/
 
-void change_owner_to_parent(connection_struct *conn, files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf)
+void change_owner_to_parent(connection_struct *conn,
+                               files_struct *fsp,
+                               const char *fname,
+                               SMB_STRUCT_STAT *psbuf)
 {
        const char *parent_path = parent_dirname(fname);
        SMB_STRUCT_STAT parent_st;
@@ -94,56 +106,67 @@ void change_owner_to_parent(connection_struct *conn, files_struct *fsp, const ch
 
        ret = SMB_VFS_STAT(conn, parent_path, &parent_st);
        if (ret == -1) {
-               DEBUG(0,("change_owner_to_parent: failed to stat parent directory %s. Error was %s\n",
-                       parent_path, strerror(errno) ));
+               DEBUG(0,("change_owner_to_parent: failed to stat parent "
+                        "directory %s. Error was %s\n",
+                        parent_path, strerror(errno) ));
                return;
        }
 
-       if (fsp && fsp->fd != -1) {
+       if (fsp && fsp->fh->fd != -1) {
                become_root();
-               ret = SMB_VFS_FCHOWN(fsp, fsp->fd, parent_st.st_uid, (gid_t)-1);
+               ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1);
                unbecome_root();
                if (ret == -1) {
-                       DEBUG(0,("change_owner_to_parent: failed to fchown file %s to parent directory uid %u. \
-Error was %s\n",
-                               fname, (unsigned int)parent_st.st_uid, strerror(errno) ));
+                       DEBUG(0,("change_owner_to_parent: failed to fchown "
+                                "file %s to parent directory uid %u. Error "
+                                "was %s\n", fname,
+                                (unsigned int)parent_st.st_uid,
+                                strerror(errno) ));
                }
 
-               DEBUG(10,("change_owner_to_parent: changed new file %s to parent directory uid %u.\n",
-                       fname, (unsigned int)parent_st.st_uid ));
+               DEBUG(10,("change_owner_to_parent: changed new file %s to "
+                         "parent directory uid %u.\n", fname,
+                         (unsigned int)parent_st.st_uid ));
 
        } else {
-               /* We've already done an lstat into psbuf, and we know it's a directory. If
-                  we can cd into the directory and the dev/ino are the same then we can safely
-                  chown without races as we're locking the directory in place by being in it.
-                  This should work on any UNIX (thanks tridge :-). JRA.
+               /* We've already done an lstat into psbuf, and we know it's a
+                  directory. If we can cd into the directory and the dev/ino
+                  are the same then we can safely chown without races as
+                  we're locking the directory in place by being in it.  This
+                  should work on any UNIX (thanks tridge :-). JRA.
                */
 
                pstring saved_dir;
                SMB_STRUCT_STAT sbuf;
 
                if (!vfs_GetWd(conn,saved_dir)) {
-                       DEBUG(0,("change_owner_to_parent: failed to get current working directory\n"));
+                       DEBUG(0,("change_owner_to_parent: failed to get "
+                                "current working directory\n"));
                        return;
                }
 
                /* Chdir into the new path. */
                if (vfs_ChDir(conn, fname) == -1) {
-                       DEBUG(0,("change_owner_to_parent: failed to change current working directory to %s. \
-Error was %s\n", fname, strerror(errno) ));
+                       DEBUG(0,("change_owner_to_parent: failed to change "
+                                "current working directory to %s. Error "
+                                "was %s\n", fname, strerror(errno) ));
                        goto out;
                }
 
                if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
-                       DEBUG(0,("change_owner_to_parent: failed to stat directory '.' (%s) \
-Error was %s\n", fname, strerror(errno)));
+                       DEBUG(0,("change_owner_to_parent: failed to stat "
+                                "directory '.' (%s) Error was %s\n",
+                                fname, strerror(errno)));
                        goto out;
                }
 
                /* Ensure we're pointing at the same place. */
-               if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || sbuf.st_mode != psbuf->st_mode ) {
-                       DEBUG(0,("change_owner_to_parent: device/inode/mode on directory %s changed. Refusing to chown !\n",
-                               fname ));
+               if (sbuf.st_dev != psbuf->st_dev ||
+                   sbuf.st_ino != psbuf->st_ino ||
+                   sbuf.st_mode != psbuf->st_mode ) {
+                       DEBUG(0,("change_owner_to_parent: "
+                                "device/inode/mode on directory %s changed. "
+                                "Refusing to chown !\n", fname ));
                        goto out;
                }
 
@@ -151,14 +174,16 @@ Error was %s\n", fname, strerror(errno)));
                ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1);
                unbecome_root();
                if (ret == -1) {
-                       DEBUG(10,("change_owner_to_parent: failed to chown directory %s to parent directory uid %u. \
-Error was %s\n",
-                               fname, (unsigned int)parent_st.st_uid, strerror(errno) ));
+                       DEBUG(10,("change_owner_to_parent: failed to chown "
+                                 "directory %s to parent directory uid %u. "
+                                 "Error was %s\n", fname,
+                                 (unsigned int)parent_st.st_uid, strerror(errno) ));
                        goto out;
                }
 
-               DEBUG(10,("change_owner_to_parent: changed ownership of new directory %s to parent directory uid %u.\n",
-                       fname, (unsigned int)parent_st.st_uid ));
+               DEBUG(10,("change_owner_to_parent: changed ownership of new "
+                         "directory %s to parent directory uid %u.\n",
+                         fname, (unsigned int)parent_st.st_uid ));
 
   out:
 
@@ -170,13 +195,19 @@ Error was %s\n",
  Open a file.
 ****************************************************************************/
 
-static BOOL open_file(files_struct *fsp,connection_struct *conn,
-                     const char *fname,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access)
+static BOOL open_file(files_struct *fsp,
+                       connection_struct *conn,
+                       const char *fname,
+                       SMB_STRUCT_STAT *psbuf,
+                       int flags,
+                       mode_t unx_mode,
+                       uint32 access_mask)
 {
        int accmode = (flags & O_ACCMODE);
        int local_flags = flags;
+       BOOL file_existed = VALID_STAT(*psbuf);
 
-       fsp->fd = -1;
+       fsp->fh->fd = -1;
        fsp->oplock_type = NO_OPLOCK;
        errno = EPERM;
 
@@ -199,9 +230,9 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
                        check_for_pipe(fname);
                        return False;
                } else if(flags & O_CREAT) {
-                       /* We don't want to write - but we must make sure that O_CREAT
-                          doesn't create the file if we have write access into the
-                          directory.
+                       /* We don't want to write - but we must make sure that
+                          O_CREAT doesn't create the file if we have write
+                          access into the directory.
                        */
                        flags &= ~O_CREAT;
                        local_flags &= ~O_CREAT;
@@ -221,12 +252,14 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
         */
 
        if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
-               DEBUG(10,("open_file: truncate requested on read-only open for file %s\n",fname ));
+               DEBUG(10,("open_file: truncate requested on read-only open "
+                         "for file %s\n",fname ));
                local_flags = (flags & ~O_ACCMODE)|O_RDWR;
        }
 
-       if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
-                       (local_flags & O_CREAT) || ((local_flags & O_TRUNC) == O_TRUNC) ) {
+       if ((access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
+           (local_flags & O_CREAT) ||
+           ((local_flags & O_TRUNC) == O_TRUNC) ) {
 
                /*
                 * We can't actually truncate here as the file may be locked.
@@ -242,42 +275,50 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
                 * open flags. JRA.
                 */
 
-               if (VALID_STAT(*psbuf) && S_ISFIFO(psbuf->st_mode))
+               if (file_existed && S_ISFIFO(psbuf->st_mode)) {
                        local_flags |= O_NONBLOCK;
+               }
 #endif
 
                /* Don't create files with Microsoft wildcard characters. */
-               if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname))  {
-                       set_saved_error_triple(ERRDOS, ERRinvalidname, NT_STATUS_OBJECT_NAME_INVALID);
+               if ((local_flags & O_CREAT) && !file_existed &&
+                   ms_has_wild(fname))  {
+                       set_saved_error_triple(ERRDOS, ERRinvalidname,
+                                              NT_STATUS_OBJECT_NAME_INVALID);
                        return False;
                }
 
                /* Actually do the open */
-               fsp->fd = fd_open(conn, fname, local_flags, mode);
-               if (fsp->fd == -1)  {
-                       DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n",
+               fsp->fh->fd = fd_open(conn, fname, local_flags, unx_mode);
+               if (fsp->fh->fd == -1)  {
+                       DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
+                                "(flags=%d)\n",
                                 fname,strerror(errno),local_flags,flags));
                        check_for_pipe(fname);
                        return False;
                }
 
                /* Inherit the ACL if the file was created. */
-               if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf))
-                       inherit_access_acl(conn, fname, mode);
+               if ((local_flags & O_CREAT) && !file_existed) {
+                       inherit_access_acl(conn, fname, unx_mode);
+               }
 
-       } else
-               fsp->fd = -1; /* What we used to call a stat open. */
+       } else {
+               fsp->fh->fd = -1; /* What we used to call a stat open. */
+       }
 
-       if (!VALID_STAT(*psbuf)) {
+       if (!file_existed) {
                int ret;
 
-               if (fsp->fd == -1)
+               if (fsp->fh->fd == -1) {
                        ret = SMB_VFS_STAT(conn, fname, psbuf);
-               else {
-                       ret = SMB_VFS_FSTAT(fsp,fsp->fd,psbuf);
+               else {
+                       ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf);
                        /* If we have an fd, this stat should succeed. */
-                       if (ret == -1)
-                               DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) ));
+                       if (ret == -1) {
+                               DEBUG(0,("Error doing fstat on open file %s "
+                                        "(%s)\n", fname,strerror(errno) ));
+                       }
                }
 
                /* For a non-io open, this stat failing means file not found. JRA */
@@ -305,18 +346,20 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
        fsp->vuid = current_user.vuid;
        fsp->file_pid = global_smbpid;
        fsp->can_lock = True;
-       fsp->can_read = ((flags & O_WRONLY)==0);
-       fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
-       fsp->share_mode = 0;
-       fsp->desired_access = desired_access;
+       fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
+       if (!CAN_WRITE(conn)) {
+               fsp->can_write = False;
+       } else {
+               fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
+       }
        fsp->print_file = False;
        fsp->modified = False;
        fsp->oplock_type = NO_OPLOCK;
        fsp->sent_oplock_break = NO_BREAK_SENT;
        fsp->is_directory = False;
        fsp->is_stat = False;
-       fsp->directory_delete_on_close = False;
-       if (conn->aio_write_behind_list && is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) {
+       if (conn->aio_write_behind_list &&
+           is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) {
                fsp->aio_write_behind = True;
        }
 
@@ -349,293 +392,119 @@ static BOOL is_executable(const char *fname)
        return False;
 }
 
-enum {AFAIL,AREAD,AWRITE,AALL};
-
-/*******************************************************************
- Reproduce the share mode access table.
- This is horrendoously complex, and really can't be justified on any
- rational grounds except that this is _exactly_ what NT does. See
- the DENY1 and DENY2 tests in smbtorture for a comprehensive set of
- test routines.
-********************************************************************/
-
-static int access_table(int new_deny,int old_deny,int old_mode,
-                       BOOL same_pid, BOOL isexe)
-{
-         if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
-
-         if (same_pid) {
-                 if (isexe && old_mode == DOS_OPEN_RDONLY && 
-                     old_deny == DENY_DOS && new_deny == DENY_READ) {
-                         return AFAIL;
-                 }
-                 if (!isexe && old_mode == DOS_OPEN_RDONLY && 
-                     old_deny == DENY_DOS && new_deny == DENY_DOS) {
-                         return AREAD;
-                 }
-                 if (new_deny == DENY_FCB && old_deny == DENY_DOS) {
-                         if (isexe) return AFAIL;
-                         if (old_mode == DOS_OPEN_RDONLY) return AFAIL;
-                         return AALL;
-                 }
-                 if (old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS) {
-                         if (new_deny == DENY_FCB || new_deny == DENY_READ) {
-                                 if (isexe) return AREAD;
-                                 return AFAIL;
-                         }
-                 }
-                 if (old_deny == DENY_FCB) {
-                         if (new_deny == DENY_DOS || new_deny == DENY_FCB) return AALL;
-                         return AFAIL;
-                 }
-         }
-
-         if (old_deny == DENY_DOS || new_deny == DENY_DOS || 
-             old_deny == DENY_FCB || new_deny == DENY_FCB) {
-                 if (isexe) {
-                         if (old_deny == DENY_FCB || new_deny == DENY_FCB) {
-                                 return AFAIL;
-                         }
-                         if (old_deny == DENY_DOS) {
-                                 if (new_deny == DENY_READ && 
-                                     (old_mode == DOS_OPEN_RDONLY || 
-                                      old_mode == DOS_OPEN_RDWR)) {
-                                         return AFAIL;
-                                 }
-                                 if (new_deny == DENY_WRITE && 
-                                     (old_mode == DOS_OPEN_WRONLY || 
-                                      old_mode == DOS_OPEN_RDWR)) {
-                                         return AFAIL;
-                                 }
-                                 return AALL;
-                         }
-                         if (old_deny == DENY_NONE) return AALL;
-                         if (old_deny == DENY_READ) return AWRITE;
-                         if (old_deny == DENY_WRITE) return AREAD;
-                 }
-                 /* it isn't a exe, dll, sym or com file */
-                 if (old_deny == new_deny && same_pid)
-                         return(AALL);    
-
-                 if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL;
-                 if (old_mode == DOS_OPEN_RDONLY) return(AREAD);
-                 
-                 return(AFAIL);
-         }
-         
-         switch (new_deny) 
-                 {
-                 case DENY_WRITE:
-                         if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD);
-                         if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE);
-                         if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL);
-                         return(AFAIL);
-                 case DENY_READ:
-                         if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD);
-                         if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE);
-                         if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL);
-                         return(AFAIL);
-                 case DENY_NONE:
-                         if (old_deny==DENY_WRITE) return(AREAD);
-                         if (old_deny==DENY_READ) return(AWRITE);
-                         if (old_deny==DENY_NONE) return(AALL);
-                         return(AFAIL);      
-                 }
-         return(AFAIL);      
-}
-
 /****************************************************************************
  Check if we can open a file with a share mode.
+ Returns True if conflict, False if not.
 ****************************************************************************/
 
-static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, uint32 desired_access,
-                            const char *fname, BOOL fcbopen, int *flags)
+static BOOL share_conflict(share_mode_entry *entry,
+                          uint32 access_mask,
+                          uint32 share_access)
 {
-       int deny_mode = GET_DENY_MODE(share_mode);
-       int old_open_mode = GET_OPEN_MODE(share->share_mode);
-       int old_deny_mode = GET_DENY_MODE(share->share_mode);
-       BOOL non_io_open_request;
-       BOOL non_io_open_existing;
-
-       /*
-        * share modes = false means don't bother to check for
-        * DENY mode conflict. This is a *really* bad idea :-). JRA.
-        */
-
-       if(!lp_share_modes(SNUM(conn)))
-               return True;
-
-       if (desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) {
-               non_io_open_request = False;
-       } else {
-               non_io_open_request = True;
-       }
-
-       if (share->desired_access & ~(SYNCHRONIZE_ACCESS|READ_CONTROL_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) {
-               non_io_open_existing = False;
-       } else {
-               non_io_open_existing = True;
-       }
-
-       /*
-        * Don't allow any opens once the delete on close flag has been
-        * set.
-        */
-
-       if (GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) {
-               DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n",
-                       fname ));
-               /* Use errno to map to correct error. */
-               set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK);
+       DEBUG(10,("share_conflict: entry->access_mask = 0x%x, "
+                 "entry->share_access = 0x%x, "
+                 "entry->private_options = 0x%x\n",
+                 (unsigned int)entry->access_mask,
+                 (unsigned int)entry->share_access,
+                 (unsigned int)entry->private_options));
+
+       DEBUG(10,("share_conflict: access_mask = 0x%x, share_access = 0x%x\n",
+                 (unsigned int)access_mask, (unsigned int)share_access));
+
+       if ((entry->access_mask & (FILE_WRITE_DATA|
+                                  FILE_APPEND_DATA|
+                                  FILE_READ_DATA|
+                                  FILE_EXECUTE|
+                                  DELETE_ACCESS)) == 0) {
+               DEBUG(10,("share_conflict: No conflict due to "
+                         "entry->access_mask = 0x%x\n",
+                         (unsigned int)entry->access_mask ));
                return False;
        }
 
-       /* this is a nasty hack, but necessary until we rewrite our open
-          handling to use a NTCreateX call as the basic call.
-          NT may open a file with neither read nor write access, and in
-                  this case it expects the open not to conflict with any
-                  existing deny modes. This happens (for example) during a
-                  "xcopy /o" where the second file descriptor is used for
-                  ACL sets
-                  (tridge)
-       */
-
-       /*
-        * This is a bit wierd - the test for desired access not having the
-        * critical bits seems seems odd. Firstly, if both opens have no
-        * critical bits then always ignore. Then check the "allow delete"
-        * then check for either. This probably isn't quite right yet but
-        * gets us much closer. JRA.
-        */
-
-       /*
-        * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE
-        * and the existing desired_acces then share modes don't conflict.
-        */
-
-       if (non_io_open_request && non_io_open_existing) {
-
-               /*
-                * Wrinkle discovered by smbtorture....
-                * If both are non-io open and requester is asking for delete and current open has delete access
-                * but neither open has allowed file share delete then deny.... this is very strange and
-                * seems to be the only case in which non-io opens conflict. JRA.
-                */
-
-               if ((desired_access & DELETE_ACCESS) && (share->desired_access & DELETE_ACCESS) && 
-                               (!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) {
-                       DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n",
-                               fname ));
-                       set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
-                       return False;
-               }
-
-               DEBUG(5,("check_share_mode: Allowing open on file %s as both desired access (0x%x) \
-and existing desired access (0x%x) are non-data opens\n", 
-                       fname, (unsigned int)desired_access, (unsigned int)share->desired_access ));
-               return True;
-       } else if (non_io_open_request || non_io_open_existing) {
-               /*
-                * If either are non-io opens then share modes don't conflict.
-                */
-               DEBUG(5,("check_share_mode: One non-io open. Allowing open on file %s as desired access (0x%x) doesn't conflict with\
-existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access ));
-               return True;
-       }
-
-       /*
-        * If delete access was requested and the existing share mode doesn't have
-        * ALLOW_SHARE_DELETE then deny.
-        */
-
-       if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) {
-               DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n",
-                       fname ));
-               set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
+       if ((access_mask & (FILE_WRITE_DATA|
+                           FILE_APPEND_DATA|
+                           FILE_READ_DATA|
+                           FILE_EXECUTE|
+                           DELETE_ACCESS)) == 0) {
+               DEBUG(10,("share_conflict: No conflict due to "
+                         "access_mask = 0x%x\n",
+                         (unsigned int)access_mask ));
                return False;
        }
 
-       /*
-        * The inverse of the above.
-        * If delete access was granted and the new share mode doesn't have
-        * ALLOW_SHARE_DELETE then deny.
-        */
-
-       if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) {
-               DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n",
-                       fname ));
-               set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
-               return False;
-       }
-
-#if 0
-       /* Bluarc test may need this ... needs further investigation. */
-       if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) {
-               set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
-               return False;
+#if 1 /* JRA TEST - Superdebug. */
+#define CHECK_MASK(num, am, right, sa, share) \
+       DEBUG(10,("share_conflict: [%d] am (0x%x) & right (0x%x) = 0x%x\n", \
+               (unsigned int)(num), (unsigned int)(am), \
+               (unsigned int)(right), (unsigned int)(am)&(right) )); \
+       DEBUG(10,("share_conflict: [%d] sa (0x%x) & share (0x%x) = 0x%x\n", \
+               (unsigned int)(num), (unsigned int)(sa), \
+               (unsigned int)(share), (unsigned int)(sa)&(share) )); \
+       if (((am) & (right)) && !((sa) & (share))) { \
+               DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \
+sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \
+                       (unsigned int)(share) )); \
+               set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \
+               return True; \
+       }
+#else
+#define CHECK_MASK(num, am, right, sa, share) \
+       if (((am) & (right)) && !((sa) & (share))) { \
+               DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \
+sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \
+                       (unsigned int)(share) )); \
+               set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \
+               return True; \
        }
 #endif
 
-       /*
-        * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE
-        * then share modes don't conflict. Likewise with existing desired access.
-        */
-
-       if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
-               !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) {
-               DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with \
-existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access ));
-               return True;
-       }
-
-       {
-               int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
-                                               (share->pid == sys_getpid()),is_executable(fname));
-
-               if ((access_allowed == AFAIL) ||
-                       (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
-                       (access_allowed == AREAD && *flags != O_RDONLY) ||
-                       (access_allowed == AWRITE && *flags != O_WRONLY)) {
-
-                       DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n",
-                               deny_mode,old_deny_mode,old_open_mode,
-                               (int)share->pid,fname, fcbopen, *flags, access_allowed));
-
-                       set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
-                       return False;
-               }
-
-               if (access_allowed == AREAD)
-                       *flags = O_RDONLY;
-
-               if (access_allowed == AWRITE)
-                       *flags = O_WRONLY;
+       CHECK_MASK(1, entry->access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA,
+                  share_access, FILE_SHARE_WRITE);
+       CHECK_MASK(2, access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA,
+                  entry->share_access, FILE_SHARE_WRITE);
+       
+       CHECK_MASK(3, entry->access_mask, FILE_READ_DATA | FILE_EXECUTE,
+                  share_access, FILE_SHARE_READ);
+       CHECK_MASK(4, access_mask, FILE_READ_DATA | FILE_EXECUTE,
+                  entry->share_access, FILE_SHARE_READ);
 
-       }
+       CHECK_MASK(5, entry->access_mask, DELETE_ACCESS,
+                  share_access, FILE_SHARE_DELETE);
+       CHECK_MASK(6, access_mask, DELETE_ACCESS,
+                  entry->share_access, FILE_SHARE_DELETE);
 
-       return True;
+       DEBUG(10,("share_conflict: No conflict.\n"));
+       return False;
 }
 
-
 #if defined(DEVELOPER)
-static void validate_my_share_entries(int num, share_mode_entry *share_entry)
+static void validate_my_share_entries(int num,
+                                       share_mode_entry *share_entry)
 {
        files_struct *fsp;
 
-       if (share_entry->pid != sys_getpid())
+       if (share_entry->pid != sys_getpid()) {
                return;
+       }
 
-       fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id);
+       fsp = file_find_dif(share_entry->dev, share_entry->inode,
+                           share_entry->share_file_id);
        if (!fsp) {
-               DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) ));
-               smb_panic("validate_my_share_entries: Cannot match a share entry with an open file\n");
+               DEBUG(0,("validate_my_share_entries: PANIC : %s\n",
+                        share_mode_str(num, share_entry) ));
+               smb_panic("validate_my_share_entries: Cannot match a "
+                         "share entry with an open file\n");
        }
 
        if (((uint16)fsp->oplock_type) != share_entry->op_type) {
                pstring str;
-               DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) ));
-               slprintf(str, sizeof(str)-1, "validate_my_share_entries: file %s, oplock_type = 0x%x, op_type = 0x%x\n",
-                               fsp->fsp_name, (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type );
+               DEBUG(0,("validate_my_share_entries: PANIC : %s\n",
+                        share_mode_str(num, share_entry) ));
+               slprintf(str, sizeof(str)-1, "validate_my_share_entries: "
+                        "file %s, oplock_type = 0x%x, op_type = 0x%x\n",
+                        fsp->fsp_name, (unsigned int)fsp->oplock_type,
+                        (unsigned int)share_entry->op_type );
                smb_panic(str);
        }
 }
@@ -655,42 +524,75 @@ static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_li
        }
 }
 
+static BOOL cause_oplock_break(int request, int existing, uint32 access_mask)
+{
+       if ((access_mask == DELETE_ACCESS) &&
+           (request == NO_OPLOCK)) {
+               /* This is a delete request */
+               return (BATCH_OPLOCK_TYPE(existing) != 0);
+       }
+
+       if (EXCLUSIVE_OPLOCK_TYPE(existing) && (request != NO_OPLOCK)) {
+               return True;
+       }
+
+       if ((existing != NO_OPLOCK) && (request == NO_OPLOCK)) {
+               return True;
+       }
+
+       return False;
+}
+
 /****************************************************************************
  Deal with open deny mode and oplock break processing.
  Invarient: Share mode must be locked on entry and exit.
  Returns -1 on error, or number of share modes on success (may be zero).
 ****************************************************************************/
 
-static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev,
+static int open_mode_check(connection_struct *conn,
+                          const char *fname,
+                          SMB_DEV_T dev,
                           SMB_INO_T inode, 
-                          uint32 desired_access,
-                          int share_mode, int *p_flags, int *p_oplock_request,
+                          uint32 access_mask,
+                          uint32 share_access,
+                          uint32 create_options,
+                          int *p_flags,
+                          int *p_oplock_request,
                           BOOL *p_all_current_opens_are_level_II)
 {
        int i;
        int num_share_modes;
        int oplock_contention_count = 0;
        share_mode_entry *old_shares = NULL;
-       BOOL fcbopen = False;
        BOOL broke_oplock;
+       BOOL delete_on_close;
 
-       if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB)
-               fcbopen = True;
-       
-       num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
+       num_share_modes = get_share_modes(dev, inode, &old_shares, &delete_on_close);
        
        if(num_share_modes == 0) {
                SAFE_FREE(old_shares);
                return 0;
        }
        
-       if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) &&
-               ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) {
-               /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */
+       if (access_mask &&
+           ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES|
+                             FILE_WRITE_ATTRIBUTES))==0) &&
+           ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|
+                            FILE_WRITE_ATTRIBUTES)) != 0)) {
+               /* Stat open that doesn't trigger oplock breaks or share mode
+                * checks... ! JRA. */
                SAFE_FREE(old_shares);
                return num_share_modes;
        }
 
+       /* A delete on close prohibits everything */
+
+       if (delete_on_close) {
+               SAFE_FREE(old_shares);
+               errno = EACCES;
+               return -1;
+       }
+
        /*
         * Check if the share modes will give us access.
         */
@@ -703,132 +605,152 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T
                *p_all_current_opens_are_level_II = True;
                
                for(i = 0; i < num_share_modes; i++) {
-                       BOOL cause_oplock_break = False;
                        share_mode_entry *share_entry = &old_shares[i];
+                       BOOL opb_ret;
                        
 #if defined(DEVELOPER)
                        validate_my_share_entries(i, share_entry);
 #endif
 
                        /* 
-                        * By observation of NetBench, oplocks are broken *before* share
-                        * modes are checked. This allows a file to be closed by the client
-                        * if the share mode would deny access and the client has an oplock. 
-                        * Check if someone has an oplock on this file. If so we must break 
-                        * it before continuing. 
+                        * By observation of NetBench, oplocks are broken
+                        * *before* share modes are checked. This allows a
+                        * file to be closed by the client if the share mode
+                        * would deny access and the client has an oplock.
+                        * Check if someone has an oplock on this file. If so
+                        * we must break it before continuing.
                         */
-                       
-                       /* Was this a delete this file request ? */
-                       if (!*p_oplock_request && desired_access == DELETE_ACCESS &&
-                                       !BATCH_OPLOCK_TYPE(share_entry->op_type)) {
-                               /* Don't break the oplock in this case. */
-                               cause_oplock_break = False;
-                       } else if((*p_oplock_request && EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) ||
-                          (!*p_oplock_request && (share_entry->op_type != NO_OPLOCK))) {
-                               cause_oplock_break = True;
+
+                       if (!cause_oplock_break(*p_oplock_request,
+                                               share_entry->op_type,
+                                               access_mask)) {
+                               if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) {
+                                       *p_all_current_opens_are_level_II = False;
+                               }
+                               continue;
                        }
 
-                       if(cause_oplock_break) {
-                               BOOL opb_ret;
+                       /* This is an oplock break */
 
-                               DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \
-dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsigned int)dev, (double)inode));
+                       DEBUG(5,("open_mode_check: oplock_request = %d, "
+                                "breaking oplock (%x) on file %s, "
+                                "dev = %x, inode = %.0f\n",
+                                *p_oplock_request, share_entry->op_type,
+                                fname, (unsigned int)dev, (double)inode));
                                
-                               /* Ensure the reply for the open uses the correct sequence number. */
-                               /* This isn't a real deferred packet as it's response will also increment
-                                * the sequence.
-                                */
-                               srv_defer_sign_response(get_current_mid());
+                       /* Ensure the reply for the open uses the correct
+                        * sequence number. */
+                       /* This isn't a real deferred packet as it's response
+                        * will also increment the sequence.
+                        */
+                       srv_defer_sign_response(get_current_mid());
 
-                               /* Oplock break - unlock to request it. */
-                               unlock_share_entry(conn, dev, inode);
-                               
-                               opb_ret = request_oplock_break(share_entry);
+                       /* Oplock break - unlock to request it. */
+                       unlock_share_entry(conn, dev, inode);
                                
-                               /* Now relock. */
-                               lock_share_entry(conn, dev, inode);
+                       opb_ret = request_oplock_break(share_entry);
                                
-                               if(opb_ret == False) {
-                                       DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \
-dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
-                                       SAFE_FREE(old_shares);
-                                       set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
-                                       return -1;
-                               }
+                       /* Now relock. */
+                       lock_share_entry(conn, dev, inode);
                                
-                               broken_entry = SMB_MALLOC_P(struct share_mode_entry_list);
-                               if (!broken_entry) {
-                                       smb_panic("open_mode_check: malloc fail.\n");
-                               }
-                               broken_entry->entry = *share_entry;
-                               DLIST_ADD(broken_entry_list, broken_entry);
-                               broke_oplock = True;
+                       if (!opb_ret) {
+                               DEBUG(0,("open_mode_check: FAILED when breaking "
+                                        "oplock (%x) on file %s, dev = %x, "
+                                        "inode = %.0f\n",
+                                        old_shares[i].op_type, fname,
+                                        (unsigned int)dev, (double)inode));
+                               SAFE_FREE(old_shares);
+                               set_saved_error_triple(ERRDOS, ERRbadshare,
+                                                      NT_STATUS_SHARING_VIOLATION);
+                               return -1;
+                       }
                                
-                       } else if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) {
-                               *p_all_current_opens_are_level_II = False;
+                       broken_entry = SMB_MALLOC_P(struct share_mode_entry_list);
+                       if (!broken_entry) {
+                               smb_panic("open_mode_check: malloc fail.\n");
                        }
+                       broken_entry->entry = *share_entry;
+                       DLIST_ADD(broken_entry_list, broken_entry);
+                       broke_oplock = True;
+                               
                } /* end for */
                
                if (broke_oplock) {
                        /* Update the current open table. */
                        SAFE_FREE(old_shares);
-                       num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
+                       num_share_modes = get_share_modes(dev, inode,
+                                                         &old_shares,
+                                                         &delete_on_close);
                }
 
-               /* Now we check the share modes, after any oplock breaks. */
-               for(i = 0; i < num_share_modes; i++) {
-                       share_mode_entry *share_entry = &old_shares[i];
+               if (lp_share_modes(SNUM(conn))) {
+                       /* Now we check the share modes, after any oplock breaks. */
+                       for(i = 0; i < num_share_modes; i++) {
+                               share_mode_entry *share_entry = &old_shares[i];
 
-                       /* someone else has a share lock on it, check to see if we can too */
-                       if (!check_share_mode(conn, share_entry, share_mode, desired_access,
-                                               fname, fcbopen, p_flags)) {
-                               SAFE_FREE(old_shares);
-                               free_broken_entry_list(broken_entry_list);
-                               errno = EACCES;
-                               return -1;
-                        }
+                               /* someone else has a share lock on it, check to see
+                                * if we can too */
+                               if (share_conflict(share_entry, access_mask,
+                                                  share_access)) {
+                                       SAFE_FREE(old_shares);
+                                       free_broken_entry_list(broken_entry_list);
+                                       errno = EACCES;
+                                       return -1;
+                               }
+                       }
                }
 
-               for(broken_entry = broken_entry_list; broken_entry; broken_entry = broken_entry->next) {
+               for(broken_entry = broken_entry_list; broken_entry;
+                   broken_entry = broken_entry->next) {
                        oplock_contention_count++;
                        
                        /* Paranoia check that this is no longer an exlusive entry. */
                        for(i = 0; i < num_share_modes; i++) {
                                share_mode_entry *share_entry = &old_shares[i];
                                
-                               if (share_modes_identical(&broken_entry->entry, share_entry) && 
-                                           EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) {
+                               if (!(share_modes_identical(&broken_entry->entry,
+                                                           share_entry) && 
+                                     EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type))) {
+                                       continue;
+                               }
                                        
-                                       /*
-                                        * This should not happen. The target left this oplock
-                                        * as exlusive.... The process *must* be dead.... 
-                                        */
+                               /*
+                                * This should not happen. The target left this oplock
+                                * as exlusive.... The process *must* be dead.... 
+                                */
                                        
-                                       DEBUG(0,("open_mode_check: exlusive oplock left by process %d \
-after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n",
-                                               (int)broken_entry->entry.pid, fname, (unsigned int)dev, (double)inode));
+                               DEBUG(0,("open_mode_check: exlusive oplock left by "
+                                        "process %d after break ! For file %s, "
+                                        "dev = %x, inode = %.0f. Deleting it to "
+                                        "continue...\n",
+                                        (int)broken_entry->entry.pid, fname,
+                                        (unsigned int)dev, (double)inode));
                                        
-                                       if (process_exists(broken_entry->entry.pid)) {
-                                               DEBUG(0,("open_mode_check: Existent process %lu left active oplock.\n",
-                                                        (unsigned long)broken_entry->entry.pid ));
-                                       }
+                               if (process_exists(broken_entry->entry.pid)) {
+                                       DEBUG(0,("open_mode_check: Existent process "
+                                                "%lu left active oplock.\n",
+                                                (unsigned long)broken_entry->entry.pid ));
+                               }
                                        
-                                       if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) {
-                                               free_broken_entry_list(broken_entry_list);
-                                               errno = EACCES;
-                                               set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
-                                               return -1;
-                                       }
+                               if (del_share_entry(dev, inode, &broken_entry->entry,
+                                                   NULL, &delete_on_close) == -1) {
+                                       free_broken_entry_list(broken_entry_list);
+                                       errno = EACCES;
+                                       set_saved_error_triple(ERRDOS, ERRbadshare,
+                                                              NT_STATUS_SHARING_VIOLATION);
+                                       return -1;
+                               }
                                        
-                                       /*
-                                        * We must reload the share modes after deleting the 
-                                        * other process's entry.
-                                        */
+                               /*
+                                * We must reload the share modes after deleting the 
+                                * other process's entry.
+                                */
                                        
-                                       SAFE_FREE(old_shares);
-                                       num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
-                                       break;
-                               }
+                               SAFE_FREE(old_shares);
+                               num_share_modes = get_share_modes(dev, inode,
+                                                                 &old_shares,
+                                                                 &delete_on_close);
+                               break;
                        } /* end for paranoia... */
                } /* end for broken_entry */
                free_broken_entry_list(broken_entry_list);
@@ -853,7 +775,9 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n"
  Delete the record for a handled deferred open entry.
 ****************************************************************************/
 
-static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode)
+static void delete_defered_open_entry_record(connection_struct *conn,
+                                               SMB_DEV_T dev,
+                                               SMB_INO_T inode)
 {
        uint16 mid = get_current_mid();
        pid_t mypid = sys_getpid();
@@ -868,7 +792,7 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T
        for (i = 0; i < num_de_entries; i++) {
                deferred_open_entry *entry = &de_array[i];
                if (entry->pid == mypid && entry->mid == mid && entry->dev == dev &&
-                       entry->inode == inode) {
+                               entry->inode == inode) {
 
                        /* Remove the deferred open entry from the array. */
                        delete_deferred_open_entry(entry);
@@ -883,8 +807,11 @@ static void delete_defered_open_entry_record(connection_struct *conn, SMB_DEV_T
  Handle the 1 second delay in returning a SHARING_VIOLATION error.
 ****************************************************************************/
 
-void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv,
-               char *fname, SMB_DEV_T dev, SMB_INO_T inode)
+static void defer_open_sharing_error(connection_struct *conn,
+                                    struct timeval *ptv,
+                                    const char *fname,
+                                    SMB_DEV_T dev,
+                                    SMB_INO_T inode)
 {
        uint16 mid = get_current_mid();
        pid_t mypid = sys_getpid();
@@ -906,10 +833,12 @@ void defer_open_sharing_error(connection_struct *conn, struct timeval *ptv,
                        /*
                         * Check if a 1 second timeout has expired.
                         */
-                       if (usec_time_diff(ptv, &entry->time) > SHARING_VIOLATION_USEC_WAIT) {
-                               DEBUG(10,("defer_open_sharing_error: Deleting deferred open entry for mid %u, \
-file %s\n",
-                                       (unsigned int)mid, fname ));
+                       if (usec_time_diff(ptv, &entry->time) >
+                           SHARING_VIOLATION_USEC_WAIT) {
+                               DEBUG(10,("defer_open_sharing_error: Deleting "
+                                         "deferred open entry for mid %u, "
+                                         "file %s\n",
+                                         (unsigned int)mid, fname ));
 
                                /* Expired, return a real error. */
                                /* Remove the deferred open entry from the array. */
@@ -919,24 +848,30 @@ file %s\n",
                                return;
                        }
                        /*
-                        * If the timeout hasn't expired yet and we still have a sharing violation,
-                        * just leave the entry in the deferred open array alone. We do need to
-                        * reschedule this open call though (with the original created time).
+                        * If the timeout hasn't expired yet and we still have
+                        * a sharing violation, just leave the entry in the
+                        * deferred open array alone. We do need to reschedule
+                        * this open call though (with the original created
+                        * time).
                         */
-                       DEBUG(10,("defer_open_sharing_error: time [%u.%06u] updating \
-deferred open entry for mid %u, file %s\n",
-                               (unsigned int)entry->time.tv_sec,
-                               (unsigned int)entry->time.tv_usec,
-                               (unsigned int)mid, fname ));
-
-                       push_sharing_violation_open_smb_message(&entry->time, (char *)&dib, sizeof(dib));
+                       DEBUG(10,("defer_open_sharing_error: time [%u.%06u] "
+                                 "updating deferred open entry for mid %u, file %s\n",
+                                 (unsigned int)entry->time.tv_sec,
+                                 (unsigned int)entry->time.tv_usec,
+                                 (unsigned int)mid, fname ));
+
+                       push_sharing_violation_open_smb_message(&entry->time,
+                                                               (char *)&dib,
+                                                               sizeof(dib));
                        SAFE_FREE(de_array);
                        return;
                }
        }
 
-       DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred open entry for mid %u, file %s\n",
-               (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, (unsigned int)mid, fname ));
+       DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred "
+                 "open entry for mid %u, file %s\n",
+                 (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec,
+                 (unsigned int)mid, fname ));
 
        if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) {
                SAFE_FREE(de_array);
@@ -963,80 +898,302 @@ deferred open entry for mid %u, file %s\n",
  This requires a patch to Linux.
 ****************************************************************************/
 
-static void kernel_flock(files_struct *fsp, int deny_mode)
+static void kernel_flock(files_struct *fsp, uint32 share_mode)
 {
 #if HAVE_KERNEL_SHARE_MODES
        int kernel_mode = 0;
-       if (deny_mode == DENY_READ) kernel_mode = LOCK_MAND|LOCK_WRITE;
-       else if (deny_mode == DENY_WRITE) kernel_mode = LOCK_MAND|LOCK_READ;
-       else if (deny_mode == DENY_ALL) kernel_mode = LOCK_MAND;
-       if (kernel_mode) flock(fsp->fd, kernel_mode);
+       if (share_mode == FILE_SHARE_WRITE) {
+               kernel_mode = LOCK_MAND|LOCK_WRITE;
+       } else if (share_mode == FILE_SHARE_READ) {
+               kernel_mode = LOCK_MAND|LOCK_READ;
+       } else if (share_mode == FILE_SHARE_NONE) {
+               kernel_mode = LOCK_MAND;
+       }
+       if (kernel_mode) {
+               flock(fsp->fh->fd, kernel_mode);
+       }
 #endif
-       ;;
+       ;
 }
 
+/****************************************************************************
+ On overwrite open ensure that the attributes match.
+****************************************************************************/
 
-static BOOL open_match_attributes(connection_struct *conn, const char *path, uint32 old_dos_mode, uint32 new_dos_mode,
-               mode_t existing_mode, mode_t new_mode, mode_t *returned_mode)
+static BOOL open_match_attributes(connection_struct *conn,
+                               const char *path,
+                               uint32 old_dos_attr,
+                               uint32 new_dos_attr,
+                               mode_t existing_unx_mode,
+                               mode_t new_unx_mode,
+                               mode_t *returned_unx_mode)
 {
-       uint32 noarch_old_dos_mode, noarch_new_dos_mode;
+       uint32 noarch_old_dos_attr, noarch_new_dos_attr;
 
-       noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE);
-       noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE);
+       noarch_old_dos_attr = (old_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE);
+       noarch_new_dos_attr = (new_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE);
 
-       if((noarch_old_dos_mode == 0 && noarch_new_dos_mode != 0) || 
-          (noarch_old_dos_mode != 0 && ((noarch_old_dos_mode & noarch_new_dos_mode) == noarch_old_dos_mode)))
-               *returned_mode = new_mode;
-       else
-               *returned_mode = (mode_t)0;
+       if((noarch_old_dos_attr == 0 && noarch_new_dos_attr != 0) || 
+          (noarch_old_dos_attr != 0 && ((noarch_old_dos_attr & noarch_new_dos_attr) == noarch_old_dos_attr))) {
+               *returned_unx_mode = new_unx_mode;
+       } else {
+               *returned_unx_mode = (mode_t)0;
+       }
 
-       DEBUG(10,("open_match_attributes: file %s old_dos_mode = 0x%x, existing_mode = 0%o, new_dos_mode = 0x%x returned_mode = 0%o\n",
-               path,
-               old_dos_mode, (unsigned int)existing_mode, new_dos_mode, (unsigned int)*returned_mode ));
+       DEBUG(10,("open_match_attributes: file %s old_dos_attr = 0x%x, "
+                 "existing_unx_mode = 0%o, new_dos_attr = 0x%x "
+                 "returned_unx_mode = 0%o\n",
+                 path,
+                 (unsigned int)old_dos_attr,
+                 (unsigned int)existing_unx_mode,
+                 (unsigned int)new_dos_attr,
+                 (unsigned int)*returned_unx_mode ));
 
        /* If we're mapping SYSTEM and HIDDEN ensure they match. */
        if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
-               if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM))
+               if ((old_dos_attr & FILE_ATTRIBUTE_SYSTEM) &&
+                   !(new_dos_attr & FILE_ATTRIBUTE_SYSTEM)) {
                        return False;
+               }
        }
        if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
-               if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN))
+               if ((old_dos_attr & FILE_ATTRIBUTE_HIDDEN) &&
+                   !(new_dos_attr & FILE_ATTRIBUTE_HIDDEN)) {
                        return False;
+               }
        }
        return True;
 }
 
 /****************************************************************************
- Open a file with a share mode.
+ Special FCB or DOS processing in the case of a sharing violation.
+ Try and find a duplicated file handle.
 ****************************************************************************/
 
-files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, 
-                              int share_mode,int ofun, uint32 new_dos_mode, int oplock_request, 
-                              int *Access,int *action)
+static files_struct *fcb_or_dos_open(connection_struct *conn,
+                                    const char *fname, SMB_DEV_T dev,
+                                    SMB_INO_T inode,
+                                    uint32 access_mask,
+                                    uint32 share_access,
+                                    uint32 create_options)
 {
-       return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, new_dos_mode,
-                                oplock_request, Access, action);
+       files_struct *fsp;
+       files_struct *dup_fsp;
+
+       DEBUG(5,("fcb_or_dos_open: attempting old open semantics for "
+                "file %s.\n", fname ));
+
+       for(fsp = file_find_di_first(dev, inode); fsp;
+           fsp = file_find_di_next(fsp)) {
+
+               DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, "
+                         "vuid = %u, file_pid = %u, private_options = 0x%x "
+                         "access_mask = 0x%x\n", fsp->fsp_name,
+                         fsp->fh->fd, (unsigned int)fsp->vuid,
+                         (unsigned int)fsp->file_pid,
+                         (unsigned int)fsp->fh->private_options,
+                         (unsigned int)fsp->access_mask ));
+
+               if (fsp->fh->fd != -1 &&
+                   fsp->vuid == current_user.vuid &&
+                   fsp->file_pid == global_smbpid &&
+                   (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
+                                                NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
+                   (fsp->access_mask & FILE_WRITE_DATA) &&
+                   strequal(fsp->fsp_name, fname)) {
+                       DEBUG(10,("fcb_or_dos_open: file match\n"));
+                       break;
+               }
+       }
+
+       if (!fsp) {
+               return NULL;
+       }
+
+       /* quite an insane set of semantics ... */
+       if (is_executable(fname) &&
+           (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
+               DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n"));
+               return NULL;
+       }
+
+       /* We need to duplicate this fsp. */
+       dup_fsp = dup_file_fsp(fsp, access_mask, share_access, create_options);
+       if (!dup_fsp) {
+               return NULL;
+       }
+
+       return dup_fsp;
+}
+
+/****************************************************************************
+ Open a file with a share mode - old openX method - map into NTCreate.
+****************************************************************************/
+
+BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func,
+                               uint32 *paccess_mask,
+                               uint32 *pshare_mode,
+                               uint32 *pcreate_disposition,
+                               uint32 *pcreate_options)
+{
+       uint32 access_mask;
+       uint32 share_mode;
+       uint32 create_disposition;
+       uint32 create_options = 0;
+
+       DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
+                 "open_func = 0x%x\n",
+                 fname, (unsigned int)deny_mode, (unsigned int)open_func ));
+
+       /* Create the NT compatible access_mask. */
+       switch (GET_OPENX_MODE(deny_mode)) {
+               case DOS_OPEN_RDONLY:
+                       access_mask = FILE_GENERIC_READ;
+                       break;
+               case DOS_OPEN_WRONLY:
+                       access_mask = FILE_GENERIC_WRITE;
+                       break;
+               case DOS_OPEN_EXEC: /* This used to be FILE_READ_DATA... */
+               case DOS_OPEN_RDWR:
+               case DOS_OPEN_FCB:
+                       access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
+                       break;
+               default:
+                       DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
+                                 (unsigned int)GET_OPENX_MODE(deny_mode)));
+                       return False;
+       }
+
+       /* Create the NT compatible create_disposition. */
+       switch (open_func) {
+               case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
+                       create_disposition = FILE_CREATE;
+                       break;
+
+               case OPENX_FILE_EXISTS_OPEN:
+                       create_disposition = FILE_OPEN;
+                       break;
+
+               case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
+                       create_disposition = FILE_OPEN_IF;
+                       break;
+       
+               case OPENX_FILE_EXISTS_TRUNCATE:
+                       create_disposition = FILE_OVERWRITE;
+                       break;
+
+               case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
+                       create_disposition = FILE_OVERWRITE_IF;
+                       break;
+
+               default:
+                       /* From samba4 - to be confirmed. */
+                       if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
+                               create_disposition = FILE_CREATE;
+                               break;
+                       }
+                       DEBUG(10,("map_open_params_to_ntcreate: bad "
+                                 "open_func 0x%x\n", (unsigned int)open_func));
+                       return False;
+       }
+       /* Create the NT compatible share modes. */
+       switch (GET_DENY_MODE(deny_mode)) {
+               case DENY_ALL:
+                       share_mode = FILE_SHARE_NONE;
+                       break;
+
+               case DENY_WRITE:
+                       share_mode = FILE_SHARE_READ;
+                       break;
+
+               case DENY_READ:
+                       share_mode = FILE_SHARE_WRITE;
+                       break;
+
+               case DENY_NONE:
+                       share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+                       break;
+
+               case DENY_DOS:
+                       create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
+                       if (is_executable(fname)) {
+                               share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+                       } else {
+                               if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
+                                       share_mode = FILE_SHARE_READ;
+                               } else {
+                                       share_mode = FILE_SHARE_NONE;
+                               }
+                       }
+                       break;
+
+               case DENY_FCB:
+                       create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
+                       share_mode = FILE_SHARE_NONE;
+                       break;
+
+               default:
+                       DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
+                               (unsigned int)GET_DENY_MODE(deny_mode) ));
+                       return False;
+       }
+
+       DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
+                 "share_mode = 0x%x, create_disposition = 0x%x, "
+                 "create_options = 0x%x\n",
+                 fname,
+                 (unsigned int)access_mask,
+                 (unsigned int)share_mode,
+                 (unsigned int)create_disposition,
+                 (unsigned int)create_options ));
+
+       if (paccess_mask) {
+               *paccess_mask = access_mask;
+       }
+       if (pshare_mode) {
+               *pshare_mode = share_mode;
+       }
+       if (pcreate_disposition) {
+               *pcreate_disposition = create_disposition;
+       }
+       if (pcreate_options) {
+               *pcreate_options = create_options;
+       }
+
+       return True;
+
 }
 
+/* Map generic permissions to file object specific permissions */
+                                                                                                               
+struct generic_mapping file_generic_mapping = {
+       FILE_GENERIC_READ,
+       FILE_GENERIC_WRITE,
+       FILE_GENERIC_EXECUTE,
+       FILE_GENERIC_ALL
+};
+
 /****************************************************************************
  Open a file with a share mode.
 ****************************************************************************/
 
-files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf, 
-                               uint32 desired_access, 
-                               int share_mode,int ofun, uint32 new_dos_mode,
-                               int oplock_request, 
-                               int *Access,int *paction)
+files_struct *open_file_ntcreate(connection_struct *conn,
+                                const char *fname,
+                                SMB_STRUCT_STAT *psbuf,
+                                uint32 access_mask,            /* access bits (FILE_READ_DATA etc.) */
+                                uint32 share_access,           /* share constants (FILE_SHARE_READ etc). */
+                                uint32 create_disposition,     /* FILE_OPEN_IF etc. */
+                                uint32 create_options,         /* options such as delete on close. */
+                                uint32 new_dos_attributes,     /* attributes used for new file. */
+                                int oplock_request,            /* internal Samba oplock codes. */
+                                                               /* Information (FILE_EXISTS etc.) */
+                                int *pinfo)
 {
        int flags=0;
        int flags2=0;
-       int deny_mode = GET_DENY_MODE(share_mode);
-       BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode);
-       BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode);
        BOOL file_existed = VALID_STAT(*psbuf);
-       BOOL fcbopen = False;
        BOOL def_acl = False;
-       BOOL add_share_mode = True;
        BOOL internal_only_open = False;
        SMB_DEV_T dev = 0;
        SMB_INO_T inode = 0;
@@ -1044,15 +1201,40 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
        BOOL all_current_opens_are_level_II = False;
        BOOL fsp_open = False;
        files_struct *fsp = NULL;
-       int open_mode=0;
-       uint16 port = 0;
-       mode_t new_mode = (mode_t)0;
-       int action;
-       uint32 existing_dos_mode = 0;
+       mode_t new_unx_mode = (mode_t)0;
+       mode_t unx_mode = (mode_t)0;
+       int info;
+       uint32 existing_dos_attributes = 0;
        struct pending_message_list *pml = NULL;
+       uint16 port = 0;
        uint16 mid = get_current_mid();
-       /* We add aARCH to this as this mode is only used if the file is created new. */
-       mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname, True);
+
+       if (conn->printer) {
+               /* 
+                * Printers are handled completely differently.
+                * Most of the passed parameters are ignored.
+                */
+
+               if (pinfo) {
+                       *pinfo = FILE_WAS_CREATED;
+               }
+
+               DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname));
+
+               return print_fsp_open(conn, fname);
+       }
+
+       /* We add aARCH to this as this mode is only used if the file is
+        * created new. */
+       unx_mode = unix_mode(conn, new_dos_attributes | aARCH,fname, True);
+
+       DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x "
+                  "access_mask=0x%x share_access=0x%x "
+                  "create_disposition = 0x%x create_options=0x%x "
+                  "unix mode=0%o oplock_request=%d\n",
+                  fname, new_dos_attributes, access_mask, share_access,
+                  create_disposition, create_options, unx_mode,
+                  oplock_request));
 
        if (oplock_request == INTERNAL_OPEN_ONLY) {
                internal_only_open = True;
@@ -1065,52 +1247,42 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
                memcpy(&dib, pml->private_data.data, sizeof(dib));
 
                /* There could be a race condition where the dev/inode pair
-                       has changed since we deferred the message. If so, just
-                       remove the deferred open entry and return sharing violation. */
-
-               /* If the timeout value is non-zero, we need to just
-                       return sharing violation. Don't retry the open
-                       as we were not notified of a close and we don't want to
-                       trigger another spurious oplock break. */
-
-               if (!file_existed || dib.dev != psbuf->st_dev || dib.inode != psbuf->st_ino ||
-                               pml->msg_time.tv_sec || pml->msg_time.tv_usec) {
+                  has changed since we deferred the message. If so, just
+                  remove the deferred open entry and return sharing
+                  violation. */
+
+               /* If the timeout value is non-zero, we need to just return
+                  sharing violation. Don't retry the open as we were not
+                  notified of a close and we don't want to trigger another
+                  spurious oplock break. */
+
+               if (!file_existed || dib.dev != psbuf->st_dev ||
+                   dib.inode != psbuf->st_ino || pml->msg_time.tv_sec ||
+                   pml->msg_time.tv_usec) {
                        /* Ensure we don't reprocess this message. */
                        remove_sharing_violation_open_smb_message(mid);
 
                        /* Now remove the deferred open entry under lock. */
                        lock_share_entry(conn, dib.dev, dib.inode);
-                       delete_defered_open_entry_record(conn, dib.dev, dib.inode);
+                       delete_defered_open_entry_record(conn, dib.dev,
+                                                        dib.inode);
                        unlock_share_entry(conn, dib.dev, dib.inode);
 
-                       set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
+                       set_saved_error_triple(ERRDOS, ERRbadshare,
+                                              NT_STATUS_SHARING_VIOLATION);
                        return NULL;
                }
                /* Ensure we don't reprocess this message. */
                remove_sharing_violation_open_smb_message(mid);
-
-       }
-
-       if (conn->printer) {
-               /* printers are handled completely differently. Most of the passed parameters are
-                       ignored */
-               if (Access)
-                       *Access = DOS_OPEN_WRONLY;
-               if (paction)
-                       *paction = FILE_WAS_CREATED;
-               return print_fsp_open(conn, fname);
        }
 
-       DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
-               fname, new_dos_mode, share_mode, ofun, (int)mode,  oplock_request ));
-
        if (!check_name(fname,conn)) {
                return NULL;
        } 
 
-       new_dos_mode &= SAMBA_ATTRIBUTES_MASK;
+       new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
        if (file_existed) {
-               existing_dos_mode = dos_mode(conn, fname, psbuf);
+               existing_dos_attributes = dos_mode(conn, fname, psbuf);
        }
 
        /* ignore any oplock requests if oplocks are disabled */
@@ -1119,114 +1291,173 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
        }
 
        /* this is for OS/2 long file names - say we don't support them */
-       if (strstr(fname,".+,;=[].")) {
-               /* OS/2 Workplace shell fix may be main code stream in a later release. */ 
-               set_saved_error_triple(ERRDOS, ERRcannotopen, NT_STATUS_OBJECT_NAME_NOT_FOUND);
-               DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n"));
+       if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) {
+               /* OS/2 Workplace shell fix may be main code stream in a later
+                * release. */ 
+               set_saved_error_triple(ERRDOS, ERRcannotopen,
+                                      NT_STATUS_OBJECT_NAME_NOT_FOUND);
+               DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not "
+                        "supported.\n"));
                return NULL;
        }
 
-       if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed)  {
-               DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n",
-                       fname ));
-               if (S_ISDIR(psbuf->st_mode)) {
-                       errno = EISDIR;
-               } else {
-                       errno = EEXIST;
-               }
-               return NULL;
-       }
-      
-       if (CAN_WRITE(conn) && (GET_FILE_CREATE_DISPOSITION(ofun) == FILE_CREATE_IF_NOT_EXIST))
-               flags2 |= O_CREAT;
+       switch( create_disposition ) {
+               /*
+                * Currently we're using FILE_SUPERSEDE as the same as
+                * FILE_OVERWRITE_IF but they really are
+                * different. FILE_SUPERSEDE deletes an existing file
+                * (requiring delete access) then recreates it.
+                */
+               case FILE_SUPERSEDE:
+                       /* If file exists replace/overwrite. If file doesn't
+                        * exist create. */
+                       flags2 |= (O_CREAT | O_TRUNC);
+                       break;
 
-       if (CAN_WRITE(conn) && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE))
-               flags2 |= O_TRUNC;
+               case FILE_OVERWRITE_IF:
+                       /* If file exists replace/overwrite. If file doesn't
+                        * exist create. */
+                       flags2 |= (O_CREAT | O_TRUNC);
+                       break;
 
-       /* We only care about matching attributes on file exists and truncate. */
-       if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) {
-               if (!open_match_attributes(conn, fname, existing_dos_mode, new_dos_mode,
-                                       psbuf->st_mode, mode, &new_mode)) {
-                       DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n",
-                                               fname, existing_dos_mode, new_dos_mode,
-                                               (int)psbuf->st_mode, (int)mode ));
+               case FILE_OPEN:
+                       /* If file exists open. If file doesn't exist error. */
+                       if (!file_existed) {
+                               DEBUG(5,("open_file_ntcreate: FILE_OPEN "
+                                        "requested for file %s and file "
+                                        "doesn't exist.\n", fname ));
+                               set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+                               errno = ENOENT;
+                               return NULL;
+                       }
+                       break;
+
+               case FILE_OVERWRITE:
+                       /* If file exists overwrite. If file doesn't exist
+                        * error. */
+                       if (!file_existed) {
+                               DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE "
+                                        "requested for file %s and file "
+                                        "doesn't exist.\n", fname ));
+                               set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+                               errno = ENOENT;
+                               return NULL;
+                       }
+                       flags2 |= O_TRUNC;
+                       break;
+
+               case FILE_CREATE:
+                       /* If file exists error. If file doesn't exist
+                        * create. */
+                       if (file_existed) {
+                               DEBUG(5,("open_file_ntcreate: FILE_CREATE "
+                                        "requested for file %s and file "
+                                        "already exists.\n", fname ));
+                               if (S_ISDIR(psbuf->st_mode)) {
+                                       errno = EISDIR;
+                               } else {
+                                       errno = EEXIST;
+                               }
+                               return NULL;
+                       }
+                       flags2 |= (O_CREAT|O_EXCL);
+                       break;
+
+               case FILE_OPEN_IF:
+                       /* If file exists open. If file doesn't exist
+                        * create. */
+                       flags2 |= O_CREAT;
+                       break;
+
+               default:
+                       set_saved_error_triple(ERRDOS, ERRinvalidparam,
+                                              NT_STATUS_INVALID_PARAMETER);
+                       return NULL;
+       }
+
+       /* We only care about matching attributes on file exists and
+        * overwrite. */
+
+       if (file_existed && ((create_disposition == FILE_OVERWRITE) ||
+                            (create_disposition == FILE_OVERWRITE_IF))) {
+               if (!open_match_attributes(conn, fname,
+                                          existing_dos_attributes,
+                                          new_dos_attributes, psbuf->st_mode,
+                                          unx_mode, &new_unx_mode)) {
+                       DEBUG(5,("open_file_ntcreate: attributes missmatch "
+                                "for file %s (%x %x) (0%o, 0%o)\n",
+                                fname, existing_dos_attributes,
+                                new_dos_attributes,
+                                (unsigned int)psbuf->st_mode,
+                                (unsigned int)unx_mode ));
                        errno = EACCES;
                        return NULL;
                }
        }
 
-       if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL)
-               flags2 |= O_EXCL;
+       /* This is a nasty hack - must fix... JRA. */
+       if (access_mask == MAXIMUM_ALLOWED_ACCESS) {
+               access_mask = FILE_GENERIC_ALL;
+       }
 
-       /* note that we ignore the append flag as 
-               append does not mean the same thing under dos and unix */
+       /*
+        * Convert GENERIC bits to specific bits.
+        */
 
-       switch (GET_OPEN_MODE(share_mode)) {
-               case DOS_OPEN_EXEC:
-               case DOS_OPEN_RDONLY:
-                       flags = O_RDONLY;
-                       if (desired_access == 0)
-                               desired_access = FILE_READ_DATA;
-                       break;
-               case DOS_OPEN_WRONLY: 
-                       flags = O_WRONLY; 
-                       if (desired_access == 0)
-                               desired_access = FILE_WRITE_DATA;
-                       break;
-               case DOS_OPEN_FCB: 
-                       fcbopen = True;
-                       flags = O_RDWR; 
-                       if (desired_access == 0)
-                               desired_access = FILE_READ_DATA|FILE_WRITE_DATA;
-                       break;
-               case DOS_OPEN_RDWR: 
-                       flags = O_RDWR; 
-                       if (desired_access == 0)
-                               desired_access = FILE_READ_DATA|FILE_WRITE_DATA;
-                       break;
-               default:
-                       /* Force DOS error. */
-                       set_saved_error_triple(ERRDOS, ERRinvalidparam, NT_STATUS_INVALID);
-                       return NULL;
+       se_map_generic(&access_mask, &file_generic_mapping);
+
+       DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping "
+                  "access_mask=0x%x\n", fname, access_mask ));
+
+       /*
+        * Note that we ignore the append flag as append does not
+        * mean the same thing under DOS and Unix.
+        */
+
+       if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) {
+               flags = O_RDWR;
+       } else {
+               flags = O_RDONLY;
        }
 
+       /*
+        * Currently we only look at FILE_WRITE_THROUGH for create options.
+        */
+
 #if defined(O_SYNC)
-       if (GET_FILE_SYNC_OPENMODE(share_mode)) {
+       if (create_options & FILE_WRITE_THROUGH) {
                flags2 |= O_SYNC;
        }
 #endif /* O_SYNC */
   
-       if (flags != O_RDONLY && file_existed && 
-                       (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_mode))) {
-               if (!fcbopen) {
-                       DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n",
-                               fname, !CAN_WRITE(conn) ? "share" : "file" ));
-                       errno = EACCES;
-                       return NULL;
-               }
-               flags = O_RDONLY;
+       if (!CAN_WRITE(conn)) {
+               /*
+                * We should really return a permission denied error if either
+                * O_CREAT or O_TRUNC are set, but for compatibility with
+                * older versions of Samba we just AND them out.
+                */
+               flags2 &= ~(O_CREAT|O_TRUNC);
        }
 
-       if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
-               DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
-               errno = EINVAL;
-               return NULL;
-       }
+       /*
+        * Ensure we can't write on a read-only share or file.
+        */
 
-       if (desired_access && ((desired_access & ~(SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES))==0) &&
-               ((desired_access & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES)) != 0)) {
-               /* Stat open that doesn't trigger oplock breaks or share mode checks... ! JRA. */
-               deny_mode = DENY_NONE;
-               if (file_existed) {
-                       oplock_request = 0;
-                       add_share_mode = False;
-                       flags2 &= ~O_CREAT;
-               }
+       if (flags != O_RDONLY && file_existed &&
+           (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_attributes))) {
+               DEBUG(5,("open_file_ntcreate: write access requested for "
+                        "file %s on read only %s\n",
+                        fname, !CAN_WRITE(conn) ? "share" : "file" ));
+               set_saved_error_triple(ERRDOS, ERRnoaccess,
+                                      NT_STATUS_ACCESS_DENIED);
+               errno = EACCES;
+               return NULL;
        }
 
        fsp = file_new(conn);
-       if(!fsp)
+       if(!fsp) {
                return NULL;
+       }
 
        if (file_existed) {
 
@@ -1235,47 +1466,86 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
 
                lock_share_entry(conn, dev, inode);
 
-               num_share_modes = open_mode_check(conn, fname, dev, inode, 
-                                                 desired_access,
-                                                 share_mode,
-                                                 &flags, &oplock_request, &all_current_opens_are_level_II);
+               num_share_modes = open_mode_check(conn, fname, dev, inode,
+                                                 access_mask, share_access,
+                                                 create_options,
+                                                 &flags, &oplock_request,
+                                                 &all_current_opens_are_level_II);
                if(num_share_modes == -1) {
 
+                       if (!internal_only_open) {
+                               NTSTATUS status;
+                               get_saved_error_triple(NULL, NULL, &status);
+                               if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) {
+                                       /* Check if this can be done with the
+                                        * deny_dos and fcb calls. */
+                                       if (create_options &
+                                           (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
+                                            NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
+                                               files_struct *fsp_dup;
+                                               fsp_dup = fcb_or_dos_open(conn, fname, dev,
+                                                                         inode, access_mask,
+                                                                         share_access,
+                                                                         create_options);
+
+                                               if (fsp_dup) {
+                                                       unlock_share_entry(conn, dev, inode);
+                                                       file_free(fsp);
+                                                       if (pinfo) {
+                                                               *pinfo = FILE_WAS_OPENED;
+                                                       }
+                                                       conn->num_files_open++;
+                                                       return fsp_dup;
+                                               }
+                                       }
+                               }
+                       }
+
                        /*
-                        * This next line is a subtlety we need for MS-Access. If a file open will
-                        * fail due to share permissions and also for security (access)
-                        * reasons, we need to return the access failed error, not the
-                        * share error. This means we must attempt to open the file anyway
-                        * in order to get the UNIX access error - even if we're going to
-                        * fail the open for share reasons. This is bad, as we're burning
-                        * another fd if there are existing locks but there's nothing else
-                        * we can do. We also ensure we're not going to create or tuncate
-                        * the file as we only want an access decision at this stage. JRA.
+                        * This next line is a subtlety we need for
+                        * MS-Access. If a file open will fail due to share
+                        * permissions and also for security (access) reasons,
+                        * we need to return the access failed error, not the
+                        * share error. This means we must attempt to open the
+                        * file anyway in order to get the UNIX access error -
+                        * even if we're going to fail the open for share
+                        * reasons. This is bad, as we're burning another fd
+                        * if there are existing locks but there's nothing
+                        * else we can do. We also ensure we're not going to
+                        * create or tuncate the file as we only want an
+                        * access decision at this stage. JRA.
                         */
                        errno = 0;
                        fsp_open = open_file(fsp,conn,fname,psbuf,
-                                               flags|(flags2&~(O_TRUNC|O_CREAT)),mode,desired_access);
+                                            flags|(flags2&~(O_TRUNC|O_CREAT)),
+                                            unx_mode,access_mask);
 
-                       DEBUG(4,("open_file_shared : share_mode deny - calling open_file with \
-flags=0x%X flags2=0x%X mode=0%o returned %d\n",
-                               flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open ));
+                       DEBUG(4,("open_file_ntcreate : share_mode deny - "
+                                "calling open_file with flags=0x%X "
+                                "flags2=0x%X mode=0%o returned %d\n",
+                                flags, (flags2&~(O_TRUNC|O_CREAT)),
+                                (unsigned int)unx_mode, (int)fsp_open ));
 
                        if (!fsp_open && errno) {
                                /* Default error. */
-                               set_saved_error_triple(ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED);
+                               set_saved_error_triple(ERRDOS, ERRnoaccess,
+                                                      NT_STATUS_ACCESS_DENIED);
                        }
 
                        /* 
-                        * If we're returning a share violation, ensure we cope with
-                        * the braindead 1 second delay.
+                        * If we're returning a share violation, ensure we
+                        * cope with the braindead 1 second delay.
                         */
 
                        if (!internal_only_open) {
                                NTSTATUS status;
                                get_saved_error_triple(NULL, NULL, &status);
                                if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) {
-                                       /* The fsp->open_time here represents the current time of day. */
-                                       defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode);
+                                       /* The fsp->open_time here represents
+                                        * the current time of day. */
+                                       defer_open_sharing_error(conn,
+                                                                &fsp->open_time,
+                                                                fname, dev, inode);
                                }
                        }
 
@@ -1286,7 +1556,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                                 * We have detected a sharing violation here
                                 * so return the correct error code
                                 */
-                               set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
+                               set_saved_error_triple(ERRDOS, ERRbadshare,
+                                                      NT_STATUS_SHARING_VIOLATION);
                        }
                        file_free(fsp);
                        return NULL;
@@ -1302,35 +1573,39 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
         */
 
         if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) &&
-                       (def_acl = directory_has_default_acl(conn, parent_dirname(fname))))
-                mode = 0777;
+                       (def_acl = directory_has_default_acl(conn, parent_dirname(fname)))) {
+               unx_mode = 0777;
+       }
 
        DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
-                       flags,flags2,(int)mode));
+                       (unsigned int)flags,(unsigned int)flags2,(unsigned int)unx_mode));
 
        /*
         * open_file strips any O_TRUNC flags itself.
         */
 
-       fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,mode,desired_access);
+       fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,access_mask);
 
-       if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT) && fcbopen) {
-               if((fsp_open = open_file(fsp,conn,fname,psbuf,O_RDONLY,mode,desired_access)) == True)
+       if (!fsp_open && (flags == O_RDWR) && (errno != ENOENT)) {
+               if((fsp_open = open_file(fsp,conn,fname,psbuf,
+                                        O_RDONLY,unx_mode,access_mask)) == True) {
                        flags = O_RDONLY;
+               }
        }
 
        if (!fsp_open) {
-               if(file_existed)
+               if(file_existed) {
                        unlock_share_entry(conn, dev, inode);
+               }
                file_free(fsp);
                return NULL;
        }
 
        /*
-        * Deal with the race condition where two smbd's detect the file doesn't
-        * exist and do the create at the same time. One of them will win and
-        * set a share mode, the other (ie. this one) should check if the
-        * requested share mode for this create is allowed.
+        * Deal with the race condition where two smbd's detect the file
+        * doesn't exist and do the create at the same time. One of them will
+        * win and set a share mode, the other (ie. this one) should check if
+        * the requested share mode for this create is allowed.
         */
 
        if (!file_existed) { 
@@ -1347,22 +1622,47 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
 
                lock_share_entry_fsp(fsp);
 
-               num_share_modes = open_mode_check(conn, fname, dev, inode, 
-                                                 desired_access,
-                                                 share_mode,
-                                                 &flags, &oplock_request, &all_current_opens_are_level_II);
+               num_share_modes = open_mode_check(conn, fname, dev, inode,
+                                                 access_mask, share_access,
+                                                 create_options,
+                                                 &flags, &oplock_request,
+                                                 &all_current_opens_are_level_II);
 
                if(num_share_modes == -1) {
-                       /* 
-                        * If we're returning a share violation, ensure we cope with
-                        * the braindead 1 second delay.
-                        */
-
                        NTSTATUS status;
                        get_saved_error_triple(NULL, NULL, &status);
                        if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) {
-                               /* The fsp->open_time here represents the current time of day. */
-                               defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode);
+                               /* Check if this can be done with the deny_dos
+                                * and fcb calls. */
+                               if (create_options &
+                                   (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
+                                    NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
+                                       files_struct *fsp_dup;
+                                       fsp_dup = fcb_or_dos_open(conn, fname, dev, inode,
+                                                                 access_mask, share_access,
+                                                                 create_options);
+                                       if (fsp_dup) {
+                                               unlock_share_entry(conn, dev, inode);
+                                               fd_close(conn, fsp);
+                                               file_free(fsp);
+                                               if (pinfo) {
+                                                       *pinfo = FILE_WAS_OPENED;
+                                               }
+                                               conn->num_files_open++;
+                                               return fsp_dup;
+                                       }
+                               }
+
+                               /* 
+                                * If we're returning a share violation,
+                                * ensure we cope with the braindead 1 second
+                                * delay.
+                                */
+
+                               /* The fsp->open_time here represents the
+                                * current time of day. */
+                               defer_open_sharing_error(conn, &fsp->open_time,
+                                                        fname, dev, inode);
                        }
 
                        unlock_share_entry_fsp(fsp);
@@ -1372,7 +1672,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                         * We have detected a sharing violation here, so
                         * return the correct code.
                         */
-                       set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION);
+                       set_saved_error_triple(ERRDOS, ERRbadshare,
+                                              NT_STATUS_SHARING_VIOLATION);
                        return NULL;
                }
 
@@ -1381,8 +1682,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                 * exist. Ensure we return the correct value for action.
                 */
 
-               if (num_share_modes > 0)
+               if (num_share_modes > 0) {
                        file_existed = True;
+               }
 
                /*
                 * We exit this block with the share entry *locked*.....
@@ -1395,7 +1697,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
            mode and we have already checked our more authoritative
            locking database for permission to set this deny mode. If
            the kernel refuses the operations then the kernel is wrong */
-       kernel_flock(fsp, deny_mode);
+
+       kernel_flock(fsp, share_access);
 
        /*
         * At this point onwards, we can guarentee that the share entry
@@ -1409,9 +1712,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
 
        if (flags2&O_TRUNC) {
                /*
-                * We are modifing the file after open - update the stat struct..
+                * We are modifing the file after open - update the stat
+                * struct..
                 */
-               if ((SMB_VFS_FTRUNCATE(fsp,fsp->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) {
+               if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) ||
+                   (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) {
                        unlock_share_entry_fsp(fsp);
                        fd_close(conn,fsp);
                        file_free(fsp);
@@ -1419,44 +1724,28 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                }
        }
 
-       switch (flags) {
-               case O_RDONLY:
-                       open_mode = DOS_OPEN_RDONLY;
-                       break;
-               case O_RDWR:
-                       open_mode = DOS_OPEN_RDWR;
-                       break;
-               case O_WRONLY:
-                       open_mode = DOS_OPEN_WRONLY;
-                       break;
-       }
+       /* Record the options we were opened with. */
+       fsp->share_access = share_access;
+       fsp->fh->private_options = create_options;
+       fsp->access_mask = access_mask;
 
-       fsp->share_mode = SET_DENY_MODE(deny_mode) | 
-                                               SET_OPEN_MODE(open_mode) | 
-                                               SET_ALLOW_SHARE_DELETE(allow_share_delete);
-
-       DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode ));
-
-       if (Access) {
-               (*Access) = (SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode));
-       }
-
-       action = 0;
-
-       if (file_existed && !(flags2 & O_TRUNC))
-               action = FILE_WAS_OPENED;
-       if (file_existed && (flags2 & O_TRUNC))
-               action = FILE_WAS_OVERWRITTEN;
-       if (!file_existed) {
-               action = FILE_WAS_CREATED;
+       if (file_existed) {
+               if (!(flags2 & O_TRUNC)) {
+                       info = FILE_WAS_OPENED;
+               } else {
+                       info = FILE_WAS_OVERWRITTEN;
+               }
+       } else {
+               info = FILE_WAS_CREATED;
                /* Change the owner if required. */
                if (lp_inherit_owner(SNUM(conn))) {
-                       change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf);
+                       change_owner_to_parent(conn, fsp, fsp->fsp_name,
+                                              psbuf);
                }
        }
 
-       if (paction) {
-               *paction = action;
+       if (pinfo) {
+               *pinfo = info;
        }
 
        /* 
@@ -1465,7 +1754,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
         */
 
        if(oplock_request && (num_share_modes == 0) && 
-                       !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp, oplock_request) ) {
+          !IS_VETO_OPLOCK_PATH(conn,fname) &&
+          set_file_oplock(fsp, oplock_request) ) {
                port = global_oplock_port;
        } else if (oplock_request && all_current_opens_are_level_II) {
                port = global_oplock_port;
@@ -1476,26 +1766,25 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                oplock_request = 0;
        }
 
-       if (add_share_mode) {
-               set_share_mode(fsp, port, oplock_request);
-       }
+       set_share_mode(fsp, port, oplock_request);
 
-       if (delete_on_close) {
-               uint32 dosmode = existing_dos_mode;
+       if (create_options & FILE_DELETE_ON_CLOSE) {
+               uint32 dosattr= existing_dos_attributes;
                NTSTATUS result;
 
-               if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) {
-                       dosmode = new_dos_mode;
+               if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
+                               info == FILE_WAS_SUPERSEDED) {
+                       dosattr = new_dos_attributes;
                }
-               result = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
 
-               if (NT_STATUS_V(result) !=  NT_STATUS_V(NT_STATUS_OK)) {
+               result = can_set_delete_on_close(fsp, True, dosattr);
+
+               if (!NT_STATUS_IS_OK(result)) {
                        uint8 u_e_c;
                        uint32 u_e_code;
+                       BOOL dummy_del_on_close;
                        /* Remember to delete the mode we just added. */
-                       if (add_share_mode) {
-                               del_share_mode(fsp, NULL);
-                       }
+                       del_share_mode(fsp, NULL, &dummy_del_on_close);
                        unlock_share_entry_fsp(fsp);
                        fd_close(conn,fsp);
                        file_free(fsp);
@@ -1503,12 +1792,17 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                        set_saved_error_triple(u_e_c, u_e_code, result);
                        return NULL;
                }
+               set_delete_on_close(fsp, True);
        }
        
-       if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) {
+       if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
+                               info == FILE_WAS_SUPERSEDED) {
                /* Files should be initially set as archive */
-               if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
-                &n