diff options
author | Jeremy Allison <jra@samba.org> | 2002-02-26 17:58:17 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2002-02-26 17:58:17 +0000 |
commit | e085782dfacd077e3616887b758c5a4e822ea9a9 (patch) | |
tree | c842615d8b953ba85efbe222cd0e363dac4e5cd9 | |
parent | 1716c915dfa609890e0bbb4122e6ab683362cae6 (diff) | |
download | samba-e085782dfacd077e3616887b758c5a4e822ea9a9.tar.gz samba-e085782dfacd077e3616887b758c5a4e822ea9a9.tar.xz samba-e085782dfacd077e3616887b758c5a4e822ea9a9.zip |
Back port tridge's xcopy /o fix.
Jeremy.
-rw-r--r-- | source/include/proto.h | 6 | ||||
-rw-r--r-- | source/smbd/nttrans.c | 9 | ||||
-rw-r--r-- | source/smbd/open.c | 61 |
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); |