This is a nasty hack to fix "xcopy /o" from win2000 on a Samba share
authorAndrew Tridgell <tridge@samba.org>
Tue, 26 Feb 2002 05:45:33 +0000 (05:45 +0000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 26 Feb 2002 05:45:33 +0000 (05:45 +0000)
The hack passes the true ntcreate desired_access down to open_file_shared1()
from the ntcreatex function. This is used to determine if share modes
should be used in denying this open.

This hack will become unnecessary when we redo open.c to use the proper
NTCreateX semantics rather than trying to jam the ntcreate semantics into
openX semantics.

source/smbd/nttrans.c
source/smbd/open.c

index 694cfb92a311a945634def7c2b998a61d04cf63d..501f0e9ab05ddd50ac8d5cba85a282c0e4db7d70 100644 (file)
@@ -717,8 +717,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
@@ -1213,7 +1216,8 @@ 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) { 
index aab7b5079e66ed4377847cce966ed19156718348..7396233c26e4176da9616ef6adc2e380ca354a4f 100644 (file)
@@ -437,8 +437,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;
@@ -510,13 +512,27 @@ 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 */
@@ -608,6 +624,19 @@ static void kernel_flock(files_struct *fsp, int deny_mode)
 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)
+{
+       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;
@@ -736,8 +765,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) {
 
                        /*
@@ -801,8 +832,10 @@ 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);