summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/include/doserr.h3
-rw-r--r--source/include/ntlmssp.h1
-rw-r--r--source/include/smb.h140
-rw-r--r--source/include/smb_macros.h11
-rw-r--r--source/include/vfs.h3
-rw-r--r--source/lib/util.c22
-rw-r--r--source/libsmb/clifile.c2
-rw-r--r--source/libsmb/errormap.c4
-rw-r--r--source/locking/locking.c120
-rw-r--r--source/locking/posix.c38
-rw-r--r--source/modules/vfs_afsacl.c4
-rw-r--r--source/printing/nt_printing.c79
-rw-r--r--source/printing/printfsp.c23
-rw-r--r--source/rpc_server/srv_srvsvc_nt.c35
-rw-r--r--source/smbd/close.c46
-rw-r--r--source/smbd/dir.c60
-rw-r--r--source/smbd/dosmode.c2
-rw-r--r--source/smbd/fake_file.c174
-rw-r--r--source/smbd/fileio.c42
-rw-r--r--source/smbd/files.c82
-rw-r--r--source/smbd/ntquotas.c1
-rw-r--r--source/smbd/nttrans.c754
-rw-r--r--source/smbd/open.c1906
-rw-r--r--source/smbd/oplock.c67
-rw-r--r--source/smbd/oplock_linux.c8
-rw-r--r--source/smbd/pipes.c89
-rw-r--r--source/smbd/posix_acls.c40
-rw-r--r--source/smbd/reply.c398
-rw-r--r--source/smbd/trans2.c257
-rw-r--r--source/smbd/vfs-wrap.c6
-rw-r--r--source/smbd/vfs.c20
-rw-r--r--source/torture/cmd_vfs.c2
-rw-r--r--source/utils/status.c72
-rw-r--r--source/web/cgi.c4
-rw-r--r--source/web/statuspage.c15
35 files changed, 2566 insertions, 1964 deletions
diff --git a/source/include/doserr.h b/source/include/doserr.h
index 77255ee4c11..647f11527b7 100644
--- a/source/include/doserr.h
+++ b/source/include/doserr.h
@@ -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 */
diff --git a/source/include/ntlmssp.h b/source/include/ntlmssp.h
index 8ab6265673c..267779c434d 100644
--- a/source/include/ntlmssp.h
+++ b/source/include/ntlmssp.h
@@ -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);
diff --git a/source/include/smb.h b/source/include/smb.h
index 50bd233da76..55baf845315 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -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.
*/
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index b7e27d22667..7a0afdfc192 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -101,15 +101,16 @@
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) )
diff --git a/source/include/vfs.h b/source/include/vfs.h
index 71b4f656279..7f6c94f6e99 100644
--- a/source/include/vfs.h
+++ b/source/include/vfs.h
@@ -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 */
diff --git a/source/lib/util.c b/source/lib/util.c
index 42cbc7288f9..de366c604ff 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -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;
+}
diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c
index 2fb5b456cc4..87c6f2568b1 100644
--- a/source/libsmb/clifile.c
+++ b/source/libsmb/clifile.c
@@ -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);
}
/****************************************************************************
diff --git a/source/libsmb/errormap.c b/source/libsmb/errormap.c
index c79561bda87..8462fbee877 100644
--- a/source/libsmb/errormap.c
+++ b/source/libsmb/errormap.c
@@ -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},
diff --git a/source/locking/locking.c b/source/locking/locking.c
index 3c5ab63b4ab..5bcf7f2eda8 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -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;
diff --git a/source/locking/posix.c b/source/locking/posix.c
index 218c4410280..c63992adc59 100644
--- a/source/locking/posix.c
+++ b/source/locking/posix.c
@@ -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);
diff --git a/source/modules/vfs_afsacl.c b/source/modules/vfs_afsacl.c
index 3b54428f14c..731ddfa5836 100644
--- a/source/modules/vfs_afsacl.c
+++ b/source/modules/vfs_afsacl.c
@@ -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;
}
}
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index b3a2ca5893b..25083002c31 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -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;
diff --git a/source/printing/printfsp.c b/source/printing/printfsp.c
index 863de9624e7..eb81dc4536f 100644
--- a/source/printing/printfsp.c
+++ b/source/printing/printfsp.c
@@ -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) {
diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c
index f8124031ce0..c3fd53a3844 100644
--- a/source/rpc_server/srv_srvsvc_nt.c
+++ b/source/rpc_server/srv_srvsvc_nt.c
@@ -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;
}
diff --git a/source/smbd/close.c b/source/smbd/close.c
index b7649bcce4f..3fc7fdb0599 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -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;
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index fd0a3035044..949e31210f6 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -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);
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index 3602e3f9081..a2bc424b8e7 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -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);
}
diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c
index 59ddb60db5e..799725a7820 100644
--- a/source/smbd/fake_file.c
+++ b/source/smbd/fake_file.c
@@ -22,77 +22,6 @@
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;
diff --git a/source/smbd/fileio.c b/source/smbd/fileio.c
index ba0766c2986..76189d114bb 100644
--- a/source/smbd/fileio.c
+++ b/source/smbd/fileio.c
@@ -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);
}
}
diff --git a/source/smbd/files.c b/source/smbd/files.c
index e893e9fefc1..80e5b0f710f 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -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;
+}
diff --git a/source/smbd/ntquotas.c b/source/smbd/ntquotas.c
index 8fbf858008b..9bc444d2536 100644
--- a/source/smbd/ntquotas.c
+++ b/source/smbd/ntquotas.c
@@ -259,4 +259,3 @@ void destroy_quota_handle(void **pqt_handle)
return;
}
-
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index cc37d531f24..f9b70de0ace 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -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,8 +307,9 @@ 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;
@@ -315,192 +317,6 @@ static void restore_case_semantics(connection_struct *conn, uint32 file_attribut
}
/****************************************************************************
- 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.
@@ -583,6 +403,66 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
}
/****************************************************************************
+ 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) {
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 9da53a5057a..810913c025d 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -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))) {
- file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL, True);
+ if (lp_map_archive(SNUM(conn)) ||
+ lp_store_dos_attributes(SNUM(conn))) {
+ file_set_dosmode(conn, fname,
+ new_dos_attributes | aARCH, NULL,
+ True);
}
}
@@ -1519,36 +1813,45 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
if (!file_existed && !def_acl) {
- int saved_errno = errno; /* We might get ENOSYS in the next call.. */
+ int saved_errno = errno; /* We might get ENOSYS in the next
+ * call.. */
- if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS)
+ if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1
+ && errno == ENOSYS) {
errno = saved_errno; /* Ignore ENOSYS */
+ }
- } else if (new_mode) {
+ } else if (new_unx_mode) {
int ret = -1;
/* Attributes need changing. File already existed. */
{
- int saved_errno = errno; /* We might get ENOSYS in the next call.. */
- ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode);
+ int saved_errno = errno; /* We might get ENOSYS in the
+ * next call.. */
+ ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd,
+ new_unx_mode);
if (ret == -1 && errno == ENOSYS) {
errno = saved_errno; /* Ignore ENOSYS */
} else {
- DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n",
- fname, (int)new_mode));
+ DEBUG(5, ("open_file_shared: failed to reset "
+ "attributes of file %s to 0%o\n",
+ fname, (unsigned int)new_unx_mode));
ret = 0; /* Don't do the fchmod below. */
}
}
- if ((ret == -1) && (SMB_VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1))
- DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n",
- fname, (int)new_mode));
+ if ((ret == -1) &&
+ (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1))
+ DEBUG(5, ("open_file_shared: failed to reset "
+ "attributes of file %s to 0%o\n",
+ fname, (unsigned int)new_unx_mode));
}
- /* If this is a successful open, we must remove any deferred open records. */
+ /* If this is a successful open, we must remove any deferred open
+ * records. */
delete_defered_open_entry_record(conn, fsp->dev, fsp->inode);
unlock_share_entry_fsp(fsp);
@@ -1561,17 +1864,20 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
Open a file for for write to ensure that we can fchmod it.
****************************************************************************/
-files_struct *open_file_fchmod(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
+files_struct *open_file_fchmod(connection_struct *conn, const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
files_struct *fsp = NULL;
BOOL fsp_open;
- if (!VALID_STAT(*psbuf))
+ if (!VALID_STAT(*psbuf)) {
return NULL;
+ }
fsp = file_new(conn);
- if(!fsp)
+ if(!fsp) {
return NULL;
+ }
/* note! we must use a non-zero desired access or we don't get
a real file descriptor. Oh what a twisted web we weave. */
@@ -1606,96 +1912,135 @@ int close_file_fchmod(files_struct *fsp)
Open a directory from an NT SMB call.
****************************************************************************/
-files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf,
- uint32 desired_access, int share_mode, int smb_ofun, int *action)
+files_struct *open_directory(connection_struct *conn,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
+ uint32 access_mask,
+ uint32 share_access,
+ uint32 create_disposition,
+ uint32 create_options,
+ int *pinfo)
{
- BOOL got_stat = False;
- files_struct *fsp = file_new(conn);
- BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode);
-
- if(!fsp)
+ files_struct *fsp = NULL;
+ BOOL dir_existed = VALID_STAT(*psbuf) ? True : False;
+ BOOL create_dir = False;
+ int info = 0;
+
+ DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, "
+ "share_access = 0x%x create_options = 0x%x, "
+ "create_disposition = 0x%x\n",
+ fname,
+ (unsigned int)access_mask,
+ (unsigned int)share_access,
+ (unsigned int)create_options,
+ (unsigned int)create_disposition));
+
+ if (is_ntfs_stream_name(fname)) {
+ DEBUG(0,("open_directory: %s is a stream name!\n", fname ));
+ /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */
+ set_saved_error_triple(ERRDOS, ERRbadpath,
+ NT_STATUS_NOT_A_DIRECTORY);
return NULL;
+ }
- if (VALID_STAT(*psbuf))
- got_stat = True;
-
- if (got_stat && (GET_FILE_OPEN_DISPOSITION(smb_ofun) == FILE_EXISTS_FAIL)) {
- file_free(fsp);
- errno = EEXIST; /* Setup so correct error is returned to client. */
+ if (dir_existed && !S_ISDIR(psbuf->st_mode)) {
+ DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
+ /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */
+ set_saved_error_triple(ERRDOS, ERRbadpath,
+ NT_STATUS_NOT_A_DIRECTORY);
return NULL;
}
- if (GET_FILE_CREATE_DISPOSITION(smb_ofun) == FILE_CREATE_IF_NOT_EXIST) {
-
- if (got_stat) {
-
- if(!S_ISDIR(psbuf->st_mode)) {
- DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
- file_free(fsp);
- errno = EACCES;
+ switch( create_disposition ) {
+ case FILE_OPEN:
+ /* If directory exists open. If directory doesn't
+ * exist error. */
+ if (!dir_existed) {
+ DEBUG(5,("open_directory: FILE_OPEN requested "
+ "for directory %s and it doesn't "
+ "exist.\n", fname ));
+ set_saved_error_triple(ERRDOS, ERRbadfile,
+ NT_STATUS_OBJECT_NAME_NOT_FOUND);
return NULL;
}
- *action = FILE_WAS_OPENED;
-
- } else {
-
- /*
- * Try and create the directory.
- */
-
- /* We know bad_path is false as it's caught earlier. */
-
- NTSTATUS status = mkdir_internal(conn, fname, False);
+ info = FILE_WAS_OPENED;
+ break;
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(2,("open_directory: unable to create %s. Error was %s\n",
- fname, strerror(errno) ));
- file_free(fsp);
- /* Ensure we return the correct NT status to the client. */
- set_saved_error_triple(0, 0, status);
+ case FILE_CREATE:
+ /* If directory exists error. If directory doesn't
+ * exist create. */
+ if (dir_existed) {
+ DEBUG(5,("open_directory: FILE_CREATE "
+ "requested for directory %s and it "
+ "already exists.\n", fname ));
+ set_saved_error_triple(ERRDOS, ERRfilexists,
+ NT_STATUS_OBJECT_NAME_COLLISION);
return NULL;
}
+ create_dir = True;
+ info = FILE_WAS_CREATED;
+ break;
- /* Ensure we're checking for a symlink here.... */
- /* We don't want to get caught by a symlink racer. */
-
- if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) {
- file_free(fsp);
- return NULL;
+ case FILE_OPEN_IF:
+ /* If directory exists open. If directory doesn't
+ * exist create. */
+ if (!dir_existed) {
+ create_dir = True;
+ info = FILE_WAS_CREATED;
+ } else {
+ info = FILE_WAS_OPENED;
}
+ break;
- if(!S_ISDIR(psbuf->st_mode)) {
- DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
- file_free(fsp);
- return NULL;
- }
+ case FILE_SUPERSEDE:
+ case FILE_OVERWRITE:
+ case FILE_OVERWRITE_IF:
+ default:
+ DEBUG(5,("open_directory: invalid create_disposition "
+ "0x%x for directory %s\n",
+ (unsigned int)create_disposition, fname));
+ file_free(fsp);
+ set_saved_error_triple(ERRDOS, ERRinvalidparam,
+ NT_STATUS_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ if (create_dir) {
+ /*
+ * Try and create the directory.
+ */
- *action = FILE_WAS_CREATED;
+ /* We know bad_path is false as it's caught earlier. */
+ NTSTATUS status = mkdir_internal(conn, fname, False);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2,("open_directory: unable to create %s. "
+ "Error was %s\n", fname, strerror(errno) ));
+ /* Ensure we return the correct NT status to the
+ * client. */
+ set_saved_error_triple(0, 0, status);
+ return NULL;
}
- } else {
- /*
- * Don't create - just check that it *was* a directory.
- */
+ /* Ensure we're checking for a symlink here.... */
+ /* We don't want to get caught by a symlink racer. */
- if(!got_stat) {
- DEBUG(3,("open_directory: unable to stat name = %s. Error was %s\n",
- fname, strerror(errno) ));
- file_free(fsp);
+ if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) {
return NULL;
}
if(!S_ISDIR(psbuf->st_mode)) {
- DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
- file_free(fsp);
+ DEBUG(0,("open_directory: %s is not a directory !\n",
+ fname ));
return NULL;
}
+ }
- *action = FILE_WAS_OPENED;
+ fsp = file_new(conn);
+ if(!fsp) {
+ return NULL;
}
-
- DEBUG(5,("open_directory: opening directory %s\n", fname));
/*
* Setup the files_struct for it.
@@ -1709,20 +2054,21 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR
fsp->can_lock = True;
fsp->can_read = False;
fsp->can_write = False;
- fsp->share_mode = share_mode;
- fsp->desired_access = desired_access;
+
+ fsp->share_access = share_access;
+ fsp->fh->private_options = create_options;
+ fsp->access_mask = access_mask;
+
fsp->print_file = False;
fsp->modified = False;
fsp->oplock_type = NO_OPLOCK;
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = True;
fsp->is_stat = False;
- fsp->directory_delete_on_close = False;
string_set(&fsp->fsp_name,fname);
- if (delete_on_close) {
- NTSTATUS status = set_delete_on_close_internal(fsp, delete_on_close, 0);
-
+ if (create_options & FILE_DELETE_ON_CLOSE) {
+ NTSTATUS status = can_set_delete_on_close(fsp, True, 0);
if (!NT_STATUS_IS_OK(status)) {
file_free(fsp);
return NULL;
@@ -1730,10 +2076,14 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR
}
/* Change the owner if required. */
- if ((*action == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) {
+ if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) {
change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf);
}
+ if (pinfo) {
+ *pinfo = info;
+ }
+
conn->num_files_open++;
return fsp;
@@ -1743,7 +2093,8 @@ files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STR
Open a pseudo-file (no locking checks - a 'stat' open).
****************************************************************************/
-files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf)
+files_struct *open_file_stat(connection_struct *conn, char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
files_struct *fsp = NULL;
@@ -1772,15 +2123,12 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST
fsp->can_lock = False;
fsp->can_read = False;
fsp->can_write = False;
- fsp->share_mode = 0;
- fsp->desired_access = 0;
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 = True;
- fsp->directory_delete_on_close = False;
string_set(&fsp->fsp_name,fname);
conn->num_files_open++;
diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c
index 8208fbebe34..3cfce5c7a1f 100644
--- a/source/smbd/oplock.c
+++ b/source/smbd/oplock.c
@@ -343,6 +343,7 @@ BOOL process_local_message(char *buffer, int buf_size)
SMB_INO_T inode;
unsigned long file_id;
uint16 break_cmd_type;
+ struct sockaddr_in toaddr;
msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET);
from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET);
@@ -366,6 +367,7 @@ BOOL process_local_message(char *buffer, int buf_size)
}
if (!koplocks->parse_message(msg_start, msg_len, &inode, &dev, &file_id)) {
DEBUG(0,("kernel oplock break parse failure!\n"));
+ return False;
}
break;
@@ -449,49 +451,54 @@ pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n",
* Now actually process the break request.
*/
- if((exclusive_oplocks_open + level_II_oplocks_open) != 0) {
- if (oplock_break(dev, inode, file_id, False) == False) {
- DEBUG(0,("process_local_message: oplock break failed.\n"));
- return False;
- }
- } else {
+ if ((exclusive_oplocks_open == 0) &&
+ (level_II_oplocks_open == 0)) {
/*
* If we have no record of any currently open oplocks,
* it's not an error, as a close command may have
* just been issued on the file that was oplocked.
* Just log a message and return success in this case.
*/
- DEBUG(3,("process_local_message: oplock break requested with no outstanding \
-oplocks. Returning success.\n"));
+ DEBUG(3,("process_local_message: oplock break requested with "
+ "no outstanding oplocks. Returning success.\n"));
+ return True;
+ }
+
+ if (!oplock_break(dev, inode, file_id, False)) {
+ DEBUG(0,("process_local_message: oplock break failed.\n"));
+ return False;
}
/*
- * Do the appropriate reply - none in the kernel or async level II case.
+ * Do the appropriate reply - none in the kernel or async level II
+ * case.
*/
- if(break_cmd_type == OPLOCK_BREAK_CMD || break_cmd_type == LEVEL_II_OPLOCK_BREAK_CMD) {
- struct sockaddr_in toaddr;
+ if (!((break_cmd_type == OPLOCK_BREAK_CMD) ||
+ (break_cmd_type == LEVEL_II_OPLOCK_BREAK_CMD))) {
+ return True;
+ }
- /* Send the message back after OR'ing in the 'REPLY' bit. */
- SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type | CMD_REPLY);
+ /* Send the message back after OR'ing in the 'REPLY' bit. */
+ SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type | CMD_REPLY);
- memset((char *)&toaddr,'\0',sizeof(toaddr));
- toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- toaddr.sin_port = htons(from_port);
- toaddr.sin_family = AF_INET;
+ memset((char *)&toaddr,'\0',sizeof(toaddr));
+ toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ toaddr.sin_port = htons(from_port);
+ toaddr.sin_family = AF_INET;
- if(sys_sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
- (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) {
- DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n",
- (int)remotepid, strerror(errno)));
- return False;
- }
-
- DEBUG(5,("process_local_message: oplock break reply sent to \
-pid %d, port %d, for file dev = %x, inode = %.0f, file_id = %lu\n",
- (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id));
+ if(sys_sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
+ (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) {
+ DEBUG(0,("process_local_message: sendto process %d failed. "
+ "Errno was %s\n", (int)remotepid, strerror(errno)));
+ return False;
}
+ DEBUG(5,("process_local_message: oplock break reply sent to pid %d, "
+ "port %d, for file dev = %x, inode = %.0f, file_id = %lu\n",
+ (int)remotepid, from_port, (unsigned int)dev,
+ (double)inode, file_id));
+
return True;
}
@@ -1150,7 +1157,7 @@ BOOL attempt_close_oplocked_file(files_struct *fsp)
{
DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name));
- if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fd != -1)) {
+ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fh->fd != -1)) {
/* Try and break the oplock. */
if (oplock_break(fsp->dev, fsp->inode, fsp->file_id, True)) {
if(file_find_fsp(fsp) == NULL) /* Did the oplock break close the file ? */
@@ -1223,6 +1230,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
pid_t pid = sys_getpid();
int num_share_modes = 0;
int i;
+ BOOL dummy;
/*
* If this file is level II oplocked then we need
@@ -1239,7 +1247,8 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
DEBUG(0,("release_level_2_oplocks_on_change: failed to lock share mode entry for file %s.\n", fsp->fsp_name ));
}
- num_share_modes = get_share_modes(fsp->conn, fsp->dev, fsp->inode, &share_list);
+ num_share_modes = get_share_modes(fsp->dev, fsp->inode, &share_list,
+ &dummy);
DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n",
num_share_modes ));
diff --git a/source/smbd/oplock_linux.c b/source/smbd/oplock_linux.c
index 78dc260939e..477832c6e8e 100644
--- a/source/smbd/oplock_linux.c
+++ b/source/smbd/oplock_linux.c
@@ -179,10 +179,10 @@ dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (doubl
static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type)
{
- if (linux_setlease(fsp->fd, F_WRLCK) == -1) {
+ if (linux_setlease(fsp->fh->fd, F_WRLCK) == -1) {
DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
inode = %.0f. (%s)\n",
- fsp->fsp_name, fsp->fd,
+ fsp->fsp_name, fsp->fh->fd,
(unsigned int)fsp->dev, (double)fsp->inode, strerror(errno)));
return False;
}
@@ -204,7 +204,7 @@ static void linux_release_kernel_oplock(files_struct *fsp)
* Check and print out the current kernel
* oplock state of this file.
*/
- int state = fcntl(fsp->fd, F_GETLEASE, 0);
+ int state = fcntl(fsp->fh->fd, F_GETLEASE, 0);
dbgtext("linux_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \
oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
(double)fsp->inode, fsp->file_id, state );
@@ -213,7 +213,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
/*
* Remove the kernel oplock on this file.
*/
- if (linux_setlease(fsp->fd, F_UNLCK) == -1) {
+ if (linux_setlease(fsp->fh->fd, F_UNLCK) == -1) {
if (DEBUGLVL(0)) {
dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " );
dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n",
diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c
index 6c7faa4c056..951c192e396 100644
--- a/source/smbd/pipes.c
+++ b/source/smbd/pipes.c
@@ -4,6 +4,7 @@
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Luke Kenneth Casson Leighton 1996-1998
Copyright (C) Paul Ashton 1997-1998.
+ Copyright (C) Jeremy Allison 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
@@ -33,11 +34,11 @@
extern struct pipe_id_info pipe_names[];
/****************************************************************************
- reply to an open and X on a named pipe
-
- This code is basically stolen from reply_open_and_X with some
- wrinkles to handle pipes.
+ Reply to an open and X on a named pipe.
+ This code is basically stolen from reply_open_and_X with some
+ wrinkles to handle pipes.
****************************************************************************/
+
int reply_open_pipe_and_X(connection_struct *conn,
char *inbuf,char *outbuf,int length,int bufsize)
{
@@ -45,7 +46,6 @@ int reply_open_pipe_and_X(connection_struct *conn,
pstring pipe_name;
uint16 vuid = SVAL(inbuf, smb_uid);
smb_np_struct *p;
- int smb_ofun = SVAL(inbuf,smb_vwv8);
int size=0,fmode=0,mtime=0,rmode=0;
int i;
@@ -55,23 +55,26 @@ int reply_open_pipe_and_X(connection_struct *conn,
/* If the name doesn't start \PIPE\ then this is directed */
/* at a mailslot or something we really, really don't understand, */
/* not just something we really don't understand. */
- if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 )
+ if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) {
return(ERROR_DOS(ERRSRV,ERRaccess));
+ }
DEBUG(4,("Opening pipe %s.\n", pipe_name));
/* See if it is one we want to handle. */
- for( i = 0; pipe_names[i].client_pipe ; i++ )
- if( strequal(pipe_name,pipe_names[i].client_pipe) )
+ for( i = 0; pipe_names[i].client_pipe ; i++ ) {
+ if( strequal(pipe_name,pipe_names[i].client_pipe)) {
break;
+ }
+ }
- if (pipe_names[i].client_pipe == NULL)
+ if (pipe_names[i].client_pipe == NULL) {
return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe));
+ }
/* Strip \PIPE\ off the name. */
pstrcpy(fname, pipe_name + PIPELEN);
-
#if 0
/*
* Hack for NT printers... JRA.
@@ -83,10 +86,11 @@ int reply_open_pipe_and_X(connection_struct *conn,
/* Known pipes arrive with DIR attribs. Remove it so a regular file */
/* can be opened and add it in after the open. */
DEBUG(3,("Known pipe %s opening.\n",fname));
- smb_ofun |= FILE_CREATE_IF_NOT_EXIST;
p = open_rpc_pipe_p(fname, conn, vuid);
- if (!p) return(ERROR_DOS(ERRSRV,ERRnofids));
+ if (!p) {
+ return(ERROR_DOS(ERRSRV,ERRnofids));
+ }
/* Prepare the reply */
set_message(outbuf,15,0,True);
@@ -111,8 +115,9 @@ int reply_open_pipe_and_X(connection_struct *conn,
}
/****************************************************************************
- reply to a write on a pipe
+ Reply to a write on a pipe.
****************************************************************************/
+
int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize)
{
smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0);
@@ -121,25 +126,27 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize)
int outsize;
char *data;
- if (!p)
+ if (!p) {
return(ERROR_DOS(ERRDOS,ERRbadfid));
+ }
data = smb_buf(inbuf) + 3;
- if (numtowrite == 0)
+ if (numtowrite == 0) {
nwritten = 0;
- else
+ } else {
nwritten = write_to_pipe(p, data, numtowrite);
+ }
- if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0))
+ if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
return (UNIXERROR(ERRDOS,ERRnoaccess));
+ }
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,nwritten);
- DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n",
- p->pnum, nwritten));
+ DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten));
return(outsize);
}
@@ -158,24 +165,25 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
int nwritten = -1;
int smb_doff = SVAL(inbuf, smb_vwv11);
BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) ==
- (PIPE_START_MESSAGE|PIPE_RAW_MODE));
+ (PIPE_START_MESSAGE|PIPE_RAW_MODE));
char *data;
- if (!p)
+ if (!p) {
return(ERROR_DOS(ERRDOS,ERRbadfid));
+ }
data = smb_base(inbuf) + smb_doff;
- if (numtowrite == 0)
+ if (numtowrite == 0) {
nwritten = 0;
- else {
+ } else {
if(pipe_start_message_raw) {
/*
* For the start of a message in named pipe byte mode,
* the first two bytes are a length-of-pdu field. Ignore
- * them (we don't trust the client. JRA.
+ * them (we don't trust the client). JRA.
*/
- if(numtowrite < 2) {
+ if(numtowrite < 2) {
DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n",
(unsigned int)numtowrite ));
return (UNIXERROR(ERRDOS,ERRnoaccess));
@@ -183,30 +191,30 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
data += 2;
numtowrite -= 2;
- }
+ }
nwritten = write_to_pipe(p, data, numtowrite);
}
- if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0))
+ if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
return (UNIXERROR(ERRDOS,ERRnoaccess));
+ }
set_message(outbuf,6,0,True);
nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
SSVAL(outbuf,smb_vwv2,nwritten);
- DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n",
- p->pnum, nwritten));
+ DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten));
return chain_reply(inbuf,outbuf,length,bufsize);
}
/****************************************************************************
- reply to a read and X
-
- This code is basically stolen from reply_read_and_X with some
- wrinkles to handle pipes.
+ Reply to a read and X.
+ This code is basically stolen from reply_read_and_X with some
+ wrinkles to handle pipes.
****************************************************************************/
+
int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
{
smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2);
@@ -223,16 +231,18 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
uint32 smb_offs = IVAL(inbuf,smb_vwv3);
#endif
- if (!p)
+ if (!p) {
return(ERROR_DOS(ERRDOS,ERRbadfid));
+ }
set_message(outbuf,12,0,True);
data = smb_buf(outbuf);
nread = read_from_pipe(p, data, smb_maxcnt, &unused);
- if (nread < 0)
+ if (nread < 0) {
return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
SSVAL(outbuf,smb_vwv5,nread);
SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
@@ -247,20 +257,23 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
}
/****************************************************************************
- reply to a close
+ Reply to a close.
****************************************************************************/
+
int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf)
{
smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0);
int outsize = set_message(outbuf,0,0,True);
- if (!p)
+ if (!p) {
return(ERROR_DOS(ERRDOS,ERRbadfid));
+ }
DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum));
- if (!close_rpc_pipe_hnd(p))
+ if (!close_rpc_pipe_hnd(p)) {
return ERROR_DOS(ERRDOS,ERRbadfid);
+ }
return(outsize);
}
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index ffcfbc4fb18..ab14638a24c 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -229,8 +229,8 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_
if (!pai_protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) {
/* Instead just remove the attribute if it exists. */
- if (fsp->fd != -1)
- SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME);
+ if (fsp->fh->fd != -1)
+ SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME);
else
SMB_VFS_REMOVEXATTR(fsp->conn, fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
return;
@@ -238,8 +238,8 @@ static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_
pai_buf = create_pai_buf(file_ace_list, dir_ace_list, pai_protected, &store_size);
- if (fsp->fd != -1)
- ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,
+ if (fsp->fh->fd != -1)
+ ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, store_size, 0);
else
ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME,
@@ -445,8 +445,8 @@ static struct pai_val *load_inherited_info(files_struct *fsp)
return NULL;
do {
- if (fsp->fd != -1)
- ret = SMB_VFS_FGETXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,
+ if (fsp->fh->fd != -1)
+ ret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, pai_buf_size);
else
ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME,
@@ -2422,7 +2422,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau
* Finally apply it to the file or directory.
*/
- if(default_ace || fsp->is_directory || fsp->fd == -1) {
+ if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) {
/*
* Some systems allow all the above calls and only fail with no ACL support
@@ -2438,7 +2438,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau
goto done;
}
} else {
- if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fd, the_acl) == -1) {
+ if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl) == -1) {
/*
* Some systems allow all the above calls and only fail with no ACL support
* when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
@@ -2668,7 +2668,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name ));
- 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) {
@@ -2692,13 +2692,13 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
} else {
/* Get the stat struct for the owner info. */
- if(SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
+ if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
return 0;
}
/*
* Get the ACL from the fd.
*/
- posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
+ posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
}
DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n",
@@ -2981,7 +2981,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_
become_root();
/* Keep the current file gid the same. */
- ret = SMB_VFS_FCHOWN(fsp, fsp->fd, uid, (gid_t)-1);
+ ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, uid, (gid_t)-1);
unbecome_root();
close_file_fchmod(fsp);
@@ -3022,11 +3022,11 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
* Get the current state of the file.
*/
- if(fsp->is_directory || fsp->fd == -1) {
+ if(fsp->is_directory || fsp->fh->fd == -1) {
if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0)
return False;
} else {
- if(SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0)
+ if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0)
return False;
}
@@ -3081,10 +3081,10 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
int ret;
- if(fsp->fd == -1)
+ if(fsp->fh->fd == -1)
ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
else
- ret = SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf);
+ ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf);
if(ret != 0)
return False;
@@ -3683,8 +3683,8 @@ static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
}
/* Get the current file ACL. */
- if (fsp && fsp->fd != -1) {
- file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
+ if (fsp && fsp->fh->fd != -1) {
+ file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
} else {
file_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_ACCESS);
}
@@ -3767,9 +3767,9 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
return False;
}
- if (fsp && fsp->fd != -1) {
+ if (fsp && fsp->fh->fd != -1) {
/* The preferred way - use an open fd. */
- if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fd, file_acl) == -1) {
+ if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, file_acl) == -1) {
DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
fname, strerror(errno) ));
SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 312a3ace23c..bb583fb94b8 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -1275,20 +1275,24 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
{
pstring fname;
int outsize = 0;
- int fmode=0;
- int share_mode;
+ uint32 fattr=0;
SMB_OFF_T size = 0;
time_t mtime=0;
- int rmode=0;
+ int info;
SMB_STRUCT_STAT sbuf;
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
- uint16 dos_attr = SVAL(inbuf,smb_vwv1);
+ int deny_mode;
+ uint32 dos_attr = SVAL(inbuf,smb_vwv1);
+ uint32 access_mask;
+ uint32 share_mode;
+ uint32 create_disposition;
+ uint32 create_options = 0;
NTSTATUS status;
START_PROFILE(SMBopen);
- share_mode = SVAL(inbuf,smb_vwv0);
+ deny_mode = SVAL(inbuf,smb_vwv0);
srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
@@ -1304,8 +1308,20 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
- fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- (uint32)dos_attr, oplock_request,&rmode,NULL);
+ if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
+ &access_mask, &share_mode, &create_disposition, &create_options)) {
+ END_PROFILE(SMBopen);
+ return ERROR_DOS(ERRDOS, ERRbadaccess);
+ }
+
+ fsp = open_file_ntcreate(conn,fname,&sbuf,
+ access_mask,
+ share_mode,
+ create_disposition,
+ create_options,
+ dos_attr,
+ oplock_request,
+ &info);
if (!fsp) {
END_PROFILE(SMBopen);
@@ -1317,10 +1333,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
}
size = sbuf.st_size;
- fmode = dos_mode(conn,fname,&sbuf);
+ fattr = dos_mode(conn,fname,&sbuf);
mtime = sbuf.st_mtime;
- if (fmode & aDIR) {
+ if (fattr & aDIR) {
DEBUG(3,("attempt to open a directory %s\n",fname));
close_file(fsp,False);
END_PROFILE(SMBopen);
@@ -1329,19 +1345,22 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
outsize = set_message(outbuf,7,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
- SSVAL(outbuf,smb_vwv1,fmode);
- if(lp_dos_filetime_resolution(SNUM(conn)) )
+ SSVAL(outbuf,smb_vwv1,fattr);
+ if(lp_dos_filetime_resolution(SNUM(conn)) ) {
put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
- else
+ } else {
put_dos_date3(outbuf,smb_vwv2,mtime);
+ }
SIVAL(outbuf,smb_vwv4,(uint32)size);
- SSVAL(outbuf,smb_vwv6,rmode);
+ SSVAL(outbuf,smb_vwv6,FILE_WAS_OPENED);
- if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
END_PROFILE(SMBopen);
return(outsize);
}
@@ -1353,21 +1372,22 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
pstring fname;
- int smb_mode = SVAL(inbuf,smb_vwv3);
- int smb_attr = SVAL(inbuf,smb_vwv5);
+ uint16 open_flags = SVAL(inbuf,smb_vwv2);
+ int deny_mode = SVAL(inbuf,smb_vwv3);
+ uint32 smb_attr = SVAL(inbuf,smb_vwv5);
/* Breakout the oplock request bits so we can set the
reply bits separately. */
BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
BOOL oplock_request = ex_oplock_request | core_oplock_request;
#if 0
- int open_flags = SVAL(inbuf,smb_vwv2);
int smb_sattr = SVAL(inbuf,smb_vwv4);
uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
#endif
int smb_ofun = SVAL(inbuf,smb_vwv8);
SMB_OFF_T size=0;
- int fmode=0,mtime=0,rmode=0;
+ uint32 fattr=0;
+ int mtime=0;
SMB_STRUCT_STAT sbuf;
int smb_action = 0;
BOOL bad_path = False;
@@ -1375,6 +1395,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
NTSTATUS status;
SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
ssize_t retval = -1;
+ uint32 access_mask;
+ uint32 share_mode;
+ uint32 create_disposition;
+ uint32 create_options = 0;
START_PROFILE(SMBopenX);
@@ -1404,18 +1428,23 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
- /* Strange open mode mapping. */
- if (smb_ofun == 0) {
- if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) {
- smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
- } else {
- END_PROFILE(SMBopenX);
- return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
- }
+ if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
+ &access_mask,
+ &share_mode,
+ &create_disposition,
+ &create_options)) {
+ END_PROFILE(SMBopenX);
+ return ERROR_DOS(ERRDOS, ERRbadaccess);
}
- fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
- oplock_request, &rmode,&smb_action);
+ fsp = open_file_ntcreate(conn,fname,&sbuf,
+ access_mask,
+ share_mode,
+ create_disposition,
+ create_options,
+ smb_attr,
+ oplock_request,
+ &smb_action);
if (!fsp) {
END_PROFILE(SMBopenX);
@@ -1446,9 +1475,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
size = get_allocation_size(conn,fsp,&sbuf);
}
- fmode = dos_mode(conn,fname,&sbuf);
+ fattr = dos_mode(conn,fname,&sbuf);
mtime = sbuf.st_mtime;
- if (fmode & aDIR) {
+ if (fattr & aDIR) {
close_file(fsp,False);
END_PROFILE(SMBopenX);
return ERROR_DOS(ERRDOS,ERRnoaccess);
@@ -1459,34 +1488,47 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
correct bit for extended oplock reply.
*/
- if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
smb_action |= EXTENDED_OPLOCK_GRANTED;
+ }
- if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
smb_action |= EXTENDED_OPLOCK_GRANTED;
+ }
/* If the caller set the core oplock request bit
and we granted one (by whatever means) - set the
correct bit for core oplock reply.
*/
- if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- set_message(outbuf,15,0,True);
+ if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
+ set_message(outbuf,19,0,True);
+ } else {
+ set_message(outbuf,15,0,True);
+ }
SSVAL(outbuf,smb_vwv2,fsp->fnum);
- SSVAL(outbuf,smb_vwv3,fmode);
- if(lp_dos_filetime_resolution(SNUM(conn)) )
+ SSVAL(outbuf,smb_vwv3,fattr);
+ if(lp_dos_filetime_resolution(SNUM(conn)) ) {
put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
- else
+ } else {
put_dos_date3(outbuf,smb_vwv4,mtime);
+ }
SIVAL(outbuf,smb_vwv6,(uint32)size);
- SSVAL(outbuf,smb_vwv8,rmode);
+ SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
SSVAL(outbuf,smb_vwv11,smb_action);
+ if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
+ SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
+ }
+
END_PROFILE(SMBopenX);
return chain_reply(inbuf,outbuf,length,bufsize);
}
@@ -1528,18 +1570,21 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
pstring fname;
int com;
int outsize = 0;
- int createmode;
- int ofun = 0;
+ uint32 fattr = SVAL(inbuf,smb_vwv0);
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
+ uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+ uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+ uint32 create_disposition;
+ uint32 create_options = 0;
+
START_PROFILE(SMBcreate);
com = SVAL(inbuf,smb_com);
- createmode = SVAL(inbuf,smb_vwv0);
srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
@@ -1554,20 +1599,27 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
- if (createmode & aVOLID)
+ if (fattr & aVOLID) {
DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
-
+ }
+
if(com == SMBmknew) {
/* We should fail if file exists. */
- ofun = FILE_CREATE_IF_NOT_EXIST;
+ create_disposition = FILE_CREATE;
} else {
- /* SMBcreate - Create if file doesn't exist, truncate if it does. */
- ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
- }
-
- /* Open file in dos compatibility share mode. */
- fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
- ofun, (uint32)createmode, oplock_request, NULL, NULL);
+ /* Create if file doesn't exist, truncate if it does. */
+ create_disposition = FILE_OPEN_IF;
+ }
+
+ /* Open file using ntcreate. */
+ fsp = open_file_ntcreate(conn,fname,&sbuf,
+ access_mask,
+ share_mode,
+ create_disposition,
+ create_options,
+ fattr,
+ oplock_request,
+ NULL);
if (!fsp) {
END_PROFILE(SMBcreate);
@@ -1581,14 +1633,16 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
- if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- DEBUG( 2, ( "new file %s\n", fname ) );
- DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
+ DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
+ DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
END_PROFILE(SMBcreate);
return(outsize);
@@ -1602,7 +1656,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
{
pstring fname;
int outsize = 0;
- int createattr;
+ uint32 fattr = SVAL(inbuf,smb_vwv0);
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
@@ -1614,7 +1668,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
START_PROFILE(SMBctemp);
- createattr = SVAL(inbuf,smb_vwv0);
srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
@@ -1642,12 +1695,15 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SMB_VFS_STAT(conn,fname,&sbuf);
- /* Open file in dos compatibility share mode. */
/* We should fail if file does not exist. */
- fsp = open_file_shared(conn,fname,&sbuf,
- SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
- FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
- (uint32)createattr, oplock_request, NULL, NULL);
+ fsp = open_file_ntcreate(conn,fname,&sbuf,
+ FILE_GENERIC_READ | FILE_GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ fattr,
+ oplock_request,
+ NULL);
/* close fd from smb_mkstemp() */
close(tmpfd);
@@ -1666,10 +1722,11 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
/* the returned filename is relative to the directory */
s = strrchr_m(fname, '/');
- if (!s)
+ if (!s) {
s = fname;
- else
+ } else {
s++;
+ }
p = smb_buf(outbuf);
#if 0
@@ -1681,15 +1738,17 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
p += namelen;
outsize = set_message_end(outbuf, p);
- if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- DEBUG( 2, ( "created temp file %s\n", fname ) );
- DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
- fname, fsp->fd, sbuf.st_mode ) );
+ DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
+ DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
+ (unsigned int)sbuf.st_mode ) );
END_PROFILE(SMBctemp);
return(outsize);
@@ -1701,26 +1760,33 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
{
- int smb_action;
- int access_mode;
files_struct *fsp;
- uint16 fmode;
+ uint32 fmode;
- if (!CAN_WRITE(conn))
+ if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
+ }
fmode = dos_mode(conn,fname,pst);
- if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
+ if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
return NT_STATUS_NO_SUCH_FILE;
+ }
- if (S_ISDIR(pst->st_mode))
+ if (S_ISDIR(pst->st_mode)) {
return NT_STATUS_OK;
+ }
/* We need a better way to return NT status codes from open... */
set_saved_error_triple(0, 0, NT_STATUS_OK);
- fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
+ fsp = open_file_ntcreate(conn, fname, pst,
+ DELETE_ACCESS,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ NULL);
if (!fsp) {
NTSTATUS ret;
@@ -1742,43 +1808,46 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
{
SMB_STRUCT_STAT sbuf;
- uint32 fmode;
- int smb_action;
- int access_mode;
+ uint32 fattr;
files_struct *fsp;
- DEBUG(10,("can_delete: %s, dirtype = %d\n",
- fname, dirtype ));
+ DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
- if (!CAN_WRITE(conn))
+ if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
+ }
if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
if(errno == ENOENT) {
- if (bad_path)
+ if (bad_path) {
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- else
+ } else {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
}
return map_nt_error_from_unix(errno);
}
- fmode = dos_mode(conn,fname,&sbuf);
+ fattr = dos_mode(conn,fname,&sbuf);
/* Can't delete a directory. */
- if (fmode & aDIR)
+ if (fattr & aDIR) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+
#if 0 /* JRATEST */
else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
return NT_STATUS_OBJECT_NAME_INVALID;
#endif /* JRATEST */
if (!lp_delete_readonly(SNUM(conn))) {
- if (fmode & aRONLY)
+ if (fattr & aRONLY) {
return NT_STATUS_CANNOT_DELETE;
+ }
}
- if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
+ if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
return NT_STATUS_NO_SUCH_FILE;
+ }
if (check_is_at_open) {
if (!can_delete_file_in_directory(conn, fname)) {
@@ -1791,8 +1860,14 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
/* We need a better way to return NT status codes from open... */
set_saved_error_triple(0, 0, NT_STATUS_OK);
- fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
+ fsp = open_file_ntcreate(conn, fname, &sbuf,
+ DELETE_ACCESS,
+ FILE_SHARE_NONE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ NULL);
if (!fsp) {
NTSTATUS ret;
@@ -2058,7 +2133,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
header.length = 4;
header.free = NULL;
- if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
+ if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
/* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
if (errno == ENOSYS) {
goto normal_readbraw;
@@ -2205,7 +2280,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
SMB_STRUCT_STAT st;
SMB_OFF_T size = 0;
- if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) {
+ if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
size = st.st_size;
}
@@ -2251,7 +2326,9 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
START_PROFILE(SMBlockread);
CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ if (!CHECK_READ(fsp,inbuf)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
release_level_2_oplocks_on_change(fsp);
@@ -2345,7 +2422,9 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int
START_PROFILE(SMBread);
CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ if (!CHECK_READ(fsp,inbuf)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtoread = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
@@ -2413,7 +2492,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
SMB_STRUCT_STAT sbuf;
DATA_BLOB header;
- if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
+ if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
return(UNIXERROR(ERRDOS,ERRnoaccess));
if (startpos > sbuf.st_size)
@@ -2442,7 +2521,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
header.length = data - outbuf;
header.free = NULL;
- if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
+ if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
/* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
if (errno == ENOSYS) {
goto normal_read;
@@ -2530,7 +2609,9 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ if (!CHECK_READ(fsp,inbuf)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
set_message(outbuf,12,0,True);
@@ -2610,7 +2691,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
}
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
tcount = IVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
@@ -2744,7 +2827,9 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
START_PROFILE(SMBwriteunlock);
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
@@ -2758,10 +2843,11 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
/* The special X/Open SMB protocol handling of
zero length writes is *NOT* done for
this call */
- if(numtowrite == 0)
+ if(numtowrite == 0) {
nwritten = 0;
- else
+ } else {
nwritten = write_file(fsp,data,startpos,numtowrite);
+ }
if (lp_syncalways(SNUM(conn)))
sync_file(conn,fsp);
@@ -2815,7 +2901,9 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
}
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
@@ -2896,7 +2984,9 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
}
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
set_message(outbuf,6,0,True);
@@ -3010,7 +3100,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
break;
case 1:
umode = SEEK_CUR;
- res = fsp->pos + startpos;
+ res = fsp->fh->pos + startpos;
break;
case 2:
umode = SEEK_END;
@@ -3022,19 +3112,19 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
}
if (umode == SEEK_END) {
- if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
+ if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
if(errno == EINVAL) {
SMB_OFF_T current_pos = startpos;
SMB_STRUCT_STAT sbuf;
- if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
+ if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
END_PROFILE(SMBlseek);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
current_pos += sbuf.st_size;
if(current_pos < 0)
- res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
+ res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
}
}
@@ -3044,7 +3134,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
}
}
- fsp->pos = res;
+ fsp->fh->pos = res;
outsize = set_message(outbuf,2,0,True);
SIVAL(outbuf,smb_vwv0,res);
@@ -3150,7 +3240,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
pstrcpy( file_name, fsp->fsp_name);
DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
- fsp->fd, fsp->fnum,
+ fsp->fh->fd, fsp->fnum,
conn->num_files_open));
/*
@@ -3201,7 +3291,9 @@ int reply_writeclose(connection_struct *conn,
START_PROFILE(SMBwriteclose);
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
@@ -3276,7 +3368,7 @@ int reply_lock(connection_struct *conn,
offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
- fsp->fd, fsp->fnum, (double)offset, (double)count));
+ fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
if (NT_STATUS_V(status)) {
@@ -3327,7 +3419,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
}
DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
- fsp->fd, fsp->fnum, (double)offset, (double)count ) );
+ fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
END_PROFILE(SMBunlock);
return(outsize);
@@ -3437,7 +3529,7 @@ int reply_printopen(connection_struct *conn,
SSVAL(outbuf,smb_vwv0,fsp->fnum);
DEBUG(3,("openprint fd=%d fnum=%d\n",
- fsp->fd, fsp->fnum));
+ fsp->fh->fd, fsp->fnum));
END_PROFILE(SMBsplopen);
return(outsize);
@@ -3463,7 +3555,7 @@ int reply_printclose(connection_struct *conn,
}
DEBUG(3,("printclose fd=%d fnum=%d\n",
- fsp->fd,fsp->fnum));
+ fsp->fh->fd,fsp->fnum));
close_err = close_file(fsp,True);
@@ -3567,7 +3659,9 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_
}
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtowrite = SVAL(smb_buf(inbuf),1);
data = smb_buf(inbuf) + 3;
@@ -4484,45 +4578,66 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
int count,BOOL target_is_directory, int *err_ret)
{
- int Access,action;
SMB_STRUCT_STAT src_sbuf, sbuf2;
SMB_OFF_T ret=-1;
files_struct *fsp1,*fsp2;
pstring dest;
uint32 dosattrs;
+ uint32 new_create_disposition;
*err_ret = 0;
pstrcpy(dest,dest1);
if (target_is_directory) {
char *p = strrchr_m(src,'/');
- if (p)
+ if (p) {
p++;
- else
+ } else {
p = src;
+ }
pstrcat(dest,"/");
pstrcat(dest,p);
}
- if (!vfs_file_exist(conn,src,&src_sbuf))
+ if (!vfs_file_exist(conn,src,&src_sbuf)) {
return(False);
+ }
+
+ if (!target_is_directory && count) {
+ new_create_disposition = FILE_OPEN;
+ } else {
+ if (!map_open_params_to_ntcreate(dest1,0,ofun,
+ NULL, NULL, &new_create_disposition, NULL)) {
+ return(False);
+ }
+ }
- fsp1 = open_file_shared(conn,src,&src_sbuf,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,&action);
+ fsp1 = open_file_ntcreate(conn,src,&src_sbuf,
+ FILE_GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ INTERNAL_OPEN_ONLY,
+ NULL);
- if (!fsp1)
+ if (!fsp1) {
return(False);
-
- if (!target_is_directory && count)
- ofun = FILE_EXISTS_OPEN;
+ }
dosattrs = dos_mode(conn, src, &src_sbuf);
- if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
+ if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
ZERO_STRUCTP(&sbuf2);
+ }
- fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
- ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
+ fsp2 = open_file_ntcreate(conn,dest,&sbuf2,
+ FILE_GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ new_create_disposition,
+ 0,
+ dosattrs,
+ INTERNAL_OPEN_ONLY,
+ NULL);
if (!fsp2) {
close_file(fsp1,False);
@@ -4530,7 +4645,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
}
if ((ofun&3) == 1) {
- if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
+ if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
/*
* Stop the copy from occurring.
@@ -4540,8 +4655,9 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
}
}
- if (src_sbuf.st_size)
+ if (src_sbuf.st_size) {
ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
+ }
close_file(fsp1,False);
@@ -4955,7 +5071,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
/* we don't support these - and CANCEL_LOCK makes w2k
and XP reboot so I don't really want to be
compatible! (tridge) */
- return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+ return ERROR_DOS(ERRDOS, ERRnoatomiclocks);
}
if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
@@ -5158,7 +5274,9 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
outsize = set_message(outbuf,8,0,True);
CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ if (!CHECK_READ(fsp,inbuf)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
maxcount = SVAL(inbuf,smb_vwv3);
@@ -5286,7 +5404,9 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
START_PROFILE(SMBwriteBmpx);
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
if (HAS_CACHED_ERROR(fsp)) {
return(CACHED_ERROR(fsp));
}
@@ -5390,7 +5510,9 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
START_PROFILE(SMBwriteBs);
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
tcount = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index d4daf1fd690..602656080ed 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -3,6 +3,7 @@
SMB transaction2 handling
Copyright (C) Jeremy Allison 1994-2003
Copyright (C) Stefan (metze) Metzmacher 2003
+ Copyright (C) Volker Lendecke 2005
Extensively modified by Andrew Tridgell, 1995
@@ -119,8 +120,8 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str
return False;
}
- if (fsp && fsp->fd != -1) {
- sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
+ if (fsp && fsp->fh->fd != -1) {
+ sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
} else {
sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
}
@@ -171,8 +172,8 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
- if (fsp && fsp->fd != -1) {
- sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
+ if (fsp && fsp->fh->fd != -1) {
+ sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
} else {
sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
}
@@ -337,10 +338,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, s
if (ea_list->ea.value.length == 0) {
/* Remove the attribute. */
- if (fsp && (fsp->fd != -1)) {
+ if (fsp && (fsp->fh->fd != -1)) {
DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
unix_ea_name, fsp->fsp_name));
- ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
+ ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
} else {
DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
unix_ea_name, fname));
@@ -355,10 +356,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, s
}
#endif
} else {
- if (fsp && (fsp->fd != -1)) {
+ if (fsp && (fsp->fh->fd != -1)) {
DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
unix_ea_name, fsp->fsp_name));
- ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name,
+ ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
ea_list->ea.value.data, ea_list->ea.value.length, 0);
} else {
DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
@@ -717,20 +718,20 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
{
char *params = *pparams;
char *pdata = *ppdata;
- int16 open_mode;
- int16 open_attr;
+ int deny_mode;
+ int32 open_attr;
BOOL oplock_request;
#if 0
BOOL return_additional_info;
int16 open_sattr;
time_t open_time;
#endif
- int16 open_ofun;
+ int open_ofun;
int32 open_size;
char *pname;
pstring fname;
SMB_OFF_T size=0;
- int fmode=0,mtime=0,rmode;
+ int fattr=0,mtime=0;
SMB_INO_T inode = 0;
SMB_STRUCT_STAT sbuf;
int smb_action = 0;
@@ -740,6 +741,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
struct ea_list *ea_list = NULL;
uint16 flags = 0;
NTSTATUS status;
+ uint32 access_mask;
+ uint32 share_mode;
+ uint32 create_disposition;
+ uint32 create_options = 0;
/*
* Ensure we have enough parameters to perform the operation.
@@ -750,7 +755,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
}
flags = SVAL(params, 0);
- open_mode = SVAL(params, 2);
+ deny_mode = SVAL(params, 2);
open_attr = SVAL(params,6);
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
if (oplock_request) {
@@ -766,16 +771,18 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
open_size = IVAL(params,14);
pname = &params[28];
- if (IS_IPC(conn))
+ if (IS_IPC(conn)) {
return(ERROR_DOS(ERRSRV,ERRaccess));
+ }
srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
- DEBUG(3,("call_trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
- fname,open_mode, open_attr, open_ofun, open_size));
+ DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
+ fname, (unsigned int)deny_mode, (unsigned int)open_attr,
+ (unsigned int)open_ofun, open_size));
/* XXXX we need to handle passed times, sattr and flags */
@@ -788,11 +795,12 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
- /* Strange open mode mapping. */
- if (open_ofun == 0) {
- if (GET_OPEN_MODE(open_mode) == DOS_OPEN_EXEC) {
- open_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
- }
+ if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
+ &access_mask,
+ &share_mode,
+ &create_disposition,
+ &create_options)) {
+ return ERROR_DOS(ERRDOS, ERRbadaccess);
}
/* Any data in this call is an EA list. */
@@ -822,8 +830,14 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
}
}
- fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
- oplock_request, &rmode,&smb_action);
+ fsp = open_file_ntcreate(conn,fname,&sbuf,
+ access_mask,
+ share_mode,
+ create_disposition,
+ create_options,
+ open_attr,
+ oplock_request,
+ &smb_action);
if (!fsp) {
talloc_destroy(ctx);
@@ -835,10 +849,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
}
size = get_file_size(sbuf);
- fmode = dos_mode(conn,fname,&sbuf);
+ fattr = dos_mode(conn,fname,&sbuf);
mtime = sbuf.st_mtime;
inode = sbuf.st_ino;
- if (fmode & aDIR) {
+ if (fattr & aDIR) {
talloc_destroy(ctx);
close_file(fsp,False);
return(ERROR_DOS(ERRDOS,ERRnoaccess));
@@ -861,10 +875,10 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
*pparams = params;
SSVAL(params,0,fsp->fnum);
- SSVAL(params,2,fmode);
+ SSVAL(params,2,open_attr);
put_dos_date2(params,4, mtime);
SIVAL(params,8, (uint32)size);
- SSVAL(params,12,rmode);
+ SSVAL(params,12,open_ofun);
SSVAL(params,16,0); /* Padding. */
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
@@ -2332,7 +2346,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
fsp.conn = conn;
fsp.fnum = -1;
- fsp.fd = -1;
+ fsp.fh->fd = -1;
/* access check */
if (current_user.uid != 0) {
@@ -2709,6 +2723,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
char *pdata = *ppdata;
uint16 info_level;
int mode=0;
+ int nlink;
SMB_OFF_T file_size=0;
SMB_BIG_UINT allocation_size=0;
unsigned int data_size = 0;
@@ -2726,7 +2741,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
files_struct *fsp = NULL;
TALLOC_CTX *ea_ctx = NULL;
struct ea_list *ea_list = NULL;
- uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
+ uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
if (!params)
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
@@ -2751,7 +2766,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
pstrcpy(fname, fsp->fsp_name);
/* We know this name is ok, it's already passed the checks. */
- } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
+ } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
/*
* This is actually a QFILEINFO on a directory
* handle (returned from an NT SMB). NT5.0 seems
@@ -2771,7 +2786,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
- delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
+ delete_pending =
+ get_delete_on_close_flag(sbuf.st_dev,
+ sbuf.st_ino);
} else {
/*
* Original code - this is an open file.
@@ -2779,13 +2796,15 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
CHECK_FSP(fsp,conn);
pstrcpy(fname, fsp->fsp_name);
- if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
+ if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
return(UNIXERROR(ERRDOS,ERRbadfid));
}
- pos = fsp->position_information;
- delete_pending = fsp->delete_on_close;
- desired_access = fsp->desired_access;
+ pos = fsp->fh->position_information;
+ delete_pending =
+ get_delete_on_close_flag(sbuf.st_dev,
+ sbuf.st_ino);
+ access_mask = fsp->access_mask;
}
} else {
NTSTATUS status = NT_STATUS_OK;
@@ -2825,6 +2844,23 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
+
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev,
+ sbuf.st_ino);
+ if (delete_pending) {
+ return ERROR_NT(NT_STATUS_DELETE_PENDING);
+ }
+ }
+
+ nlink = sbuf.st_nlink;
+
+ if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
+ /* NTFS does not seem to count ".." */
+ nlink -= 1;
+ }
+
+ if ((nlink > 0) && delete_pending) {
+ nlink -= 1;
}
if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
@@ -3054,11 +3090,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
data_size = 24;
SOFF_T(pdata,0,allocation_size);
SOFF_T(pdata,8,file_size);
- if (delete_pending & sbuf.st_nlink)
- SIVAL(pdata,16,sbuf.st_nlink - 1);
- else
- SIVAL(pdata,16,sbuf.st_nlink);
- SCVAL(pdata,20,0);
+ SIVAL(pdata,16,nlink);
+ SCVAL(pdata,20,delete_pending?1:0);
SCVAL(pdata,21,(mode&aDIR)?1:0);
SSVAL(pdata,22,0); /* Padding. */
break;
@@ -3129,10 +3162,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
pdata += 40;
SOFF_T(pdata,0,allocation_size);
SOFF_T(pdata,8,file_size);
- if (delete_pending && sbuf.st_nlink)
- SIVAL(pdata,16,sbuf.st_nlink - 1);
- else
- SIVAL(pdata,16,sbuf.st_nlink);
+ SIVAL(pdata,16,nlink);
SCVAL(pdata,20,delete_pending);
SCVAL(pdata,21,(mode&aDIR)?1:0);
SSVAL(pdata,22,0);
@@ -3160,7 +3190,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
case SMB_FILE_ACCESS_INFORMATION:
DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
- SIVAL(pdata,0,desired_access);
+ SIVAL(pdata,0,access_mask);
data_size = 4;
break;
@@ -3343,8 +3373,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
uint16 num_file_acls = 0;
uint16 num_def_acls = 0;
- if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
- file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
+ if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
+ file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
} else {
file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
}
@@ -3429,50 +3459,46 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
open_file_shared. JRA.
****************************************************************************/
-NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
+NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close,
+ uint32 dosmode)
{
- if (delete_on_close) {
- /*
- * Only allow delete on close for writable files.
- */
-
- if (!lp_delete_readonly(SNUM(fsp->conn))) {
- if (dosmode & aRONLY) {
- DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
- fsp->fsp_name ));
- return NT_STATUS_CANNOT_DELETE;
- }
- }
+ if (!delete_on_close) {
+ return NT_STATUS_OK;
+ }
- /*
- * Only allow delete on close for writable shares.
- */
+ /*
+ * Only allow delete on close for writable files.
+ */
- if (!CAN_WRITE(fsp->conn)) {
- DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
- fsp->fsp_name ));
- return NT_STATUS_ACCESS_DENIED;
- }
+ if ((dosmode & aRONLY) &&
+ !lp_delete_readonly(SNUM(fsp->conn))) {
+ DEBUG(10,("can_set_delete_on_close: file %s delete on close "
+ "flag set but file attribute is readonly.\n",
+ fsp->fsp_name ));
+ return NT_STATUS_CANNOT_DELETE;
+ }
- /*
- * Only allow delete on close for files/directories opened with delete intent.
- */
+ /*
+ * Only allow delete on close for writable shares.
+ */
- if (!(fsp->desired_access & DELETE_ACCESS)) {
- DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
- fsp->fsp_name ));
- return NT_STATUS_ACCESS_DENIED;
- }
+ if (!CAN_WRITE(fsp->conn)) {
+ DEBUG(10,("can_set_delete_on_close: file %s delete on "
+ "close flag set but write access denied on share.\n",
+ fsp->fsp_name ));
+ return NT_STATUS_ACCESS_DENIED;
}
- if(fsp->is_directory) {
- fsp->directory_delete_on_close = delete_on_close;
- DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
- delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
- } else {
- fsp->delete_on_close = delete_on_close;
- DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
- delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
+ /*
+ * Only allow delete on close for files/directories opened with delete
+ * intent.
+ */
+
+ if (!(fsp->access_mask & DELETE_ACCESS)) {
+ DEBUG(10,("can_set_delete_on_close: file %s delete on "
+ "close flag set but delete access denied.\n",
+ fsp->fsp_name ));
+ return NT_STATUS_ACCESS_DENIED;
}
return NT_STATUS_OK;
@@ -3487,10 +3513,12 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, u
if flag is set.
****************************************************************************/
-NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
+NTSTATUS set_delete_on_close(files_struct *fsp, BOOL delete_on_close)
{
- DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
- delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
+ DEBUG(10,("set_delete_on_close: %s delete on close flag for "
+ "fnum = %d, file %s\n",
+ delete_on_close ? "Adding" : "Removing", fsp->fnum,
+ fsp->fsp_name ));
if (fsp->is_directory || fsp->is_stat)
return NT_STATUS_OK;
@@ -3499,8 +3527,9 @@ NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
return NT_STATUS_ACCESS_DENIED;
if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
- DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
- fsp->fsp_name ));
+ DEBUG(0,("set_delete_on_close: failed to change delete "
+ "on close flag for file %s\n",
+ fsp->fsp_name ));
unlock_share_entry_fsp(fsp);
return NT_STATUS_ACCESS_DENIED;
}
@@ -3632,7 +3661,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
fsp = file_fsp(params,0);
info_level = SVAL(params,2);
- if(fsp && (fsp->is_directory || fsp->fd == -1)) {
+ if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
/*
* This is actually a SETFILEINFO on a directory
* handle (returned from an NT SMB). NT5.0 seems
@@ -3648,7 +3677,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
* Doing a DELETE_ON_CLOSE should cancel a print job.
*/
if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
- fsp->share_mode = FILE_DELETE_ON_CLOSE;
+ fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
@@ -3664,7 +3693,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
CHECK_FSP(fsp,conn);
pstrcpy(fname, fsp->fsp_name);
- fd = fsp->fd;
+ fd = fsp->fh->fd;
if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
@@ -3881,8 +3910,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
if (fd == -1) {
files_struct *new_fsp = NULL;
- int access_mode = 0;
- int action = 0;
if(global_oplock_break) {
/* Queue this file modify as we are the process of an oplock break. */
@@ -3894,16 +3921,20 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
return -1;
}
- new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
- SET_OPEN_MODE(DOS_OPEN_RDWR),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
+ new_fsp = open_file_ntcreate(conn, fname, &sbuf,
+ FILE_WRITE_DATA,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
FILE_ATTRIBUTE_NORMAL,
- INTERNAL_OPEN_ONLY, &access_mode, &action);
+ INTERNAL_OPEN_ONLY,
+ NULL);
- if (new_fsp == NULL)
+ if (new_fsp == NULL) {
return(UNIXERROR(ERRDOS,ERRbadpath));
+ }
ret = vfs_allocate_file_space(new_fsp, allocation_size);
- if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
+ if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
new_fsp->fnum, strerror(errno)));
ret = -1;
@@ -3963,14 +3994,15 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
if (fsp == NULL)
return(UNIXERROR(ERRDOS,ERRbadfid));
- status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
+ status = can_set_delete_on_close(fsp, delete_on_close,
+ dosmode);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
/* The set is across all open files on this dev/inode pair. */
- status =set_delete_on_close_over_all(fsp, delete_on_close);
+ status =set_delete_on_close(fsp, delete_on_close);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -3998,7 +4030,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
fname, (double)position_information ));
if (fsp) {
- fsp->position_information = position_information;
+ fsp->fh->position_information = position_information;
}
/* We're done. We only get position info in this call. */
@@ -4422,8 +4454,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
if (fd == -1) {
files_struct *new_fsp = NULL;
- int access_mode = 0;
- int action = 0;
if(global_oplock_break) {
/* Queue this file modify as we are the process of an oplock break. */
@@ -4435,22 +4465,27 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
return -1;
}
- new_fsp = open_file_shared(conn, fname, &sbuf,
- SET_OPEN_MODE(DOS_OPEN_RDWR),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
+ new_fsp = open_file_ntcreate(conn, fname, &sbuf,
+ FILE_WRITE_DATA,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
FILE_ATTRIBUTE_NORMAL,
- INTERNAL_OPEN_ONLY, &access_mode, &action);
+ INTERNAL_OPEN_ONLY,
+ NULL);
- if (new_fsp == NULL)
+ if (new_fsp == NULL) {
return(UNIXERROR(ERRDOS,ERRbadpath));
+ }
ret = vfs_set_filelen(new_fsp, size);
close_file(new_fsp,True);
} else {
ret = vfs_set_filelen(fsp, size);
}
- if (ret == -1)
+ if (ret == -1) {
return (UNIXERROR(ERRHRD,ERRdiskfull));
+ }
}
/*
diff --git a/source/smbd/vfs-wrap.c b/source/smbd/vfs-wrap.c
index 1d205e59779..39ac402f346 100644
--- a/source/smbd/vfs-wrap.c
+++ b/source/smbd/vfs-wrap.c
@@ -226,7 +226,7 @@ ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void
if (result == -1 && errno == ESPIPE) {
/* Maintain the fiction that pipes can be seeked (sought?) on. */
result = SMB_VFS_READ(fsp, fd, data, n);
- fsp->pos = 0;
+ fsp->fh->pos = 0;
}
#else /* HAVE_PREAD */
@@ -237,7 +237,7 @@ ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, int fd, void
if (curr == -1 && errno == ESPIPE) {
/* Maintain the fiction that pipes can be seeked (sought?) on. */
result = SMB_VFS_READ(fsp, fd, data, n);
- fsp->pos = 0;
+ fsp->fh->pos = 0;
return result;
}
@@ -660,7 +660,7 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs
SMB_OFF_T retlen;
SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
- retlen = SMB_VFS_WRITE(fsp,fsp->fd,(char *)zero_space,current_len_to_write);
+ retlen = SMB_VFS_WRITE(fsp,fsp->fh->fd,(char *)zero_space,current_len_to_write);
if (retlen <= 0)
return -1;
diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c
index 11adfed6946..67970f203ac 100644
--- a/source/smbd/vfs.c
+++ b/source/smbd/vfs.c
@@ -430,7 +430,7 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
while (total < byte_count)
{
- ssize_t ret = SMB_VFS_READ(fsp, fsp->fd, buf + total,
+ ssize_t ret = SMB_VFS_READ(fsp, fsp->fh->fd, buf + total,
byte_count - total);
if (ret == 0) return total;
@@ -452,7 +452,7 @@ ssize_t vfs_pread_data(files_struct *fsp, char *buf,
while (total < byte_count)
{
- ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fd, buf + total,
+ ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fh->fd, buf + total,
byte_count - total, offset + total);
if (ret == 0) return total;
@@ -477,7 +477,7 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N)
ssize_t ret;
while (total < N) {
- ret = SMB_VFS_WRITE(fsp,fsp->fd,buffer + total,N - total);
+ ret = SMB_VFS_WRITE(fsp,fsp->fh->fd,buffer + total,N - total);
if (ret == -1)
return -1;
@@ -496,7 +496,7 @@ ssize_t vfs_pwrite_data(files_struct *fsp,const char *buffer,
ssize_t ret;
while (total < N) {
- ret = SMB_VFS_PWRITE(fsp, fsp->fd, buffer + total,
+ ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, buffer + total,
N - total, offset + total);
if (ret == -1)
@@ -535,7 +535,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len)
return -1;
}
- ret = SMB_VFS_FSTAT(fsp,fsp->fd,&st);
+ ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st);
if (ret == -1)
return ret;
@@ -549,7 +549,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len)
fsp->fsp_name, (double)st.st_size ));
flush_write_cache(fsp, SIZECHANGE_FLUSH);
- if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, (SMB_OFF_T)len)) != -1) {
+ if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, (SMB_OFF_T)len)) != -1) {
set_filelen_write_cache(fsp, len);
}
return ret;
@@ -591,7 +591,7 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len)
release_level_2_oplocks_on_change(fsp);
DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len));
flush_write_cache(fsp, SIZECHANGE_FLUSH);
- if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, len)) != -1)
+ if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fh->fd, len)) != -1)
set_filelen_write_cache(fsp, len);
return ret;
@@ -617,7 +617,7 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
ssize_t pwrite_ret;
release_level_2_oplocks_on_change(fsp);
- ret = SMB_VFS_FSTAT(fsp,fsp->fd,&st);
+ ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st);
if (ret == -1) {
return ret;
}
@@ -646,7 +646,7 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
while (total < num_to_write) {
size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (num_to_write - total));
- pwrite_ret = SMB_VFS_PWRITE(fsp, fsp->fd, sparse_buf, curr_write_size, offset + total);
+ pwrite_ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, sparse_buf, curr_write_size, offset + total);
if (pwrite_ret == -1) {
DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n",
fsp->fsp_name, strerror(errno) ));
@@ -685,7 +685,7 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n)
in_fsp = in;
out_fsp = out;
- return transfer_file_internal(in_fsp->fd, out_fsp->fd, n, read_fn, write_fn);
+ return transfer_file_internal(in_fsp->fh->fd, out_fsp->fh->fd, n, read_fn, write_fn);
}
/*******************************************************************
diff --git a/source/torture/cmd_vfs.c b/source/torture/cmd_vfs.c
index 2c977485449..974d3b8feed 100644
--- a/source/torture/cmd_vfs.c
+++ b/source/torture/cmd_vfs.c
@@ -286,7 +286,7 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c
vfs->files[fd] = SMB_MALLOC_P(struct files_struct);
vfs->files[fd]->fsp_name = SMB_STRDUP(argv[1]);
- vfs->files[fd]->fd = fd;
+ vfs->files[fd]->fh->fd = fd;
vfs->files[fd]->conn = vfs->conn;
printf("open: fd=%d\n", fd);
return NT_STATUS_OK;
diff --git a/source/utils/status.c b/source/utils/status.c
index 75e7cb3de71..f3c88616662 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -111,37 +111,47 @@ static void print_share_mode(share_mode_entry *e, char *fname)
count++;
if (Ucrit_checkPid(e->pid)) {
- d_printf("%-5d ",(int)e->pid);
- switch (GET_DENY_MODE(e->share_mode)) {
- case DENY_NONE: d_printf("DENY_NONE "); break;
- case DENY_ALL: d_printf("DENY_ALL "); break;
- case DENY_DOS: d_printf("DENY_DOS "); break;
- case DENY_READ: d_printf("DENY_READ "); break;
- case DENY_WRITE:printf("DENY_WRITE "); break;
- case DENY_FCB: d_printf("DENY_FCB "); break;
- }
- d_printf("0x%-8x ",(unsigned int)e->desired_access);
- switch (e->share_mode&0xF) {
- case 0: d_printf("RDONLY "); break;
- case 1: d_printf("WRONLY "); break;
- case 2: d_printf("RDWR "); break;
- }
-
- if((e->op_type &
- (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ==
- (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
- d_printf("EXCLUSIVE+BATCH ");
- else if (e->op_type & EXCLUSIVE_OPLOCK)
- d_printf("EXCLUSIVE ");
- else if (e->op_type & BATCH_OPLOCK)
- d_printf("BATCH ");
- else if (e->op_type & LEVEL_II_OPLOCK)
- d_printf("LEVEL_II ");
- else
- d_printf("NONE ");
-
- d_printf(" %s %s",fname,
- asctime(LocalTime((time_t *)&e->time.tv_sec)));
+ d_printf("%-5d ",(int)e->pid);
+ switch (map_share_mode_to_deny_mode(e->share_access,
+ e->private_options)) {
+ case DENY_NONE: d_printf("DENY_NONE "); break;
+ case DENY_ALL: d_printf("DENY_ALL "); break;
+ case DENY_DOS: d_printf("DENY_DOS "); break;
+ case DENY_READ: d_printf("DENY_READ "); break;
+ case DENY_WRITE:printf("DENY_WRITE "); break;
+ case DENY_FCB: d_printf("DENY_FCB "); break;
+ default: {
+ d_printf("unknown-please report ! "
+ "e->share_access = 0x%x, "
+ "e->private_options = 0x%x\n",
+ (unsigned int)e->share_access,
+ (unsigned int)e->private_options );
+ break;
+ }
+ }
+ d_printf("0x%-8x ",(unsigned int)e->access_mask);
+ if (e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA)) {
+ d_printf("RDWR ");
+ } else if (e->access_mask & FILE_WRITE_DATA) {
+ d_printf("WRONLY ");
+ } else {
+ d_printf("RDONLY ");
+ }
+
+ if((e->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ==
+ (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) {
+ d_printf("EXCLUSIVE+BATCH ");
+ } else if (e->op_type & EXCLUSIVE_OPLOCK) {
+ d_printf("EXCLUSIVE ");
+ } else if (e->op_type & BATCH_OPLOCK) {
+ d_printf("BATCH ");
+ } else if (e->op_type & LEVEL_II_OPLOCK) {
+ d_printf("LEVEL_II ");
+ } else {
+ d_printf("NONE ");
+ }
+
+ d_printf(" %s %s",fname, asctime(LocalTime((time_t *)&e->time.tv_sec)));
}
}
diff --git a/source/web/cgi.c b/source/web/cgi.c
index 5d52ad62793..6c9cfce13cd 100644
--- a/source/web/cgi.c
+++ b/source/web/cgi.c
@@ -457,6 +457,10 @@ static void cgi_download(char *file)
printf("Content-Type: image/gif\r\n");
} else if (strcmp(p,".jpg")==0) {
printf("Content-Type: image/jpeg\r\n");
+ } else if (strcmp(p,".png")==0) {
+ printf("Content-Type: image/png\r\n");
+ } else if (strcmp(p,".css")==0) {
+ printf("Content-Type: text/css\r\n");
} else if (strcmp(p,".txt")==0) {
printf("Content-Type: text/plain\r\n");
} else {
diff --git a/source/web/statuspage.c b/source/web/statuspage.c
index 57b5d0f7b73..871e07b5d06 100644
--- a/source/web/statuspage.c
+++ b/source/web/statuspage.c
@@ -108,23 +108,28 @@ static char *tstring(time_t t)
static void print_share_mode(share_mode_entry *e, char *fname)
{
char *utf8_fname;
+ int deny_mode = map_share_mode_to_deny_mode(e->share_access,
+ e->private_options);
printf("<tr><td>%s</td>",_(mapPid2Machine(e->pid)));
printf("<td>");
- switch ((e->share_mode>>4)&0xF) {
+ switch ((deny_mode>>4)&0xF) {
case DENY_NONE: printf("DENY_NONE"); break;
case DENY_ALL: printf("DENY_ALL "); break;
case DENY_DOS: printf("DENY_DOS "); break;
+ case DENY_FCB: printf("DENY_FCB "); break;
case DENY_READ: printf("DENY_READ "); break;
case DENY_WRITE:printf("DENY_WRITE "); break;
}
printf("</td>");
printf("<td>");
- switch (e->share_mode&0xF) {
- case 0: printf("%s", _("RDONLY ")); break;
- case 1: printf("%s", _("WRONLY ")); break;
- case 2: printf("%s", _("RDWR ")); break;
+ if (e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA)) {
+ printf("%s", _("RDWR "));
+ } else if (e->access_mask & FILE_WRITE_DATA) {
+ printf("%s", _("WRONLY "));
+ } else {
+ printf("%s", _("RDONLY "));
}
printf("</td>");