#include "includes.h"
+extern struct current_user current_user;
+
/****************************************************************************
Run a file if it is a magic script.
****************************************************************************/
Deal with removing a share mode on last close.
****************************************************************************/
-static int close_remove_share_mode(files_struct *fsp, enum file_close_type close_type)
+static NTSTATUS close_remove_share_mode(files_struct *fsp,
+ enum file_close_type close_type)
{
connection_struct *conn = fsp->conn;
BOOL delete_file = False;
struct share_mode_lock *lck;
SMB_STRUCT_STAT sbuf;
+ NTSTATUS status = NT_STATUS_OK;
/*
* Lock the share entries, and determine if we should delete
if (lck == NULL) {
DEBUG(0, ("close_remove_share_mode: Could not get share mode "
"lock for file %s\n", fsp->fsp_name));
- return EINVAL;
+ return NT_STATUS_INVALID_PARAMETER;
}
if (!del_share_mode(lck, fsp)) {
"entry for file %s\n", fsp->fsp_name));
}
- delete_file = (lck->delete_on_close | lck->initial_delete_on_close);
+ if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
+ BOOL became_user = False;
+
+ /* Initial delete on close was set and no one else
+ * wrote a real delete on close. */
+
+ if (current_user.vuid != fsp->vuid) {
+ become_user(conn, fsp->vuid);
+ became_user = True;
+ }
+ set_delete_on_close_lck(lck, True, ¤t_user.ut);
+ if (became_user) {
+ unbecome_user();
+ }
+ }
+
+ delete_file = lck->delete_on_close;
if (delete_file) {
int i;
|| !delete_file
|| (lck->delete_token == NULL)) {
TALLOC_FREE(lck);
- return 0;
+ return NT_STATUS_OK;
}
/*
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) ));
+ /*
+ * Don't save the errno here, we ignore this error
+ */
goto done;
}
fsp->fsp_name,
(unsigned int)fsp->dev, (double)fsp->inode,
(unsigned int)sbuf.st_dev, (double)sbuf.st_ino ));
+ /*
+ * Don't save the errno here, we ignore this error
+ */
goto done;
}
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) ));
+
+ status = map_nt_error_from_unix(errno);
goto done;
}
+ status = NT_STATUS_FILE_DELETED;
+
done:
/* unbecome user. */
pop_sec_ctx();
- process_pending_change_notify_queue((time_t)0);
-
TALLOC_FREE(lck);
- return 0;
+ return status;
}
/****************************************************************************
DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
}
- delete_dir = (lck->delete_on_close | lck->initial_delete_on_close);
+ if (fsp->initial_delete_on_close) {
+ BOOL became_user = False;
+
+ /* Initial delete on close was set - for
+ * directories we don't care if anyone else
+ * wrote a real delete on close. */
+
+ if (current_user.vuid != fsp->vuid) {
+ become_user(fsp->conn, fsp->vuid);
+ became_user = True;
+ }
+ send_stat_cache_delete_message(fsp->fsp_name);
+ set_delete_on_close_lck(lck, True, ¤t_user.ut);
+ if (became_user) {
+ unbecome_user();
+ }
+ }
+
+ delete_dir = lck->delete_on_close;
+
+ if (delete_dir) {
+ int i;
+ /* See if others still have the dir open. If this is the
+ * case, then don't delete */
+ for (i=0; i<lck->num_share_modes; i++) {
+ if (is_valid_share_mode_entry(&lck->share_modes[i])) {
+ delete_dir = False;
+ break;
+ }
+ }
+ }
if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
delete_dir &&
if(ok) {
remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
- remove_pending_change_notify_requests_by_filename(fsp, NT_STATUS_DELETE_PENDING);
-
}
- process_pending_change_notify_queue((time_t)0);
} else {
TALLOC_FREE(lck);
remove_pending_change_notify_requests_by_fid(