}
}
- /* Actually do the open */
- status = fd_open_atomic(conn, fsp, local_flags,
+ /*
+ * Actually do the open - if O_TRUNC is needed handle it
+ * below under the share mode lock.
+ */
+ status = fd_open_atomic(conn, fsp, local_flags & ~O_TRUNC,
unx_mode, p_file_created);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
return;
}
+ if (share_entry->share_file_id == 0) {
+ /* INTERNAL_OPEN_ONLY */
+ return;
+ }
+
if (!is_valid_share_mode_entry(share_entry)) {
return;
}
/****************************************************************************
Deal with share modes
- Invarient: Share mode must be locked on entry and exit.
+ Invariant: Share mode must be locked on entry and exit.
Returns -1 on error, or number of share modes on success (may be zero).
****************************************************************************/
struct smb_request *req,
struct deferred_open_record *state)
{
+ struct deferred_open_record *open_rec;
+
DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred "
"open entry for mid %llu\n",
(unsigned int)request_time.tv_sec,
(unsigned int)request_time.tv_usec,
(unsigned long long)req->mid));
- if (!push_deferred_open_message_smb(req, request_time, timeout,
- state->id, (char *)state, sizeof(*state))) {
+ open_rec = talloc(NULL, struct deferred_open_record);
+ if (open_rec == NULL) {
TALLOC_FREE(lck);
- exit_server("push_deferred_open_message_smb failed");
+ exit_server("talloc failed");
}
+
+ *open_rec = *state;
+
if (lck) {
struct defer_open_state *watch_state;
struct tevent_req *watch_req;
bool ret;
- watch_state = talloc(req->sconn, struct defer_open_state);
+ watch_state = talloc(open_rec, struct defer_open_state);
if (watch_state == NULL) {
exit_server("talloc failed");
}
timeval_sum(&request_time, &timeout));
SMB_ASSERT(ret);
}
+
+ if (!push_deferred_open_message_smb(req, request_time, timeout,
+ state->id, open_rec)) {
+ TALLOC_FREE(lck);
+ exit_server("push_deferred_open_message_smb failed");
+ }
}
static void defer_open_done(struct tevent_req *req)
Return true if this is a state pointer to an asynchronous create.
****************************************************************************/
-bool is_deferred_open_async(const void *ptr)
+bool is_deferred_open_async(const struct deferred_open_record *rec)
{
- const struct deferred_open_record *state = (const struct deferred_open_record *)ptr;
-
- return state->async_open;
+ return rec->async_open;
}
static bool clear_ads(uint32_t create_disposition)
create_options, (unsigned int)unx_mode, oplock_request,
(unsigned int)private_flags));
- if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) {
- DEBUG(0, ("No smb request but not an internal only open!\n"));
- return NT_STATUS_INTERNAL_ERROR;
+ if (req == NULL) {
+ /* Ensure req == NULL means INTERNAL_OPEN_ONLY */
+ SMB_ASSERT(((oplock_request & INTERNAL_OPEN_ONLY) != 0));
+ } else {
+ /* And req != NULL means no INTERNAL_OPEN_ONLY */
+ SMB_ASSERT(((oplock_request & INTERNAL_OPEN_ONLY) == 0));
}
/*
*/
if (req) {
- void *ptr;
+ struct deferred_open_record *open_rec;
if (get_deferred_open_message_state(req,
&request_time,
- &ptr)) {
+ &open_rec)) {
/* Remember the absolute time of the original
request with this mid. We'll use it later to
see if this has timed out. */
/* If it was an async create retry, the file
didn't exist. */
- if (is_deferred_open_async(ptr)) {
+ if (is_deferred_open_async(open_rec)) {
SET_STAT_INVALID(smb_fname->st);
file_existed = false;
}
*/
state.delayed_for_oplocks = false;
state.async_open = false;
- state.id = lck->data->id;
+ state.id = fsp->file_id;
defer_open(lck, request_time, timeval_set(0, 0), req, &state);
TALLOC_FREE(lck);
DEBUG(10, ("No Samba oplock around after EWOULDBLOCK. "
return status;
}
+ /* Should we atomically (to the client at least) truncate ? */
+ if ((!new_file_created) &&
+ (flags2 & O_TRUNC) &&
+ (!S_ISFIFO(fsp->fsp_name->st.st_ex_mode))) {
+ int ret;
+
+ ret = vfs_set_filelen(fsp, 0);
+ if (ret != 0) {
+ status = map_nt_error_from_unix(errno);
+ TALLOC_FREE(lck);
+ fd_close(fsp);
+ return status;
+ }
+ }
+
grant_fsp_oplock_type(fsp, lck, oplock_request);
/*
return NT_STATUS_OK;
}
-
-/****************************************************************************
- Open a file for for write to ensure that we can fchmod it.
-****************************************************************************/
-
-NTSTATUS open_file_fchmod(connection_struct *conn,
- struct smb_filename *smb_fname,
- files_struct **result)
-{
- if (!VALID_STAT(smb_fname->st)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- return SMB_VFS_CREATE_FILE(
- conn, /* conn */
- NULL, /* req */
- 0, /* root_dir_fid */
- smb_fname, /* fname */
- FILE_WRITE_DATA, /* access_mask */
- (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
- FILE_SHARE_DELETE),
- FILE_OPEN, /* create_disposition*/
- 0, /* create_options */
- 0, /* file_attributes */
- INTERNAL_OPEN_ONLY, /* oplock_request */
- 0, /* allocation_size */
- 0, /* private_flags */
- NULL, /* sd */
- NULL, /* ea_list */
- result, /* result */
- NULL); /* pinfo */
-}
-
static NTSTATUS mkdir_internal(connection_struct *conn,
struct smb_filename *smb_dname,
uint32 file_attributes)
FILE_DIRECTORY_FILE, /* create_options */
FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
0, /* oplock_request */
+ NULL, /* lease */
0, /* allocation_size */
0, /* private_flags */
NULL, /* sd */
0, /* create_options */
FILE_ATTRIBUTE_NORMAL, /* file_attributes */
0, /* oplock_request */
+ NULL, /* lease */
0, /* allocation_size */
NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE, /* private_flags */
NULL, /* sd */
uint32_t create_options,
uint32_t file_attributes,
uint32_t oplock_request,
+ struct smb2_lease *lease,
uint64_t allocation_size,
uint32_t private_flags,
struct security_descriptor *sd,