2007-08-31 01:46:42 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-08-17 11:40:06 +04:00
filename handling routines
Copyright ( C ) Andrew Tridgell 1992 - 1998
2007-09-08 00:57:01 +04:00
Copyright ( C ) Jeremy Allison 1999 - 2007
2000-01-27 00:25:35 +03:00
Copyright ( C ) Ying Chen 2000
2007-07-12 02:39:11 +04:00
Copyright ( C ) Volker Lendecke 2007
2007-08-31 01:46:42 +04:00
1998-08-17 11:40:06 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1998-08-17 11:40:06 +04:00
( at your option ) any later version .
2007-08-31 01:46:42 +04:00
1998-08-17 11:40:06 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2007-08-31 01:46:42 +04:00
1998-08-17 11:40:06 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-08-17 11:40:06 +04:00
*/
2000-01-27 00:25:35 +03:00
/*
* New hash table stat cache code added by Ying Chen .
*/
1998-08-17 11:40:06 +04:00
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2010-08-18 18:44:47 +04:00
# include "fake_file.h"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2012-05-23 15:22:47 +04:00
# include "smbd/globals.h"
1998-08-17 11:40:06 +04:00
2017-05-18 21:56:39 +03:00
uint32_t ucf_flags_from_smb_request ( struct smb_request * req )
2016-10-13 13:42:59 +03:00
{
uint32_t ucf_flags = 0 ;
2017-05-18 22:18:58 +03:00
if ( req ! = NULL ) {
if ( req - > posix_pathnames ) {
ucf_flags | = UCF_POSIX_PATHNAMES ;
}
if ( req - > flags2 & FLAGS2_DFS_PATHNAMES ) {
ucf_flags | = UCF_DFS_PATHNAME ;
}
2016-10-13 13:42:59 +03:00
}
2017-05-18 21:56:39 +03:00
return ucf_flags ;
}
uint32_t filename_create_ucf_flags ( struct smb_request * req , uint32_t create_disposition )
{
uint32_t ucf_flags = 0 ;
ucf_flags | = ucf_flags_from_smb_request ( req ) ;
2016-10-13 13:42:59 +03:00
switch ( create_disposition ) {
case FILE_OPEN :
case FILE_OVERWRITE :
break ;
case FILE_SUPERSEDE :
case FILE_CREATE :
case FILE_OPEN_IF :
case FILE_OVERWRITE_IF :
ucf_flags | = UCF_PREP_CREATEFILE ;
break ;
}
return ucf_flags ;
}
2008-01-20 01:25:36 +03:00
static NTSTATUS build_stream_path ( TALLOC_CTX * mem_ctx ,
connection_struct * conn ,
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().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname ) ;
1998-08-17 11:40:06 +04:00
/****************************************************************************
1998-08-28 00:38:53 +04:00
Mangle the 2 nd name and check if it is then equal to the first name .
1998-08-17 11:40:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2007-10-19 04:40:25 +04:00
static bool mangled_equal ( const char * name1 ,
2007-08-31 01:46:42 +04:00
const char * name2 ,
const struct share_params * p )
1998-08-17 11:40:06 +04:00
{
2007-09-08 00:57:01 +04:00
char mname [ 13 ] ;
2007-08-31 01:46:42 +04:00
2007-09-08 00:57:01 +04:00
if ( ! name_to_8_3 ( name2 , mname , False , p ) ) {
return False ;
}
return strequal ( name1 , mname ) ;
1998-08-17 11:40:06 +04:00
}
2007-01-13 04:29:10 +03:00
/****************************************************************************
Cope with the differing wildcard and non - wildcard error cases .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-31 01:46:42 +04:00
static NTSTATUS determine_path_error ( const char * name ,
2015-12-12 01:36:33 +03:00
bool allow_wcard_last_component ,
bool posix_pathnames )
2007-01-13 04:29:10 +03:00
{
const char * p ;
2015-12-12 01:36:33 +03:00
bool name_has_wild = false ;
2007-01-13 04:29:10 +03:00
if ( ! allow_wcard_last_component ) {
/* Error code within a pathname. */
return NT_STATUS_OBJECT_PATH_NOT_FOUND ;
}
/* We're terminating here so we
* can be a little slower and get
* the error code right . Windows
* treats the last part of the pathname
* separately I think , so if the last
* component is a wildcard then we treat
* this . / as " end of component " */
p = strchr ( name , ' / ' ) ;
2015-12-12 01:36:33 +03:00
if ( ! posix_pathnames ) {
name_has_wild = ms_has_wild ( name ) ;
}
if ( ! p & & ( name_has_wild | | ISDOT ( name ) ) ) {
2007-01-13 04:29:10 +03:00
/* Error code at the end of a pathname. */
return NT_STATUS_OBJECT_NAME_INVALID ;
} else {
/* Error code within a pathname. */
return NT_STATUS_OBJECT_PATH_NOT_FOUND ;
}
}
2007-08-31 01:46:42 +04:00
2009-11-26 00:17:56 +03:00
static NTSTATUS check_for_dot_component ( const struct smb_filename * smb_fname )
{
/* Ensure we catch all names with in "/."
this is disallowed under Windows and
in POSIX they ' ve already been removed . */
const char * p = strstr ( smb_fname - > base_name , " /. " ) ; /*mb safe*/
if ( p ) {
if ( p [ 2 ] = = ' / ' ) {
/* Error code within a pathname. */
return NT_STATUS_OBJECT_PATH_NOT_FOUND ;
} else if ( p [ 2 ] = = ' \0 ' ) {
/* Error code at the end of a pathname. */
return NT_STATUS_OBJECT_NAME_INVALID ;
}
}
return NT_STATUS_OK ;
}
2010-09-11 10:28:15 +04:00
/****************************************************************************
Optimization for common case where the missing part
is in the last component and the client already
sent the correct case .
Returns NT_STATUS_OK to mean continue the tree walk
( possibly with modified start pointer ) .
Any other NT_STATUS_XXX error means terminate the path
lookup here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS check_parent_exists ( TALLOC_CTX * ctx ,
connection_struct * conn ,
bool posix_pathnames ,
2011-04-04 21:15:16 +04:00
const struct smb_filename * smb_fname ,
2010-09-11 10:28:15 +04:00
char * * pp_dirpath ,
char * * pp_start )
{
struct smb_filename parent_fname ;
const char * last_component = NULL ;
NTSTATUS status ;
int ret ;
2015-12-12 01:38:49 +03:00
bool parent_fname_has_wild = false ;
2010-09-11 10:28:15 +04:00
ZERO_STRUCT ( parent_fname ) ;
if ( ! parent_dirname ( ctx , smb_fname - > base_name ,
& parent_fname . base_name ,
& last_component ) ) {
return NT_STATUS_NO_MEMORY ;
}
2015-12-12 01:38:49 +03:00
if ( ! posix_pathnames ) {
parent_fname_has_wild = ms_has_wild ( parent_fname . base_name ) ;
}
2010-09-11 10:28:15 +04:00
/*
* If there was no parent component in
* smb_fname - > base_name of the parent name
* contained a wildcard then don ' t do this
* optimization .
*/
if ( ( smb_fname - > base_name = = last_component ) | |
2015-12-12 01:38:49 +03:00
parent_fname_has_wild ) {
2010-09-11 10:28:15 +04:00
return NT_STATUS_OK ;
}
if ( posix_pathnames ) {
ret = SMB_VFS_LSTAT ( conn , & parent_fname ) ;
} else {
ret = SMB_VFS_STAT ( conn , & parent_fname ) ;
}
/* If the parent stat failed, just continue
with the normal tree walk . */
if ( ret = = - 1 ) {
return NT_STATUS_OK ;
}
status = check_for_dot_component ( & parent_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
/* Parent exists - set "start" to be the
2015-03-23 17:38:35 +03:00
* last component to shorten the tree walk . */
2010-09-11 10:28:15 +04:00
/*
2011-05-06 03:19:49 +04:00
* Safe to use discard_const_p
2010-09-11 10:28:15 +04:00
* here as last_component points
* into our smb_fname - > base_name .
*/
2011-05-05 21:41:59 +04:00
* pp_start = discard_const_p ( char , last_component ) ;
2010-09-11 10:28:15 +04:00
/* Update dirpath. */
TALLOC_FREE ( * pp_dirpath ) ;
* pp_dirpath = talloc_strdup ( ctx , parent_fname . base_name ) ;
2010-09-11 10:33:18 +04:00
if ( ! * pp_dirpath ) {
return NT_STATUS_NO_MEMORY ;
}
2010-09-11 10:28:15 +04:00
DEBUG ( 5 , ( " check_parent_exists: name "
" = %s, dirpath = %s, "
" start = %s \n " ,
smb_fname - > base_name ,
* pp_dirpath ,
* pp_start ) ) ;
return NT_STATUS_OK ;
}
2017-01-12 03:30:38 +03:00
/*
* Re - order a known good @ GMT - token path .
*/
static NTSTATUS rearrange_snapshot_path ( struct smb_filename * smb_fname ,
char * startp ,
char * endp )
{
size_t endlen = 0 ;
size_t gmt_len = endp - startp ;
char gmt_store [ gmt_len + 1 ] ;
char * parent = NULL ;
const char * last_component = NULL ;
char * newstr ;
bool ret ;
DBG_DEBUG ( " |%s| -> " , smb_fname - > base_name ) ;
/* Save off the @GMT-token. */
memcpy ( gmt_store , startp , gmt_len ) ;
gmt_store [ gmt_len ] = ' \0 ' ;
if ( * endp = = ' / ' ) {
/* Remove any trailing '/' */
endp + + ;
}
if ( * endp = = ' \0 ' ) {
/*
* @ GMT - token was at end of path .
* Remove any preceeding ' / '
*/
if ( startp > smb_fname - > base_name & & startp [ - 1 ] = = ' / ' ) {
startp - - ;
}
}
/* Remove @GMT-token from the path. */
endlen = strlen ( endp ) ;
memmove ( startp , endp , endlen + 1 ) ;
/* Split the remaining path into components. */
ret = parent_dirname ( smb_fname ,
smb_fname - > base_name ,
& parent ,
& last_component ) ;
if ( ret = = false ) {
/* Must terminate debug with \n */
DBG_DEBUG ( " NT_STATUS_NO_MEMORY \n " ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( ISDOT ( parent ) ) {
if ( last_component [ 0 ] = = ' \0 ' ) {
newstr = talloc_strdup ( smb_fname ,
gmt_store ) ;
} else {
newstr = talloc_asprintf ( smb_fname ,
" %s/%s " ,
gmt_store ,
last_component ) ;
}
} else {
newstr = talloc_asprintf ( smb_fname ,
" %s/%s/%s " ,
gmt_store ,
parent ,
last_component ) ;
}
TALLOC_FREE ( parent ) ;
TALLOC_FREE ( smb_fname - > base_name ) ;
smb_fname - > base_name = newstr ;
DBG_DEBUG ( " |%s| \n " , newstr ) ;
return NT_STATUS_OK ;
}
/*
* Canonicalize any incoming pathname potentially containining
* a @ GMT - token into a path that looks like :
*
* @ GMT - YYYY - MM - DD - HH - MM - SS / path / name / components / last_component
*
* Leaves single path @ GMT - token - component alone :
*
* @ GMT - YYYY - MM - DD - HH - MM - SS - > @ GMT - YYYY - MM - DD - HH - MM - SS
*
* Eventually when struct smb_filename is updated and the VFS
* ABI is changed this will remove the @ GMT - YYYY - MM - DD - HH - MM - SS
* and store in the struct smb_filename as a struct timeval field
* instead .
*/
static NTSTATUS canonicalize_snapshot_path ( struct smb_filename * smb_fname )
{
char * startp = strchr_m ( smb_fname - > base_name , ' @ ' ) ;
char * endp = NULL ;
struct tm tm ;
if ( startp = = NULL ) {
/* No @ */
return NT_STATUS_OK ;
}
startp = strstr_m ( startp , " @GMT- " ) ;
if ( startp = = NULL ) {
/* No @ */
return NT_STATUS_OK ;
}
if ( ( startp > smb_fname - > base_name ) & & ( startp [ - 1 ] ! = ' / ' ) ) {
/* the GMT-token does not start a path-component */
return NT_STATUS_OK ;
}
endp = strptime ( startp , GMT_FORMAT , & tm ) ;
if ( endp = = NULL ) {
/* Not a valid timestring. */
return NT_STATUS_OK ;
}
if ( endp [ 0 ] = = ' \0 ' ) {
return rearrange_snapshot_path ( smb_fname ,
startp ,
endp ) ;
}
if ( endp [ 0 ] ! = ' / ' ) {
/*
* It is not a complete path component , i . e . the path
* component continues after the gmt - token .
*/
return NT_STATUS_OK ;
}
return rearrange_snapshot_path ( smb_fname ,
startp ,
endp ) ;
}
1998-08-17 11:40:06 +04:00
/****************************************************************************
This routine is called to convert names from the dos namespace to unix
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().
2009-04-08 00:39:57 +04:00
namespace . It needs to handle any case conversions , mangling , format changes ,
streams etc .
1998-08-17 11:40:06 +04:00
We assume that we have already done a chdir ( ) to the right " root " directory
for this service .
2007-08-31 01:46:42 +04:00
The function will return an NTSTATUS error if some part of the name except for
the last part cannot be resolved , else NT_STATUS_OK .
2007-01-13 02:47:16 +03:00
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().
2009-04-08 00:39:57 +04:00
Note NT_STATUS_OK doesn ' t mean the name exists or is valid , just that we
didn ' t get any fatal errors that should immediately terminate the calling SMB
processing whilst resolving .
1998-08-17 11:40:06 +04:00
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().
2009-04-08 00:39:57 +04:00
If the UCF_SAVE_LCOMP flag is passed in , then the unmodified last component
of the pathname is set in smb_filename - > original_lcomp .
1998-08-17 11:40:06 +04:00
2009-07-25 05:38:40 +04:00
If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in , then a MS wildcard was detected
and should be allowed in the last component of the path only .
2000-10-19 06:58:24 +04:00
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().
2009-04-08 00:39:57 +04:00
If the orig_path was a stream , smb_filename - > base_name will point to the base
filename , and smb_filename - > stream_name will point to the stream name . If
orig_path was not a stream , then smb_filename - > stream_name will be NULL .
On exit from unix_convert , the smb_filename - > st stat struct will be populated
if the file exists and was found , if not this stat struct will be filled with
zeros ( and this can be detected by checking for nlinks = 0 , which can never be
true for any file ) .
1998-08-17 11:40:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-09-14 02:08:59 +04:00
NTSTATUS unix_convert ( TALLOC_CTX * ctx ,
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().
2009-04-08 00:39:57 +04:00
connection_struct * conn ,
const char * orig_path ,
struct smb_filename * * smb_fname_out ,
uint32_t ucf_flags )
1998-08-17 11:40:06 +04:00
{
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().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname = NULL ;
2016-01-07 23:33:18 +03:00
/*
* This looks strange . But we need " start " initialized to " " here but
* it can ' t be a const char * , so ' char * start = " " ; ' does not work .
*/
char cnull = ' \0 ' ;
char * start = & cnull ;
char * end ;
2007-07-12 02:39:11 +04:00
char * dirpath = NULL ;
2008-01-20 01:25:36 +03:00
char * stream = NULL ;
2007-10-19 04:40:25 +04:00
bool component_was_mangled = False ;
bool name_has_wildcard = False ;
2015-12-22 22:32:20 +03:00
bool posix_pathnames = ( ucf_flags & UCF_POSIX_PATHNAMES ) ;
2009-07-25 05:38:40 +04:00
bool allow_wcard_last_component =
( ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP ) ;
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().
2009-04-08 00:39:57 +04:00
bool save_last_component = ucf_flags & UCF_SAVE_LCOMP ;
2009-07-22 20:52:09 +04:00
NTSTATUS status ;
2009-02-05 03:33:52 +03:00
int ret = - 1 ;
2002-07-15 14:35:28 +04:00
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().
2009-04-08 00:39:57 +04:00
* smb_fname_out = NULL ;
2009-07-22 20:52:09 +04:00
smb_fname = talloc_zero ( ctx , struct smb_filename ) ;
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().
2009-04-08 00:39:57 +04:00
if ( smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2007-01-13 02:47:16 +03:00
}
2002-07-15 14:35:28 +04:00
if ( conn - > printer ) {
/* we don't ever use the filenames on a printer share as a
filename - so don ' t convert them */
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().
2009-04-08 00:39:57 +04:00
if ( ! ( smb_fname - > base_name = talloc_strdup ( smb_fname ,
orig_path ) ) ) {
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2007-09-08 00:57:01 +04:00
}
2009-07-22 20:52:09 +04:00
goto done ;
2002-07-15 14:35:28 +04:00
}
2016-03-18 02:20:17 +03:00
smb_fname - > flags = posix_pathnames ? SMB_FILENAME_POSIX_PATH : 0 ;
2007-07-12 02:39:11 +04:00
DEBUG ( 5 , ( " unix_convert called on file \" %s \" \n " , orig_path ) ) ;
2002-07-15 14:35:28 +04:00
2007-07-12 02:39:11 +04:00
/*
2007-08-31 01:46:42 +04:00
* Conversion to basic unix format is already done in
* check_path_syntax ( ) .
2002-07-15 14:35:28 +04:00
*/
2007-07-12 02:39:11 +04:00
/*
2004-03-03 23:55:59 +03:00
* Names must be relative to the root of the service - any leading / .
* and trailing / ' s should have been trimmed by check_path_syntax ( ) .
2002-07-15 14:35:28 +04:00
*/
2004-03-03 23:55:59 +03:00
# ifdef DEVELOPER
2007-07-12 02:39:11 +04:00
SMB_ASSERT ( * orig_path ! = ' / ' ) ;
2004-03-03 23:55:59 +03:00
# endif
2002-07-15 14:35:28 +04:00
/*
* If we trimmed down to a single ' \0 ' character
* then we should use the " . " directory to avoid
* searching the cache , but not if we are in a
* printing share .
2004-03-03 23:55:59 +03:00
* As we know this is valid we can return true here .
2002-07-15 14:35:28 +04:00
*/
2007-07-12 02:39:11 +04:00
if ( ! * orig_path ) {
2009-07-22 20:52:09 +04:00
if ( ! ( smb_fname - > base_name = talloc_strdup ( smb_fname , " . " ) ) ) {
status = NT_STATUS_NO_MEMORY ;
goto err ;
2007-07-12 02:39:11 +04:00
}
2009-07-22 20:52:09 +04:00
if ( SMB_VFS_STAT ( conn , smb_fname ) ! = 0 ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
2004-05-14 05:22:17 +04:00
}
2009-07-22 20:52:09 +04:00
DEBUG ( 5 , ( " conversion finished \" \" -> %s \n " ,
smb_fname - > base_name ) ) ;
2007-07-12 02:39:11 +04:00
goto done ;
2007-01-13 02:47:16 +03:00
}
2007-08-31 01:46:42 +04:00
if ( orig_path [ 0 ] = = ' . ' & & ( orig_path [ 1 ] = = ' / ' | |
orig_path [ 1 ] = = ' \0 ' ) ) {
2007-01-13 02:47:16 +03:00
/* Start of pathname can't be "." only. */
2007-07-12 02:39:11 +04:00
if ( orig_path [ 1 ] = = ' \0 ' | | orig_path [ 2 ] = = ' \0 ' ) {
2009-07-22 20:52:09 +04:00
status = NT_STATUS_OBJECT_NAME_INVALID ;
2007-01-13 04:07:39 +03:00
} else {
2009-07-22 20:52:09 +04:00
status = determine_path_error ( & orig_path [ 2 ] ,
2015-12-12 01:36:33 +03:00
allow_wcard_last_component ,
posix_pathnames ) ;
2007-01-13 04:07:39 +03:00
}
2009-07-22 20:52:09 +04:00
goto err ;
2002-07-15 14:35:28 +04:00
}
2009-07-22 20:52:09 +04:00
/* Start with the full orig_path as given by the caller. */
if ( ! ( smb_fname - > base_name = talloc_strdup ( smb_fname , orig_path ) ) ) {
2008-11-18 21:57:54 +03:00
DEBUG ( 0 , ( " talloc_strdup failed \n " ) ) ;
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2008-11-18 21:57:54 +03:00
}
2017-01-12 03:30:38 +03:00
/* Canonicalize any @GMT- paths. */
if ( posix_pathnames = = false ) {
status = canonicalize_snapshot_path ( smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto err ;
}
}
2008-11-18 21:57:54 +03:00
/*
* Large directory fix normalization . If we ' re case sensitive , and
* the case preserving parameters are set to " no " , normalize the case of
* the incoming filename from the client WHETHER IT EXISTS OR NOT !
* This is in conflict with the current ( 3.0 .20 ) man page , but is
* what people expect from the " large directory howto " . I ' ll update
* the man page . Thanks to jht @ samba . org for finding this . JRA .
*/
if ( conn - > case_sensitive & & ! conn - > case_preserve & &
! conn - > short_case_preserve ) {
2014-02-03 06:12:09 +04:00
if ( ! strnorm ( smb_fname - > base_name , lp_default_case ( SNUM ( conn ) ) ) ) {
2012-08-09 02:49:34 +04:00
DEBUG ( 0 , ( " strnorm %s failed \n " , smb_fname - > base_name ) ) ;
status = NT_STATUS_INVALID_PARAMETER ;
goto err ;
}
2008-11-18 21:57:54 +03:00
}
2002-07-15 14:35:28 +04:00
/*
* Ensure saved_last_component is valid even if file exists .
*/
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().
2009-04-08 00:39:57 +04:00
if ( save_last_component ) {
2009-07-22 20:52:09 +04:00
end = strrchr_m ( smb_fname - > base_name , ' / ' ) ;
2007-01-13 02:47:16 +03:00
if ( end ) {
2009-07-22 20:52:09 +04:00
smb_fname - > original_lcomp = talloc_strdup ( smb_fname ,
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().
2009-04-08 00:39:57 +04:00
end + 1 ) ;
2007-01-13 02:47:16 +03:00
} else {
2009-07-22 20:52:09 +04:00
smb_fname - > original_lcomp =
talloc_strdup ( smb_fname , smb_fname - > base_name ) ;
}
if ( smb_fname - > original_lcomp = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err ;
2008-11-18 19:03:38 +03:00
}
2002-07-15 14:35:28 +04:00
}
2009-07-22 20:52:09 +04:00
/*
* Strip off the stream , and add it back when we ' re done with the
* base_name .
*/
2009-02-05 03:33:52 +03:00
if ( ! posix_pathnames ) {
2009-07-22 20:52:09 +04:00
stream = strchr_m ( smb_fname - > base_name , ' : ' ) ;
2008-01-20 08:53:49 +03:00
if ( stream ! = NULL ) {
2009-07-22 20:52:09 +04:00
char * tmp = talloc_strdup ( smb_fname , stream ) ;
2008-01-20 08:53:49 +03:00
if ( tmp = = NULL ) {
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2008-01-20 08:53:49 +03:00
}
2009-07-22 20:52:09 +04:00
/*
* Since this is actually pointing into
* smb_fname - > base_name this truncates base_name .
*/
2008-01-20 08:53:49 +03:00
* stream = ' \0 ' ;
stream = tmp ;
2015-09-16 22:03:34 +03:00
if ( smb_fname - > base_name [ 0 ] = = ' \0 ' ) {
/*
* orig_name was just a stream name .
* This is a stream on the root of
* the share . Replace base_name with
* a " . "
*/
smb_fname - > base_name =
talloc_strdup ( smb_fname , " . " ) ;
if ( smb_fname - > base_name = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err ;
}
if ( SMB_VFS_STAT ( conn , smb_fname ) ! = 0 ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
2015-10-01 03:12:11 +03:00
/* dirpath must exist. */
dirpath = talloc_strdup ( ctx , " " ) ;
if ( dirpath = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err ;
}
2015-09-16 22:03:34 +03:00
DEBUG ( 5 , ( " conversion finished %s -> %s \n " ,
orig_path ,
smb_fname - > base_name ) ) ;
goto done ;
}
2008-01-20 01:25:36 +03:00
}
}
2009-07-22 20:52:09 +04:00
start = smb_fname - > base_name ;
2002-07-15 14:35:28 +04:00
2009-07-22 20:52:09 +04:00
/*
2010-12-06 16:05:49 +03:00
* If we ' re providing case insensitive semantics or
2007-12-23 04:38:18 +03:00
* the underlying filesystem is case insensitive ,
* then a case - normalized hit in the stat - cache is
* authoratitive . JRA .
2009-07-22 20:52:09 +04:00
*
* Note : We ' re only checking base_name . The stream_name will be
* added and verified in build_stream_path ( ) .
2007-12-23 04:38:18 +03:00
*/
2009-07-22 20:52:09 +04:00
if ( ( ! conn - > case_sensitive | | ! ( conn - > fs_capabilities &
FILE_CASE_SENSITIVE_SEARCH ) ) & &
2011-10-22 04:46:12 +04:00
stat_cache_lookup ( conn , posix_pathnames , & smb_fname - > base_name , & dirpath , & start ,
2009-07-22 20:52:09 +04:00
& smb_fname - > st ) ) {
2007-07-12 02:39:11 +04:00
goto done ;
}
/*
* Make sure " dirpath " is an allocated string , we use this for
2010-12-06 16:05:49 +03:00
* building the directories with talloc_asprintf and free it .
2007-07-12 02:39:11 +04:00
*/
2007-09-08 00:57:01 +04:00
if ( ( dirpath = = NULL ) & & ( ! ( dirpath = talloc_strdup ( ctx , " " ) ) ) ) {
DEBUG ( 0 , ( " talloc_strdup failed \n " ) ) ;
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2002-07-15 14:35:28 +04:00
}
2007-07-12 02:39:11 +04:00
/*
2009-11-26 00:17:56 +03:00
* If we have a wildcard we must walk the path to
* find where the error is , even if case sensitive
* is true .
2002-07-15 14:35:28 +04:00
*/
2015-12-12 01:41:38 +03:00
if ( ! posix_pathnames ) {
/* POSIX pathnames have no wildcards. */
name_has_wildcard = ms_has_wild ( smb_fname - > base_name ) ;
if ( name_has_wildcard & & ! allow_wcard_last_component ) {
/* Wildcard not valid anywhere. */
status = NT_STATUS_OBJECT_NAME_INVALID ;
goto fail ;
}
2009-02-05 03:33:52 +03:00
}
2009-11-26 00:17:56 +03:00
DEBUG ( 5 , ( " unix_convert begin: name = %s, dirpath = %s, start = %s \n " ,
smb_fname - > base_name , dirpath , start ) ) ;
if ( ! name_has_wildcard ) {
/*
* stat the name - if it exists then we can add the stream back ( if
* there was one ) and be done !
*/
if ( posix_pathnames ) {
ret = SMB_VFS_LSTAT ( conn , smb_fname ) ;
} else {
ret = SMB_VFS_STAT ( conn , smb_fname ) ;
}
if ( ret = = 0 ) {
status = check_for_dot_component ( smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-15 13:42:43 +04:00
goto fail ;
2007-01-13 02:47:16 +03:00
}
2009-11-26 00:17:56 +03:00
/* Add the path (not including the stream) to the cache. */
stat_cache_add ( orig_path , smb_fname - > base_name ,
conn - > case_sensitive ) ;
DEBUG ( 5 , ( " conversion of base_name finished %s -> %s \n " ,
orig_path , smb_fname - > base_name ) ) ;
goto done ;
2007-01-13 02:47:16 +03:00
}
2002-07-15 14:35:28 +04:00
2011-04-04 21:22:03 +04:00
/* Stat failed - ensure we don't use it. */
SET_STAT_INVALID ( smb_fname - > st ) ;
2010-09-11 10:28:15 +04:00
if ( errno = = ENOENT ) {
/* Optimization when creating a new file - only
2013-04-30 02:21:00 +04:00
the last component doesn ' t exist .
NOTE : check_parent_exists ( ) doesn ' t preserve errno .
*/
int saved_errno = errno ;
2010-09-11 10:28:15 +04:00
status = check_parent_exists ( ctx ,
conn ,
posix_pathnames ,
smb_fname ,
& dirpath ,
& start ) ;
2013-04-30 02:21:00 +04:00
errno = saved_errno ;
2010-09-11 10:28:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
}
2009-11-26 00:17:56 +03:00
/*
* A special case - if we don ' t have any wildcards or mangling chars and are case
2010-12-06 16:05:49 +03:00
* sensitive or the underlying filesystem is case insensitive then searching
2009-11-26 00:17:56 +03:00
* won ' t help .
*/
2002-07-15 14:35:28 +04:00
2009-11-26 00:17:56 +03:00
if ( ( conn - > case_sensitive | | ! ( conn - > fs_capabilities &
FILE_CASE_SENSITIVE_SEARCH ) ) & &
! mangle_is_mangled ( smb_fname - > base_name , conn - > params ) ) {
2002-07-15 14:35:28 +04:00
2009-11-26 00:17:56 +03:00
status = check_for_dot_component ( smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
/*
* The stat failed . Could be ok as it could be
* a new file .
*/
if ( errno = = ENOTDIR | | errno = = ELOOP ) {
status = NT_STATUS_OBJECT_PATH_NOT_FOUND ;
goto fail ;
} else if ( errno = = ENOENT ) {
/*
* Was it a missing last component ?
* or a missing intermediate component ?
*/
struct smb_filename parent_fname ;
2010-09-09 03:55:24 +04:00
const char * last_component = NULL ;
2009-11-26 00:17:56 +03:00
ZERO_STRUCT ( parent_fname ) ;
if ( ! parent_dirname ( ctx , smb_fname - > base_name ,
& parent_fname . base_name ,
2010-09-09 03:55:24 +04:00
& last_component ) ) {
2009-11-26 00:17:56 +03:00
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
if ( posix_pathnames ) {
ret = SMB_VFS_LSTAT ( conn , & parent_fname ) ;
} else {
ret = SMB_VFS_STAT ( conn , & parent_fname ) ;
}
if ( ret = = - 1 ) {
if ( errno = = ENOTDIR | |
errno = = ENOENT | |
errno = = ELOOP ) {
status = NT_STATUS_OBJECT_PATH_NOT_FOUND ;
goto fail ;
}
}
2010-09-09 03:55:24 +04:00
2009-11-26 00:17:56 +03:00
/*
* Missing last component is ok - new file .
* Also deal with permission denied elsewhere .
* Just drop out to done .
*/
goto done ;
}
}
2010-09-09 03:55:24 +04:00
} else {
/*
* We have a wildcard in the pathname .
*
* Optimization for common case where the wildcard
* is in the last component and the client already
* sent the correct case .
2013-04-30 02:21:00 +04:00
* NOTE : check_parent_exists ( ) doesn ' t preserve errno .
2010-09-09 03:55:24 +04:00
*/
2013-04-30 02:21:00 +04:00
int saved_errno = errno ;
2010-09-11 10:28:15 +04:00
status = check_parent_exists ( ctx ,
conn ,
posix_pathnames ,
smb_fname ,
& dirpath ,
& start ) ;
2013-04-30 02:21:00 +04:00
errno = saved_errno ;
2010-09-11 10:28:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-09-09 03:55:24 +04:00
goto fail ;
}
2007-01-13 02:47:16 +03:00
}
2002-07-15 14:35:28 +04:00
2007-07-12 02:39:11 +04:00
/*
* is_mangled ( ) was changed to look at an entire pathname , not
2002-07-15 14:35:28 +04:00
* just a component . JRA .
*/
2007-01-13 02:47:16 +03:00
if ( mangle_is_mangled ( start , conn - > params ) ) {
2002-07-15 14:35:28 +04:00
component_was_mangled = True ;
2007-01-13 02:47:16 +03:00
}
2002-07-15 14:35:28 +04:00
2007-07-12 02:39:11 +04:00
/*
* Now we need to recursively match the name against the real
2002-07-15 14:35:28 +04:00
* directory structure .
*/
2007-07-12 02:39:11 +04:00
/*
2002-07-15 14:35:28 +04:00
* Match each part of the path name separately , trying the names
* as is first , then trying to scan the directory for matching names .
*/
for ( ; start ; start = ( end ? end + 1 : ( char * ) NULL ) ) {
2007-07-12 02:39:11 +04:00
/*
2002-07-15 14:35:28 +04:00
* Pinpoint the end of this section of the filename .
*/
2007-08-31 01:46:42 +04:00
/* mb safe. '/' can't be in any encoded char. */
end = strchr ( start , ' / ' ) ;
2002-07-15 14:35:28 +04:00
2007-07-12 02:39:11 +04:00
/*
2002-07-15 14:35:28 +04:00
* Chop the name at this point .
*/
2007-01-13 02:47:16 +03:00
if ( end ) {
2002-07-15 14:35:28 +04:00
* end = 0 ;
2007-01-13 02:47:16 +03:00
}
2002-07-15 14:35:28 +04:00
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().
2009-04-08 00:39:57 +04:00
if ( save_last_component ) {
TALLOC_FREE ( smb_fname - > original_lcomp ) ;
2009-07-22 20:52:09 +04:00
smb_fname - > original_lcomp = talloc_strdup ( smb_fname ,
2007-09-08 00:57:01 +04:00
end ? end + 1 : start ) ;
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().
2009-04-08 00:39:57 +04:00
if ( ! smb_fname - > original_lcomp ) {
2007-09-08 00:57:01 +04:00
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2007-09-08 00:57:01 +04:00
}
2007-01-13 02:47:16 +03:00
}
/* The name cannot have a component of "." */
if ( ISDOT ( start ) ) {
2007-01-13 04:29:10 +03:00
if ( ! end ) {
2007-01-13 02:47:16 +03:00
/* Error code at the end of a pathname. */
2009-07-22 20:52:09 +04:00
status = NT_STATUS_OBJECT_NAME_INVALID ;
2007-07-12 02:39:11 +04:00
} else {
2009-07-22 20:52:09 +04:00
status = determine_path_error ( end + 1 ,
2015-12-12 01:36:33 +03:00
allow_wcard_last_component ,
posix_pathnames ) ;
2007-01-13 02:47:16 +03:00
}
2007-07-12 02:39:11 +04:00
goto fail ;
2007-01-13 02:47:16 +03:00
}
/* The name cannot have a wildcard if it's not
the last component . */
2015-12-12 01:41:38 +03:00
if ( ! posix_pathnames ) {
name_has_wildcard = ms_has_wild ( start ) ;
}
2007-01-13 02:47:16 +03:00
/* Wildcards never valid within a pathname. */
if ( name_has_wildcard & & end ) {
2009-07-22 20:52:09 +04:00
status = NT_STATUS_OBJECT_NAME_INVALID ;
2007-07-12 02:39:11 +04:00
goto fail ;
2007-01-13 02:47:16 +03:00
}
2002-07-15 14:35:28 +04:00
2010-09-09 03:55:24 +04:00
/* Skip the stat call if it's a wildcard end. */
if ( name_has_wildcard ) {
DEBUG ( 5 , ( " Wildcard %s \n " , start ) ) ;
goto done ;
}
2007-07-12 02:39:11 +04:00
/*
2002-07-15 14:35:28 +04:00
* Check if the name exists up to this point .
*/
2009-02-05 03:33:52 +03:00
if ( posix_pathnames ) {
2009-07-22 20:52:09 +04:00
ret = SMB_VFS_LSTAT ( conn , smb_fname ) ;
2009-02-05 03:33:52 +03:00
} else {
2009-07-22 20:52:09 +04:00
ret = SMB_VFS_STAT ( conn , smb_fname ) ;
2009-02-05 03:33:52 +03:00
}
if ( ret = = 0 ) {
2002-07-15 14:35:28 +04:00
/*
2007-08-31 01:46:42 +04:00
* It exists . it must either be a directory or this must
* be the last part of the path for it to be OK .
2002-07-15 14:35:28 +04:00
*/
2009-07-22 20:52:09 +04:00
if ( end & & ! S_ISDIR ( smb_fname - > st . st_ex_mode ) ) {
2002-07-15 14:35:28 +04:00
/*
2007-08-31 01:46:42 +04:00
* An intermediate part of the name isn ' t
* a directory .
2002-07-15 14:35:28 +04:00
*/
DEBUG ( 5 , ( " Not a dir %s \n " , start ) ) ;
* end = ' / ' ;
2007-07-12 02:39:11 +04:00
/*
2007-08-31 01:46:42 +04:00
* We need to return the fact that the
* intermediate name resolution failed . This
* is used to return an error of ERRbadpath
* rather than ERRbadfile . Some Windows
* applications depend on the difference between
2004-06-11 21:54:23 +04:00
* these two errors .
*/
2009-07-22 20:52:09 +04:00
status = NT_STATUS_OBJECT_PATH_NOT_FOUND ;
2007-07-12 02:39:11 +04:00
goto fail ;
2002-07-15 14:35:28 +04:00
}
} else {
2007-07-12 02:39:11 +04:00
char * found_name = NULL ;
2002-07-15 14:35:28 +04:00
/* Stat failed - ensure we don't use it. */
2009-07-22 20:52:09 +04:00
SET_STAT_INVALID ( smb_fname - > st ) ;
2002-07-15 14:35:28 +04:00
2007-08-31 01:46:42 +04:00
/*
* Reset errno so we can detect
* directory open errors .
*/
2004-06-11 21:54:23 +04:00
errno = 0 ;
2002-07-15 14:35:28 +04:00
/*
* Try to find this part of the path in the directory .
*/
2007-08-31 01:46:42 +04:00
if ( name_has_wildcard | |
2009-05-02 04:28:38 +04:00
( get_real_filename ( conn , dirpath , start ,
talloc_tos ( ) ,
& found_name ) = = - 1 ) ) {
2007-07-12 02:39:11 +04:00
char * unmangled ;
2002-07-15 14:35:28 +04:00
if ( end ) {
/*
2007-08-31 01:46:42 +04:00
* An intermediate part of the name
* can ' t be found .
2002-07-15 14:35:28 +04:00
*/
2007-08-31 01:46:42 +04:00
DEBUG ( 5 , ( " Intermediate not found %s \n " ,
start ) ) ;
2002-07-15 14:35:28 +04:00
* end = ' / ' ;
2007-07-12 02:39:11 +04:00
/*
2007-08-31 01:46:42 +04:00
* We need to return the fact that the
* intermediate name resolution failed .
* This is used to return an error of
* ERRbadpath rather than ERRbadfile .
* Some Windows applications depend on
* the difference between these two
* errors .
2002-07-15 14:35:28 +04:00
*/
2007-01-13 05:13:45 +03:00
2007-07-12 03:54:01 +04:00
/*
* ENOENT , ENOTDIR and ELOOP all map
* to NT_STATUS_OBJECT_PATH_NOT_FOUND
* in the filename walk .
*/
2007-01-13 05:13:45 +03:00
2007-07-12 03:54:01 +04:00
if ( errno = = ENOENT | |
errno = = ENOTDIR | |
errno = = ELOOP ) {
2009-07-22 20:52:09 +04:00
status =
2007-08-31 01:46:42 +04:00
NT_STATUS_OBJECT_PATH_NOT_FOUND ;
2007-07-12 02:39:11 +04:00
}
else {
2009-07-22 20:52:09 +04:00
status =
2007-08-31 01:46:42 +04:00
map_nt_error_from_unix ( errno ) ;
2007-01-13 02:47:16 +03:00
}
2007-07-12 02:39:11 +04:00
goto fail ;
2002-07-15 14:35:28 +04:00
}
2007-07-12 02:39:11 +04:00
2009-05-30 13:30:16 +04:00
/*
* ENOENT / EACCESS are the only valid errors
2013-08-19 14:26:00 +04:00
* here .
2009-05-30 13:30:16 +04:00
*/
2013-08-19 14:26:00 +04:00
if ( errno = = EACCES ) {
2013-12-03 22:19:09 +04:00
if ( ( ucf_flags & UCF_PREP_CREATEFILE ) = = 0 ) {
2013-12-03 16:20:17 +04:00
status = NT_STATUS_ACCESS_DENIED ;
goto fail ;
} else {
2013-08-19 14:26:00 +04:00
/*
* This is the dropbox
* behaviour . A dropbox is a
* directory with only - wx
* permissions , so
* get_real_filename fails
* with EACCESS , it needs to
* list the directory . We
* nevertheless want to allow
* users creating a file .
*/
2013-12-03 16:20:17 +04:00
errno = 0 ;
2013-08-19 14:26:00 +04:00
}
}
if ( ( errno ! = 0 ) & & ( errno ! = ENOENT ) ) {
2007-07-12 03:54:01 +04:00
/*
* ENOTDIR and ELOOP both map to
* NT_STATUS_OBJECT_PATH_NOT_FOUND
* in the filename walk .
*/
if ( errno = = ENOTDIR | |
errno = = ELOOP ) {
2009-07-22 20:52:09 +04:00
status =
2007-08-31 01:46:42 +04:00
NT_STATUS_OBJECT_PATH_NOT_FOUND ;
2009-05-30 13:30:16 +04:00
} else {
2009-07-22 20:52:09 +04:00
status =
2007-08-31 01:46:42 +04:00
map_nt_error_from_unix ( errno ) ;
2007-01-13 05:13:45 +03:00
}
2009-05-30 13:30:16 +04:00
goto fail ;
2004-06-11 21:54:23 +04:00
}
2005-11-22 19:21:52 +03:00
/*
2002-07-15 14:35:28 +04:00
* Just the last part of the name doesn ' t exist .
2005-11-22 19:21:52 +03:00
* We need to strupper ( ) or strlower ( ) it as
2007-08-31 01:46:42 +04:00
* this conversion may be used for file creation
* purposes . Fix inspired by
* Thomas Neumann < t . neumann @ iku - ag . de > .
2002-07-15 14:35:28 +04:00
*/
2005-11-22 19:21:52 +03:00
if ( ! conn - > case_preserve | |
2007-08-31 01:46:42 +04:00
( mangle_is_8_3 ( start , False ,
conn - > params ) & &
2005-11-22 19:21:52 +03:00
! conn - > short_case_preserve ) ) {
2012-08-09 02:49:34 +04:00
if ( ! strnorm ( start ,
2014-02-03 06:12:09 +04:00
lp_default_case ( SNUM ( conn ) ) ) ) {
2012-08-09 02:49:34 +04:00
DEBUG ( 0 , ( " strnorm %s failed \n " ,
start ) ) ;
status = NT_STATUS_INVALID_PARAMETER ;
goto err ;
}
2005-11-22 19:21:52 +03:00
}
2002-07-15 14:35:28 +04:00
/*
2007-08-31 01:46:42 +04:00
* check on the mangled stack to see if we can
* recover the base of the filename .
2002-07-15 14:35:28 +04:00
*/
2007-07-12 02:39:11 +04:00
if ( mangle_is_mangled ( start , conn - > params )
2007-09-08 00:57:01 +04:00
& & mangle_lookup_name_from_8_3 ( ctx ,
start ,
& unmangled ,
conn - > params ) ) {
2007-07-12 02:39:11 +04:00
char * tmp ;
2009-07-22 20:52:09 +04:00
size_t start_ofs =
start - smb_fname - > base_name ;
2007-07-12 02:39:11 +04:00
if ( * dirpath ! = ' \0 ' ) {
2009-07-22 20:52:09 +04:00
tmp = talloc_asprintf (
smb_fname , " %s/%s " ,
dirpath , unmangled ) ;
2007-09-08 00:57:01 +04:00
TALLOC_FREE ( unmangled ) ;
2007-07-12 02:39:11 +04:00
}
else {
tmp = unmangled ;
}
if ( tmp = = NULL ) {
2007-09-08 00:57:01 +04:00
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2007-07-12 02:39:11 +04:00
}
2009-07-22 20:52:09 +04:00
TALLOC_FREE ( smb_fname - > base_name ) ;
smb_fname - > base_name = tmp ;
start =
smb_fname - > base_name + start_ofs ;
2007-07-12 02:39:11 +04:00
end = start + strlen ( start ) ;
2002-07-15 14:35:28 +04:00
}
DEBUG ( 5 , ( " New file %s \n " , start ) ) ;
2007-07-12 02:39:11 +04:00
goto done ;
2002-07-15 14:35:28 +04:00
}
2007-07-12 02:39:11 +04:00
/*
2007-08-31 01:46:42 +04:00
* Restore the rest of the string . If the string was
* mangled the size may have changed .
2002-07-15 14:35:28 +04:00
*/
if ( end ) {
2007-07-12 02:39:11 +04:00
char * tmp ;
2009-07-22 20:52:09 +04:00
size_t start_ofs =
start - smb_fname - > base_name ;
2007-07-12 02:39:11 +04:00
if ( * dirpath ! = ' \0 ' ) {
2009-07-22 20:52:09 +04:00
tmp = talloc_asprintf ( smb_fname ,
2007-09-08 00:57:01 +04:00
" %s/%s/%s " , dirpath ,
found_name , end + 1 ) ;
2003-02-07 07:11:36 +03:00
}
2007-07-12 02:39:11 +04:00
else {
2009-07-22 20:52:09 +04:00
tmp = talloc_asprintf ( smb_fname ,
2007-09-08 00:57:01 +04:00
" %s/%s " , found_name ,
end + 1 ) ;
2007-07-12 02:39:11 +04:00
}
if ( tmp = = NULL ) {
2007-09-08 00:57:01 +04:00
DEBUG ( 0 , ( " talloc_asprintf failed \n " ) ) ;
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2007-07-12 02:39:11 +04:00
}
2009-07-22 20:52:09 +04:00
TALLOC_FREE ( smb_fname - > base_name ) ;
smb_fname - > base_name = tmp ;
start = smb_fname - > base_name + start_ofs ;
2007-07-12 02:39:11 +04:00
end = start + strlen ( found_name ) ;
2002-07-15 14:35:28 +04:00
* end = ' \0 ' ;
2002-10-11 05:19:00 +04:00
} else {
2007-07-12 02:39:11 +04:00
char * tmp ;
2009-07-22 20:52:09 +04:00
size_t start_ofs =
start - smb_fname - > base_name ;
2007-07-12 02:39:11 +04:00
if ( * dirpath ! = ' \0 ' ) {
2009-07-22 20:52:09 +04:00
tmp = talloc_asprintf ( smb_fname ,
2007-09-08 00:57:01 +04:00
" %s/%s " , dirpath ,
found_name ) ;
2007-09-12 03:57:59 +04:00
} else {
2009-07-22 20:52:09 +04:00
tmp = talloc_strdup ( smb_fname ,
2007-09-08 00:57:01 +04:00
found_name ) ;
2007-07-12 02:39:11 +04:00
}
if ( tmp = = NULL ) {
2007-09-08 00:57:01 +04:00
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2007-07-12 02:39:11 +04:00
}
2009-07-22 20:52:09 +04:00
TALLOC_FREE ( smb_fname - > base_name ) ;
smb_fname - > base_name = tmp ;
start = smb_fname - > base_name + start_ofs ;
2007-07-12 02:39:11 +04:00
2002-10-11 05:19:00 +04:00
/*
2007-08-31 01:46:42 +04:00
* We just scanned for , and found the end of
* the path . We must return a valid stat struct
* if it exists . JRA .
2002-10-11 05:19:00 +04:00
*/
2009-02-05 03:33:52 +03:00
if ( posix_pathnames ) {
2009-07-22 20:52:09 +04:00
ret = SMB_VFS_LSTAT ( conn , smb_fname ) ;
2009-02-05 03:33:52 +03:00
} else {
2009-07-22 20:52:09 +04:00
ret = SMB_VFS_STAT ( conn , smb_fname ) ;
2009-02-05 03:33:52 +03:00
}
2009-07-22 20:52:09 +04:00
if ( ret ! = 0 ) {
SET_STAT_INVALID ( smb_fname - > st ) ;
2002-10-11 05:19:00 +04:00
}
2002-07-15 14:35:28 +04:00
}
2007-07-12 02:39:11 +04:00
2007-09-08 00:57:01 +04:00
TALLOC_FREE ( found_name ) ;
2002-07-15 14:35:28 +04:00
} /* end else */
2007-08-31 01:46:42 +04:00
/*
2002-07-15 14:35:28 +04:00
* Add to the dirpath that we have resolved so far .
*/
2007-07-12 02:39:11 +04:00
if ( * dirpath ! = ' \0 ' ) {
2007-09-08 00:57:01 +04:00
char * tmp = talloc_asprintf ( ctx ,
" %s/%s " , dirpath , start ) ;
if ( ! tmp ) {
DEBUG ( 0 , ( " talloc_asprintf failed \n " ) ) ;
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2007-07-12 02:39:11 +04:00
}
2007-09-08 00:57:01 +04:00
TALLOC_FREE ( dirpath ) ;
2007-07-12 02:39:11 +04:00
dirpath = tmp ;
}
else {
2007-09-08 00:57:01 +04:00
TALLOC_FREE ( dirpath ) ;
if ( ! ( dirpath = talloc_strdup ( ctx , start ) ) ) {
DEBUG ( 0 , ( " talloc_strdup failed \n " ) ) ;
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2007-07-12 02:39:11 +04:00
}
}
2002-07-15 14:35:28 +04:00
/*
2009-07-22 20:52:09 +04:00
* Cache the dirpath thus far . Don ' t cache a name with mangled
* or wildcard components as this can change the size .
2002-07-15 14:35:28 +04:00
*/
2007-01-13 02:47:16 +03:00
if ( ! component_was_mangled & & ! name_has_wildcard ) {
2007-08-31 01:46:42 +04:00
stat_cache_add ( orig_path , dirpath ,
conn - > case_sensitive ) ;
2007-01-13 02:47:16 +03:00
}
2007-07-12 02:39:11 +04:00
/*
2002-07-15 14:35:28 +04:00
* Restore the / that we wiped out earlier .
*/
2007-01-13 02:47:16 +03:00
if ( end ) {
2002-07-15 14:35:28 +04:00
* end = ' / ' ;
2007-01-13 02:47:16 +03:00
}
2002-07-15 14:35:28 +04:00
}
2007-07-12 02:39:11 +04:00
2002-07-15 14:35:28 +04:00
/*
2009-07-22 20:52:09 +04:00
* Cache the full path . Don ' t cache a name with mangled or wildcard
* components as this can change the size .
2002-07-15 14:35:28 +04:00
*/
2000-12-12 03:11:34 +03:00
2007-01-13 02:47:16 +03:00
if ( ! component_was_mangled & & ! name_has_wildcard ) {
2009-07-22 20:52:09 +04:00
stat_cache_add ( orig_path , smb_fname - > base_name ,
conn - > case_sensitive ) ;
2007-01-13 02:47:16 +03:00
}
2000-12-12 03:11:34 +03:00
2007-07-12 02:39:11 +04:00
/*
2002-07-15 14:35:28 +04:00
* The name has been resolved .
*/
1998-08-28 00:38:53 +04:00
2009-07-22 20:52:09 +04:00
DEBUG ( 5 , ( " conversion finished %s -> %s \n " , orig_path ,
smb_fname - > base_name ) ) ;
2007-07-12 02:39:11 +04:00
done :
2009-07-22 20:52:09 +04:00
/* Add back the stream if one was stripped off originally. */
2008-01-20 01:25:36 +03:00
if ( stream ! = NULL ) {
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().
2009-04-08 00:39:57 +04:00
smb_fname - > stream_name = stream ;
2008-01-20 01:25:36 +03:00
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().
2009-04-08 00:39:57 +04:00
/* Check path now that the base_name has been converted. */
2015-09-16 22:42:46 +03:00
status = build_stream_path ( ctx , conn , smb_fname ) ;
2009-07-22 20:52:09 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-20 01:25:36 +03:00
goto fail ;
}
}
2007-09-08 00:57:01 +04:00
TALLOC_FREE ( dirpath ) ;
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().
2009-04-08 00:39:57 +04:00
* smb_fname_out = smb_fname ;
2007-08-20 00:00:43 +04:00
return NT_STATUS_OK ;
2007-08-16 19:44:13 +04:00
fail :
2007-08-20 00:00:43 +04:00
DEBUG ( 10 , ( " dirpath = [%s] start = [%s] \n " , dirpath , start ) ) ;
2015-09-25 22:06:57 +03:00
if ( dirpath & & * dirpath ! = ' \0 ' ) {
2009-07-22 20:52:09 +04:00
smb_fname - > base_name = talloc_asprintf ( smb_fname , " %s/%s " ,
dirpath , start ) ;
2007-09-08 00:57:01 +04:00
} else {
2009-07-22 20:52:09 +04:00
smb_fname - > base_name = talloc_strdup ( smb_fname , start ) ;
2007-09-08 00:57:01 +04:00
}
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().
2009-04-08 00:39:57 +04:00
if ( ! smb_fname - > base_name ) {
2007-09-08 00:57:01 +04:00
DEBUG ( 0 , ( " talloc_asprintf failed \n " ) ) ;
2009-07-22 20:52:09 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
2007-09-08 00:57:01 +04:00
}
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().
2009-04-08 00:39:57 +04:00
* smb_fname_out = smb_fname ;
2007-09-08 00:57:01 +04:00
TALLOC_FREE ( dirpath ) ;
2009-07-22 20:52:09 +04:00
return status ;
err :
TALLOC_FREE ( smb_fname ) ;
return status ;
1998-08-17 11:40:06 +04:00
}
/****************************************************************************
2015-02-09 17:42:23 +03:00
Ensure a path is not vetoed .
1998-08-17 11:40:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2015-02-09 17:42:08 +03:00
static NTSTATUS check_veto_path ( connection_struct * conn , const char * name )
1998-08-17 11:40:06 +04:00
{
2009-11-23 18:33:53 +03:00
if ( IS_VETO_PATH ( conn , name ) ) {
2004-03-06 01:32:45 +03:00
/* Is it not dot or dot dot. */
2011-07-26 03:12:45 +04:00
if ( ! ( ISDOT ( name ) | | ISDOTDOT ( name ) ) ) {
2011-10-22 01:12:41 +04:00
DEBUG ( 5 , ( " check_veto_path: file path name %s vetoed \n " ,
2007-08-31 01:46:42 +04:00
name ) ) ;
2007-01-17 05:09:37 +03:00
return map_nt_error_from_unix ( ENOENT ) ;
2002-07-15 14:35:28 +04:00
}
}
2011-10-22 01:12:41 +04:00
return NT_STATUS_OK ;
}
/****************************************************************************
Check a filename - possibly calling check_reduced_name .
This is called by every routine before it allows an operation on a filename .
It does any final confirmation necessary to ensure that the filename is
a valid one for the user to access .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS check_name ( connection_struct * conn , const char * name )
{
NTSTATUS status = check_veto_path ( conn , name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
1998-08-17 11:40:06 +04:00
2014-02-04 06:09:03 +04:00
if ( ! lp_widelinks ( SNUM ( conn ) ) | | ! lp_follow_symlinks ( SNUM ( conn ) ) ) {
2017-03-28 03:04:58 +03:00
status = check_reduced_name ( conn , NULL , name ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-31 01:46:42 +04:00
DEBUG ( 5 , ( " check_name: name %s failed with %s \n " , name ,
nt_errstr ( status ) ) ) ;
2007-01-17 05:09:37 +03:00
return status ;
}
2004-06-11 21:54:23 +04:00
}
1998-08-17 11:40:06 +04:00
2007-01-17 05:09:37 +03:00
return NT_STATUS_OK ;
1998-08-17 11:40:06 +04:00
}
2012-02-25 02:12:05 +04:00
/****************************************************************************
2012-03-01 05:04:08 +04:00
Must be called as root . Creates the struct privilege_paths
2012-02-25 02:12:05 +04:00
attached to the struct smb_request if this call is successful .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS check_name_with_privilege ( connection_struct * conn ,
struct smb_request * smbreq ,
const char * name )
{
NTSTATUS status = check_veto_path ( conn , name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return check_reduced_name_with_privilege ( conn ,
name ,
2012-03-01 05:04:08 +04:00
smbreq ) ;
2012-02-25 02:12:05 +04:00
}
2007-07-12 02:39:11 +04:00
/****************************************************************************
Check if two filenames are equal .
This needs to be careful about whether we are case sensitive .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool fname_equal ( const char * name1 , const char * name2 ,
bool case_sensitive )
2007-07-12 02:39:11 +04:00
{
/* Normal filename handling */
2007-09-08 00:57:01 +04:00
if ( case_sensitive ) {
2007-07-12 02:39:11 +04:00
return ( strcmp ( name1 , name2 ) = = 0 ) ;
2007-09-08 00:57:01 +04:00
}
2007-07-12 02:39:11 +04:00
return ( strequal ( name1 , name2 ) ) ;
}
1998-08-17 11:40:06 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Scan a directory to find a filename , matching without case sensitivity .
If the name looks like a mangled name then try via the mangling functions
1998-08-17 11:40:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2009-05-02 04:28:38 +04:00
static int get_real_filename_full_scan ( connection_struct * conn ,
const char * path , const char * name ,
2009-05-09 13:12:52 +04:00
bool mangled ,
2009-05-02 04:28:38 +04:00
TALLOC_CTX * mem_ctx , char * * found_name )
1998-08-17 11:40:06 +04:00
{
2009-04-23 16:54:52 +04:00
struct smb_Dir * cur_dir ;
2009-11-16 11:49:23 +03:00
const char * dname = NULL ;
char * talloced = NULL ;
2007-07-12 02:39:11 +04:00
char * unmangled_name = NULL ;
2009-04-23 16:54:52 +04:00
long curpos ;
2016-02-27 02:55:14 +03:00
struct smb_filename * smb_fname = NULL ;
2002-07-15 14:35:28 +04:00
/* handle null paths */
2007-09-08 00:57:01 +04:00
if ( ( path = = NULL ) | | ( * path = = 0 ) ) {
2002-07-15 14:35:28 +04:00
path = " . " ;
2007-09-08 00:57:01 +04:00
}
2002-07-15 14:35:28 +04:00
2007-12-23 01:55:37 +03:00
/* If we have a case-sensitive filesystem, it doesn't do us any
* good to search for a name . If a case variation of the name was
* there , then the original stat ( 2 ) would have found it .
*/
if ( ! mangled & & ! ( conn - > fs_capabilities & FILE_CASE_SENSITIVE_SEARCH ) ) {
errno = ENOENT ;
2008-12-10 05:03:51 +03:00
return - 1 ;
2007-12-23 01:55:37 +03:00
}
2002-07-15 14:35:28 +04:00
/*
* The incoming name can be mangled , and if we de - mangle it
* here it will not compare correctly against the filename ( name2 )
2007-09-08 00:57:01 +04:00
* read from the directory and then mangled by the name_to_8_3 ( )
2002-07-15 14:35:28 +04:00
* call . We need to mangle both names or neither .
* ( JRA ) .
2005-10-28 05:42:03 +04:00
*
* Fix for bug found by Dina Fine . If in case sensitive mode then
* the mangle cache is no good ( 3 letter extension could be wrong
* case - so don ' t demangle in this case - leave as mangled and
* allow the mangling of the directory entry read ( which is done
* case insensitively ) to match instead . This will lead to more
* false positive matches but we fail completely without it . JRA .
2002-07-15 14:35:28 +04:00
*/
2005-10-28 05:42:03 +04:00
if ( mangled & & ! conn - > case_sensitive ) {
2008-12-09 15:40:41 +03:00
mangled = ! mangle_lookup_name_from_8_3 ( talloc_tos ( ) , name ,
& unmangled_name ,
conn - > params ) ;
2007-09-14 22:24:31 +04:00
if ( ! mangled ) {
/* Name is now unmangled. */
2007-09-08 00:57:01 +04:00
name = unmangled_name ;
}
2005-10-28 05:42:03 +04:00
}
2002-07-15 14:35:28 +04:00
2016-02-27 02:55:14 +03:00
smb_fname = synthetic_smb_fname ( talloc_tos ( ) ,
path ,
NULL ,
2016-03-19 07:19:38 +03:00
NULL ,
0 ) ;
2016-02-27 02:55:14 +03:00
if ( smb_fname = = NULL ) {
TALLOC_FREE ( unmangled_name ) ;
return - 1 ;
}
2002-07-15 14:35:28 +04:00
/* open the directory */
2016-02-27 02:55:14 +03:00
if ( ! ( cur_dir = OpenDir ( talloc_tos ( ) , conn , smb_fname , NULL , 0 ) ) ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 3 , ( " scan dir didn't open dir [%s] \n " , path ) ) ;
2007-09-08 00:57:01 +04:00
TALLOC_FREE ( unmangled_name ) ;
2016-02-27 02:55:14 +03:00
TALLOC_FREE ( smb_fname ) ;
2008-12-10 05:03:51 +03:00
return - 1 ;
2002-07-15 14:35:28 +04:00
}
2016-02-27 02:55:14 +03:00
TALLOC_FREE ( smb_fname ) ;
2002-07-15 14:35:28 +04:00
/* now scan for matching names */
2005-01-29 00:01:58 +03:00
curpos = 0 ;
2009-11-16 11:49:23 +03:00
while ( ( dname = ReadDirName ( cur_dir , & curpos , NULL , & talloced ) ) ) {
2004-03-06 01:32:45 +03:00
/* Is it dot or dot dot. */
2007-09-08 00:57:01 +04:00
if ( ISDOT ( dname ) | | ISDOTDOT ( dname ) ) {
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2002-07-15 14:35:28 +04:00
continue ;
2004-03-06 01:32:45 +03:00
}
2002-07-15 14:35:28 +04:00
/*
* At this point dname is the unmangled name .
2007-08-31 01:46:42 +04:00
* name is either mangled or not , depending on the state
* of the " mangled " variable . JRA .
2002-07-15 14:35:28 +04:00
*/
/*
* Check mangled name against mangled name , or unmangled name
* against unmangled name .
*/
2007-08-31 01:46:42 +04:00
if ( ( mangled & & mangled_equal ( name , dname , conn - > params ) ) | |
fname_equal ( name , dname , conn - > case_sensitive ) ) {
2002-07-15 14:35:28 +04:00
/* we've found the file, change it's name and return */
2008-12-09 15:40:41 +03:00
* found_name = talloc_strdup ( mem_ctx , dname ) ;
2007-09-08 00:57:01 +04:00
TALLOC_FREE ( unmangled_name ) ;
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( cur_dir ) ;
2007-09-08 00:57:01 +04:00
if ( ! * found_name ) {
errno = ENOMEM ;
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2008-12-10 05:03:51 +03:00
return - 1 ;
2007-09-08 00:57:01 +04:00
}
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2008-12-10 05:03:51 +03:00
return 0 ;
2002-07-15 14:35:28 +04:00
}
2009-11-16 11:49:23 +03:00
TALLOC_FREE ( talloced ) ;
2002-07-15 14:35:28 +04:00
}
2007-09-08 00:57:01 +04:00
TALLOC_FREE ( unmangled_name ) ;
2008-01-12 19:08:04 +03:00
TALLOC_FREE ( cur_dir ) ;
2004-06-11 21:54:23 +04:00
errno = ENOENT ;
2008-12-10 05:03:51 +03:00
return - 1 ;
1998-08-17 11:40:06 +04:00
}
2008-01-20 01:25:36 +03:00
2009-05-02 04:28:38 +04:00
/****************************************************************************
Wrapper around the vfs get_real_filename and the full directory scan
fallback .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int get_real_filename ( connection_struct * conn , const char * path ,
const char * name , TALLOC_CTX * mem_ctx ,
char * * found_name )
{
int ret ;
2009-05-09 13:12:52 +04:00
bool mangled ;
mangled = mangle_is_mangled ( name , conn - > params ) ;
if ( mangled ) {
return get_real_filename_full_scan ( conn , path , name , mangled ,
mem_ctx , found_name ) ;
}
2009-05-02 04:28:38 +04:00
/* Try the vfs first to take advantage of case-insensitive stat. */
ret = SMB_VFS_GET_REAL_FILENAME ( conn , path , name , mem_ctx , found_name ) ;
/*
* If the case - insensitive stat was successful , or returned an error
* other than EOPNOTSUPP then there is no need to fall back on the
* full directory scan .
*/
if ( ret = = 0 | | ( ret = = - 1 & & errno ! = EOPNOTSUPP ) ) {
return ret ;
}
2009-05-09 13:12:52 +04:00
return get_real_filename_full_scan ( conn , path , name , mangled , mem_ctx ,
found_name ) ;
2009-05-02 04:28:38 +04:00
}
2008-01-20 01:25:36 +03:00
static NTSTATUS build_stream_path ( TALLOC_CTX * mem_ctx ,
connection_struct * conn ,
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().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname )
2008-01-20 01:25:36 +03:00
{
NTSTATUS status ;
2011-10-14 02:41:53 +04:00
unsigned int i , num_streams = 0 ;
2008-01-20 01:25:36 +03:00
struct stream_struct * streams = NULL ;
2009-06-23 02:26:56 +04:00
if ( SMB_VFS_STAT ( conn , smb_fname ) = = 0 ) {
2009-07-22 20:52:09 +04:00
DEBUG ( 10 , ( " '%s' exists \n " , smb_fname_str_dbg ( smb_fname ) ) ) ;
2008-01-20 01:25:36 +03:00
return NT_STATUS_OK ;
}
if ( errno ! = ENOENT ) {
2009-08-29 02:53:05 +04:00
DEBUG ( 10 , ( " vfs_stat failed: %s \n " , strerror ( errno ) ) ) ;
2008-01-20 01:25:36 +03:00
status = map_nt_error_from_unix ( errno ) ;
goto fail ;
}
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().
2009-04-08 00:39:57 +04:00
/* Fall back to a case-insensitive scan of all streams on the file. */
2016-03-05 01:16:13 +03:00
status = vfs_streaminfo ( conn , NULL , smb_fname , mem_ctx ,
2011-10-17 22:10:29 +04:00
& num_streams , & streams ) ;
2008-01-20 01:25:36 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
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().
2009-04-08 00:39:57 +04:00
SET_STAT_INVALID ( smb_fname - > st ) ;
2008-01-20 01:25:36 +03:00
return NT_STATUS_OK ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " vfs_streaminfo failed: %s \n " , nt_errstr ( status ) ) ) ;
goto fail ;
}
for ( i = 0 ; i < num_streams ; i + + ) {
DEBUG ( 10 , ( " comparing [%s] and [%s]: " ,
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().
2009-04-08 00:39:57 +04:00
smb_fname - > stream_name , streams [ i ] . name ) ) ;
if ( fname_equal ( smb_fname - > stream_name , streams [ i ] . name ,
2008-01-20 01:25:36 +03:00
conn - > case_sensitive ) ) {
DEBUGADD ( 10 , ( " equal \n " ) ) ;
break ;
}
DEBUGADD ( 10 , ( " not equal \n " ) ) ;
}
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().
2009-04-08 00:39:57 +04:00
/* Couldn't find the stream. */
2008-01-20 01:25:36 +03:00
if ( i = = num_streams ) {
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().
2009-04-08 00:39:57 +04:00
SET_STAT_INVALID ( smb_fname - > st ) ;
2008-01-20 01:25:36 +03:00
TALLOC_FREE ( streams ) ;
return NT_STATUS_OK ;
}
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().
2009-04-08 00:39:57 +04:00
DEBUG ( 10 , ( " case insensitive stream. requested: %s, actual: %s \n " ,
smb_fname - > stream_name , streams [ i ] . name ) ) ;
2008-01-20 01:25:36 +03:00
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().
2009-04-08 00:39:57 +04:00
TALLOC_FREE ( smb_fname - > stream_name ) ;
2009-07-22 20:52:09 +04:00
smb_fname - > stream_name = talloc_strdup ( smb_fname , streams [ i ] . name ) ;
if ( smb_fname - > stream_name = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
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().
2009-04-08 00:39:57 +04:00
SET_STAT_INVALID ( smb_fname - > st ) ;
2008-01-20 01:25:36 +03:00
2009-06-23 02:26:56 +04:00
if ( SMB_VFS_STAT ( conn , smb_fname ) = = 0 ) {
2009-07-22 20:52:09 +04:00
DEBUG ( 10 , ( " '%s' exists \n " , smb_fname_str_dbg ( smb_fname ) ) ) ;
2009-06-23 02:26:56 +04:00
}
status = NT_STATUS_OK ;
2008-01-20 01:25:36 +03:00
fail :
TALLOC_FREE ( streams ) ;
return status ;
}
2009-06-19 00:13:38 +04:00
2009-07-24 23:13:07 +04:00
/**
* Go through all the steps to validate a filename .
*
* @ param ctx talloc_ctx to allocate memory with .
* @ param conn connection struct for vfs calls .
* @ param dfs_path Whether this path requires dfs resolution .
2012-04-24 16:07:00 +04:00
* @ param smbreq SMB request if we ' re using privileges .
2009-07-24 23:13:07 +04:00
* @ param name_in The unconverted name .
* @ param ucf_flags flags to pass through to unix_convert ( ) .
2009-07-25 05:38:40 +04:00
* UCF_ALWAYS_ALLOW_WCARD_LCOMP will be OR ' d in if
* p_cont_wcard ! = NULL and is true and
* UCF_COND_ALLOW_WCARD_LCOMP .
2009-07-24 23:13:07 +04:00
* @ param p_cont_wcard If not NULL , will be set to true if the dfs path
* resolution detects a wildcard .
* @ param pp_smb_fname The final converted name will be allocated if the
* return is NT_STATUS_OK .
*
* @ return NT_STATUS_OK if all operations completed succesfully , appropriate
* error otherwise .
*/
2012-02-25 02:12:05 +04:00
static NTSTATUS filename_convert_internal ( TALLOC_CTX * ctx ,
2009-06-19 00:13:38 +04:00
connection_struct * conn ,
bool dfs_path ,
2012-02-25 02:12:05 +04:00
struct smb_request * smbreq ,
2009-06-19 00:13:38 +04:00
const char * name_in ,
2009-07-24 23:13:07 +04:00
uint32_t ucf_flags ,
bool * ppath_contains_wcard ,
2009-07-21 21:28:28 +04:00
struct smb_filename * * pp_smb_fname )
2009-06-19 00:13:38 +04:00
{
NTSTATUS status ;
* pp_smb_fname = NULL ;
2017-05-18 21:34:33 +03:00
if ( dfs_path ) {
2017-05-18 21:41:10 +03:00
bool path_contains_wcard = false ;
2017-05-18 21:36:56 +03:00
char * fname = NULL ;
2017-05-18 21:34:33 +03:00
status = resolve_dfspath_wcard ( ctx , conn ,
2009-06-19 00:13:38 +04:00
name_in ,
2016-03-25 21:23:29 +03:00
ucf_flags ,
2012-05-23 15:22:47 +04:00
! conn - > sconn - > using_smb2 ,
2009-07-24 23:13:07 +04:00
& fname ,
2017-05-18 21:41:10 +03:00
& path_contains_wcard ) ;
2017-05-18 21:34:33 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " filename_convert_internal: resolve_dfspath "
" failed for name %s with %s \n " ,
name_in ,
nt_errstr ( status ) ) ) ;
return status ;
}
2017-05-18 21:36:56 +03:00
name_in = fname ;
2017-05-18 21:41:10 +03:00
if ( ppath_contains_wcard ! = NULL & & path_contains_wcard ) {
* ppath_contains_wcard = path_contains_wcard ;
}
2009-06-19 00:13:38 +04:00
}
2009-07-24 23:13:07 +04:00
2009-08-19 11:58:38 +04:00
if ( is_fake_file_path ( name_in ) ) {
SMB_STRUCT_STAT st ;
ZERO_STRUCT ( st ) ;
st . st_ex_nlink = 1 ;
2013-04-12 13:49:19 +04:00
* pp_smb_fname = synthetic_smb_fname_split ( ctx ,
2016-03-10 03:00:47 +03:00
name_in ,
( ucf_flags & UCF_POSIX_PATHNAMES ) ) ;
2013-04-12 13:49:19 +04:00
if ( * pp_smb_fname = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2016-03-10 02:50:02 +03:00
( * pp_smb_fname ) - > st = st ;
2013-04-12 13:49:19 +04:00
return NT_STATUS_OK ;
2009-08-19 11:58:38 +04:00
}
2009-07-24 23:13:07 +04:00
/*
2009-07-25 05:38:40 +04:00
* If the caller conditionally allows wildcard lookups , only add the
* always allow if the path actually does contain a wildcard .
2009-07-24 23:13:07 +04:00
*/
2009-07-25 05:38:40 +04:00
if ( ucf_flags & UCF_COND_ALLOW_WCARD_LCOMP & &
ppath_contains_wcard ! = NULL & & * ppath_contains_wcard ) {
ucf_flags | = UCF_ALWAYS_ALLOW_WCARD_LCOMP ;
2009-07-24 23:13:07 +04:00
}
2017-05-18 21:36:56 +03:00
status = unix_convert ( ctx , conn , name_in , pp_smb_fname , ucf_flags ) ;
2009-06-19 00:13:38 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-02-25 02:12:05 +04:00
DEBUG ( 10 , ( " filename_convert_internal: unix_convert failed "
2009-06-19 00:13:38 +04:00
" for name %s with %s \n " ,
2017-05-18 21:36:56 +03:00
name_in ,
2009-06-19 00:13:38 +04:00
nt_errstr ( status ) ) ) ;
return status ;
}
2011-10-22 01:12:41 +04:00
if ( ( ucf_flags & UCF_UNIX_NAME_LOOKUP ) & &
VALID_STAT ( ( * pp_smb_fname ) - > st ) & &
S_ISLNK ( ( * pp_smb_fname ) - > st . st_ex_mode ) ) {
return check_veto_path ( conn , ( * pp_smb_fname ) - > base_name ) ;
}
2012-02-25 02:12:05 +04:00
if ( ! smbreq ) {
status = check_name ( conn , ( * pp_smb_fname ) - > base_name ) ;
} else {
status = check_name_with_privilege ( conn , smbreq , ( * pp_smb_fname ) - > base_name ) ;
}
2009-06-19 00:13:38 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-02-25 02:12:05 +04:00
DEBUG ( 3 , ( " filename_convert_internal: check_name failed "
2009-06-19 00:13:38 +04:00
" for name %s with %s \n " ,
2009-07-21 21:28:28 +04:00
smb_fname_str_dbg ( * pp_smb_fname ) ,
2009-06-19 00:13:38 +04:00
nt_errstr ( status ) ) ) ;
2009-07-21 21:28:28 +04:00
TALLOC_FREE ( * pp_smb_fname ) ;
2009-06-19 00:13:38 +04:00
return status ;
}
2009-07-02 03:14:40 +04:00
2009-06-19 00:13:38 +04:00
return status ;
}
2012-02-25 02:12:05 +04:00
/*
* Go through all the steps to validate a filename .
* Non - root version .
*/
NTSTATUS filename_convert ( TALLOC_CTX * ctx ,
connection_struct * conn ,
bool dfs_path ,
const char * name_in ,
uint32_t ucf_flags ,
bool * ppath_contains_wcard ,
struct smb_filename * * pp_smb_fname )
{
return filename_convert_internal ( ctx ,
conn ,
dfs_path ,
NULL ,
name_in ,
ucf_flags ,
ppath_contains_wcard ,
pp_smb_fname ) ;
}
/*
* Go through all the steps to validate a filename .
* root ( privileged ) version .
*/
NTSTATUS filename_convert_with_privilege ( TALLOC_CTX * ctx ,
connection_struct * conn ,
struct smb_request * smbreq ,
const char * name_in ,
uint32_t ucf_flags ,
bool * ppath_contains_wcard ,
struct smb_filename * * pp_smb_fname )
{
return filename_convert_internal ( ctx ,
conn ,
smbreq - > flags2 & FLAGS2_DFS_PATHNAMES ,
smbreq ,
name_in ,
ucf_flags ,
ppath_contains_wcard ,
pp_smb_fname ) ;
}