diff options
author | Jeremy Allison <jra@samba.org> | 1998-10-23 03:34:50 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 1998-10-23 03:34:50 +0000 |
commit | 5e6a7cd99d29d1cf068fc517272559c1cf47ea3a (patch) | |
tree | 26f9188c69683491516c6bc3ee4a5e7599552c93 /source/smbd/trans2.c | |
parent | a66c56d70e7e663f3a19cbfcc2e704653d8fc9b2 (diff) | |
download | samba-5e6a7cd99d29d1cf068fc517272559c1cf47ea3a.tar.gz samba-5e6a7cd99d29d1cf068fc517272559c1cf47ea3a.tar.xz samba-5e6a7cd99d29d1cf068fc517272559c1cf47ea3a.zip |
Reasonably large change to give us *exactly* correct NT delete on close semantics.
This was trickier than it looks :-). Check out the new DELETE_ON_CLOSE
flag in the share modes and the new code that iterates through all open
files on the same device and inode in files.c and trans2.c
Also changed the code that modifies share mode entries to take
generic function pointers rather than doing a specific thing so
this sort of change should be easier in the future.
Jeremy.
Diffstat (limited to 'source/smbd/trans2.c')
-rw-r--r-- | source/smbd/trans2.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index f8d90cd8718..1c2bdb1ddfa 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -1655,14 +1655,64 @@ static int call_trans2setfilepathinfo(connection_struct *conn, { if (tran_call == TRANSACT2_SETFILEINFO) { files_struct *fsp = file_fsp(params,0); + BOOL delete_on_close = (CVAL(pdata,0) ? True : False); + if(fsp->is_directory) return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * We can only set the delete on close flag if + * the share mode contained ALLOW_SHARE_DELETE + */ + + if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode)) + return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * If the flag has changed from its previous value then + * modify the share mode entry for all files we have open + * on this device and inode to tell other smbds we have + * changed the delete on close flag. + */ + + if(GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode) != delete_on_close) + { + int token; + files_struct *iterate_fsp; + SMB_DEV_T dev = fsp->fd_ptr->dev; + SMB_INO_T inode = fsp->fd_ptr->inode; + int new_share_mode = (delete_on_close ? + (fsp->share_mode | DELETE_ON_CLOSE_FLAG) : + (fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) ); + + DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name )); + + if(lock_share_entry(fsp->conn, dev, inode, &token) == False) + return(ERROR(ERRDOS,ERRnoaccess)); + + /* + * Go through all files we have open on the same device and + * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG. + */ + + for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp; + iterate_fsp = file_find_di_next(iterate_fsp)) + { + if(modify_share_mode(token, iterate_fsp, new_share_mode)==False) + DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \ +dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); + } + + unlock_share_entry(fsp->conn, dev, inode, token); + } + /* * Set the delete on close flag in the reference * counted struct. Delete when the last reference * goes away. */ - fsp->fd_ptr->delete_on_close = CVAL(pdata,0); + fsp->fd_ptr->delete_on_close = delete_on_close; } else return(ERROR(ERRDOS,ERRunknownlevel)); break; |