diff options
author | Tim Prouty <tprouty@samba.org> | 2009-04-07 13:39:57 -0700 |
---|---|---|
committer | Tim Prouty <tprouty@samba.org> | 2009-05-20 17:40:15 -0700 |
commit | c1a21d085d758284fe6997a05396f225da683352 (patch) | |
tree | 5cb74bc432c5e3c76f8eaac6652a3125ea108515 /source3/smbd/nttrans.c | |
parent | 5d3d51e9ad1e4db8d9580ce7f2ba4e86e658bb13 (diff) | |
download | samba-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.c | 90 |
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)); |