summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/reply.c239
1 files changed, 133 insertions, 106 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 22064ad0ab..3db11b9068 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -6026,13 +6026,10 @@ 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 *name = NULL;
- char *newname = NULL;
- char *p;
+ struct smb_filename *smb_fname_src = NULL;
+ struct smb_filename *smb_fname_dst = NULL;
+ char *fname_src_dir = NULL;
+ char *fname_src_mask = NULL;
int count=0;
NTSTATUS status = NT_STATUS_OK;
struct smb_Dir *dir_hnd = NULL;
@@ -6041,29 +6038,19 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
int create_options = 0;
bool posix_pathnames = lp_posix_pathnames();
- status = unix_convert(ctx, conn, name_in, &smb_fname,
+ status = unix_convert(ctx, conn, name_in, &smb_fname_src,
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, newname_in, &smb_fname_new,
+ status = unix_convert(ctx, conn, newname_in, &smb_fname_dst,
(UCF_SAVE_LCOMP |
(dest_has_wild ? UCF_ALLOW_WCARD_LCOMP : 0)));
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
- status = get_full_smb_filename(ctx, smb_fname_new, &newname);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
/*
* Split the old name into directory and last component
* strings. Note that unix_convert may have stripped off a
@@ -6073,23 +6060,12 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
* as this is checked in resolve_wildcards().
*/
- p = strrchr_m(name,'/');
- if (!p) {
- directory = talloc_strdup(ctx, ".");
- if (!directory) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
- mask = name;
- } else {
- *p = 0;
- directory = talloc_strdup(ctx, name);
- if (!directory) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
- mask = p+1;
- *p = '/'; /* Replace needed for exceptional test below. */
+ /* Split up the directory from the filename/mask. */
+ status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
+ &fname_src_dir, &fname_src_mask);
+ if (!NT_STATUS_IS_OK(status)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
/*
@@ -6101,41 +6077,47 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask, conn->params)) {
+ if (!VALID_STAT(smb_fname_src->st) &&
+ mangle_is_mangled(fname_src_mask, conn->params)) {
char *new_mask = NULL;
- mangle_lookup_name_from_8_3(ctx,
- mask,
- &new_mask,
- conn->params );
+ mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
+ conn->params);
if (new_mask) {
- mask = new_mask;
+ TALLOC_FREE(fname_src_mask);
+ fname_src_mask = new_mask;
}
}
if (!src_has_wild) {
files_struct *fsp;
+ char *fname_src = NULL;
+ char *fname_dst = NULL;
/*
- * No wildcards - just process the one file.
+ * Only one file needs to be renamied. Append the mask back
+ * onto the directory.
*/
- /* Add a terminating '/' to the directory name. */
- directory = talloc_asprintf_append(directory,
- "/%s",
- mask);
- if (!directory) {
+ TALLOC_FREE(smb_fname_src->base_name);
+ smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
+ "%s/%s",
+ fname_src_dir,
+ fname_src_mask);
+ if (!smb_fname_src->base_name) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
- /* Ensure newname contains a '/' also */
- if(strrchr_m(newname,'/') == 0) {
- newname = talloc_asprintf(ctx,
- "./%s",
- newname);
- if (!newname) {
+ /* Ensure dst fname contains a '/' also */
+ if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
+ char *tmp;
+ tmp = talloc_asprintf(smb_fname_dst, "./%s",
+ smb_fname_dst->base_name);
+ if (!tmp) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
+ TALLOC_FREE(smb_fname_dst->base_name);
+ smb_fname_dst->base_name = tmp;
}
DEBUG(3, ("rename_internals: case_sensitive = %d, "
@@ -6143,32 +6125,41 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
"directory = %s, newname = %s, "
"last_component_dest = %s\n",
conn->case_sensitive, conn->case_preserve,
- conn->short_case_preserve, directory,
- newname, smb_fname_new->original_lcomp));
+ conn->short_case_preserve, smb_fname_src->base_name,
+ smb_fname_dst->base_name,
+ smb_fname_dst->original_lcomp));
/* The dest name still may have wildcards. */
if (dest_has_wild) {
- char *mod_newname = NULL;
- if (!resolve_wildcards(ctx,
- directory,newname,&mod_newname)) {
+ char *fname_dst_mod = NULL;
+ if (!resolve_wildcards(smb_fname_dst,
+ smb_fname_src->base_name,
+ smb_fname_dst->base_name,
+ &fname_dst_mod)) {
DEBUG(6, ("rename_internals: resolve_wildcards "
- "%s %s failed\n",
- directory,
- newname));
+ "%s %s failed\n",
+ smb_fname_src->base_name,
+ smb_fname_dst->base_name));
status = NT_STATUS_NO_MEMORY;
goto out;
}
- newname = mod_newname;
+ TALLOC_FREE(smb_fname_dst->base_name);
+ smb_fname_dst->base_name = fname_dst_mod;
}
- ZERO_STRUCT(smb_fname->st);
+ status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ ZERO_STRUCT(smb_fname_src->st);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, directory, &smb_fname->st);
+ SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
} else {
- SMB_VFS_STAT(conn, directory, &smb_fname->st);
+ SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
}
- if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
create_options |= FILE_DIRECTORY_FILE;
}
@@ -6176,7 +6167,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- directory, /* fname */
+ fname_src, /* fname */
0, /* create_file_flags */
access_mask, /* access_mask */
(FILE_SHARE_READ | /* share_access */
@@ -6190,40 +6181,54 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
NULL, /* ea_list */
&fsp, /* result */
NULL, /* pinfo */
- &smb_fname->st); /* psbuf */
+ &smb_fname_src->st); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("Could not open rename source %s: %s\n",
- directory, nt_errstr(status)));
+ fname_src, nt_errstr(status)));
+ TALLOC_FREE(fname_src);
goto out;
}
- status = rename_internals_fsp(conn, fsp, newname,
- smb_fname_new->original_lcomp,
+ status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(fname_src);
+ goto out;
+ }
+
+ status = rename_internals_fsp(conn, fsp, fname_dst,
+ smb_fname_dst->original_lcomp,
attrs, replace_if_exists);
close_file(req, fsp, NORMAL_CLOSE);
DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(status), directory,newname));
+ nt_errstr(status), fname_src, fname_dst));
+ TALLOC_FREE(fname_src);
+ TALLOC_FREE(fname_dst);
goto out;
}
/*
* Wildcards - process each file that matches.
*/
- if (strequal(mask,"????????.???")) {
- mask[0] = '*';
- mask[1] = '\0';
+ if (strequal(fname_src_mask, "????????.???")) {
+ TALLOC_FREE(fname_src_mask);
+ fname_src_mask = talloc_strdup(ctx, "*");
+ if (!fname_src_mask) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
}
- status = check_name(conn, directory);
+ status = check_name(conn, fname_src_dir);
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
- dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
+ dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
+ attrs);
if (dir_hnd == NULL) {
status = map_nt_error_from_unix(errno);
goto out;
@@ -6235,9 +6240,10 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
* - gentest fix. JRA
*/
- while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) {
+ while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
files_struct *fsp = NULL;
- char *fname = NULL;
+ char *fname_src = NULL;
+ char *fname_dst = NULL;
char *destname = NULL;
bool sysdir_entry = False;
@@ -6250,12 +6256,12 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
}
}
- if (!is_visible_file(conn, directory, dname, &smb_fname->st,
- False)) {
+ if (!is_visible_file(conn, fname_src_dir, dname,
+ &smb_fname_src->st, false)) {
continue;
}
- if(!mask_match(dname, mask, conn->case_sensitive)) {
+ if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
continue;
}
@@ -6264,20 +6270,21 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
break;
}
- fname = talloc_asprintf(ctx,
- "%s/%s",
- directory,
- dname);
- if (!fname) {
+ TALLOC_FREE(smb_fname_src->base_name);
+ smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
+ "%s/%s",
+ fname_src_dir,
+ dname);
+ if (!smb_fname_src->base_name) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
- if (!resolve_wildcards(ctx,
- fname,newname,&destname)) {
+ if (!resolve_wildcards(ctx, smb_fname_src->base_name,
+ smb_fname_dst->base_name,
+ &destname)) {
DEBUG(6, ("resolve_wildcards %s %s failed\n",
- fname, destname));
- TALLOC_FREE(fname);
+ smb_fname_src->base_name, destname));
continue;
}
if (!destname) {
@@ -6285,16 +6292,30 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
goto out;
}
- ZERO_STRUCT(smb_fname->st);
+ TALLOC_FREE(smb_fname_dst->base_name);
+ smb_fname_dst->base_name = destname;
+
+ status = get_full_smb_filename(ctx, smb_fname_src, &fname_src);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ status = get_full_smb_filename(ctx, smb_fname_dst, &fname_dst);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(fname_src);
+ goto out;
+ }
+
+ ZERO_STRUCT(smb_fname_src->st);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, fname, &smb_fname->st);
+ SMB_VFS_LSTAT(conn, fname_src, &smb_fname_src->st);
} else {
- SMB_VFS_STAT(conn, fname, &smb_fname->st);
+ SMB_VFS_STAT(conn, fname_src, &smb_fname_src->st);
}
create_options = 0;
- if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
create_options |= FILE_DIRECTORY_FILE;
}
@@ -6302,7 +6323,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- fname, /* fname */
+ fname_src, /* fname */
0, /* create_file_flags */
access_mask, /* access_mask */
(FILE_SHARE_READ | /* share_access */
@@ -6316,16 +6337,18 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
NULL, /* ea_list */
&fsp, /* result */
NULL, /* pinfo */
- &smb_fname->st); /* psbuf */
+ &smb_fname_src->st); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
"returned %s rename %s -> %s\n",
- nt_errstr(status), directory, newname));
+ nt_errstr(status), fname_src, fname_dst));
+ TALLOC_FREE(fname_src);
+ TALLOC_FREE(fname_dst);
break;
}
- status = rename_internals_fsp(conn, fsp, destname, dname,
+ status = rename_internals_fsp(conn, fsp, fname_dst, dname,
attrs, replace_if_exists);
close_file(req, fsp, NORMAL_CLOSE);
@@ -6333,17 +6356,19 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("rename_internals_fsp returned %s for "
"rename %s -> %s\n", nt_errstr(status),
- directory, newname));
+ fname_src, fname_dst));
break;
+ TALLOC_FREE(fname_src);
+ TALLOC_FREE(fname_dst);
}
count++;
DEBUG(3,("rename_internals: doing rename on %s -> "
- "%s\n",fname,destname));
+ "%s\n", fname_src, fname_dst));
- TALLOC_FREE(fname);
- TALLOC_FREE(destname);
+ TALLOC_FREE(fname_src);
+ TALLOC_FREE(fname_dst);
}
TALLOC_FREE(dir_hnd);
@@ -6352,8 +6377,10 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
}
out:
- TALLOC_FREE(smb_fname);
- TALLOC_FREE(smb_fname_new);
+ TALLOC_FREE(smb_fname_src);
+ TALLOC_FREE(smb_fname_dst);
+ TALLOC_FREE(fname_src_dir);
+ TALLOC_FREE(fname_src_mask);
return status;
}