return;
}
- chmod(fsp->fsp_name,0755);
- ret = smbrun(fsp->fsp_name,&tmp_fd);
+ /* Ensure we don't depend on user's PATH. */
+ p = talloc_asprintf(ctx, "./%s", fsp->fsp_name);
+ if (!p) {
+ TALLOC_FREE(ctx);
+ return;
+ }
+
+ if (chmod(fsp->fsp_name,0755) == -1) {
+ TALLOC_FREE(ctx);
+ return;
+ }
+ ret = smbrun(p,&tmp_fd);
DEBUG(3,("Invoking magic command %s gave %d\n",
- fsp->fsp_name,ret));
+ p,ret));
unlink(fsp->fsp_name);
if (ret != 0 || tmp_fd == -1) {
static NTSTATUS close_filestruct(files_struct *fsp)
{
NTSTATUS status = NT_STATUS_OK;
- connection_struct *conn = fsp->conn;
-
+
if (fsp->fh->fd != -1) {
if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
status = map_nt_error_from_unix(errno);
delete_write_cache(fsp);
}
- conn->num_files_open--;
return status;
-}
+}
/****************************************************************************
If any deferred opens are waiting on this close, notify them.
Delete all streams
****************************************************************************/
-static NTSTATUS delete_all_streams(connection_struct *conn, const char *fname)
+NTSTATUS delete_all_streams(connection_struct *conn, const char *fname)
{
struct stream_struct *stream_info;
int i;
* This prevents race conditions with the file being created. JRA.
*/
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
+ lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+ NULL);
if (lck == NULL) {
DEBUG(0, ("close_remove_share_mode: Could not get share mode "
return NT_STATUS_INVALID_PARAMETER;
}
+ if (fsp->write_time_forced) {
+ set_close_write_time(fsp, lck->changed_write_time);
+ }
+
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(5,("close_remove_share_mode: file %s. Delete on close was set "
"- deleting file.\n", fsp->fsp_name));
+ /*
+ * Don't try to update the write time when we delete the file
+ */
+ fsp->update_write_time_on_close = false;
+
if (!unix_token_equal(lck->delete_token, ¤t_user.ut)) {
/* Become the user who requested the delete. */
return status;
}
+void set_close_write_time(struct files_struct *fsp, struct timespec ts)
+{
+ DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts))));
+
+ if (null_timespec(ts)) {
+ return;
+ }
+ /*
+ * if the write time on close is explict set, then don't
+ * need to fix it up to the value in the locking db
+ */
+ fsp->write_time_forced = false;
+
+ fsp->update_write_time_on_close = true;
+ fsp->close_write_time = ts;
+}
+
+static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
+{
+ SMB_STRUCT_STAT sbuf;
+ struct smb_file_time ft;
+ NTSTATUS status;
+
+ ZERO_STRUCT(sbuf);
+ ZERO_STRUCT(ft);
+
+ if (!fsp->update_write_time_on_close) {
+ return NT_STATUS_OK;
+ }
+
+ if (null_timespec(fsp->close_write_time)) {
+ fsp->close_write_time = timespec_current();
+ }
+
+ /* Ensure we have a valid stat struct for the source. */
+ if (fsp->fh->fd != -1) {
+ if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ } else {
+ if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf) == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ }
+
+ if (!VALID_STAT(sbuf)) {
+ /* if it doesn't seem to be a real file */
+ return NT_STATUS_OK;
+ }
+
+ ft.mtime = fsp->close_write_time;
+ status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name,
+ &sbuf, &ft, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ return NT_STATUS_OK;
+}
+
/****************************************************************************
Close a file.
delete on close is done on normal and shutdown close.
****************************************************************************/
-static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_type)
+static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
+ enum file_close_type close_type)
{
NTSTATUS status = NT_STATUS_OK;
NTSTATUS saved_status1 = NT_STATUS_OK;
NTSTATUS saved_status2 = NT_STATUS_OK;
NTSTATUS saved_status3 = NT_STATUS_OK;
+ NTSTATUS saved_status4 = NT_STATUS_OK;
connection_struct *conn = fsp->conn;
if (fsp->aio_write_behind) {
if (fsp->print_file) {
print_fsp_end(fsp, close_type);
- file_free(fsp);
+ file_free(req, fsp);
return NT_STATUS_OK;
}
* Ensure pending modtime is set after close.
*/
- if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) {
- set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
- } else if (!null_timespec(fsp->last_write_time)) {
- set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
- }
+ saved_status4 = update_write_time_on_close(fsp);
if (NT_STATUS_IS_OK(status)) {
if (!NT_STATUS_IS_OK(saved_status1)) {
status = saved_status2;
} else if (!NT_STATUS_IS_OK(saved_status3)) {
status = saved_status3;
+ } else if (!NT_STATUS_IS_OK(saved_status4)) {
+ status = saved_status4;
}
}
DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
- conn->user,fsp->fsp_name,
- conn->num_files_open,
+ conn->server_info->unix_name,fsp->fsp_name,
+ conn->num_files_open - 1,
nt_errstr(status) ));
- file_free(fsp);
+ file_free(req, fsp);
return status;
}
Close a directory opened by an NT SMB call.
****************************************************************************/
-static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_type)
+static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
+ enum file_close_type close_type)
{
struct share_mode_lock *lck = 0;
bool delete_dir = False;
* reference to a directory also.
*/
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
+ lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+ NULL);
if (lck == NULL) {
DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
fsp, NT_STATUS_OK);
}
- /*
- * Do the code common to files and directories.
- */
- close_filestruct(fsp);
- file_free(fsp);
- return status;
-}
+ status = fd_close(fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
+ fsp->fsp_name, fsp->fh->fd, errno, strerror(errno)));
+ }
-/****************************************************************************
- Close a 'stat file' opened internally.
-****************************************************************************/
-
-static NTSTATUS close_stat(files_struct *fsp)
-{
/*
* Do the code common to files and directories.
*/
close_filestruct(fsp);
- file_free(fsp);
- return NT_STATUS_OK;
+ file_free(req, fsp);
+ return status;
}
/****************************************************************************
Close a files_struct.
****************************************************************************/
-NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type)
+NTSTATUS close_file(struct smb_request *req, files_struct *fsp,
+ enum file_close_type close_type)
{
NTSTATUS status;
struct files_struct *base_fsp = fsp->base_fsp;
if(fsp->is_directory) {
- status = close_directory(fsp, close_type);
- } else if (fsp->is_stat) {
- status = close_stat(fsp);
+ status = close_directory(req, fsp, close_type);
} else if (fsp->fake_file_handle != NULL) {
- status = close_fake_file(fsp);
+ status = close_fake_file(req, fsp);
} else {
- status = close_normal_file(fsp, close_type);
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ status = close_normal_file(req, fsp, close_type);
}
if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) {
*/
SMB_ASSERT(base_fsp->base_fsp == NULL);
- close_file(base_fsp, close_type);
+ close_file(req, base_fsp, close_type);
}
return status;
}
+
+/****************************************************************************
+ Deal with an (authorized) message to close a file given the share mode
+ entry.
+****************************************************************************/
+
+void msg_close_file(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
+{
+ files_struct *fsp = NULL;
+ struct share_mode_entry e;
+
+ message_to_share_mode_entry(&e, (char *)data->data);
+
+ if(DEBUGLVL(10)) {
+ char *sm_str = share_mode_str(NULL, 0, &e);
+ if (!sm_str) {
+ smb_panic("talloc failed");
+ }
+ DEBUG(10,("msg_close_file: got request to close share mode "
+ "entry %s\n", sm_str));
+ TALLOC_FREE(sm_str);
+ }
+
+ fsp = file_find_dif(e.id, e.share_file_id);
+ if (!fsp) {
+ DEBUG(10,("msg_close_file: failed to find file.\n"));
+ return;
+ }
+ close_file(NULL, fsp, NORMAL_CLOSE);
+}