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 | 9bb7ac81b6e4d33e1be49447dbdbbb8d24259f53 (patch) | |
tree | 0bffe55dcb3dee8574d89546af83bd44cd476491 /source3/smbd | |
parent | 1e60cc49f5ecb864ab965a6e7ab9287e1204d1d6 (diff) | |
download | samba-9bb7ac81b6e4d33e1be49447dbdbbb8d24259f53.tar.gz samba-9bb7ac81b6e4d33e1be49447dbdbbb8d24259f53.tar.bz2 samba-9bb7ac81b6e4d33e1be49447dbdbbb8d24259f53.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.
(This used to be commit 5e6a7cd99d29d1cf068fc517272559c1cf47ea3a)
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/close.c | 1 | ||||
-rw-r--r-- | source3/smbd/files.c | 35 | ||||
-rw-r--r-- | source3/smbd/open.c | 23 | ||||
-rw-r--r-- | source3/smbd/reply.c | 2 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 52 |
5 files changed, 109 insertions, 4 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 2dba691a1c..50ad01f575 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -142,6 +142,7 @@ void close_file(files_struct *fsp, BOOL normal_close) */ if (normal_close && last_reference && delete_on_close) { + DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n")); if(dos_unlink(fsp->fsp_name) != 0) DEBUG(0,("close_file: file %s. Delete on close was set and unlink failed \ with error %s\n", fsp->fsp_name, strerror(errno) )); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index c369a45bab..e58c3834a0 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -277,6 +277,41 @@ files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval return NULL; } +/**************************************************************************** + Find the first fsp given a device and inode. +****************************************************************************/ + +files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) +{ + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp->open && + fsp->fd_ptr->dev == dev && + fsp->fd_ptr->inode == inode ) + return fsp; + } + + return NULL; +} + +/**************************************************************************** + Find the next fsp having the same device and inode. +****************************************************************************/ + +files_struct *file_find_di_next(files_struct *start_fsp) +{ + files_struct *fsp; + + for (fsp = start_fsp->next;fsp;fsp=fsp->next) { + if (fsp->open && + fsp->fd_ptr->dev == start_fsp->fd_ptr->dev && + fsp->fd_ptr->inode == start_fsp->fd_ptr->inode ) + return fsp; + } + + return NULL; +} /**************************************************************************** find a fsp that is open for printing diff --git a/source3/smbd/open.c b/source3/smbd/open.c index b6b2ef5bb8..aac4b02fba 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -659,6 +659,26 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, int old_open_mode = GET_OPEN_MODE(share->share_mode); int old_deny_mode = GET_DENY_MODE(share->share_mode); + /* + * Setup the potential error to return. + */ + + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + + /* + * Don't allow any open 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 )); + unix_ERR_code = ERRnoaccess; + return False; + } + if (old_deny_mode > 4 || old_open_mode > 2) { DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", @@ -688,6 +708,7 @@ static int check_share_mode( share_mode_entry *share, int deny_mode, *flags = O_WRONLY; } + return True; } @@ -865,8 +886,6 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou free((char *)old_shares); unlock_share_entry(conn, dev, inode, token); errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; return; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bc19f1a931..babdd2056c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3615,7 +3615,7 @@ no oplock granted on this file.\n", fsp->fnum)); /* Remove the oplock flag from the sharemode. */ lock_share_entry(fsp->conn, dev, inode, &token); - if(remove_share_oplock(fsp, token)==False) { + if(remove_share_oplock(token, fsp)==False) { DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index f8d90cd871..1c2bdb1ddf 100644 --- a/source3/smbd/trans2.c +++ b/source3/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; |