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/trans2.c | |
parent | 5d3d51e9ad1e4db8d9580ce7f2ba4e86e658bb13 (diff) | |
download | samba-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().
Diffstat (limited to 'source3/smbd/trans2.c')
-rw-r--r-- | source3/smbd/trans2.c | 128 |
1 files changed, 87 insertions, 41 deletions
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; |