diff options
-rw-r--r-- | source3/smbd/close.c | 118 |
1 files changed, 67 insertions, 51 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 282c4acb24..bc2d6c3507 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -149,6 +149,7 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close connection_struct *conn = fsp->conn; BOOL delete_file = False; struct share_mode_lock *lck; + SMB_STRUCT_STAT sbuf; /* * Lock the share entries, and determine if we should delete @@ -159,12 +160,14 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); if (lck == NULL) { - DEBUG(0, ("close_remove_share_mode: Could not get share mode lock for file %s\n", fsp->fsp_name)); + DEBUG(0, ("close_remove_share_mode: Could not get share mode " + "lock for file %s\n", fsp->fsp_name)); return EINVAL; } if (!del_share_mode(lck, fsp)) { - DEBUG(0, ("close_remove_share_mode: Could not delete share entry for file %s\n", fsp->fsp_name)); + DEBUG(0, ("close_remove_share_mode: Could not delete share " + "entry for file %s\n", fsp->fsp_name)); } delete_file = (lck->delete_on_close | lck->initial_delete_on_close); @@ -190,63 +193,76 @@ static int close_remove_share_mode(files_struct *fsp, enum file_close_type close * reference to a file. */ - if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && - delete_file && - lck->delete_token) { - SMB_STRUCT_STAT sbuf; + if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) + || !delete_file + || (lck->delete_token == NULL)) { + TALLOC_FREE(lck); + return 0; + } - DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set - deleting file.\n", - fsp->fsp_name)); + /* + * Ok, we have to delete the file + */ - /* Become the user who requested the delete. */ + DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " + "- deleting file.\n", fsp->fsp_name)); - if (!push_sec_ctx()) { - smb_panic("close_remove_share_mode: file %s. failed to push sec_ctx.\n"); - } + /* Become the user who requested the delete. */ - set_sec_ctx(lck->delete_token->uid, - lck->delete_token->gid, - lck->delete_token->ngroups, - lck->delete_token->groups, - NULL); + if (!push_sec_ctx()) { + smb_panic("close_remove_share_mode: file %s. failed to push " + "sec_ctx.\n"); + } - /* We can only delete the file if the name we have - is still valid and hasn't been renamed. */ - - if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) { - DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " - "and stat failed with error %s\n", - fsp->fsp_name, strerror(errno) )); - } else { - if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { - DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set and " - "dev and/or inode does not match\n", - fsp->fsp_name )); - DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, inode = %.0f " - "stat dev = %x, inode = %.0f\n", - fsp->fsp_name, - (unsigned int)fsp->dev, (double)fsp->inode, - (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); - - } else if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { - /* - * This call can potentially fail as another smbd may have - * had the file open with delete on close set and deleted - * it when its last reference to this file went away. Hence - * we log this but not at debug level zero. - */ - - DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " - "and unlink failed with error %s\n", - fsp->fsp_name, strerror(errno) )); - } - } - /* unbecome user. */ - pop_sec_ctx(); + set_sec_ctx(lck->delete_token->uid, + lck->delete_token->gid, + lck->delete_token->ngroups, + lck->delete_token->groups, + NULL); + + /* We can only delete the file if the name we have is still valid and + hasn't been renamed. */ - process_pending_change_notify_queue((time_t)0); + if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) { + DEBUG(5,("close_remove_share_mode: file %s. Delete on close " + "was set and stat failed with error %s\n", + fsp->fsp_name, strerror(errno) )); + goto done; + } + + if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { + DEBUG(5,("close_remove_share_mode: file %s. Delete on close " + "was set and dev and/or inode does not match\n", + fsp->fsp_name )); + DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, " + "inode = %.0f stat dev = %x, inode = %.0f\n", + fsp->fsp_name, + (unsigned int)fsp->dev, (double)fsp->inode, + (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); + goto done; + } + + if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { + /* + * This call can potentially fail as another smbd may + * have had the file open with delete on close set and + * deleted it when its last reference to this file + * went away. Hence we log this but not at debug level + * zero. + */ + + DEBUG(5,("close_remove_share_mode: file %s. Delete on close " + "was set and unlink failed with error %s\n", + fsp->fsp_name, strerror(errno) )); + goto done; } + done: + /* unbecome user. */ + pop_sec_ctx(); + + process_pending_change_notify_queue((time_t)0); + TALLOC_FREE(lck); return 0; } |