summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Prouty <tprouty@samba.org>2009-04-07 13:39:57 -0700
committerTim Prouty <tprouty@samba.org>2009-05-20 17:40:15 -0700
commitc1a21d085d758284fe6997a05396f225da683352 (patch)
tree5cb74bc432c5e3c76f8eaac6652a3125ea108515
parent5d3d51e9ad1e4db8d9580ce7f2ba4e86e658bb13 (diff)
downloadsamba-c1a21d085d758284fe6997a05396f225da683352.tar.gz
samba-c1a21d085d758284fe6997a05396f225da683352.tar.bz2
samba-c1a21d085d758284fe6997a05396f225da683352.zip
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based operations to operate on a struct smb_filename instead of a char *. This same concept already exists in source4. My goals for this series of patches are to eventually: 1) Solve the stream vs. posix filename that contains a colon ambiguity that currently exists. 2) Make unix_convert the only function that parses the stream name. 3) Clean up the unix_convert API. 4) Change all path based vfs operation to take a struct smb_filename. 5) Make is_ntfs_stream_name() a constant operation that can simply check the state of struct smb_filename rather than re-parse the filename. 6) Eliminate the need for split_ntfs_stream_name() to exist. My strategy is to start from the inside at unix_convert() and work my way out through the vfs layer, call by call. This first patch does just that, by changing unix_convert and all of its callers to operate on struct smb_filename. Since this is such a large change, I plan on pushing the patches in phases, where each phase keeps full compatibility and passes make test. The API of unix_convert has been simplified from: NTSTATUS unix_convert(TALLOC_CTX *ctx, connection_struct *conn, const char *orig_path, bool allow_wcard_last_component, char **pp_conv_path, char **pp_saved_last_component, SMB_STRUCT_STAT *pst) to: NTSTATUS unix_convert(TALLOC_CTX *ctx, connection_struct *conn, const char *orig_path, struct smb_filename *smb_fname, uint32_t ucf_flags) Currently the smb_filename struct looks like: struct smb_filename { char *base_name; char *stream_name; char *original_lcomp; SMB_STRUCT_STAT st; }; One key point here is the decision to break up the base_name and stream_name. I have introduced a helper function called get_full_smb_filename() that takes an smb_filename struct and allocates the full_name. I changed the callers of unix_convert() to subsequently call get_full_smb_filename() for the time being, but I plan to eventually eliminate get_full_smb_filename().
-rw-r--r--source3/include/proto.h12
-rw-r--r--source3/include/smb.h16
-rw-r--r--source3/modules/onefs_open.c15
-rw-r--r--source3/printing/nt_printing.c17
-rw-r--r--source3/smbd/filename.c175
-rw-r--r--source3/smbd/msdfs.c15
-rw-r--r--source3/smbd/nttrans.c90
-rw-r--r--source3/smbd/open.c15
-rw-r--r--source3/smbd/reply.c488
-rw-r--r--source3/smbd/trans2.c128
10 files changed, 588 insertions, 383 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 6f298ad9a0..a45fa42e3d 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6264,13 +6264,13 @@ int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst);
/* The following definitions come from smbd/filename.c */
+NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx, const struct smb_filename *smb_fname,
+ char **full_name);
NTSTATUS unix_convert(TALLOC_CTX *ctx,
- connection_struct *conn,
- const char *orig_path,
- bool allow_wcard_last_component,
- char **pp_conv_path,
- char **pp_saved_last_component,
- SMB_STRUCT_STAT *pst);
+ connection_struct *conn,
+ const char *orig_path,
+ struct smb_filename **smb_fname,
+ uint32_t ucf_flags);
NTSTATUS check_name(connection_struct *conn, const char *name);
int get_real_filename(connection_struct *conn, const char *path,
const char *name, TALLOC_CTX *mem_ctx,
diff --git a/source3/include/smb.h b/source3/include/smb.h
index abcd49451c..9332df3cd2 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1925,4 +1925,20 @@ struct smb_file_time {
struct timespec create_time;
};
+/*
+ * unix_convert_flags
+ */
+#define UCF_SAVE_LCOMP 0x00000001
+#define UCF_ALLOW_WCARD_LCOMP 0x00000002
+
+/*
+ * smb_filename
+ */
+struct smb_filename {
+ char *base_name;
+ char *stream_name;
+ char *original_lcomp;
+ SMB_STRUCT_STAT st;
+};
+
#endif /* _SMB_H */
diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c
index dc8bf10a94..7d4379f1fc 100644
--- a/source3/modules/onefs_open.c
+++ b/source3/modules/onefs_open.c
@@ -2058,16 +2058,27 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle,
/* Convert dos path to unix path if it hasn't already been done. */
if (create_file_flags & CFF_DOS_PATH) {
+ struct smb_filename *smb_fname = NULL;
char *converted_fname;
SET_STAT_INVALID(sbuf);
- status = unix_convert(talloc_tos(), conn, fname, False,
- &converted_fname, NULL, &sbuf);
+ status = unix_convert(talloc_tos(), conn, fname, &smb_fname,
+ 0);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+
+ status = get_full_smb_filename(talloc_tos(), &smb_fname,
+ &converted_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(smb_fname);
+ goto fail;
+ }
+
+ sbuf = smb_fname->st;
fname = converted_fname;
+ TALLOC_FREE(smb_fname);
} else {
if (psbuf != NULL) {
sbuf = *psbuf;
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 34b7a577f8..39e9661bd6 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -638,7 +638,9 @@ static char *driver_unix_convert(connection_struct *conn,
const char *old_name,
SMB_STRUCT_STAT *pst)
{
+ NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
+ struct smb_filename *smb_fname = NULL;
char *name = talloc_strdup(ctx, old_name);
char *new_name = NULL;
@@ -651,7 +653,20 @@ static char *driver_unix_convert(connection_struct *conn,
return NULL;
}
trim_string(name,"/","/");
- unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
+
+ status = unix_convert(ctx, conn, name, &smb_fname, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ return NULL;
+ }
+
+ *pst = smb_fname->st;
+ status = get_full_smb_filename(ctx, smb_fname, &new_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(smb_fname);
+ return NULL;
+ }
+
+ TALLOC_FREE(smb_fname);
return new_name;
}
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 0d5529b6b0..36503483a8 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -29,10 +29,7 @@
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
connection_struct *conn,
const char *orig_path,
- const char *basepath,
- const char *streamname,
- SMB_STRUCT_STAT *pst,
- char **path);
+ struct smb_filename *smb_fname);
/****************************************************************************
Mangle the 2nd name and check if it is then equal to the first name.
@@ -83,10 +80,27 @@ static NTSTATUS determine_path_error(const char *name,
}
}
+NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx, const struct smb_filename *smb_fname,
+ char **full_name)
+{
+ if (smb_fname->stream_name) {
+ *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name,
+ smb_fname->stream_name);
+ } else {
+ *full_name = talloc_strdup(ctx, smb_fname->base_name);
+ }
+
+ if (!*full_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+}
+
/****************************************************************************
This routine is called to convert names from the dos namespace to unix
-namespace. It needs to handle any case conversions, mangling, format
-changes etc.
+namespace. It needs to handle any case conversions, mangling, format changes,
+streams etc.
We assume that we have already done a chdir() to the right "root" directory
for this service.
@@ -94,32 +108,34 @@ for this service.
The function will return an NTSTATUS error if some part of the name except for
the last part cannot be resolved, else NT_STATUS_OK.
-Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't
-get any fatal errors that should immediately terminate the calling
-SMB processing whilst resolving.
+Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
+didn't get any fatal errors that should immediately terminate the calling SMB
+processing whilst resolving.
-If the saved_last_component != 0, then the unmodified last component
-of the pathname is returned there. If saved_last_component == 0 then nothing
-is returned there.
+If the UCF_SAVE_LCOMP flag is passed in, then the unmodified last component
+of the pathname is set in smb_filename->original_lcomp.
-If last_component_wcard is true then a MS wildcard was detected and
+If UCF_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard was detected and
should be allowed in the last component of the path only.
-On exit from unix_convert, if *pst was not null, then the file stat
-struct will be returned if the file exists and was found, if not this
-stat struct will be filled with zeros (and this can be detected by checking
-for nlinks = 0, which can never be true for any file).
+If the orig_path was a stream, smb_filename->base_name will point to the base
+filename, and smb_filename->stream_name will point to the stream name. If
+orig_path was not a stream, then smb_filename->stream_name will be NULL.
+
+On exit from unix_convert, the smb_filename->st stat struct will be populated
+if the file exists and was found, if not this stat struct will be filled with
+zeros (and this can be detected by checking for nlinks = 0, which can never be
+true for any file).
****************************************************************************/
NTSTATUS unix_convert(TALLOC_CTX *ctx,
- connection_struct *conn,
- const char *orig_path,
- bool allow_wcard_last_component,
- char **pp_conv_path,
- char **pp_saved_last_component,
- SMB_STRUCT_STAT *pst)
+ connection_struct *conn,
+ const char *orig_path,
+ struct smb_filename **smb_fname_out,
+ uint32_t ucf_flags)
{
SMB_STRUCT_STAT st;
+ struct smb_filename *smb_fname = NULL;
char *start, *end;
char *dirpath = NULL;
char *name = NULL;
@@ -127,21 +143,26 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
bool component_was_mangled = False;
bool name_has_wildcard = False;
bool posix_pathnames = false;
+ bool allow_wcard_last_component = ucf_flags & UCF_ALLOW_WCARD_LCOMP;
+ bool save_last_component = ucf_flags & UCF_SAVE_LCOMP;
NTSTATUS result;
int ret = -1;
- SET_STAT_INVALID(*pst);
- *pp_conv_path = NULL;
- if(pp_saved_last_component) {
- *pp_saved_last_component = NULL;
+ *smb_fname_out = NULL;
+
+ smb_fname = TALLOC_ZERO_P(talloc_tos(), struct smb_filename);
+ if (smb_fname == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
if (conn->printer) {
/* we don't ever use the filenames on a printer share as a
filename - so don't convert them */
- if (!(*pp_conv_path = talloc_strdup(ctx,orig_path))) {
+ if (!(smb_fname->base_name = talloc_strdup(smb_fname,
+ orig_path))) {
return NT_STATUS_NO_MEMORY;
}
+ *smb_fname_out = smb_fname;
return NT_STATUS_OK;
}
@@ -174,7 +195,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
return NT_STATUS_NO_MEMORY;
}
if (SMB_VFS_STAT(conn,name,&st) == 0) {
- *pst = st;
+ smb_fname->st = st;
} else {
return map_nt_error_from_unix(errno);
}
@@ -217,18 +238,20 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
* Ensure saved_last_component is valid even if file exists.
*/
- if(pp_saved_last_component) {
+ if(save_last_component) {
end = strrchr_m(name, '/');
if (end) {
- *pp_saved_last_component = talloc_strdup(ctx, end + 1);
+ smb_fname->original_lcomp = talloc_strdup(ctx,
+ end + 1);
} else {
- *pp_saved_last_component = talloc_strdup(ctx,
- name);
+ smb_fname->original_lcomp = talloc_strdup(ctx, name);
}
}
posix_pathnames = lp_posix_pathnames();
+ /* Strip off the stream. Should we use any of the other stream parsing
+ * at this point? Also, should we set the is_stream bit? */
if (!posix_pathnames) {
stream = strchr_m(name, ':');
@@ -253,7 +276,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
if((!conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
stat_cache_lookup(conn, &name, &dirpath, &start, &st)) {
- *pst = st;
+ smb_fname->st = st;
goto done;
}
@@ -295,7 +318,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
}
stat_cache_add(orig_path, name, conn->case_sensitive);
DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
- *pst = st;
+ smb_fname->st = st;
goto done;
}
@@ -346,11 +369,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*end = 0;
}
- if (pp_saved_last_component) {
- TALLOC_FREE(*pp_saved_last_component);
- *pp_saved_last_component = talloc_strdup(ctx,
+ if (save_last_component) {
+ TALLOC_FREE(smb_fname->original_lcomp);
+ smb_fname->original_lcomp = talloc_strdup(ctx,
end ? end + 1 : start);
- if (!*pp_saved_last_component) {
+ if (!smb_fname->original_lcomp) {
DEBUG(0, ("talloc failed\n"));
return NT_STATUS_NO_MEMORY;
}
@@ -427,7 +450,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
* struct. JRA.
*/
- *pst = st;
+ smb_fname->st = st;
}
} else {
@@ -621,7 +644,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
}
if (ret == 0) {
- *pst = st;
+ smb_fname->st = st;
} else {
SET_STAT_INVALID(st);
}
@@ -703,35 +726,34 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
done:
+ smb_fname->base_name = name;
+
if (stream != NULL) {
- char *tmp = NULL;
+ smb_fname->stream_name = stream;
- result = build_stream_path(ctx, conn, orig_path, name, stream,
- pst, &tmp);
+ /* Check path now that the base_name has been converted. */
+ result = build_stream_path(ctx, conn, orig_path, smb_fname);
if (!NT_STATUS_IS_OK(result)) {
goto fail;
}
-
- DEBUG(10, ("build_stream_path returned %s\n", tmp));
-
- TALLOC_FREE(name);
- name = tmp;
}
- *pp_conv_path = name;
TALLOC_FREE(dirpath);
+ *smb_fname_out = smb_fname;
return NT_STATUS_OK;
fail:
DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
if (*dirpath != '\0') {
- *pp_conv_path = talloc_asprintf(ctx,
- "%s/%s", dirpath, start);
+ smb_fname->base_name = talloc_asprintf(ctx, "%s/%s", dirpath,
+ start);
} else {
- *pp_conv_path = talloc_strdup(ctx, start);
+ smb_fname->base_name = talloc_strdup(ctx, start);
}
- if (!*pp_conv_path) {
+ if (!smb_fname->base_name) {
DEBUG(0, ("talloc_asprintf failed\n"));
return NT_STATUS_NO_MEMORY;
}
+
+ *smb_fname_out = smb_fname;
TALLOC_FREE(name);
TALLOC_FREE(dirpath);
return result;
@@ -923,25 +945,19 @@ int get_real_filename(connection_struct *conn, const char *path,
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
connection_struct *conn,
const char *orig_path,
- const char *basepath,
- const char *streamname,
- SMB_STRUCT_STAT *pst,
- char **path)
+ struct smb_filename *smb_fname)
{
- SMB_STRUCT_STAT st;
char *result = NULL;
NTSTATUS status;
unsigned int i, num_streams;
struct stream_struct *streams = NULL;
- result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname);
- if (result == NULL) {
+ status = get_full_smb_filename(mem_ctx, smb_fname, &result);
+ if (!NT_STATUS_IS_OK(status)) {
return NT_STATUS_NO_MEMORY;
}
- if (SMB_VFS_STAT(conn, result, &st) == 0) {
- *pst = st;
- *path = result;
+ if (SMB_VFS_STAT(conn, result, &smb_fname->st) == 0) {
return NT_STATUS_OK;
}
@@ -951,12 +967,12 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
goto fail;
}
- status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx,
+ /* Fall back to a case-insensitive scan of all streams on the file. */
+ status = SMB_VFS_STREAMINFO(conn, NULL, smb_fname->base_name, mem_ctx,
&num_streams, &streams);
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
- SET_STAT_INVALID(*pst);
- *path = result;
+ SET_STAT_INVALID(smb_fname->st);
return NT_STATUS_OK;
}
@@ -967,8 +983,8 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
for (i=0; i<num_streams; i++) {
DEBUG(10, ("comparing [%s] and [%s]: ",
- streamname, streams[i].name));
- if (fname_equal(streamname, streams[i].name,
+ smb_fname->stream_name, streams[i].name));
+ if (fname_equal(smb_fname->stream_name, streams[i].name,
conn->case_sensitive)) {
DEBUGADD(10, ("equal\n"));
break;
@@ -976,28 +992,33 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
DEBUGADD(10, ("not equal\n"));
}
+ /* Couldn't find the stream. */
if (i == num_streams) {
- SET_STAT_INVALID(*pst);
- *path = result;
+ SET_STAT_INVALID(smb_fname->st);
TALLOC_FREE(streams);
return NT_STATUS_OK;
}
- TALLOC_FREE(result);
+ DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
+ smb_fname->stream_name, streams[i].name));
+
- result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name);
- if (result == NULL) {
+ TALLOC_FREE(smb_fname->stream_name);
+ smb_fname->stream_name = talloc_strdup(mem_ctx, streams[i].name);
+
+ TALLOC_FREE(result);
+ status = get_full_smb_filename(mem_ctx, smb_fname, &result);
+ if (!NT_STATUS_IS_OK(status)) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
- SET_STAT_INVALID(*pst);
+ SET_STAT_INVALID(smb_fname->st);
- if (SMB_VFS_STAT(conn, result, pst) == 0) {
+ if (SMB_VFS_STAT(conn, result, &smb_fname->st) == 0) {
stat_cache_add(orig_path, result, conn->case_sensitive);
}
- *path = result;
TALLOC_FREE(streams);
return NT_STATUS_OK;
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index efbc05ceb0..7f99a186aa 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -515,8 +515,8 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
{
char *p = NULL;
char *q = NULL;
- SMB_STRUCT_STAT sbuf;
NTSTATUS status;
+ struct smb_filename *smb_fname = NULL;
char *localpath = NULL;
char *canon_dfspath = NULL; /* Canonicalized dfs path. (only '/'
components). */
@@ -536,13 +536,22 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
* think this is needed. JRA.
*/
- status = unix_convert(ctx, conn, pdp->reqpath, search_flag, &localpath,
- NULL, &sbuf);
+ status = unix_convert(ctx, conn, pdp->reqpath, &smb_fname,
+ search_flag ? UCF_ALLOW_WCARD_LCOMP : 0);
+
if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,
NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
return status;
}
+ status = get_full_smb_filename(ctx, smb_fname, &localpath);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(smb_fname);
+ return status;
+ }
+
+ TALLOC_FREE(smb_fname);
+
/* Optimization - check if we can redirect the whole path. */
if (is_msdfs_link_internal(ctx, conn, localpath, pp_targetpath, NULL)) {
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 7e75eea6b4..d51c9a6d67 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1155,11 +1155,10 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
const char *newname_in,
uint32 attrs)
{
- SMB_STRUCT_STAT sbuf1, sbuf2;
+ struct smb_filename *smb_fname = NULL;
+ struct smb_filename *smb_fname_new = NULL;
char *oldname = NULL;
char *newname = NULL;
- char *last_component_oldname = NULL;
- char *last_component_newname = NULL;
files_struct *fsp1,*fsp2;
uint32 fattr;
int info;
@@ -1167,59 +1166,69 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
NTSTATUS status = NT_STATUS_OK;
char *parent;
- ZERO_STRUCT(sbuf1);
- ZERO_STRUCT(sbuf2);
-
if (!CAN_WRITE(conn)) {
- return NT_STATUS_MEDIA_WRITE_PROTECTED;
+ status = NT_STATUS_MEDIA_WRITE_PROTECTED;
+ goto out;
}
- status = unix_convert(ctx, conn, oldname_in, False, &oldname,
- &last_component_oldname, &sbuf1);
+ status = unix_convert(ctx, conn, oldname_in, &smb_fname, 0);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_fname, &oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
}
status = check_name(conn, oldname);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
/* Source must already exist. */
- if (!VALID_STAT(sbuf1)) {
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ if (!VALID_STAT(smb_fname->st)) {
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ goto out;
}
/* Ensure attributes match. */
- fattr = dos_mode(conn,oldname,&sbuf1);
+ fattr = dos_mode(conn, oldname, &smb_fname->st);
if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) {
- return NT_STATUS_NO_SUCH_FILE;
+ status = NT_STATUS_NO_SUCH_FILE;
+ goto out;
}
- status = unix_convert(ctx, conn, newname_in, False, &newname,
- &last_component_newname, &sbuf2);
+ status = unix_convert(ctx, conn, newname_in, &smb_fname_new, 0);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_fname_new, &newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
}
status = check_name(conn, newname);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
/* Disallow if newname already exists. */
- if (VALID_STAT(sbuf2)) {
- return NT_STATUS_OBJECT_NAME_COLLISION;
+ if (VALID_STAT(smb_fname_new->st)) {
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
+ goto out;
}
/* No links from a directory. */
- if (S_ISDIR(sbuf1.st_mode)) {
- return NT_STATUS_FILE_IS_A_DIRECTORY;
+ if (S_ISDIR(smb_fname->st.st_mode)) {
+ status = NT_STATUS_FILE_IS_A_DIRECTORY;
+ goto out;
}
/* Ensure this is within the share. */
status = check_reduced_name(conn, oldname);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
DEBUG(10,("copy_internals: doing file copy %s to %s\n",
@@ -1243,10 +1252,10 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
NULL, /* ea_list */
&fsp1, /* result */
&info, /* pinfo */
- &sbuf1); /* psbuf */
+ &smb_fname->st); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
status = SMB_VFS_CREATE_FILE(
@@ -1267,15 +1276,15 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
NULL, /* ea_list */
&fsp2, /* result */
&info, /* pinfo */
- &sbuf2); /* psbuf */
+ &smb_fname_new->st); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
close_file(NULL, fsp1, ERROR_CLOSE);
- return status;
+ goto out;
}
- if (sbuf1.st_size) {
- ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size);
+ if (smb_fname->st.st_size) {
+ ret = vfs_transfer_file(fsp1, fsp2, smb_fname->st.st_size);
}
/*
@@ -1287,7 +1296,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
close_file(NULL, fsp1, NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- set_close_write_time(fsp2, get_mtimespec(&sbuf1));
+ set_close_write_time(fsp2, get_mtimespec(&smb_fname->st));
status = close_file(NULL, fsp2, NORMAL_CLOSE);
@@ -1295,15 +1304,24 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
creates the file. This isn't the correct thing to do in the copy
case. JRA */
if (!parent_dirname(talloc_tos(), newname, &parent, NULL)) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
- file_set_dosmode(conn, newname, fattr, &sbuf2, parent, false);
+ file_set_dosmode(conn, newname, fattr, &smb_fname_new->st, parent,
+ false);
TALLOC_FREE(parent);
- if (ret < (SMB_OFF_T)sbuf1.st_size) {
- return NT_STATUS_DISK_FULL;
+ if (ret < (SMB_OFF_T)smb_fname->st.st_size) {
+ status = NT_STATUS_DISK_FULL;
+ goto out;
+ }
+ out:
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
+ if (smb_fname_new) {
+ TALLOC_FREE(smb_fname_new);
}
-
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
nt_errstr(status), oldname, newname));
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index a0ae82a73c..e6f523a162 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -3442,16 +3442,27 @@ NTSTATUS create_file_default(connection_struct *conn,
}
if (create_file_flags & CFF_DOS_PATH) {
+ struct smb_filename *smb_fname = NULL;
char *converted_fname;
SET_STAT_INVALID(sbuf);
- status = unix_convert(talloc_tos(), conn, fname, False,
- &converted_fname, NULL, &sbuf);
+ status = unix_convert(talloc_tos(), conn, fname, &smb_fname,
+ 0);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+
+ status = get_full_smb_filename(talloc_tos(), smb_fname,
+ &converted_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(smb_fname);
+ goto fail;
+ }
+
+ sbuf = smb_fname->st;
fname = converted_fname;
+ TALLOC_FREE(smb_fname);
} else {
if (psbuf != NULL) {
sbuf = *psbuf;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 879550bb2e..c15ebbe35e 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -966,8 +966,8 @@ static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
void reply_checkpath(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_filename *smb_fname = NULL;
char *name = NULL;
- SMB_STRUCT_STAT sbuf;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
@@ -999,7 +999,12 @@ void reply_checkpath(struct smb_request *req)
DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
- status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
+ status = unix_convert(ctx, conn, name, &smb_fname, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto path_err;
+ }
+
+ status = get_full_smb_filename(ctx, smb_fname, &name);
if (!NT_STATUS_IS_OK(status)) {
goto path_err;
}
@@ -1010,25 +1015,32 @@ void reply_checkpath(struct smb_request *req)
goto path_err;
}
- if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
+ if (!VALID_STAT(smb_fname->st) &&
+ (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
status = map_nt_error_from_unix(errno);
goto path_err;
}
- if (!S_ISDIR(sbuf.st_mode)) {
+ if (!S_ISDIR(smb_fname->st.st_mode)) {
reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
ERRDOS, ERRbadpath);
- END_PROFILE(SMBcheckpath);
- return;
+ goto out;
}
reply_outbuf(req, 0, 0);
-
+ out:
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
END_PROFILE(SMBcheckpath);
return;
- path_err:
+ path_err:
+
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
END_PROFILE(SMBcheckpath);
@@ -1061,8 +1073,8 @@ void reply_checkpath(struct smb_request *req)
void reply_getatr(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_filename *smb_fname = NULL;
char *fname = NULL;
- SMB_STRUCT_STAT sbuf;
int mode=0;
SMB_OFF_T size=0;
time_t mtime=0;
@@ -1076,8 +1088,7 @@ void reply_getatr(struct smb_request *req)
p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBgetatr);
- return;
+ goto out;
}
status = resolve_dfspath(ctx, conn,
@@ -1088,12 +1099,10 @@ void reply_getatr(struct smb_request *req)
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- END_PROFILE(SMBgetatr);
- return;
+ goto out;
}
reply_nterror(req, status);
- END_PROFILE(SMBgetatr);
- return;
+ goto out;
}
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
@@ -1106,29 +1115,32 @@ void reply_getatr(struct smb_request *req)
size = 0;
mtime = 0;
} else {
- status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
+ status = unix_convert(ctx, conn, fname, &smb_fname, 0);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBgetatr);
- return;
+ goto out;
+ }
+ status = get_full_smb_filename(ctx, smb_fname, &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ goto out;
}
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
reply_nterror(req, status);
- END_PROFILE(SMBgetatr);
- return;
+ goto out;
}
- if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
+ if (!VALID_STAT(smb_fname->st) &&
+ (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
reply_unixerror(req, ERRDOS,ERRbadfile);
- END_PROFILE(SMBgetatr);
- return;
+ goto out;
}
- mode = dos_mode(conn,fname,&sbuf);
- size = sbuf.st_size;
- mtime = sbuf.st_mtime;
+ mode = dos_mode(conn, fname, &smb_fname->st);
+ size = smb_fname->st.st_size;
+ mtime = smb_fname->st.st_mtime;
if (mode & aDIR) {
size = 0;
}
@@ -1151,6 +1163,10 @@ void reply_getatr(struct smb_request *req)
DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
+ out:
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
END_PROFILE(SMBgetatr);
return;
}
@@ -1163,10 +1179,10 @@ void reply_setatr(struct smb_request *req)
{
struct smb_file_time ft;
connection_struct *conn = req->conn;
+ struct smb_filename *smb_fname = NULL;
char *fname = NULL;
int mode;
time_t mtime;
- SMB_STRUCT_STAT sbuf;
const char *p;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
@@ -1177,15 +1193,14 @@ void reply_setatr(struct smb_request *req)
if (req->wct < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
+ goto out;
}
p = (const char *)req->buf + 1;
p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBsetatr);
- return;
+ goto out;
}
status = resolve_dfspath(ctx, conn,
@@ -1196,26 +1211,28 @@ void reply_setatr(struct smb_request *req)
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- END_PROFILE(SMBsetatr);
- return;
+ goto out;
}
reply_nterror(req, status);
- END_PROFILE(SMBsetatr);
- return;
+ goto out;
}
- status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
+ status = unix_convert(ctx, conn, fname, &smb_fname, 0);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBsetatr);
- return;
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_fname, &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ goto out;
}
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBsetatr);
- return;
+ goto out;
}
if (fname[0] == '.' && fname[1] == '\0') {
@@ -1224,8 +1241,7 @@ void reply_setatr(struct smb_request *req)
* condition. Might be moved to somewhere else later -- vl
*/
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- END_PROFILE(SMBsetatr);
- return;
+ goto out;
}
mode = SVAL(req->vwv+0, 0);
@@ -1233,30 +1249,32 @@ void reply_setatr(struct smb_request *req)
ft.mtime = convert_time_t_to_timespec(mtime);
status = smb_set_file_time(conn, NULL, fname,
- &sbuf, &ft, true);
+ &smb_fname->st, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
reply_unixerror(req, ERRDOS, ERRnoaccess);
- END_PROFILE(SMBsetatr);
- return;
+ goto out;
}
if (mode != FILE_ATTRIBUTE_NORMAL) {
- if (VALID_STAT_OF_DIR(sbuf))
+ if (VALID_STAT_OF_DIR(smb_fname->st))
mode |= aDIR;
else
mode &= ~aDIR;
- if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
+ if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
+ false) != 0) {
reply_unixerror(req, ERRDOS, ERRnoaccess);
- END_PROFILE(SMBsetatr);
- return;
+ goto out;
}
}
reply_outbuf(req, 0, 0);
DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
-
+ out:
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
END_PROFILE(SMBsetatr);
return;
}
@@ -1399,10 +1417,18 @@ void reply_search(struct smb_request *req)
/* dirtype &= ~aDIR; */
if (status_len == 0) {
- SMB_STRUCT_STAT sbuf;
+ struct smb_filename *smb_fname = NULL;
- nt_status = unix_convert(ctx, conn, path, True,
- &directory, NULL, &sbuf);
+ nt_status = unix_convert(ctx, conn, path, &smb_fname,
+ UCF_ALLOW_WCARD_LCOMP);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ reply_nterror(req, nt_status);
+ END_PROFILE(SMBsearch);
+ return;
+ }
+
+ nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
+ TALLOC_FREE(smb_fname);
if (!NT_STATUS_IS_OK(nt_status)) {
reply_nterror(req, nt_status);
END_PROFILE(SMBsearch);
@@ -2142,12 +2168,12 @@ void reply_mknew(struct smb_request *req)
void reply_ctemp(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint32 fattr;
files_struct *fsp;
int oplock_request;
int tmpfd;
- SMB_STRUCT_STAT sbuf;
char *s;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
@@ -2156,8 +2182,7 @@ void reply_ctemp(struct smb_request *req)
if (req->wct < 3) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
fattr = SVAL(req->vwv+0, 0);
@@ -2167,8 +2192,7 @@ void reply_ctemp(struct smb_request *req)
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
if (*fname) {
fname = talloc_asprintf(ctx,
@@ -2180,8 +2204,7 @@ void reply_ctemp(struct smb_request *req)
if (!fname) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
status = resolve_dfspath(ctx, conn,
@@ -2192,37 +2215,38 @@ void reply_ctemp(struct smb_request *req)
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
reply_nterror(req, status);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
- status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
+ status = unix_convert(ctx, conn, fname, &smb_fname, 0);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_fname, &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ goto out;
}
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
tmpfd = mkstemp(fname);
if (tmpfd == -1) {
reply_unixerror(req, ERRDOS, ERRnoaccess);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
- SET_STAT_INVALID(sbuf);
- SMB_VFS_STAT(conn,fname,&sbuf);
+ SET_STAT_INVALID(smb_fname->st);
+ SMB_VFS_STAT(conn, fname, &smb_fname->st);
/* We should fail if file does not exist. */
status = SMB_VFS_CREATE_FILE(
@@ -2242,7 +2266,7 @@ void reply_ctemp(struct smb_request *req)
NULL, /* ea_list */
&fsp, /* result */
NULL, /* pinfo */
- &sbuf); /* psbuf */
+ &smb_fname->st); /* psbuf */
/* close fd from mkstemp() */
close(tmpfd);
@@ -2250,12 +2274,10 @@ void reply_ctemp(struct smb_request *req)
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
reply_openerror(req, status);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
reply_outbuf(req, 1, 0);
@@ -2277,8 +2299,7 @@ void reply_ctemp(struct smb_request *req)
if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
== -1) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBctemp);
- return;
+ goto out;
}
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
@@ -2293,8 +2314,11 @@ void reply_ctemp(struct smb_request *req)
DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
- fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
-
+ fsp->fh->fd, (unsigned int)smb_fname->st.st_mode));
+ out:
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
END_PROFILE(SMBctemp);
return;
}
@@ -2479,24 +2503,33 @@ static NTSTATUS do_unlink(connection_struct *conn,
NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
uint32 dirtype, const char *name_in, bool has_wild)
{
+ struct smb_filename *smb_fname = NULL;
const char *directory = NULL;
char *mask = NULL;
char *name = NULL;
char *p = NULL;
int count=0;
NTSTATUS status = NT_STATUS_OK;
- SMB_STRUCT_STAT sbuf, st;
+ SMB_STRUCT_STAT st;
TALLOC_CTX *ctx = talloc_tos();
- status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
+ status = unix_convert(ctx, conn, name_in, &smb_fname,
+ has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
+ status = get_full_smb_filename(ctx, smb_fname, &name);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(smb_fname);
+ return status;
+ }
+
p = strrchr_m(name,'/');
if (!p) {
directory = talloc_strdup(ctx, ".");
if (!directory) {
+ TALLOC_FREE(smb_fname);
return NT_STATUS_NO_MEMORY;
}
mask = name;
@@ -2515,7 +2548,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
+ if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask,conn->params)) {
char *new_mask = NULL;
mangle_lookup_name_from_8_3(ctx,
mask,
@@ -2525,6 +2558,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
mask = new_mask;
}
}
+ TALLOC_FREE(smb_fname);
if (!has_wild) {
directory = talloc_asprintf(ctx,
@@ -5141,9 +5175,9 @@ void reply_printwrite(struct smb_request *req)
void reply_mkdir(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_filename *smb_dname = NULL;
char *directory = NULL;
NTSTATUS status;
- SMB_STRUCT_STAT sbuf;
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBmkdir);
@@ -5152,8 +5186,7 @@ void reply_mkdir(struct smb_request *req)
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBmkdir);
- return;
+ goto out;
}
status = resolve_dfspath(ctx, conn,
@@ -5164,26 +5197,28 @@ void reply_mkdir(struct smb_request *req)
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- END_PROFILE(SMBmkdir);
- return;
+ goto out;
}
reply_nterror(req, status);
- END_PROFILE(SMBmkdir);
- return;
+ goto out;
}
- status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
+ status = unix_convert(ctx, conn, directory, &smb_dname, 0);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBmkdir);
- return;
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_dname, &directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ goto out;
}
status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBmkdir);
- return;
+ goto out;
}
status = create_directory(conn, req, directory);
@@ -5204,14 +5239,16 @@ void reply_mkdir(struct smb_request *req)
}
reply_nterror(req, status);
- END_PROFILE(SMBmkdir);
- return;
+ goto out;
}
reply_outbuf(req, 0, 0);
DEBUG( 3, ( "mkdir %s\n", directory ) );
-
+ out:
+ if (smb_dname) {
+ TALLOC_FREE(smb_dname);
+ }
END_PROFILE(SMBmkdir);
return;
}
@@ -5418,8 +5455,8 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
void reply_rmdir(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_filename *smb_dname = NULL;
char *directory = NULL;
- SMB_STRUCT_STAT sbuf;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
@@ -5429,8 +5466,7 @@ void reply_rmdir(struct smb_request *req)
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBrmdir);
- return;
+ goto out;
}
status = resolve_dfspath(ctx, conn,
@@ -5441,41 +5477,44 @@ void reply_rmdir(struct smb_request *req)
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- END_PROFILE(SMBrmdir);
- return;
+ goto out;
}
reply_nterror(req, status);
- END_PROFILE(SMBrmdir);
- return;
+ goto out;
}
- status = unix_convert(ctx, conn, directory, False, &directory,
- NULL, &sbuf);
+ status = unix_convert(ctx, conn, directory, &smb_dname, 0);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBrmdir);
- return;
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_dname, &directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ goto out;
}
status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBrmdir);
- return;
+ goto out;
}
dptr_closepath(directory, req->smbpid);
status = rmdir_internals(ctx, conn, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBrmdir);
- return;
+ goto out;
}
reply_outbuf(req, 0, 0);
DEBUG( 3, ( "rmdir %s\n", directory ) );
-
+ out:
+ if (smb_dname) {
+ TALLOC_FREE(smb_dname);
+ }
END_PROFILE(SMBrmdir);
return;
}
@@ -5936,35 +5975,42 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
bool dest_has_wild,
uint32_t access_mask)
{
+ struct smb_filename *smb_fname = NULL;
+ struct smb_filename *smb_fname_new = NULL;
char *directory = NULL;
char *mask = NULL;
- char *last_component_src = NULL;
- char *last_component_dest = NULL;
char *name = NULL;
char *newname = NULL;
char *p;
int count=0;
NTSTATUS status = NT_STATUS_OK;
- SMB_STRUCT_STAT sbuf1, sbuf2;
struct smb_Dir *dir_hnd = NULL;
const char *dname;
long offset = 0;
int create_options = 0;
bool posix_pathnames = lp_posix_pathnames();
- ZERO_STRUCT(sbuf1);
- ZERO_STRUCT(sbuf2);
+ status = unix_convert(ctx, conn, name_in, &smb_fname,
+ src_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_fname, &name);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
- status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
- &last_component_src, &sbuf1);
+ status = unix_convert(ctx, conn, newname_in, &smb_fname_new,
+ (UCF_SAVE_LCOMP |
+ (dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
- status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
- &last_component_dest, &sbuf2);
+ status = get_full_smb_filename(ctx, smb_fname_new, &newname);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
/*
@@ -5980,14 +6026,16 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
if (!p) {
directory = talloc_strdup(ctx, ".");
if (!directory) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
mask = name;
} else {
*p = 0;
directory = talloc_strdup(ctx, name);
if (!directory) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
mask = p+1;
*p = '/'; /* Replace needed for exceptional test below. */
@@ -6002,7 +6050,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
+ if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask, conn->params)) {
char *new_mask = NULL;
mangle_lookup_name_from_8_3(ctx,
mask,
@@ -6024,7 +6072,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
"/%s",
mask);
if (!directory) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
/* Ensure newname contains a '/' also */
@@ -6033,7 +6082,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
"./%s",
newname);
if (!newname) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
}
@@ -6043,7 +6093,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
"last_component_dest = %s\n",
conn->case_sensitive, conn->case_preserve,
conn->short_case_preserve, directory,
- newname, last_component_dest));
+ newname, smb_fname_new->original_lcomp));
/* The dest name still may have wildcards. */
if (dest_has_wild) {
@@ -6054,19 +6104,20 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
"%s %s failed\n",
directory,
newname));
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
newname = mod_newname;
}
- ZERO_STRUCT(sbuf1);
+ ZERO_STRUCT(smb_fname->st);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, directory, &sbuf1);
+ SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
} else {
- SMB_VFS_STAT(conn, directory, &sbuf1);
+ SMB_VFS_STAT(conn, directory, &smb_fname->st);
}
- if (S_ISDIR(sbuf1.st_mode)) {
+ if (S_ISDIR(smb_fname->st.st_mode)) {
create_options |= FILE_DIRECTORY_FILE;
}
@@ -6088,16 +6139,16 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
NULL, /* ea_list */
&fsp, /* result */
NULL, /* pinfo */
- &sbuf1); /* psbuf */
+ &smb_fname->st); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("Could not open rename source %s: %s\n",
directory, nt_errstr(status)));
- return status;
+ goto out;
}
status = rename_internals_fsp(conn, fsp, newname,
- last_component_dest,
+ smb_fname_new->original_lcomp,
attrs, replace_if_exists);
close_file(req, fsp, NORMAL_CLOSE);
@@ -6105,7 +6156,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
nt_errstr(status), directory,newname));
- return status;
+ goto out;
}
/*
@@ -6118,12 +6169,13 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
if (dir_hnd == NULL) {
- return map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
+ goto out;
}
status = NT_STATUS_NO_SUCH_FILE;
@@ -6132,7 +6184,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
* - gentest fix. JRA
*/
- while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
+ while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
files_struct *fsp = NULL;
char *fname = NULL;
char *destname = NULL;
@@ -6147,7 +6199,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
}
}
- if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+ if (!is_visible_file(conn, directory, dname, &smb_fname->st,
+ False)) {
continue;
}
@@ -6165,7 +6218,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
directory,
dname);
if (!fname) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
if (!resolve_wildcards(ctx,
@@ -6176,19 +6230,20 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
continue;
}
if (!destname) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
- ZERO_STRUCT(sbuf1);
+ ZERO_STRUCT(smb_fname->st);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, fname, &sbuf1);
+ SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
} else {
- SMB_VFS_STAT(conn, fname, &sbuf1);
+ SMB_VFS_STAT(conn, fname, &smb_fname->st);
}
create_options = 0;
- if (S_ISDIR(sbuf1.st_mode)) {
+ if (S_ISDIR(smb_fname->st.st_mode)) {
create_options |= FILE_DIRECTORY_FILE;
}
@@ -6210,7 +6265,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
NULL, /* ea_list */
&fsp, /* result */
NULL, /* pinfo */
- &sbuf1); /* psbuf */
+ &smb_fname->st); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
@@ -6245,6 +6300,13 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
status = map_nt_error_from_unix(errno);
}
+ out:
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
+ if (smb_fname_new) {
+ TALLOC_FREE(smb_fname_new);
+ }
return status;
}
@@ -6505,6 +6567,8 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
void reply_copy(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_filename *smb_fname = NULL;
+ struct smb_filename *smb_fname_new = NULL;
char *name = NULL;
char *newname = NULL;
char *directory = NULL;
@@ -6520,7 +6584,6 @@ void reply_copy(struct smb_request *req)
bool target_is_directory=False;
bool source_has_wild = False;
bool dest_has_wild = False;
- SMB_STRUCT_STAT sbuf1, sbuf2;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
@@ -6528,8 +6591,7 @@ void reply_copy(struct smb_request *req)
if (req->wct < 3) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
tid2 = SVAL(req->vwv+0, 0);
@@ -6541,15 +6603,13 @@ void reply_copy(struct smb_request *req)
&status, &source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
&status, &dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
@@ -6558,8 +6618,7 @@ void reply_copy(struct smb_request *req)
/* can't currently handle inter share copies XXXX */
DEBUG(3,("Rejecting inter-share copy\n"));
reply_doserror(req, ERRSRV, ERRinvdevice);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
status = resolve_dfspath_wcard(ctx, conn,
@@ -6571,12 +6630,10 @@ void reply_copy(struct smb_request *req)
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
status = resolve_dfspath_wcard(ctx, conn,
@@ -6588,50 +6645,55 @@ void reply_copy(struct smb_request *req)
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
- status = unix_convert(ctx, conn, name, source_has_wild,
- &name, NULL, &sbuf1);
+ status = unix_convert(ctx, conn, name, &smb_fname,
+ source_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
- status = unix_convert(ctx, conn, newname, dest_has_wild,
- &newname, NULL, &sbuf2);
+ status = get_full_smb_filename(ctx, smb_fname, &name);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
+ }
+
+ status = unix_convert(ctx, conn, newname, &smb_fname_new,
+ dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_fname_new, &newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ goto out;
}
- target_is_directory = VALID_STAT_OF_DIR(sbuf2);
+ target_is_directory = VALID_STAT_OF_DIR(smb_fname_new->st);
if ((flags&1) && target_is_directory) {
reply_doserror(req, ERRDOS, ERRbadfile);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
if ((flags&2) && !target_is_directory) {
reply_doserror(req, ERRDOS, ERRbadpath);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
- if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
+ if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname->st)) {
/* wants a tree copy! XXXX */
DEBUG(3,("Rejecting tree copy\n"));
reply_doserror(req, ERRSRV, ERRerror);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
p = strrchr_m(name,'/');
@@ -6645,8 +6707,7 @@ void reply_copy(struct smb_request *req)
if (!directory) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
/*
@@ -6658,7 +6719,8 @@ void reply_copy(struct smb_request *req)
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
+ if (!VALID_STAT(smb_fname->st) &&
+ mangle_is_mangled(mask, conn->params)) {
char *new_mask = NULL;
mangle_lookup_name_from_8_3(ctx,
mask,
@@ -6678,8 +6740,7 @@ void reply_copy(struct smb_request *req)
if (!resolve_wildcards(ctx,
directory,newname,&mod_newname)) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
newname = mod_newname;
}
@@ -6687,15 +6748,13 @@ void reply_copy(struct smb_request *req)
status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
status = check_name(conn, newname);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
status = copy_file(ctx,conn,directory,newname,ofun,
@@ -6703,8 +6762,7 @@ void reply_copy(struct smb_request *req)
if(!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
} else {
count++;
}
@@ -6720,21 +6778,20 @@ void reply_copy(struct smb_request *req)
status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
if (dir_hnd == NULL) {
status = map_nt_error_from_unix(errno);
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
error = ERRbadfile;
- while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
+ while ((dname = ReadDirName(dir_hnd, &offset,
+ &smb_fname->st))) {
char *destname = NULL;
char *fname = NULL;
@@ -6742,7 +6799,8 @@ void reply_copy(struct smb_request *req)
continue;
}
- if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+ if (!is_visible_file(conn, directory, dname,
+ &smb_fname->st, False)) {
continue;
}
@@ -6758,8 +6816,7 @@ void reply_copy(struct smb_request *req)
if (!fname) {
TALLOC_FREE(dir_hnd);
reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
if (!resolve_wildcards(ctx,
@@ -6769,24 +6826,21 @@ void reply_copy(struct smb_request *req)
if (!destname) {
TALLOC_FREE(dir_hnd);
reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
status = check_name(conn, destname);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
reply_nterror(req, status);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
@@ -6807,18 +6861,22 @@ void reply_copy(struct smb_request *req)
/* Error on close... */
errno = err;
reply_unixerror(req, ERRHRD, ERRgeneral);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
reply_doserror(req, ERRDOS, error);
- END_PROFILE(SMBcopy);
- return;
+ goto out;
}
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf,smb_vwv0,count);
-
+ out:
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
+ if (smb_fname_new) {
+ TALLOC_FREE(smb_fname_new);
+ }
END_PROFILE(SMBcopy);
return;
}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index edbb0dfc4d..a498e24d74 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1882,6 +1882,7 @@ static void call_trans2findfirst(connection_struct *conn,
maxentries then so be it. We assume that the redirector has
enough room for the fixed number of parameter bytes it has
requested. */
+ struct smb_filename *smb_dname = NULL;
char *params = *pparams;
char *pdata = *ppdata;
char *data_end;
@@ -1904,7 +1905,6 @@ static void call_trans2findfirst(connection_struct *conn,
bool out_of_space = False;
int space_remaining;
bool mask_contains_wcard = False;
- SMB_STRUCT_STAT sbuf;
struct ea_list *ea_list = NULL;
NTSTATUS ntstatus = NT_STATUS_OK;
bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
@@ -1981,7 +1981,17 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return;
}
- ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
+ ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
+ (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ reply_nterror(req, ntstatus);
+ return;
+ }
+
+ mask = smb_dname->original_lcomp;
+
+ ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
+ TALLOC_FREE(smb_dname);
if (!NT_STATUS_IS_OK(ntstatus)) {
reply_nterror(req, ntstatus);
return;
@@ -3834,6 +3844,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
SMB_STRUCT_STAT sbuf;
char *dos_fname = NULL;
char *fname = NULL;
+ struct smb_filename *smb_fname = NULL;
char *fullpathname;
char *base_name;
char *p;
@@ -3981,11 +3992,20 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
return;
}
- status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
+ status = unix_convert(ctx, conn, fname, &smb_fname, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+ sbuf = smb_fname->st;
+
+ status = get_full_smb_filename(ctx, smb_fname, &fname);
+ TALLOC_FREE(smb_fname);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
}
+
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
@@ -4821,57 +4841,64 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
const char *oldname_in,
const char *newname_in)
{
- SMB_STRUCT_STAT sbuf1, sbuf2;
- char *last_component_oldname = NULL;
- char *last_component_newname = NULL;
+ struct smb_filename *smb_fname = NULL;
+ struct smb_filename *smb_fname_new = NULL;
char *oldname = NULL;
char *newname = NULL;
NTSTATUS status = NT_STATUS_OK;
- ZERO_STRUCT(sbuf1);
- ZERO_STRUCT(sbuf2);
+ status = unix_convert(ctx, conn, oldname_in, &smb_fname, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
- status = unix_convert(ctx, conn, oldname_in, False, &oldname,
- &last_component_oldname, &sbuf1);
+ status = get_full_smb_filename(ctx, smb_fname, &oldname);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
status = check_name(conn, oldname);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
/* source must already exist. */
- if (!VALID_STAT(sbuf1)) {
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ if (!VALID_STAT(smb_fname->st)) {
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ goto out;
}
- status = unix_convert(ctx, conn, newname_in, False, &newname,
- &last_component_newname, &sbuf2);
+ status = unix_convert(ctx, conn, newname_in, &smb_fname_new, 0);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_fname_new, &newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
}
status = check_name(conn, newname);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
/* Disallow if newname already exists. */
- if (VALID_STAT(sbuf2)) {
- return NT_STATUS_OBJECT_NAME_COLLISION;
+ if (VALID_STAT(smb_fname_new->st)) {
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
+ goto out;
}
/* No links from a directory. */
- if (S_ISDIR(sbuf1.st_mode)) {
- return NT_STATUS_FILE_IS_A_DIRECTORY;
+ if (S_ISDIR(smb_fname->st.st_mode)) {
+ status = NT_STATUS_FILE_IS_A_DIRECTORY;
+ goto out;
}
/* Ensure this is within the share. */
status = check_reduced_name(conn, oldname);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
@@ -4879,9 +4906,15 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
status = map_nt_error_from_unix(errno);
DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
- nt_errstr(status), newname, oldname));
+ nt_errstr(status), newname, oldname));
+ }
+ out:
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
+ if (smb_fname_new) {
+ TALLOC_FREE(smb_fname_new);
}
-
return status;
}
@@ -5382,9 +5415,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
uint32 len;
char *newname = NULL;
char *base_name = NULL;
+ struct smb_filename *smb_fname = NULL;
bool dest_has_wcard = False;
- SMB_STRUCT_STAT sbuf;
- char *newname_last_component = NULL;
NTSTATUS status = NT_STATUS_OK;
char *p;
TALLOC_CTX *ctx = talloc_tos();
@@ -5393,8 +5425,6 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- ZERO_STRUCT(sbuf);
-
overwrite = (CVAL(pdata,0) ? True : False);
root_fid = IVAL(pdata,4);
len = IVAL(pdata,8);
@@ -5466,10 +5496,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
return NT_STATUS_NO_MEMORY;
}
- status = unix_convert(ctx, conn, newname, False,
- &newname,
- &newname_last_component,
- &sbuf);
+ status = unix_convert(ctx, conn, newname, &smb_fname,
+ UCF_SAVE_LCOMP);
/* If an error we expect this to be
* NT_STATUS_OBJECT_PATH_NOT_FOUND */
@@ -5477,7 +5505,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
if (!NT_STATUS_IS_OK(status)
&& !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
status)) {
- return status;
+ goto out;
}
}
@@ -5485,8 +5513,9 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
fsp->fnum, fsp->fsp_name, base_name ));
status = rename_internals_fsp(conn, fsp, base_name,
- newname_last_component, 0,
- overwrite);
+ smb_fname ?
+ smb_fname->original_lcomp : NULL,
+ 0, overwrite);
} else {
DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
fname, base_name ));
@@ -5494,7 +5523,10 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
overwrite, False, dest_has_wcard,
FILE_WRITE_ATTRIBUTES);
}
-
+ out:
+ if (smb_fname) {
+ TALLOC_FREE(smb_fname);
+ }
return status;
}
@@ -6700,6 +6732,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
uint16 info_level;
SMB_STRUCT_STAT sbuf;
char *fname = NULL;
+ struct smb_filename *smb_fname = NULL;
files_struct *fsp = NULL;
NTSTATUS status = NT_STATUS_OK;
int data_return_size = 0;
@@ -6814,8 +6847,15 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
return;
}
- status = unix_convert(ctx, conn, fname, False,
- &fname, NULL, &sbuf);
+ status = unix_convert(ctx, conn, fname, &smb_fname, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+ sbuf = smb_fname->st;
+
+ status = get_full_smb_filename(ctx, smb_fname, &fname);
+ TALLOC_FREE(smb_fname);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
@@ -7129,10 +7169,10 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
char **ppdata, int total_data,
unsigned int max_data_bytes)
{
+ struct smb_filename *smb_dname = NULL;
char *params = *pparams;
char *pdata = *ppdata;
char *directory = NULL;
- SMB_STRUCT_STAT sbuf;
NTSTATUS status = NT_STATUS_OK;
struct ea_list *ea_list = NULL;
TALLOC_CTX *ctx = talloc_tos();
@@ -7157,7 +7197,13 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
- status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
+ status = unix_convert(ctx, conn, directory, &smb_dname, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+
+ status = get_full_smb_filename(ctx, smb_dname, &directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;