#include "includes.h"
#include "system/filesys.h"
+#include "lib/util/server_id.h"
#include "printing.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
+#include "smbd/scavenger.h"
#include "fake_file.h"
#include "transfer_file.h"
#include "auth.h"
#include "messages.h"
+#include "../librpc/gen_ndr/open_files.h"
/****************************************************************************
Run a file if it is a magic script.
char *fname = NULL;
NTSTATUS status;
- if (!*lp_magicscript(SNUM(conn))) {
+ if (!*lp_magic_script(talloc_tos(), SNUM(conn))) {
return NT_STATUS_OK;
}
p++;
}
- if (!strequal(lp_magicscript(SNUM(conn)),p)) {
+ if (!strequal(lp_magic_script(talloc_tos(), SNUM(conn)),p)) {
status = NT_STATUS_OK;
goto out;
}
- if (*lp_magicoutput(SNUM(conn))) {
- magic_output = lp_magicoutput(SNUM(conn));
+ if (*lp_magic_output(talloc_tos(), SNUM(conn))) {
+ magic_output = lp_magic_output(talloc_tos(), SNUM(conn));
} else {
magic_output = talloc_asprintf(ctx,
"%s.out",
status = map_nt_error_from_unix(errno);
goto out;
}
- ret = smbrun(p,&tmp_fd);
+ ret = smbrun(p, &tmp_fd, NULL);
DEBUG(3,("Invoking magic command %s gave %d\n",
p,ret));
goto out;
}
- if (transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_ex_size) == (SMB_OFF_T)-1) {
+ if (transfer_file(tmp_fd,outfd,(off_t)st.st_ex_size) == (off_t)-1) {
int err = errno;
close(tmp_fd);
close(outfd);
NTSTATUS status = NT_STATUS_OK;
if (fsp->fh->fd != -1) {
- if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
+ if(flush_write_cache(fsp, SAMBA_CLOSE_FLUSH) == -1) {
status = map_nt_error_from_unix(errno);
}
delete_write_cache(fsp);
return status;
}
-/****************************************************************************
- If any deferred opens are waiting on this close, notify them.
-****************************************************************************/
-
-static void notify_deferred_opens(struct messaging_context *msg_ctx,
- struct share_mode_lock *lck)
-{
- int i;
-
- if (!should_notify_deferred_opens()) {
- return;
- }
-
- for (i=0; i<lck->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->share_modes[i];
-
- if (!is_deferred_open_entry(e)) {
- continue;
- }
-
- if (procid_is_me(&e->pid)) {
- /*
- * We need to notify ourself to retry the open. Do
- * this by finding the queued SMB record, moving it to
- * the head of the queue and changing the wait time to
- * zero.
- */
- schedule_deferred_open_message_smb(e->op_mid);
- } else {
- char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
-
- share_mode_entry_to_message(msg, e);
-
- messaging_send_buf(msg_ctx, e->pid, MSG_SMB_OPEN_RETRY,
- (uint8 *)msg,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
- }
- }
-}
-
/****************************************************************************
Delete all streams
****************************************************************************/
-NTSTATUS delete_all_streams(connection_struct *conn, const char *fname)
+NTSTATUS delete_all_streams(connection_struct *conn,
+ const struct smb_filename *smb_fname)
{
- struct stream_struct *stream_info;
+ struct stream_struct *stream_info = NULL;
int i;
- unsigned int num_streams;
+ unsigned int num_streams = 0;
TALLOC_CTX *frame = talloc_stackframe();
NTSTATUS status;
- status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(),
- &num_streams, &stream_info);
+ status = vfs_streaminfo(conn, NULL, smb_fname, talloc_tos(),
+ &num_streams, &stream_info);
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
DEBUG(10, ("no streams around\n"));
}
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n",
+ DEBUG(10, ("vfs_streaminfo failed: %s\n",
nt_errstr(status)));
goto fail;
}
for (i=0; i<num_streams; i++) {
int res;
- struct smb_filename *smb_fname_stream = NULL;
+ struct smb_filename *smb_fname_stream;
if (strequal(stream_info[i].name, "::$DATA")) {
continue;
}
- status = create_synthetic_smb_fname(talloc_tos(), fname,
- stream_info[i].name, NULL,
- &smb_fname_stream);
+ smb_fname_stream = synthetic_smb_fname(talloc_tos(),
+ smb_fname->base_name,
+ stream_info[i].name,
+ NULL,
+ (smb_fname->flags &
+ ~SMB_FILENAME_POSIX_PATH));
- if (!NT_STATUS_IS_OK(status)) {
+ if (smb_fname_stream == NULL) {
DEBUG(0, ("talloc_aprintf failed\n"));
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
enum file_close_type close_type)
{
connection_struct *conn = fsp->conn;
+ struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
bool delete_file = false;
bool changed_user = false;
struct share_mode_lock *lck = NULL;
NTSTATUS tmp_status;
struct file_id id;
const struct security_unix_token *del_token = NULL;
+ const struct security_token *del_nt_token = NULL;
+ bool got_tokens = false;
+ bool normal_close;
/* Ensure any pending write time updates are done. */
if (fsp->update_write_time_event) {
- update_write_time_handler(smbd_event_context(),
+ update_write_time_handler(fsp->conn->sconn->ev_ctx,
fsp->update_write_time_event,
timeval_current(),
(void *)fsp);
* This prevents race conditions with the file being created. JRA.
*/
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
- NULL);
-
+ lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
if (lck == NULL) {
DEBUG(0, ("close_remove_share_mode: Could not get share mode "
"lock for file %s\n", fsp_str_dbg(fsp)));
- status = NT_STATUS_INVALID_PARAMETER;
- goto done;
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Remove the oplock before potentially deleting the file. */
+ if(fsp->oplock_type) {
+ remove_oplock_under_lock(fsp, lck);
}
if (fsp->write_time_forced) {
DEBUG(10,("close_remove_share_mode: write time forced "
"for file %s\n",
fsp_str_dbg(fsp)));
- set_close_write_time(fsp, lck->changed_write_time);
+ set_close_write_time(fsp, lck->data->changed_write_time);
} else if (fsp->update_write_time_on_close) {
/* Someone had a pending write. */
if (null_timespec(fsp->close_write_time)) {
}
}
- if (!del_share_mode(lck, fsp)) {
- DEBUG(0, ("close_remove_share_mode: Could not delete share "
- "entry for file %s\n",
- fsp_str_dbg(fsp)));
- }
-
if (fsp->initial_delete_on_close &&
!is_delete_on_close_set(lck, fsp->name_hash)) {
bool became_user = False;
became_user = True;
}
fsp->delete_on_close = true;
- set_delete_on_close_lck(fsp, lck, True, get_current_utok(conn));
+ set_delete_on_close_lck(fsp, lck,
+ get_current_nttok(conn),
+ get_current_utok(conn));
if (became_user) {
unbecome_user();
}
/* See if others still have the file open via this pathname.
If this is the case, then don't delete. If all opens are
POSIX delete now. */
- for (i=0; i<lck->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->share_modes[i];
- if (is_valid_share_mode_entry(e) &&
- e->name_hash == fsp->name_hash) {
- if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
- continue;
- }
- delete_file = False;
- break;
+ for (i=0; i<lck->data->num_share_modes; i++) {
+ struct share_mode_entry *e = &lck->data->share_modes[i];
+
+ if (!is_valid_share_mode_entry(e)) {
+ continue;
+ }
+ if (e->name_hash != fsp->name_hash) {
+ continue;
}
+ if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)
+ && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
+ continue;
+ }
+ if (serverid_equal(&self, &e->pid) &&
+ (e->share_file_id == fsp->fh->gen_id)) {
+ continue;
+ }
+ if (share_mode_stale_pid(lck->data, i)) {
+ continue;
+ }
+ delete_file = False;
+ break;
}
}
- /* Notify any deferred opens waiting on this close. */
- notify_deferred_opens(conn->sconn->msg_ctx, lck);
- reply_to_oplock_break_requests(fsp);
-
/*
* NT can set delete_on_close of the last open
* reference to a file.
*/
- if (!(close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) ||
- !delete_file) {
- TALLOC_FREE(lck);
- return NT_STATUS_OK;
+ normal_close = (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE);
+
+ if (!normal_close || !delete_file) {
+ status = NT_STATUS_OK;
+ goto done;
}
/*
*/
fsp->update_write_time_on_close = false;
- del_token = get_delete_on_close_token(lck, fsp->name_hash);
- SMB_ASSERT(del_token != NULL);
+ got_tokens = get_delete_on_close_token(lck, fsp->name_hash,
+ &del_nt_token, &del_token);
+ SMB_ASSERT(got_tokens);
if (!unix_token_equal(del_token, get_current_utok(conn))) {
/* Become the user who requested the delete. */
del_token->gid,
del_token->ngroups,
del_token->groups,
- NULL);
+ del_nt_token);
changed_user = true;
}
if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
&& !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
- status = delete_all_streams(conn, fsp->fsp_name->base_name);
+ status = delete_all_streams(conn, fsp->fsp_name);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("delete_all_streams failed: %s\n",
*/
fsp->delete_on_close = false;
- set_delete_on_close_lck(fsp, lck, false, NULL);
+ reset_delete_on_close_lck(fsp, lck);
done:
pop_sec_ctx();
}
+ if (fsp->kernel_share_modes_taken) {
+ int ret_flock;
+
+ /* remove filesystem sharemodes */
+ ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, 0, 0);
+ if (ret_flock == -1) {
+ DEBUG(2, ("close_remove_share_mode: removing kernel "
+ "flock for %s failed: %s\n",
+ fsp_str_dbg(fsp), strerror(errno)));
+ }
+ }
+
+ if (!del_share_mode(lck, fsp)) {
+ DEBUG(0, ("close_remove_share_mode: Could not delete share "
+ "entry for file %s\n", fsp_str_dbg(fsp)));
+ }
+
TALLOC_FREE(lck);
if (delete_file) {
return NT_STATUS_OK;
}
- /* On close if we're changing the real file time we
- * must update it in the open file db too. */
- (void)set_write_time(fsp->file_id, fsp->close_write_time);
+ /*
+ * get_existing_share_mode_lock() isn't really the right
+ * call here, as we're being called after
+ * close_remove_share_mode() inside close_normal_file()
+ * so it's quite normal to not have an existing share
+ * mode here. However, get_share_mode_lock() doesn't
+ * work because that will create a new share mode if
+ * one doesn't exist - so stick with this call (just
+ * ignore any error we get if the share mode doesn't
+ * exist.
+ */
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, NULL);
+ lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
if (lck) {
+ /* On close if we're changing the real file time we
+ * must update it in the open file db too. */
+ (void)set_write_time(fsp->file_id, fsp->close_write_time);
+
/* Close write times overwrite sticky write times
so we must replace any sticky write time here. */
- if (!null_timespec(lck->changed_write_time)) {
+ if (!null_timespec(lck->data->changed_write_time)) {
(void)set_sticky_write_time(fsp->file_id, fsp->close_write_time);
}
TALLOC_FREE(lck);
}
ft.mtime = fsp->close_write_time;
- /* We must use NULL for the fsp handle here, as smb_set_file_time()
- checks the fsp access_mask, which may not include FILE_WRITE_ATTRIBUTES.
- As this is a close based update, we are not directly changing the
+ /* As this is a close based update, we are not directly changing the
file attributes from a client call, but indirectly from a write. */
- status = smb_set_file_time(fsp->conn, NULL, fsp->fsp_name, &ft, false);
+ status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10,("update_write_time_on_close: smb_set_file_time "
"on file %s returned %s\n",
NTSTATUS status = NT_STATUS_OK;
NTSTATUS tmp;
connection_struct *conn = fsp->conn;
+ bool is_durable = false;
+
+ if (fsp->num_aio_requests != 0) {
+
+ if (close_type != SHUTDOWN_CLOSE) {
+ /*
+ * reply_close and the smb2 close must have
+ * taken care of this. No other callers of
+ * close_file should ever have created async
+ * I/O.
+ *
+ * We need to panic here because if we close()
+ * the fd while we have outstanding async I/O
+ * requests, in the worst case we could end up
+ * writing to the wrong file.
+ */
+ DEBUG(0, ("fsp->num_aio_requests=%u\n",
+ fsp->num_aio_requests));
+ smb_panic("can not close with outstanding aio "
+ "requests");
+ }
- if (close_type == ERROR_CLOSE) {
- cancel_aio_by_fsp(fsp);
- } else {
/*
- * If we're finishing async io on a close we can get a write
- * error here, we must remember this.
+ * For shutdown close, just drop the async requests
+ * including a potential close request pending for
+ * this fsp. Drop the close request first, the
+ * destructor for the aio_requests would execute it.
*/
- int ret = wait_for_aio_completion(fsp);
- if (ret) {
- status = ntstatus_keeperror(
- status, map_nt_error_from_unix(ret));
+ TALLOC_FREE(fsp->deferred_close);
+
+ while (fsp->num_aio_requests != 0) {
+ /*
+ * The destructor of the req will remove
+ * itself from the fsp.
+ * Don't use TALLOC_FREE here, this will overwrite
+ * what the destructor just wrote into
+ * aio_requests[0].
+ */
+ talloc_free(fsp->aio_requests[0]);
}
}
tmp = close_filestruct(fsp);
status = ntstatus_keeperror(status, tmp);
+ if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
+ is_durable = fsp->op->global->durable;
+ }
+
+ if (close_type != SHUTDOWN_CLOSE) {
+ is_durable = false;
+ }
+
+ if (is_durable) {
+ DATA_BLOB new_cookie = data_blob_null;
+
+ tmp = SMB_VFS_DURABLE_DISCONNECT(fsp,
+ fsp->op->global->backend_cookie,
+ fsp->op,
+ &new_cookie);
+ if (NT_STATUS_IS_OK(tmp)) {
+ struct timeval tv;
+ NTTIME now;
+
+ if (req != NULL) {
+ tv = req->request_time;
+ } else {
+ tv = timeval_current();
+ }
+ now = timeval_to_nttime(&tv);
+
+ data_blob_free(&fsp->op->global->backend_cookie);
+ fsp->op->global->backend_cookie = new_cookie;
+
+ fsp->op->compat = NULL;
+ tmp = smbXsrv_open_close(fsp->op, now);
+ if (!NT_STATUS_IS_OK(tmp)) {
+ DEBUG(1, ("Failed to update smbXsrv_open "
+ "record when disconnecting durable "
+ "handle for file %s: %s - "
+ "proceeding with normal close\n",
+ fsp_str_dbg(fsp), nt_errstr(tmp)));
+ }
+ scavenger_schedule_disconnected(fsp);
+ } else {
+ DEBUG(1, ("Failed to disconnect durable handle for "
+ "file %s: %s - proceeding with normal "
+ "close\n", fsp_str_dbg(fsp), nt_errstr(tmp)));
+ }
+ if (!NT_STATUS_IS_OK(tmp)) {
+ is_durable = false;
+ }
+ }
+
+ if (is_durable) {
+ /*
+ * This is the case where we successfully disconnected
+ * a durable handle and closed the underlying file.
+ * In all other cases, we proceed with a genuine close.
+ */
+ DEBUG(10, ("%s disconnected durable handle for file %s\n",
+ conn->session_info->unix_info->unix_name,
+ fsp_str_dbg(fsp)));
+ file_free(req, fsp);
+ return NT_STATUS_OK;
+ }
+
+ if (fsp->op != NULL) {
+ /*
+ * Make sure the handle is not marked as durable anymore
+ */
+ fsp->op->global->durable = false;
+ }
+
if (fsp->print_file) {
/* FIXME: return spool errors */
print_spool_end(fsp, close_type);
return NT_STATUS_OK;
}
- /* Remove the oplock before potentially deleting the file. */
- if(fsp->oplock_type) {
- release_file_oplock(fsp);
- }
-
/* If this is an old DOS or FCB open and we have multiple opens on
the same handle we only have one share mode. Ensure we only remove
the share mode on the last close. */
status = ntstatus_keeperror(status, tmp);
DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
- conn->session_info->unix_name, fsp_str_dbg(fsp),
+ conn->session_info->unix_info->unix_name, fsp_str_dbg(fsp),
conn->num_files_open - 1,
nt_errstr(status) ));
return status;
}
/****************************************************************************
- Static function used by reply_rmdir to delete an entire directory
+ Function used by reply_rmdir to delete an entire directory
tree recursively. Return True on ok, False on fail.
****************************************************************************/
-static bool recursive_rmdir(TALLOC_CTX *ctx,
- connection_struct *conn,
- struct smb_filename *smb_dname)
+bool recursive_rmdir(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ struct smb_filename *smb_dname)
{
const char *dname = NULL;
char *talloced = NULL;
SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
- dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
+ dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0);
if(dir_hnd == NULL)
return False;
struct smb_filename *smb_dname_full = NULL;
char *fullname = NULL;
bool do_break = true;
- NTSTATUS status;
if (ISDOT(dname) || ISDOTDOT(dname)) {
TALLOC_FREE(talloced);
goto err_break;
}
- status = create_synthetic_smb_fname(talloc_tos(), fullname,
- NULL, NULL,
- &smb_dname_full);
- if (!NT_STATUS_IS_OK(status)) {
+ smb_dname_full = synthetic_smb_fname(talloc_tos(),
+ fullname,
+ NULL,
+ NULL,
+ smb_dname->flags);
+ if (smb_dname_full == NULL) {
+ errno = ENOMEM;
goto err_break;
}
if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
goto err_break;
}
- if(SMB_VFS_RMDIR(conn,
- smb_dname_full->base_name) != 0) {
+ if(SMB_VFS_RMDIR(conn, smb_dname_full) != 0) {
goto err_break;
}
} else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
}
ret = SMB_VFS_UNLINK(conn, smb_dname);
} else {
- ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
+ ret = SMB_VFS_RMDIR(conn, smb_dname);
}
if (ret == 0) {
notify_fname(conn, NOTIFY_ACTION_REMOVED,
return NT_STATUS_OK;
}
- if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
+ if(((errno == ENOTEMPTY)||(errno == EEXIST)) && *lp_veto_files(talloc_tos(), SNUM(conn))) {
/*
* Check to see if the only thing in this directory are
* vetoed files/directories. If so then delete them and
char *talloced = NULL;
long dirpos = 0;
struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
- smb_dname->base_name, NULL,
+ smb_dname, NULL,
0);
if(dir_hnd == NULL) {
/* We only have veto files/directories.
* Are we allowed to delete them ? */
- if(!lp_recursive_veto_delete(SNUM(conn))) {
+ if(!lp_delete_veto_files(SNUM(conn))) {
TALLOC_FREE(dir_hnd);
errno = ENOTEMPTY;
goto err;
struct smb_filename *smb_dname_full = NULL;
char *fullname = NULL;
bool do_break = true;
- NTSTATUS status;
if (ISDOT(dname) || ISDOTDOT(dname)) {
TALLOC_FREE(talloced);
goto err_break;
}
- status = create_synthetic_smb_fname(talloc_tos(),
- fullname, NULL,
- NULL,
- &smb_dname_full);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
+ smb_dname_full = synthetic_smb_fname(talloc_tos(),
+ fullname,
+ NULL,
+ NULL,
+ smb_dname->flags);
+ if (smb_dname_full == NULL) {
+ errno = ENOMEM;
goto err_break;
}
goto err_break;
}
if(SMB_VFS_RMDIR(conn,
- smb_dname_full->base_name) != 0) {
+ smb_dname_full) != 0) {
goto err_break;
}
} else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
}
TALLOC_FREE(dir_hnd);
/* Retry the rmdir */
- ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
+ ret = SMB_VFS_RMDIR(conn, smb_dname);
}
err:
static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
enum file_close_type close_type)
{
+ struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
struct share_mode_lock *lck = NULL;
bool delete_dir = False;
NTSTATUS status = NT_STATUS_OK;
NTSTATUS status1 = NT_STATUS_OK;
+ const struct security_token *del_nt_token = NULL;
const struct security_unix_token *del_token = NULL;
+ NTSTATUS notify_status;
+
+ if (fsp->conn->sconn->using_smb2) {
+ notify_status = STATUS_NOTIFY_CLEANUP;
+ } else {
+ notify_status = NT_STATUS_OK;
+ }
/*
* NT can set delete_on_close of the last open
* reference to a directory also.
*/
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
- NULL);
-
+ lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
if (lck == NULL) {
DEBUG(0, ("close_directory: Could not get share mode lock for "
"%s\n", fsp_str_dbg(fsp)));
- status = NT_STATUS_INVALID_PARAMETER;
- goto out;
- }
-
- if (!del_share_mode(lck, fsp)) {
- DEBUG(0, ("close_directory: Could not delete share entry for "
- "%s\n", fsp_str_dbg(fsp)));
+ return NT_STATUS_INVALID_PARAMETER;
}
if (fsp->initial_delete_on_close) {
}
send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
fsp->fsp_name->base_name);
- set_delete_on_close_lck(fsp, lck, true,
+ set_delete_on_close_lck(fsp, lck,
+ get_current_nttok(fsp->conn),
get_current_utok(fsp->conn));
fsp->delete_on_close = true;
if (became_user) {
}
}
- del_token = get_delete_on_close_token(lck, fsp->name_hash);
- delete_dir = (del_token != NULL);
+ delete_dir = get_delete_on_close_token(lck, fsp->name_hash,
+ &del_nt_token, &del_token);
if (delete_dir) {
int i;
/* See if others still have the dir open. If this is the
* case, then don't delete. If all opens are POSIX delete now. */
- for (i=0; i<lck->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->share_modes[i];
+ for (i=0; i<lck->data->num_share_modes; i++) {
+ struct share_mode_entry *e = &lck->data->share_modes[i];
if (is_valid_share_mode_entry(e) &&
e->name_hash == fsp->name_hash) {
- if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
+ if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) &&
+ (e->flags & SHARE_MODE_FLAG_POSIX_OPEN))
+ {
+ continue;
+ }
+ if (serverid_equal(&self, &e->pid) &&
+ (e->share_file_id == fsp->fh->gen_id)) {
+ continue;
+ }
+ if (share_mode_stale_pid(lck->data, i)) {
continue;
}
delete_dir = False;
del_token->gid,
del_token->ngroups,
del_token->groups,
- NULL);
+ del_nt_token);
+
+ if (!del_share_mode(lck, fsp)) {
+ DEBUG(0, ("close_directory: Could not delete share entry for "
+ "%s\n", fsp_str_dbg(fsp)));
+ }
TALLOC_FREE(lck);
+ if ((fsp->conn->fs_capabilities & FILE_NAMED_STREAMS)
+ && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
+
+ status = delete_all_streams(fsp->conn, fsp->fsp_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(5, ("delete_all_streams failed: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+ }
+
status = rmdir_internals(talloc_tos(), fsp);
DEBUG(5,("close_directory: %s. Delete on close was set - "
* now fail as the directory has been deleted.
*/
- if(NT_STATUS_IS_OK(status)) {
- remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
+ if (NT_STATUS_IS_OK(status)) {
+ notify_status = NT_STATUS_DELETE_PENDING;
}
} else {
+ if (!del_share_mode(lck, fsp)) {
+ DEBUG(0, ("close_directory: Could not delete share entry for "
+ "%s\n", fsp_str_dbg(fsp)));
+ }
+
TALLOC_FREE(lck);
- remove_pending_change_notify_requests_by_fid(
- fsp, NT_STATUS_OK);
}
+ remove_pending_change_notify_requests_by_fid(fsp, notify_status);
+
status1 = fd_close(fsp);
if (!NT_STATUS_IS_OK(status1)) {
close_filestruct(fsp);
file_free(req, fsp);
- out:
- TALLOC_FREE(lck);
if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
status = status1;
}
struct server_id server_id,
DATA_BLOB *data)
{
- struct smbd_server_connection *sconn;
files_struct *fsp = NULL;
struct share_mode_entry e;
-
- sconn = msg_ctx_to_sconn(msg_ctx);
- if (sconn == NULL) {
- DEBUG(1, ("could not find sconn\n"));
- return;
- }
+ struct smbd_server_connection *sconn =
+ talloc_get_type_abort(private_data,
+ struct smbd_server_connection);
message_to_share_mode_entry(&e, (char *)data->data);