struct deferred_open_record {
bool delayed_for_oplocks;
+ bool async_open;
struct file_id id;
};
fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
if (fsp->fh->fd == -1) {
- status = map_nt_error_from_unix(errno);
+ int posix_errno = errno;
+#ifdef O_NOFOLLOW
+#if defined(ENOTSUP) && defined(OSF1)
+ /* handle special Tru64 errno */
+ if (errno == ENOTSUP) {
+ posix_errno = ELOOP;
+ }
+#endif /* ENOTSUP */
+#ifdef EFTYPE
+ /* fix broken NetBSD errno */
+ if (errno == EFTYPE) {
+ posix_errno = ELOOP;
+ }
+#endif /* EFTYPE */
+ /* fix broken FreeBSD errno */
+ if (errno == EMLINK) {
+ posix_errno = ELOOP;
+ }
+#endif /* O_NOFOLLOW */
+ status = map_nt_error_from_unix(posix_errno);
if (errno == EMFILE) {
static time_t last_warned = 0L;
return status;
}
+/****************************************************************************
+ Open a file - returning a guaranteed ATOMIC indication of if the
+ file was created or not.
+****************************************************************************/
+
+static NTSTATUS fd_open_atomic(struct connection_struct *conn,
+ files_struct *fsp,
+ int flags,
+ mode_t mode,
+ bool *file_created)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ bool file_existed = VALID_STAT(fsp->fsp_name->st);
+
+ *file_created = false;
+
+ if (!(flags & O_CREAT)) {
+ /*
+ * We're not creating the file, just pass through.
+ */
+ return fd_open(conn, fsp, flags, mode);
+ }
+
+ if (flags & O_EXCL) {
+ /*
+ * Fail if already exists, just pass through.
+ */
+ status = fd_open(conn, fsp, flags, mode);
+ if (NT_STATUS_IS_OK(status)) {
+ /*
+ * Here we've opened with O_CREAT|O_EXCL
+ * and got success. We *know* we created
+ * this file.
+ */
+ *file_created = true;
+ }
+ return status;
+ }
+
+ /*
+ * Now it gets tricky. We have O_CREAT, but not O_EXCL.
+ * To know absolutely if we created the file or not,
+ * we can never call O_CREAT without O_EXCL. So if
+ * we think the file existed, try without O_CREAT|O_EXCL.
+ * If we think the file didn't exist, try with
+ * O_CREAT|O_EXCL. Keep bouncing between these two
+ * requests until either the file is created, or
+ * opened. Either way, we keep going until we get
+ * a returnable result (error, or open/create).
+ */
+
+ while(1) {
+ int curr_flags = flags;
+
+ if (file_existed) {
+ /* Just try open, do not create. */
+ curr_flags &= ~(O_CREAT);
+ status = fd_open(conn, fsp, curr_flags, mode);
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ /*
+ * Someone deleted it in the meantime.
+ * Retry with O_EXCL.
+ */
+ file_existed = false;
+ DEBUG(10,("fd_open_atomic: file %s existed. "
+ "Retry.\n",
+ smb_fname_str_dbg(fsp->fsp_name)));
+ continue;
+ }
+ } else {
+ /* Try create exclusively, fail if it exists. */
+ curr_flags |= O_EXCL;
+ status = fd_open(conn, fsp, curr_flags, mode);
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_OBJECT_NAME_COLLISION)) {
+ /*
+ * Someone created it in the meantime.
+ * Retry without O_CREAT.
+ */
+ file_existed = true;
+ DEBUG(10,("fd_open_atomic: file %s "
+ "did not exist. Retry.\n",
+ smb_fname_str_dbg(fsp->fsp_name)));
+ continue;
+ }
+ if (NT_STATUS_IS_OK(status)) {
+ /*
+ * Here we've opened with O_CREAT|O_EXCL
+ * and got success. We *know* we created
+ * this file.
+ */
+ *file_created = true;
+ }
+ }
+ /* Create is done, or failed. */
+ break;
+ }
+ return status;
+}
+
/****************************************************************************
Open a file.
****************************************************************************/
int flags,
mode_t unx_mode,
uint32 access_mask, /* client requested access mask. */
- uint32 open_access_mask) /* what we're actually using in the open. */
+ uint32 open_access_mask, /* what we're actually using in the open. */
+ bool *p_file_created)
{
struct smb_filename *smb_fname = fsp->fsp_name;
NTSTATUS status = NT_STATUS_OK;
int accmode = (flags & O_ACCMODE);
int local_flags = flags;
bool file_existed = VALID_STAT(fsp->fsp_name->st);
- bool file_created = false;
fsp->fh->fd = -1;
errno = EPERM;
(!file_existed && (local_flags & O_CREAT)) ||
((local_flags & O_TRUNC) == O_TRUNC) ) {
const char *wild;
+ int ret;
/*
* We can't actually truncate here as the file may be locked.
}
/* Actually do the open */
- status = fd_open(conn, fsp, local_flags, unx_mode);
+ status = fd_open_atomic(conn, fsp, local_flags,
+ unx_mode, p_file_created);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
"(flags=%d)\n", smb_fname_str_dbg(smb_fname),
return status;
}
- if ((local_flags & O_CREAT) && !file_existed) {
- file_created = true;
- }
-
- } else {
- fsp->fh->fd = -1; /* What we used to call a stat open. */
- if (!file_existed) {
- /* File must exist for a stat open. */
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- status = smbd_check_access_rights(conn,
- smb_fname,
- access_mask);
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
- fsp->posix_open &&
- S_ISLNK(smb_fname->st.st_ex_mode)) {
- /* This is a POSIX stat open for delete
- * or rename on a symlink that points
- * nowhere. Allow. */
- DEBUG(10,("open_file: allowing POSIX "
- "open on bad symlink %s\n",
- smb_fname_str_dbg(smb_fname)));
- status = NT_STATUS_OK;
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10,("open_file: "
- "smbd_check_access_rights on file "
- "%s returned %s\n",
- smb_fname_str_dbg(smb_fname),
- nt_errstr(status) ));
- return status;
- }
- }
-
- if (!file_existed) {
- int ret;
-
- if (fsp->fh->fd == -1) {
- ret = SMB_VFS_STAT(conn, smb_fname);
- } else {
- ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
- /* If we have an fd, this stat should succeed. */
- if (ret == -1) {
- DEBUG(0,("Error doing fstat on open file %s "
- "(%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno) ));
- }
- }
-
- /* For a non-io open, this stat failing means file not found. JRA */
+ ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
if (ret == -1) {
+ /* If we have an fd, this stat should succeed. */
+ DEBUG(0,("Error doing fstat on open file %s "
+ "(%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno) ));
status = map_nt_error_from_unix(errno);
fd_close(fsp);
return status;
}
- if (file_created) {
+ if (*p_file_created) {
+ /* We created this file. */
+
bool need_re_stat = false;
/* Do all inheritance work after we've
- done a successful stat call and filled
+ done a successful fstat call and filled
in the stat struct in fsp->fsp_name. */
/* Inherit the ACL if required */
}
if (need_re_stat) {
- if (fsp->fh->fd == -1) {
- ret = SMB_VFS_STAT(conn, smb_fname);
- } else {
- ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
- /* If we have an fd, this stat should succeed. */
- if (ret == -1) {
- DEBUG(0,("Error doing fstat on open file %s "
- "(%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno) ));
- }
+ ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
+ /* If we have an fd, this stat should succeed. */
+ if (ret == -1) {
+ DEBUG(0,("Error doing fstat on open file %s "
+ "(%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno) ));
}
}
FILE_NOTIFY_CHANGE_FILE_NAME,
smb_fname->base_name);
}
+ } else {
+ fsp->fh->fd = -1; /* What we used to call a stat open. */
+ if (!file_existed) {
+ /* File must exist for a stat open. */
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ status = smbd_check_access_rights(conn,
+ smb_fname,
+ access_mask);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
+ fsp->posix_open &&
+ S_ISLNK(smb_fname->st.st_ex_mode)) {
+ /* This is a POSIX stat open for delete
+ * or rename on a symlink that points
+ * nowhere. Allow. */
+ DEBUG(10,("open_file: allowing POSIX "
+ "open on bad symlink %s\n",
+ smb_fname_str_dbg(smb_fname)));
+ status = NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("open_file: "
+ "smbd_check_access_rights on file "
+ "%s returned %s\n",
+ smb_fname_str_dbg(smb_fname),
+ nt_errstr(status) ));
+ return status;
+ }
}
/*
fsp->vuid = req ? req->vuid : UID_FIELD_INVALID;
fsp->file_pid = req ? req->smbpid : 0;
fsp->can_lock = True;
- fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
- if (!CAN_WRITE(conn)) {
- fsp->can_write = False;
- } else {
- fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
- True : False;
- }
+ fsp->can_read = ((access_mask & FILE_READ_DATA) != 0);
+ fsp->can_write =
+ CAN_WRITE(conn) &&
+ ((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0);
fsp->print_file = NULL;
fsp->modified = False;
fsp->sent_oplock_break = NO_BREAK_SENT;
int num,
struct share_mode_entry *share_entry)
{
+ struct server_id self = messaging_server_id(sconn->msg_ctx);
files_struct *fsp;
- if (!procid_is_me(&share_entry->pid)) {
+ if (!serverid_equal(&self, &share_entry->pid)) {
return;
}
return NT_STATUS_OK;
}
- *file_existed = True;
-
/* A delete on close prohibits everything */
if (is_delete_on_close_set(lck, name_hash)) {
- return NT_STATUS_DELETE_PENDING;
+ /*
+ * Check the delete on close token
+ * is valid. It could have been left
+ * after a server crash.
+ */
+ for(i = 0; i < lck->data->num_share_modes; i++) {
+ if (!share_mode_stale_pid(lck->data, i)) {
+
+ *file_existed = true;
+
+ return NT_STATUS_DELETE_PENDING;
+ }
+ }
+ return NT_STATUS_OK;
}
if (is_stat_open(access_mask)) {
}
#endif
- if (!lp_share_modes(SNUM(conn))) {
- return NT_STATUS_OK;
- }
-
/* Now we check the share modes, after any oplock breaks. */
for(i = 0; i < lck->data->num_share_modes; i++) {
continue;
}
+ *file_existed = true;
+
return NT_STATUS_SHARING_VIOLATION;
}
}
+ if (lck->data->num_share_modes != 0) {
+ *file_existed = true;
+ }
+
return NT_STATUS_OK;
}
if (BATCH_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) {
/* batch - can only be one. */
+ if (share_mode_stale_pid(lck->data, i)) {
+ DEBUG(10, ("Found stale batch oplock\n"));
+ continue;
+ }
if (*pp_ex_or_batch || *pp_batch || *got_level2 || *got_no_oplock) {
smb_panic("Bad batch oplock entry.");
}
}
if (EXCLUSIVE_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) {
+ if (share_mode_stale_pid(lck->data, i)) {
+ DEBUG(10, ("Found stale duplicate oplock\n"));
+ continue;
+ }
/* Exclusive or batch - can only be one. */
if (*pp_ex_or_batch || *got_level2 || *got_no_oplock) {
smb_panic("Bad exclusive or batch oplock entry.");
if (LEVEL_II_OPLOCK_TYPE(lck->data->share_modes[i].op_type)) {
if (*pp_batch || *pp_ex_or_batch) {
+ if (share_mode_stale_pid(lck->data, i)) {
+ DEBUG(10, ("Found stale LevelII "
+ "oplock\n"));
+ continue;
+ }
smb_panic("Bad levelII oplock entry.");
}
*got_level2 = true;
if (lck->data->share_modes[i].op_type == NO_OPLOCK) {
if (*pp_batch || *pp_ex_or_batch) {
+ if (share_mode_stale_pid(lck->data, i)) {
+ DEBUG(10, ("Found stale NO_OPLOCK "
+ "entry\n"));
+ continue;
+ }
smb_panic("Bad no oplock entry.");
}
*got_no_oplock = true;
DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n",
fsp->oplock_type, fsp_str_dbg(fsp)));
return;
- } else if (lp_locking(fsp->conn->params) && file_has_brlocks(fsp)) {
+ }
+
+ if (lp_locking(fsp->conn->params) && file_has_brlocks(fsp)) {
DEBUG(10,("grant_fsp_oplock_type: file %s has byte range locks\n",
fsp_str_dbg(fsp)));
fsp->oplock_type = NO_OPLOCK;
fsp->oplock_type, fsp_str_dbg(fsp)));
}
-bool request_timed_out(struct timeval request_time,
- struct timeval timeout)
+static bool request_timed_out(struct timeval request_time,
+ struct timeval timeout)
{
struct timeval now, end_time;
GetTimeOfDay(&now);
struct smb_request *req,
struct deferred_open_record *state)
{
- int i;
+ struct server_id self = messaging_server_id(req->sconn->msg_ctx);
/* Paranoia check */
- for (i=0; i<lck->data->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->data->share_modes[i];
+ if (lck) {
+ int i;
- if (is_deferred_open_entry(e) &&
- procid_is_me(&e->pid) &&
- (e->op_mid == req->mid)) {
- DEBUG(0, ("Trying to defer an already deferred "
- "request: mid=%llu, exiting\n",
- (unsigned long long)req->mid));
- exit_server("attempt to defer a deferred request");
+ for (i=0; i<lck->data->num_share_modes; i++) {
+ struct share_mode_entry *e = &lck->data->share_modes[i];
+
+ if (is_deferred_open_entry(e) &&
+ serverid_equal(&self, &e->pid) &&
+ (e->op_mid == req->mid)) {
+ DEBUG(0, ("Trying to defer an already deferred "
+ "request: mid=%llu, exiting\n",
+ (unsigned long long)req->mid));
+ exit_server("attempt to defer a deferred request");
+ }
}
}
state->id, (char *)state, sizeof(*state))) {
exit_server("push_deferred_open_message_smb failed");
}
- add_deferred_open(lck, req->mid, request_time,
- messaging_server_id(req->sconn->msg_ctx), state->id);
+ if (lck) {
+ add_deferred_open(lck, req->mid, request_time, self, state->id);
+ }
}
Try and find a duplicated file handle.
****************************************************************************/
-NTSTATUS fcb_or_dos_open(struct smb_request *req,
- connection_struct *conn,
- files_struct *fsp_to_dup_into,
- const struct smb_filename *smb_fname,
- struct file_id id,
- uint16 file_pid,
- uint16 vuid,
- uint32 access_mask,
- uint32 share_access,
- uint32 create_options)
+static NTSTATUS fcb_or_dos_open(struct smb_request *req,
+ connection_struct *conn,
+ files_struct *fsp_to_dup_into,
+ const struct smb_filename *smb_fname,
+ struct file_id id,
+ uint16 file_pid,
+ uint64_t vuid,
+ uint32 access_mask,
+ uint32 share_access,
+ uint32 create_options)
{
files_struct *fsp;
fsp = file_find_di_next(fsp)) {
DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, "
- "vuid = %u, file_pid = %u, private_options = 0x%x "
+ "vuid = %llu, file_pid = %u, private_options = 0x%x "
"access_mask = 0x%x\n", fsp_str_dbg(fsp),
- fsp->fh->fd, (unsigned int)fsp->vuid,
+ fsp->fh->fd, (unsigned long long)fsp->vuid,
(unsigned int)fsp->file_pid,
(unsigned int)fsp->fh->private_options,
(unsigned int)fsp->access_mask ));
a 1 second delay for share mode conflicts. */
state.delayed_for_oplocks = True;
+ state.async_open = false;
state.id = lck->data->id;
if (!request_timed_out(request_time, timeout)) {
}
}
+/****************************************************************************
+ Reschedule an open call that went asynchronous.
+****************************************************************************/
+
+static void schedule_async_open(struct timeval request_time,
+ struct smb_request *req)
+{
+ struct deferred_open_record state;
+ struct timeval timeout;
+
+ timeout = timeval_set(20, 0);
+
+ ZERO_STRUCT(state);
+ state.delayed_for_oplocks = false;
+ state.async_open = true;
+
+ if (!request_timed_out(request_time, timeout)) {
+ defer_open(NULL, request_time, timeout, req, &state);
+ }
+}
+
/****************************************************************************
Work out what access_mask to use from what the client sent us.
****************************************************************************/
TALLOC_FREE(lck);
}
+/****************************************************************************
+ Return true if this is a state pointer to an asynchronous create.
+****************************************************************************/
+
+bool is_deferred_open_async(const void *ptr)
+{
+ const struct deferred_open_record *state = (const struct deferred_open_record *)ptr;
+
+ return state->async_open;
+}
+
/****************************************************************************
Open a file with a share mode. Passed in an already created files_struct *.
****************************************************************************/
uint32 open_access_mask = access_mask;
NTSTATUS status;
char *parent_dir;
+ SMB_STRUCT_STAT saved_stat = smb_fname->st;
if (conn->printer) {
/*
if (get_deferred_open_message_state(req,
&request_time,
&ptr)) {
-
- struct deferred_open_record *state = (struct deferred_open_record *)ptr;
/* Remember the absolute time of the original
request with this mid. We'll use it later to
see if this has timed out. */
- /* Remove the deferred open entry under lock. */
- remove_deferred_open_entry(
- state->id, req->mid,
- messaging_server_id(req->sconn->msg_ctx));
+ /* If it was an async create retry, the file
+ didn't exist. */
+
+ if (is_deferred_open_async(ptr)) {
+ SET_STAT_INVALID(smb_fname->st);
+ file_existed = false;
+ } else {
+ struct deferred_open_record *state = (struct deferred_open_record *)ptr;
+ /* Remove the deferred open entry under lock. */
+ remove_deferred_open_entry(
+ state->id, req->mid,
+ messaging_server_id(req->sconn->msg_ctx));
+ }
/* Ensure we don't reprocess this message. */
remove_deferred_open_message_smb(req->sconn, req->mid);
a 1 second delay for share mode conflicts. */
state.delayed_for_oplocks = False;
+ state.async_open = false;
state.id = id;
if ((req != NULL)
fsp_open = open_file(fsp, conn, req, parent_dir,
flags|flags2, unx_mode, access_mask,
- open_access_mask);
+ open_access_mask, &new_file_created);
if (!NT_STATUS_IS_OK(fsp_open)) {
+ if (NT_STATUS_EQUAL(fsp_open, NT_STATUS_RETRY)) {
+ schedule_async_open(request_time, req);
+ }
TALLOC_FREE(lck);
return fsp_open;
}
+ if (file_existed && !check_same_dev_ino(&saved_stat, &smb_fname->st)) {
+ /*
+ * The file did exist, but some other (local or NFS)
+ * process either renamed/unlinked and re-created the
+ * file with different dev/ino after we walked the path,
+ * but before we did the open. We could retry the
+ * open but it's a rare enough case it's easier to
+ * just fail the open to prevent creating any problems
+ * in the open file db having the wrong dev/ino key.
+ */
+ TALLOC_FREE(lck);
+ fd_close(fsp);
+ DEBUG(1,("open_file_ntcreate: file %s - dev/ino mismatch. "
+ "Old (dev=0x%llu, ino =0x%llu). "
+ "New (dev=0x%llu, ino=0x%llu). Failing open "
+ " with NT_STATUS_ACCESS_DENIED.\n",
+ smb_fname_str_dbg(smb_fname),
+ (unsigned long long)saved_stat.st_ex_dev,
+ (unsigned long long)saved_stat.st_ex_ino,
+ (unsigned long long)smb_fname->st.st_ex_dev,
+ (unsigned long long)smb_fname->st.st_ex_ino));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (!file_existed) {
struct share_mode_entry *batch_entry = NULL;
struct share_mode_entry *exclusive_entry = NULL;
struct deferred_open_record state;
state.delayed_for_oplocks = False;
+ state.async_open = false;
state.id = id;
/* Do it all over again immediately. In the second
SMB_ASSERT(lck != NULL);
/* Delete streams if create_disposition requires it */
- if (file_existed && clear_ads &&
+ if (!new_file_created && clear_ads &&
!is_ntfs_stream_smb_fname(smb_fname)) {
status = delete_all_streams(conn, smb_fname->base_name);
if (!NT_STATUS_IS_OK(status)) {
* If requested, truncate the file.
*/
- if (file_existed && (flags2&O_TRUNC)) {
+ if (!new_file_created && (flags2&O_TRUNC)) {
/*
- * We are modifing the file after open - update the stat
+ * We are modifying the file after open - update the stat
* struct..
*/
if ((SMB_VFS_FTRUNCATE(fsp, 0) == -1) ||
if (is_stat_open(open_access_mask)) {
fsp->oplock_type = NO_OPLOCK;
}
+ }
+ if (new_file_created) {
+ info = FILE_WAS_CREATED;
+ } else {
if (flags2 & O_TRUNC) {
info = FILE_WAS_OVERWRITTEN;
} else {
info = FILE_WAS_OPENED;
}
- } else {
- info = FILE_WAS_CREATED;
}
if (pinfo) {
* file structs.
*/
- if (!set_file_oplock(fsp, fsp->oplock_type)) {
+ status = set_file_oplock(fsp, fsp->oplock_type);
+ if (!NT_STATUS_IS_OK(status)) {
/*
* Could not get the kernel oplock or there are byte-range
* locks on the file.
fsp->initial_delete_on_close = True;
}
- if (info == FILE_WAS_OVERWRITTEN
- || info == FILE_WAS_CREATED
- || info == FILE_WAS_SUPERSEDED) {
- new_file_created = True;
- }
-
- if (new_file_created) {
+ if (info != FILE_WAS_OPENED) {
/* Files should be initially set as archive */
if (lp_map_archive(SNUM(conn)) ||
lp_store_dos_attributes(SNUM(conn))) {
* selected.
*/
- if (!posix_open && !file_existed && !def_acl) {
+ if (!posix_open && new_file_created && !def_acl) {
int saved_errno = errno; /* We might get ENOSYS in the next
* call.. */
if(access_mask & ~(conn->share_access)) {
DEBUG(5,("mkdir_internal: failing share access "
- "%s\n", lp_servicename(SNUM(conn))));
+ "%s\n", lp_servicename(talloc_tos(), SNUM(conn))));
return NT_STATUS_ACCESS_DENIED;
}
return NT_STATUS_OK;
}
-/****************************************************************************
- Ensure we didn't get symlink raced on opening a directory.
-****************************************************************************/
-
-bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
- const SMB_STRUCT_STAT *sbuf2)
-{
- if (sbuf1->st_ex_uid != sbuf2->st_ex_uid ||
- sbuf1->st_ex_gid != sbuf2->st_ex_gid ||
- sbuf1->st_ex_dev != sbuf2->st_ex_dev ||
- sbuf1->st_ex_ino != sbuf2->st_ex_ino) {
- return false;
- }
- return true;
-}
-
/****************************************************************************
Open a directory from an NT SMB call.
****************************************************************************/
return NT_STATUS_NOT_A_DIRECTORY;
}
- /* Ensure we have a directory attribute. */
- file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
+ if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
+ /* Ensure we have a directory attribute. */
+ file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
+ }
DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, "
"share_access = 0x%x create_options = 0x%x, "
fsp = file_find_di_next(fsp)) {
if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) {
- DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n",
- fsp->fnum, fsp_str_dbg(fsp),
+ DEBUG(10,("msg_file_was_renamed: renaming file %s from %s -> %s\n",
+ fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname)));
status = fsp_set_smb_fname(fsp, smb_fname);
if (!NT_STATUS_IS_OK(status)) {
actually within this share and adjust newname accordingly. */
DEBUG(10,("msg_file_was_renamed: share mismatch (sharepath %s "
"not sharepath %s) "
- "fnum %d from %s -> %s\n",
+ "%s from %s -> %s\n",
fsp->conn->connectpath,
sharepath,
- fsp->fnum,
+ fsp_fnum_dbg(fsp),
fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname)));
}
fsp->base_fsp = base_fsp;
}
+ if (allocation_size) {
+ fsp->initial_allocation_size = smb_roundup(fsp->conn,
+ allocation_size);
+ }
+
status = open_file_ntcreate(conn,
req,
access_mask,
fsp->initial_allocation_size = smb_roundup(
fsp->conn, (uint64_t)fsp->fsp_name->st.st_ex_size);
}
+ } else {
+ fsp->initial_allocation_size = 0;
}
if ((info == FILE_WAS_CREATED) && lp_nt_acl_support(SNUM(conn)) &&
fsp->access_mask = FILE_GENERIC_ALL;
- /* Convert all the generic bits. */
- security_acl_map_generic(sd->dacl, &file_generic_mapping);
- security_acl_map_generic(sd->sacl, &file_generic_mapping);
-
if (sec_info_sent & (SECINFO_OWNER|
SECINFO_GROUP|
SECINFO_DACL|
SECINFO_SACL)) {
- status = SMB_VFS_FSET_NT_ACL(fsp, sec_info_sent, sd);
+ status = set_sd(fsp, sd, sec_info_sent);
}
fsp->access_mask = saved_access_mask;