summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2002-02-26 17:58:17 +0000
committerJeremy Allison <jra@samba.org>2002-02-26 17:58:17 +0000
commite085782dfacd077e3616887b758c5a4e822ea9a9 (patch)
treec842615d8b953ba85efbe222cd0e363dac4e5cd9
parent1716c915dfa609890e0bbb4122e6ab683362cae6 (diff)
downloadsamba-e085782dfacd077e3616887b758c5a4e822ea9a9.tar.gz
samba-e085782dfacd077e3616887b758c5a4e822ea9a9.tar.xz
samba-e085782dfacd077e3616887b758c5a4e822ea9a9.zip
Back port tridge's xcopy /o fix.
Jeremy.
-rw-r--r--source/include/proto.h6
-rw-r--r--source/smbd/nttrans.c9
-rw-r--r--source/smbd/open.c61
3 files changed, 59 insertions, 17 deletions
diff --git a/source/include/proto.h b/source/include/proto.h
index 1a254a89f31..789cf69d819 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -4290,7 +4290,11 @@ int reply_nttrans(connection_struct *conn,
int fd_close(struct connection_struct *conn, files_struct *fsp);
files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
- int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action);
+ int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action);
+files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
+ uint32 desired_access,
+ int share_mode,int ofun, mode_t mode,int oplock_request,
+ int *Access,int *action);
files_struct *open_file_stat(connection_struct *conn, char *fname,
SMB_STRUCT_STAT *psbuf, int smb_ofun, int *action);
files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf);
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 110d7ed7d26..1af57462d42 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -808,8 +808,11 @@ int reply_ntcreate_and_X(connection_struct *conn,
* before issuing an oplock break request to
* our client. JRA. */
- fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode,
- smb_ofun,unixmode, oplock_request,&rmode,&smb_action);
+ fsp = open_file_shared1(conn,fname,&sbuf,
+ desired_access,
+ smb_open_mode,
+ smb_ofun, unixmode, oplock_request,
+ &rmode,&smb_action);
if (!fsp) {
/* We cheat here. There are two cases we
@@ -1311,7 +1314,7 @@ static int call_nt_transact_create(connection_struct *conn,
* Ordinary file case.
*/
- fsp = open_file_shared(conn,fname,&sbuf,smb_open_mode,smb_ofun,unixmode,
+ fsp = open_file_shared1(conn,fname,&sbuf,desired_access,smb_open_mode,smb_ofun,unixmode,
oplock_request,&rmode,&smb_action);
if (!fsp) {
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 4b659305473..e12317f4313 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -447,8 +447,10 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i
****************************************************************************/
static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T dev,
- SMB_INO_T inode, int share_mode, int *p_flags, int *p_oplock_request,
- BOOL *p_all_current_opens_are_level_II)
+ SMB_INO_T inode,
+ uint32 desired_access,
+ int share_mode, int *p_flags, int *p_oplock_request,
+ BOOL *p_all_current_opens_are_level_II)
{
int i;
int num_share_modes;
@@ -520,13 +522,28 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
*p_all_current_opens_are_level_II = False;
}
- /* someone else has a share lock on it, check to see
- if we can too */
- if(check_share_mode(conn, share_entry, share_mode, fname, fcbopen, p_flags) == False) {
- SAFE_FREE(old_shares);
- errno = EACCES;
- return -1;
+ /* 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
+ This code should be removed once we have a propoer ntcreateX
+ open functions
+ (tridge)
+ */
+ if (desired_access == 0 ||
+ (desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE))) {
+ /* someone else has a share lock on it, check to see
+ if we can too */
+ if (!check_share_mode(conn, share_entry, share_mode,
+ fname, fcbopen, p_flags)) {
+ SAFE_FREE(old_shares);
+ errno = EACCES;
+ return -1;
+ }
}
} /* end for */
@@ -614,8 +631,23 @@ static void kernel_flock(files_struct *fsp, int deny_mode)
Open a file with a share mode. On output from this open we are guarenteeing
that
****************************************************************************/
+
files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
- int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action)
+ int share_mode,int ofun, mode_t mode,int oplock_request, int *Access,int *action)
+{
+ return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, mode,
+ oplock_request, Access, action);
+}
+
+/****************************************************************************
+ Open a file with a share mode. On output from this open we are guarenteeing
+ that
+****************************************************************************/
+
+files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
+ uint32 desired_access,
+ int share_mode,int ofun, mode_t mode,int oplock_request,
+ int *Access,int *action)
{
int flags=0;
int flags2=0;
@@ -744,8 +776,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S
lock_share_entry(conn, dev, inode);
- num_share_modes = open_mode_check(conn, fname, dev, inode, share_mode,
- &flags, &oplock_request, &all_current_opens_are_level_II);
+ num_share_modes = open_mode_check(conn, fname, dev, inode,
+ desired_access, share_mode,
+ &flags, &oplock_request, &all_current_opens_are_level_II);
+
if(num_share_modes == -1) {
/*
@@ -809,8 +843,9 @@ 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, share_mode,
- &flags, &oplock_request, &all_current_opens_are_level_II);
+ num_share_modes = open_mode_check(conn, fname, dev, inode,
+ desired_access, share_mode,
+ &flags, &oplock_request, &all_current_opens_are_level_II);
if(num_share_modes == -1) {
unlock_share_entry_fsp(fsp);