summaryrefslogtreecommitdiffstats
path: root/source3/smbd/nttrans.c
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 /source3/smbd/nttrans.c
parent5d3d51e9ad1e4db8d9580ce7f2ba4e86e658bb13 (diff)
downloadsamba-c1a21d085d758284fe6997a05396f225da683352.tar.gz
samba-c1a21d085d758284fe6997a05396f225da683352.tar.xz
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().
Diffstat (limited to 'source3/smbd/nttrans.c')
-rw-r--r--source3/smbd/nttrans.c90
1 files changed, 54 insertions, 36 deletions
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));