2015-12-13 18:32:52 +03:00
/*
* Unix SMB / CIFS implementation .
* Samba utility functions
* Copyright ( C ) Andrew Tridgell 1992 - 1998
* Copyright ( C ) Jeremy Allison 2001 - 2007
* Copyright ( C ) Simo Sorce 2001
* Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2003
* Copyright ( C ) James Peach 2006
*
* 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
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* 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 .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "replace.h"
# include <talloc.h>
# include "lib/util/samba_util.h"
# include "lib/util_path.h"
2019-10-15 17:52:30 +03:00
struct loadparm_substitution ;
2015-12-13 18:32:52 +03:00
struct share_params ;
# include "source3/param/param_proto.h"
/**
* @ brief Returns an absolute path to a file concatenating the provided
* @ a rootpath and @ a basename
*
* @ param name Filename , relative to @ a rootpath
*
* @ retval Pointer to a string containing the full path .
* */
2018-08-16 11:45:23 +03:00
static char * xx_path ( TALLOC_CTX * mem_ctx ,
const char * name ,
const char * rootpath )
2015-12-13 18:32:52 +03:00
{
char * fname = NULL ;
2018-08-16 11:45:23 +03:00
fname = talloc_strdup ( mem_ctx , rootpath ) ;
2015-12-13 18:32:52 +03:00
if ( ! fname ) {
return NULL ;
}
trim_string ( fname , " " , " / " ) ;
if ( ! directory_create_or_exist ( fname , 0755 ) ) {
return NULL ;
}
return talloc_asprintf_append ( fname , " /%s " , name ) ;
}
/**
* @ brief Returns an absolute path to a file in the Samba lock directory .
*
* @ param name File to find , relative to LOCKDIR .
*
* @ retval Pointer to a talloc ' ed string containing the full path .
* */
2018-08-16 11:51:44 +03:00
char * lock_path ( TALLOC_CTX * mem_ctx , const char * name )
2015-12-13 18:32:52 +03:00
{
2018-08-16 11:51:44 +03:00
return xx_path ( mem_ctx , name , lp_lock_directory ( ) ) ;
2015-12-13 18:32:52 +03:00
}
/**
* @ brief Returns an absolute path to a file in the Samba state directory .
*
* @ param name File to find , relative to STATEDIR .
*
* @ retval Pointer to a talloc ' ed string containing the full path .
* */
2018-08-16 11:51:44 +03:00
char * state_path ( TALLOC_CTX * mem_ctx , const char * name )
2015-12-13 18:32:52 +03:00
{
2018-08-16 11:51:44 +03:00
return xx_path ( mem_ctx , name , lp_state_directory ( ) ) ;
2015-12-13 18:32:52 +03:00
}
/**
* @ brief Returns an absolute path to a file in the Samba cache directory .
*
* @ param name File to find , relative to CACHEDIR .
*
* @ retval Pointer to a talloc ' ed string containing the full path .
* */
2018-08-16 11:51:44 +03:00
char * cache_path ( TALLOC_CTX * mem_ctx , const char * name )
2015-12-13 18:32:52 +03:00
{
2018-08-16 11:51:44 +03:00
return xx_path ( mem_ctx , name , lp_cache_directory ( ) ) ;
2015-12-13 18:32:52 +03:00
}
2017-01-17 22:33:18 +03:00
/**
* @ brief Removes any invalid path components in an absolute POSIX path .
*
* @ param ctx Talloc context to return string .
*
* @ param abs_path Absolute path string to process .
*
* @ retval Pointer to a talloc ' ed string containing the absolute full path .
* */
2020-04-21 23:24:44 +03:00
char * canonicalize_absolute_path ( TALLOC_CTX * ctx , const char * pathname_in )
{
/*
* Note we use + 2 here so if pathname_in = = " " then we
* have space to return " / " .
*/
char * pathname = talloc_array ( ctx , char , strlen ( pathname_in ) + 2 ) ;
const char * s = pathname_in ;
char * p = pathname ;
bool wrote_slash = false ;
if ( pathname = = NULL ) {
return NULL ;
}
/* Always start with a '/'. */
* p + + = ' / ' ;
wrote_slash = true ;
while ( * s ) {
/* Deal with '/' or multiples of '/'. */
if ( s [ 0 ] = = ' / ' ) {
while ( s [ 0 ] = = ' / ' ) {
/* Eat trailing '/' */
s + + ;
}
/* Update target with one '/' */
if ( ! wrote_slash ) {
* p + + = ' / ' ;
wrote_slash = true ;
}
continue ;
}
if ( wrote_slash ) {
/* Deal with "./" or ".\0" */
if ( s [ 0 ] = = ' . ' & &
( s [ 1 ] = = ' / ' | | s [ 1 ] = = ' \0 ' ) ) {
/* Eat the dot. */
s + + ;
while ( s [ 0 ] = = ' / ' ) {
/* Eat any trailing '/' */
s + + ;
}
/* Don't write anything to target. */
/* wrote_slash is still true. */
continue ;
}
/* Deal with "../" or "..\0" */
if ( s [ 0 ] = = ' . ' & & s [ 1 ] = = ' . ' & &
( s [ 2 ] = = ' / ' | | s [ 2 ] = = ' \0 ' ) ) {
/* Eat the dot dot. */
s + = 2 ;
while ( s [ 0 ] = = ' / ' ) {
/* Eat any trailing '/' */
s + + ;
}
/*
* As wrote_slash is true , we go back
* one character to point p at the slash
* we just saw .
*/
if ( p > pathname ) {
p - - ;
}
/*
* Now go back to the slash
* before the one that p currently points to .
*/
while ( p > pathname ) {
p - - ;
if ( p [ 0 ] = = ' / ' ) {
break ;
}
}
/*
* Step forward one to leave the
* last written ' / ' alone .
*/
p + + ;
/* Don't write anything to target. */
/* wrote_slash is still true. */
continue ;
}
}
/* Non-separator character, just copy. */
* p + + = * s + + ;
wrote_slash = false ;
}
if ( wrote_slash ) {
/*
* We finished on a ' / ' .
* Remove the trailing ' / ' , but not if it ' s
* the sole character in the path .
*/
if ( p > pathname + 1 ) {
p - - ;
}
}
/* Terminate and we're done ! */
* p + + = ' \0 ' ;
return pathname ;
}