static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
connection_struct *conn,
- const char *orig_path,
struct smb_filename *smb_fname);
/****************************************************************************
}
/* Parent exists - set "start" to be the
- * last compnent to shorten the tree walk. */
+ * last component to shorten the tree walk. */
/*
* Safe to use discard_const_p
if (conn->case_sensitive && !conn->case_preserve &&
!conn->short_case_preserve) {
- if (!strnorm(smb_fname->base_name, lp_defaultcase(SNUM(conn)))) {
+ if (!strnorm(smb_fname->base_name, lp_default_case(SNUM(conn)))) {
DEBUG(0, ("strnorm %s failed\n", smb_fname->base_name));
status = NT_STATUS_INVALID_PARAMETER;
goto err;
*/
*stream = '\0';
stream = tmp;
+
+ if (smb_fname->base_name[0] == '\0') {
+ /*
+ * orig_name was just a stream name.
+ * This is a stream on the root of
+ * the share. Replace base_name with
+ * a "."
+ */
+ smb_fname->base_name =
+ talloc_strdup(smb_fname, ".");
+ if (smb_fname->base_name == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto err;
+ }
+ if (SMB_VFS_STAT(conn, smb_fname) != 0) {
+ status = map_nt_error_from_unix(errno);
+ goto err;
+ }
+ DEBUG(5, ("conversion finished %s -> %s\n",
+ orig_path,
+ smb_fname->base_name));
+ goto done;
+ }
}
}
if (errno == ENOENT) {
/* Optimization when creating a new file - only
- the last component doesn't exist. */
+ the last component doesn't exist.
+ NOTE : check_parent_exists() doesn't preserve errno.
+ */
+ int saved_errno = errno;
status = check_parent_exists(ctx,
conn,
posix_pathnames,
smb_fname,
&dirpath,
&start);
+ errno = saved_errno;
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
* Optimization for common case where the wildcard
* is in the last component and the client already
* sent the correct case.
+ * NOTE : check_parent_exists() doesn't preserve errno.
*/
+ int saved_errno = errno;
status = check_parent_exists(ctx,
conn,
posix_pathnames,
smb_fname,
&dirpath,
&start);
+ errno = saved_errno;
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
/*
* ENOENT/EACCESS are the only valid errors
- * here. EACCESS needs handling here for
- * "dropboxes", i.e. directories where users
- * can only put stuff with permission -wx.
+ * here.
*/
- if ((errno != 0) && (errno != ENOENT)
- && (errno != EACCES)) {
+
+ if (errno == EACCES) {
+ if ((ucf_flags & UCF_PREP_CREATEFILE) == 0) {
+ status = NT_STATUS_ACCESS_DENIED;
+ goto fail;
+ } else {
+ /*
+ * This is the dropbox
+ * behaviour. A dropbox is a
+ * directory with only -wx
+ * permissions, so
+ * get_real_filename fails
+ * with EACCESS, it needs to
+ * list the directory. We
+ * nevertheless want to allow
+ * users creating a file.
+ */
+ errno = 0;
+ }
+ }
+
+ if ((errno != 0) && (errno != ENOENT)) {
/*
* ENOTDIR and ELOOP both map to
* NT_STATUS_OBJECT_PATH_NOT_FOUND
conn->params) &&
!conn->short_case_preserve)) {
if (!strnorm(start,
- lp_defaultcase(SNUM(conn)))) {
+ lp_default_case(SNUM(conn)))) {
DEBUG(0, ("strnorm %s failed\n",
start));
status = NT_STATUS_INVALID_PARAMETER;
smb_fname->stream_name = stream;
/* Check path now that the base_name has been converted. */
- status = build_stream_path(ctx, conn, orig_path, smb_fname);
+ status = build_stream_path(ctx, conn, smb_fname);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
return NT_STATUS_OK;
fail:
DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
- if (*dirpath != '\0') {
+ if (dirpath && *dirpath != '\0') {
smb_fname->base_name = talloc_asprintf(smb_fname, "%s/%s",
dirpath, start);
} else {
}
/****************************************************************************
- Ensure a path is not vetod.
+ Ensure a path is not vetoed.
****************************************************************************/
-NTSTATUS check_veto_path(connection_struct *conn, const char *name)
+static NTSTATUS check_veto_path(connection_struct *conn, const char *name)
{
if (IS_VETO_PATH(conn, name)) {
/* Is it not dot or dot dot. */
return status;
}
- if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
+ if (!lp_widelinks(SNUM(conn)) || !lp_follow_symlinks(SNUM(conn))) {
status = check_reduced_name(conn,name);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("check_name: name %s failed with %s\n",name,
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
connection_struct *conn,
- const char *orig_path,
struct smb_filename *smb_fname)
{
NTSTATUS status;