summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h9
-rw-r--r--source3/printing/nt_printing.c148
-rw-r--r--source3/smbd/open.c12
-rw-r--r--source3/smbd/reply.c322
-rw-r--r--source3/smbd/trans2.c30
-rw-r--r--source3/smbd/vfs.c26
6 files changed, 333 insertions, 214 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index f5e44bad64..a0ad282242 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6622,7 +6622,8 @@ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
const char *fname,
SMB_STRUCT_STAT *psbuf, files_struct **result);
NTSTATUS close_file_fchmod(struct smb_request *req, files_struct *fsp);
-NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory);
+NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
+ const struct smb_filename *smb_dname);
void msg_file_was_renamed(struct messaging_context *msg,
void *private_data,
uint32_t msg_type,
@@ -6917,8 +6918,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
void reply_mv(struct smb_request *req);
NTSTATUS copy_file(TALLOC_CTX *ctx,
connection_struct *conn,
- const char *src,
- const char *dest1,
+ struct smb_filename *smb_fname_src,
+ struct smb_filename *smb_fname_dst,
int ofun,
int count,
bool target_is_directory);
@@ -7122,7 +7123,7 @@ void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp);
bool smbd_vfs_init(connection_struct *conn);
bool vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st);
bool vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf);
-bool vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf);
+NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname);
ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count);
ssize_t vfs_pread_data(files_struct *fsp, char *buf,
size_t byte_count, SMB_OFF_T offset);
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 02ac7eeca2..1aec954f12 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -634,40 +634,30 @@ bool nt_printing_init(struct messaging_context *msg_ctx)
Function to allow filename parsing "the old way".
********************************************************************/
-static char *driver_unix_convert(connection_struct *conn,
- const char *old_name,
- SMB_STRUCT_STAT *pst)
+static NTSTATUS driver_unix_convert(connection_struct *conn,
+ const char *old_name,
+ struct smb_filename **smb_fname)
{
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
- struct smb_filename *smb_fname = NULL;
char *name = talloc_strdup(ctx, old_name);
- char *new_name = NULL;
if (!name) {
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
unix_format(name);
name = unix_clean_name(ctx, name);
if (!name) {
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
trim_string(name,"/","/");
- status = unix_convert(ctx, conn, name, &smb_fname, 0);
+ 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;
+ return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(smb_fname);
- return new_name;
+ return NT_STATUS_OK;
}
/*******************************************************************
@@ -1297,11 +1287,13 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
uint32 old_minor;
time_t old_create_time;
+ struct smb_filename *smb_fname = NULL;
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
SMB_STRUCT_STAT stat_buf;
NTSTATUS status;
+ int ret;
SET_STAT_INVALID(st);
SET_STAT_INVALID(stat_buf);
@@ -1309,8 +1301,13 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
old_create_time = (time_t)0;
/* Get file version info (if available) for previous file (if it exists) */
- filepath = driver_unix_convert(conn,old_file,&stat_buf);
- if (!filepath) {
+ status = driver_unix_convert(conn, old_file, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto error_exit;
+ }
+
+ status = get_full_smb_filename(talloc_tos(), smb_fname, &filepath);
+ if (!NT_STATUS_IS_OK(status)) {
goto error_exit;
}
@@ -1337,10 +1334,11 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
/* Old file not found, so by definition new file is in fact newer */
DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
filepath, errno));
- return 1;
+ ret = 1;
+ goto done;
} else {
- int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
+ ret = get_file_version(fsp, old_file, &old_major, &old_minor);
if (ret == -1) {
goto error_exit;
}
@@ -1361,8 +1359,13 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
fsp = NULL;
/* Get file version info (if available) for new file */
- filepath = driver_unix_convert(conn,new_file,&stat_buf);
- if (!filepath) {
+ status = driver_unix_convert(conn, new_file, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto error_exit;
+ }
+
+ status = get_full_smb_filename(talloc_tos(), smb_fname, &filepath);
+ if (!NT_STATUS_IS_OK(status)) {
goto error_exit;
}
@@ -1392,7 +1395,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
goto error_exit;
} else {
- int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
+ ret = get_file_version(fsp, new_file, &new_major, &new_minor);
if (ret == -1) {
goto error_exit;
}
@@ -1418,29 +1421,36 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
(new_major == old_major && new_minor > old_minor)) {
DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
- return 1;
+ ret = 1;
+ goto done;
}
else {
DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
- return 0;
+ ret = 0;
+ goto done;
}
} else {
/* Compare modification time/dates and choose the newest time/date */
if (new_create_time > old_create_time) {
DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
- return 1;
+ ret = 1;
+ goto done;
}
else {
DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
- return 0;
+ ret = 0;
+ goto done;
}
}
- error_exit:
- if(fsp)
- close_file(NULL, fsp, NORMAL_CLOSE);
- return -1;
+ error_exit:
+ if(fsp)
+ close_file(NULL, fsp, NORMAL_CLOSE);
+ ret = -1;
+ done:
+ TALLOC_FREE(smb_fname);
+ return ret;
}
/****************************************************************************
@@ -1453,7 +1463,8 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
{
int cversion;
NTSTATUS nt_status;
- char *driverpath = NULL;
+ struct smb_filename *smb_fname = NULL;
+ char *driverpath = NULL;
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
connection_struct *conn = NULL;
@@ -1509,17 +1520,24 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
goto error_exit;
}
- driverpath = driver_unix_convert(conn,driverpath,&st);
- if (!driverpath) {
- *perr = WERR_NOMEM;
+ nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ *perr = ntstatus_to_werror(nt_status);
goto error_exit;
}
- if (!vfs_file_exist(conn, driverpath, &st)) {
+ nt_status = vfs_file_exist(conn, smb_fname);
+ if (!NT_STATUS_IS_OK(nt_status)) {
*perr = WERR_BADFILE;
goto error_exit;
}
+ status = get_full_smb_filename(talloc_tos(), smb_fname, &driverpath);
+ if (!NT_STATUS_IS_OK(status)) {
+ *perr = WERR_NOMEM;
+ goto error_exit;
+ }
+
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
@@ -1586,6 +1604,7 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
error_exit:
cversion = -1;
done:
+ TALLOC_FREE(smb_fname);
if (fsp != NULL) {
close_file(NULL, fsp, NORMAL_CLOSE);
}
@@ -1811,10 +1830,12 @@ static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
uint32_t driver_version,
uint32_t version)
{
+ struct smb_filename *smb_fname_old = NULL;
+ struct smb_filename *smb_fname_new = NULL;
char *old_name = NULL;
char *new_name = NULL;
- SMB_STRUCT_STAT st;
NTSTATUS status;
+ WERROR ret;
old_name = talloc_asprintf(mem_ctx, "%s/%s",
short_architecture, driver_file);
@@ -1826,25 +1847,45 @@ static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
- old_name = driver_unix_convert(conn, old_name, &st);
- W_ERROR_HAVE_NO_MEMORY(old_name);
+ status = driver_unix_convert(conn, old_name, &smb_fname_old);
+ if (!NT_STATUS_IS_OK(status)) {
+ ret = WERR_NOMEM;
+ goto out;
+ }
+
+ /* Setup a synthetic smb_filename struct */
+ smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
+ if (!smb_fname_new) {
+ ret = WERR_NOMEM;
+ goto out;
+ }
- DEBUG(10,("move_driver_file_to_download_area: copying '%s' to '%s'\n",
- old_name, new_name));
+ smb_fname_new->base_name = new_name;
- status = copy_file(mem_ctx, conn, old_name, new_name,
+ DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
+ "'%s'\n", smb_fname_old->base_name,
+ smb_fname_new->base_name));
+
+ status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
OPENX_FILE_EXISTS_TRUNCATE |
OPENX_FILE_CREATE_IF_NOT_EXIST,
0, false);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("move_driver_file_to_download_area: Unable to rename [%s] to [%s]: %s\n",
- old_name, new_name, nt_errstr(status)));
- return WERR_ACCESS_DENIED;
+ DEBUG(0,("move_driver_file_to_download_area: Unable "
+ "to rename [%s] to [%s]: %s\n",
+ smb_fname_old->base_name, new_name,
+ nt_errstr(status)));
+ ret = WERR_ACCESS_DENIED;
+ goto out;
}
}
- return WERR_OK;
+ ret = WERR_OK;
+ out:
+ TALLOC_FREE(smb_fname_old);
+ TALLOC_FREE(smb_fname_new);
+ return ret;
}
WERROR move_driver_to_download_area(struct pipes_struct *p,
@@ -1854,10 +1895,10 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
const char *short_architecture;
+ struct smb_filename *smb_dname = NULL;
char *new_dir = NULL;
connection_struct *conn = NULL;
NTSTATUS nt_status;
- SMB_STRUCT_STAT st;
int i;
TALLOC_CTX *ctx = talloc_tos();
int ver = 0;
@@ -1911,15 +1952,15 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
*perr = WERR_NOMEM;
goto err_exit;
}
- new_dir = driver_unix_convert(conn,new_dir,&st);
- if (!new_dir) {
+ nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
+ if (!NT_STATUS_IS_OK(nt_status)) {
*perr = WERR_NOMEM;
goto err_exit;
}
- DEBUG(5,("Creating first directory: %s\n", new_dir));
+ DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
- create_directory(conn, NULL, new_dir);
+ create_directory(conn, NULL, smb_dname);
/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
* listed for this driver which has already been moved, skip it (note:
@@ -2044,6 +2085,7 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
}
err_exit:
+ TALLOC_FREE(smb_dname);
if (conn != NULL) {
vfs_ChDir(conn, oldcwd);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 773436fa8e..718feb4996 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2598,10 +2598,17 @@ static NTSTATUS open_directory(connection_struct *conn,
return NT_STATUS_OK;
}
-NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory)
+NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
+ const struct smb_filename *smb_dname)
{
NTSTATUS status;
files_struct *fsp;
+ char *directory = NULL;
+
+ status = get_full_smb_filename(talloc_tos(), smb_dname, &directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
@@ -2625,7 +2632,8 @@ NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, cons
if (NT_STATUS_IS_OK(status)) {
close_file(req, fsp, NORMAL_CLOSE);
}
-
+ out:
+ TALLOC_FREE(directory);
return status;
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 844bcc1882..f91a3c7550 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -5233,19 +5233,13 @@ void reply_mkdir(struct smb_request *req)
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);
+ status = check_name(conn, smb_dname->base_name);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
goto out;
}
- status = create_directory(conn, req, directory);
+ status = create_directory(conn, req, smb_dname);
DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
@@ -5268,7 +5262,7 @@ void reply_mkdir(struct smb_request *req)
reply_outbuf(req, 0, 0);
- DEBUG( 3, ( "mkdir %s\n", directory ) );
+ DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
out:
TALLOC_FREE(smb_dname);
END_PROFILE(SMBmkdir);
@@ -6434,59 +6428,80 @@ void reply_mv(struct smb_request *req)
NTSTATUS copy_file(TALLOC_CTX *ctx,
connection_struct *conn,
- const char *src,
- const char *dest1,
+ struct smb_filename *smb_fname_src,
+ struct smb_filename *smb_fname_dst,
int ofun,
int count,
bool target_is_directory)
{
- SMB_STRUCT_STAT src_sbuf, sbuf2;
+ struct smb_filename *smb_fname_dst_tmp = NULL;
+ char *fname_src = NULL;
+ char *fname_dst = NULL;
SMB_OFF_T ret=-1;
files_struct *fsp1,*fsp2;
- char *dest = NULL;
uint32 dosattrs;
uint32 new_create_disposition;
NTSTATUS status;
- dest = talloc_strdup(ctx, dest1);
- if (!dest) {
- return NT_STATUS_NO_MEMORY;
+
+ status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
+
+ /*
+ * If the target is a directory, extract the last component from the
+ * src filename and append it to the dst filename
+ */
if (target_is_directory) {
- const char *p = strrchr_m(src,'/');
+ const char *p;
+
+ /* dest/target can't be a stream if it's a directory. */
+ SMB_ASSERT(smb_fname_dst->stream_name == NULL);
+
+ p = strrchr_m(smb_fname_src->base_name,'/');
if (p) {
p++;
} else {
- p = src;
+ p = smb_fname_src->base_name;
}
- dest = talloc_asprintf_append(dest,
- "/%s",
- p);
- if (!dest) {
- return NT_STATUS_NO_MEMORY;
+ smb_fname_dst_tmp->base_name =
+ talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
+ p);
+ if (!smb_fname_dst_tmp->base_name) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
}
- if (!vfs_file_exist(conn,src,&src_sbuf)) {
- TALLOC_FREE(dest);
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ status = vfs_file_exist(conn, smb_fname_src);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
}
if (!target_is_directory && count) {
new_create_disposition = FILE_OPEN;
} else {
- if (!map_open_params_to_ntcreate(dest1,0,ofun,
- NULL, NULL, &new_create_disposition, NULL)) {
- TALLOC_FREE(dest);
- return NT_STATUS_INVALID_PARAMETER;
+ if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
+ 0, ofun, NULL, NULL,
+ &new_create_disposition,
+ NULL)) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto out;
}
}
+ status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ /* Open the src file for reading. */
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
0, /* root_dir_fid */
- src, /* fname */
+ fname_src, /* fname */
0, /* create_file_flags */
FILE_GENERIC_READ, /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
@@ -6499,23 +6514,29 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
NULL, /* ea_list */
&fsp1, /* result */
NULL, /* pinfo */
- &src_sbuf); /* psbuf */
+ &smb_fname_src->st); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(dest);
- return status;
+ goto out;
+ }
+
+ dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st);
+
+ status = get_full_smb_filename(talloc_tos(), smb_fname_dst_tmp, &fname_dst);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
}
- dosattrs = dos_mode(conn, src, &src_sbuf);
- if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
- ZERO_STRUCTP(&sbuf2);
+ if (SMB_VFS_STAT(conn, fname_dst, &smb_fname_dst_tmp->st) == -1) {
+ ZERO_STRUCTP(&smb_fname_dst_tmp->st);
}
+ /* Open the dst file for writing. */
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
0, /* root_dir_fid */
- dest, /* fname */
+ fname_dst, /* fname */
0, /* create_file_flags */
FILE_GENERIC_WRITE, /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
@@ -6528,13 +6549,11 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
NULL, /* ea_list */
&fsp2, /* result */
NULL, /* pinfo */
- &sbuf2); /* psbuf */
-
- TALLOC_FREE(dest);
+ &smb_fname_dst_tmp->st); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
close_file(NULL, fsp1, ERROR_CLOSE);
- return status;
+ goto out;
}
if ((ofun&3) == 1) {
@@ -6544,18 +6563,19 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
* Stop the copy from occurring.
*/
ret = -1;
- src_sbuf.st_ex_size = 0;
+ smb_fname_src->st.st_ex_size = 0;
}
}
- if (src_sbuf.st_ex_size) {
- ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_ex_size);
+ /* Do the actual copy. */
+ if (smb_fname_src->st.st_ex_size) {
+ ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
}
close_file(NULL, fsp1, NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- set_close_write_time(fsp2, src_sbuf.st_ex_mtime);
+ set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
/*
* As we are opening fsp1 read-only we only expect
@@ -6566,14 +6586,21 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
status = close_file(NULL, fsp2, NORMAL_CLOSE);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
- if (ret != (SMB_OFF_T)src_sbuf.st_ex_size) {
- return NT_STATUS_DISK_FULL;
+ if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
+ status = NT_STATUS_DISK_FULL;
+ goto out;
}
- return NT_STATUS_OK;
+ status = NT_STATUS_OK;
+
+ out:
+ TALLOC_FREE(smb_fname_dst_tmp);
+ TALLOC_FREE(fname_src);
+ TALLOC_FREE(fname_dst);
+ return status;
}
/****************************************************************************
@@ -6583,13 +6610,12 @@ 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;
- const char *mask = NULL;
- const char mask_star[] = "*";
+ struct smb_filename *smb_fname_src = NULL;
+ struct smb_filename *smb_fname_dst = NULL;
+ char *fname_src = NULL;
+ char *fname_dst = NULL;
+ char *fname_src_mask = NULL;
+ char *fname_src_dir = NULL;
const char *p;
int count=0;
int error = ERRnoaccess;
@@ -6615,20 +6641,20 @@ void reply_copy(struct smb_request *req)
flags = SVAL(req->vwv+2, 0);
p = (const char *)req->buf;
- p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
+ p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
&status, &source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
goto out;
}
- p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
+ p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
&status, &dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
goto out;
}
- DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
+ DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
if (tid2 != conn->cnum) {
/* can't currently handle inter share copies XXXX */
@@ -6639,8 +6665,8 @@ void reply_copy(struct smb_request *req)
status = resolve_dfspath_wcard(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
- name,
- &name,
+ fname_src,
+ &fname_src,
&source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -6654,8 +6680,8 @@ void reply_copy(struct smb_request *req)
status = resolve_dfspath_wcard(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
- newname,
- &newname,
+ fname_dst,
+ &fname_dst,
&dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -6667,33 +6693,21 @@ void reply_copy(struct smb_request *req)
goto out;
}
- status = unix_convert(ctx, conn, name, &smb_fname,
+ status = unix_convert(ctx, conn, fname_src, &smb_fname_src,
source_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, &name);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
- }
-
- status = unix_convert(ctx, conn, newname, &smb_fname_new,
+ status = unix_convert(ctx, conn, fname_dst, &smb_fname_dst,
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(smb_fname_new->st);
+ target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
if ((flags&1) && target_is_directory) {
reply_doserror(req, ERRDOS, ERRbadfile);
@@ -6705,23 +6719,25 @@ void reply_copy(struct smb_request *req)
goto out;
}
- if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname->st)) {
+ if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
/* wants a tree copy! XXXX */
DEBUG(3,("Rejecting tree copy\n"));
reply_doserror(req, ERRSRV, ERRerror);
goto out;
}
- p = strrchr_m(name,'/');
+ /* Split up the directory from the filename/mask. */
+ p = strrchr_m(smb_fname_src->base_name,'/');
if (p != NULL) {
- directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
- mask = p+1;
+ fname_src_dir = talloc_strndup(ctx, smb_fname_src->base_name,
+ PTR_DIFF(p, smb_fname_src->base_name));
+ fname_src_mask = talloc_strdup(ctx, p+1);
} else {
- directory = talloc_strdup(ctx, "./");
- mask = name;
+ fname_src_dir = talloc_strdup(ctx, "./");
+ fname_src_mask = talloc_strdup(ctx, smb_fname_src->base_name);
}
- if (!directory) {
+ if (!fname_src_dir || !fname_src_mask) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
goto out;
}
@@ -6734,47 +6750,62 @@ void reply_copy(struct smb_request *req)
* for a possible mangle. This patch from
* 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);
+
+ /* Use demangled name if one was successfully found. */
if (new_mask) {
- mask = new_mask;
+ TALLOC_FREE(fname_src_mask);
+ fname_src_mask = new_mask;
}
}
if (!source_has_wild) {
- directory = talloc_asprintf_append(directory,
- "/%s",
- mask);
+
+ /*
+ * Only one file needs to be copied. Append the mask back onto
+ * the 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) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ goto out;
+ }
+
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)) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
goto out;
}
- newname = mod_newname;
+ TALLOC_FREE(smb_fname_dst->base_name);
+ smb_fname_dst->base_name = fname_dst_mod;
}
- status = check_name(conn, directory);
+ status = check_name(conn, smb_fname_src->base_name);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
goto out;
}
- status = check_name(conn, newname);
+ status = check_name(conn, smb_fname_dst->base_name);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
goto out;
}
- status = copy_file(ctx,conn,directory,newname,ofun,
- count,target_is_directory);
+ status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
+ ofun, count, target_is_directory);
if(!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -6787,17 +6818,34 @@ void reply_copy(struct smb_request *req)
const char *dname = NULL;
long offset = 0;
- if (strequal(mask,"????????.???")) {
- mask = mask_star;
+ /*
+ * There is a wildcard that requires us to actually read the
+ * src dir and copy each file matching the mask to the dst.
+ * Right now streams won't be copied, but this could
+ * presumably be added with a nested loop for reach dir entry.
+ */
+ SMB_ASSERT(!smb_fname_src->stream_name);
+ SMB_ASSERT(!smb_fname_dst->stream_name);
+
+ smb_fname_src->stream_name = NULL;
+ smb_fname_dst->stream_name = NULL;
+
+ if (strequal(fname_src_mask,"????????.???")) {
+ TALLOC_FREE(fname_src_mask);
+ fname_src_mask = talloc_strdup(ctx, "*");
+ if (!fname_src_mask) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ goto out;
+ }
}
- status = check_name(conn, directory);
+ status = check_name(conn, fname_src_dir);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
goto out;
}
- dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
+ dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
if (dir_hnd == NULL) {
status = map_nt_error_from_unix(errno);
reply_nterror(req, status);
@@ -6806,37 +6854,42 @@ void reply_copy(struct smb_request *req)
error = ERRbadfile;
+ /* Iterate over the src dir copying each entry to the dst. */
while ((dname = ReadDirName(dir_hnd, &offset,
- &smb_fname->st))) {
+ &smb_fname_src->st))) {
char *destname = NULL;
- char *fname = NULL;
if (ISDOT(dname) || ISDOTDOT(dname)) {
continue;
}
- 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;
}
error = ERRnoaccess;
- fname = talloc_asprintf(ctx,
- "%s/%s",
- directory,
- dname);
- if (!fname) {
+
+ /* Get the src smb_fname struct setup. */
+ 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) {
TALLOC_FREE(dir_hnd);
reply_nterror(req, 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)) {
continue;
}
if (!destname) {
@@ -6845,29 +6898,33 @@ void reply_copy(struct smb_request *req)
goto out;
}
- status = check_name(conn, fname);
+ TALLOC_FREE(smb_fname_dst->base_name);
+ smb_fname_dst->base_name = destname;
+
+ status = check_name(conn, smb_fname_src->base_name);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
reply_nterror(req, status);
goto out;
}
- status = check_name(conn, destname);
+ status = check_name(conn, smb_fname_dst->base_name);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
reply_nterror(req, status);
goto out;
}
- DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
+ DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
+ smb_fname_src->base_name,
+ smb_fname_dst->base_name));
- status = copy_file(ctx,conn,fname,destname,ofun,
- count,target_is_directory);
+ status = copy_file(ctx, conn, smb_fname_src,
+ smb_fname_dst, ofun, count,
+ target_is_directory);
if (NT_STATUS_IS_OK(status)) {
count++;
}
- TALLOC_FREE(fname);
- TALLOC_FREE(destname);
}
TALLOC_FREE(dir_hnd);
}
@@ -6887,8 +6944,13 @@ void reply_copy(struct smb_request *req)
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf,smb_vwv0,count);
out:
- TALLOC_FREE(smb_fname);
- TALLOC_FREE(smb_fname_new);
+ TALLOC_FREE(smb_fname_src);
+ TALLOC_FREE(smb_fname_dst);
+ TALLOC_FREE(fname_src);
+ TALLOC_FREE(fname_dst);
+ TALLOC_FREE(fname_src_mask);
+ TALLOC_FREE(fname_src_dir);
+
END_PROFILE(SMBcopy);
return;
}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index a36e9f588a..dc2544c4e3 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -7208,23 +7208,17 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
return;
}
- status = get_full_smb_filename(ctx, smb_dname, &directory);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
- status = check_name(conn, directory);
+ status = check_name(conn, smb_dname->base_name);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
reply_nterror(req, status);
- return;
+ goto out;
}
/* Any data in this call is an EA list. */
if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
- return;
+ goto out;
}
/*
@@ -7236,21 +7230,21 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
if (total_data != 4) {
if (total_data < 10) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
+ goto out;
}
if (IVAL(pdata,0) > total_data) {
DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
IVAL(pdata,0), (unsigned int)total_data));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
+ goto out;
}
ea_list = read_ea_list(talloc_tos(), pdata + 4,
total_data - 4);
if (!ea_list) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
+ goto out;
}
}
/* If total_data == 4 Windows doesn't care what values
@@ -7258,19 +7252,19 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
* The System i QNTC IBM SMB client puts bad values here,
* so ignore them. */
- status = create_directory(conn, req, directory);
+ status = create_directory(conn, req, smb_dname);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- return;
+ goto out;
}
/* Try and set any given EA. */
if (ea_list) {
- status = set_ea(conn, NULL, directory, ea_list);
+ status = set_ea(conn, NULL, smb_dname->base_name, ea_list);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- return;
+ goto out;
}
}
@@ -7278,7 +7272,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
*pparams = (char *)SMB_REALLOC(*pparams,2);
if(*pparams == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- return;
+ goto out;
}
params = *pparams;
@@ -7286,6 +7280,8 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
+ out:
+ TALLOC_FREE(smb_dname);
return;
}
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 873e65e4a4..385454e587 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -382,18 +382,28 @@ bool vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT
Check if a file exists in the vfs.
********************************************************************/
-bool vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf)
+NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
{
- SMB_STRUCT_STAT st;
+ char *fname = NULL;
+ NTSTATUS status;
- if (!sbuf)
- sbuf = &st;
+ status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
- ZERO_STRUCTP(sbuf);
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ if (SMB_VFS_STAT(conn, fname, &smb_fname->st) == -1) {
+ goto out;
+ }
- if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
- return False;
- return(S_ISREG(sbuf->st_ex_mode));
+ /* Only return OK if stat was successful and S_ISREG */
+ if (S_ISREG(smb_fname->st.st_ex_mode)) {
+ status = NT_STATUS_OK;
+ }
+ out:
+ TALLOC_FREE(fname);
+ return status;
}
/****************************************************************************