@ -36,6 +36,7 @@
# include <unistd.h>
# include <unistd.h>
# endif
# endif
# include "mb/pg_wchar.h"
# include "pg_config_paths.h"
# include "pg_config_paths.h"
@ -45,6 +46,10 @@
# define IS_PATH_VAR_SEP(ch) ((ch) == ';')
# define IS_PATH_VAR_SEP(ch) ((ch) == ';')
# endif
# endif
# ifdef WIN32
static void debackslash_path ( char * path , int encoding ) ;
static int pg_sjis_mblen ( const unsigned char * s ) ;
# endif
static void make_relative_path ( char * ret_path , const char * target_path ,
static void make_relative_path ( char * ret_path , const char * target_path ,
const char * bin_path , const char * my_exec_path ) ;
const char * bin_path , const char * my_exec_path ) ;
static char * trim_directory ( char * path ) ;
static char * trim_directory ( char * path ) ;
@ -149,10 +154,73 @@ last_dir_separator(const char *filename)
}
}
# ifdef WIN32
/*
* Convert ' \ ' to ' / ' within the given path , assuming the path
* is in the specified encoding .
*/
static void
debackslash_path ( char * path , int encoding )
{
char * p ;
/*
* Of the supported encodings , only Shift - JIS has multibyte characters
* that can include a byte equal to ' \ ' ( 0x5C ) . So rather than implement
* a fully encoding - aware conversion , we special - case SJIS . ( Invoking the
* general encoding - aware logic in wchar . c is impractical here for
* assorted reasons . )
*/
if ( encoding = = PG_SJIS )
{
for ( p = path ; * p ; p + = pg_sjis_mblen ( ( const unsigned char * ) p ) )
{
if ( * p = = ' \\ ' )
* p = ' / ' ;
}
}
else
{
for ( p = path ; * p ; p + + )
{
if ( * p = = ' \\ ' )
* p = ' / ' ;
}
}
}
/*
/*
* make_native_path - on WIN32 , change / to \ in the path
* SJIS character leng th
*
*
* This effectively undoes canonicalize_path .
* This must match the behavior of
* pg_encoding_mblen_bounded ( PG_SJIS , s )
* In particular , unlike the version of pg_sjis_mblen in src / common / wchar . c ,
* do not allow caller to accidentally step past end - of - string .
*/
static int
pg_sjis_mblen ( const unsigned char * s )
{
int len ;
if ( * s > = 0xa1 & & * s < = 0xdf )
len = 1 ; /* 1 byte kana? */
else if ( IS_HIGHBIT_SET ( * s ) & & s [ 1 ] ! = ' \0 ' )
len = 2 ; /* kanji? */
else
len = 1 ; /* should be ASCII */
return len ;
}
# endif /* WIN32 */
/*
* make_native_path - on WIN32 , change ' / ' to ' \ ' in the path
*
* This reverses the ' \ ' - to - ' / ' transformation of debackslash_path .
* We need not worry about encodings here , since ' / ' does not appear
* as a byte of a multibyte character in any supported encoding .
*
*
* This is required because WIN32 COPY is an internal CMD . EXE
* This is required because WIN32 COPY is an internal CMD . EXE
* command and doesn ' t process forward slashes in the same way
* command and doesn ' t process forward slashes in the same way
@ -182,13 +250,14 @@ make_native_path(char *filename)
* on Windows . We need them to use filenames without spaces , for which a
* on Windows . We need them to use filenames without spaces , for which a
* short filename is the safest equivalent , eg :
* short filename is the safest equivalent , eg :
* C : / Progra ~ 1 /
* C : / Progra ~ 1 /
*
* Presently , this is only used on paths that we can assume are in a
* server - safe encoding , so there ' s no need for an encoding - aware variant .
*/
*/
void
void
cleanup_path ( char * path )
cleanup_path ( char * path )
{
{
# ifdef WIN32
# ifdef WIN32
char * ptr ;
/*
/*
* GetShortPathName ( ) will fail if the path does not exist , or short names
* GetShortPathName ( ) will fail if the path does not exist , or short names
* are disabled on this file system . In both cases , we just return the
* are disabled on this file system . In both cases , we just return the
@ -198,11 +267,8 @@ cleanup_path(char *path)
GetShortPathName ( path , path , MAXPGPATH - 1 ) ;
GetShortPathName ( path , path , MAXPGPATH - 1 ) ;
/* Replace '\' with '/' */
/* Replace '\' with '/' */
for ( ptr = path ; * ptr ; ptr + + )
/* All server-safe encodings are alike here, so just use PG_SQL_ASCII */
{
debackslash_path ( path , PG_SQL_ASCII ) ;
if ( * ptr = = ' \\ ' )
* ptr = ' / ' ;
}
# endif
# endif
}
}
@ -253,6 +319,8 @@ typedef enum
} canonicalize_state ;
} canonicalize_state ;
/*
/*
* canonicalize_path ( )
*
* Clean up path by :
* Clean up path by :
* o make Win32 path use Unix slashes
* o make Win32 path use Unix slashes
* o remove trailing quote on Win32
* o remove trailing quote on Win32
@ -260,9 +328,20 @@ typedef enum
* o remove duplicate ( adjacent ) separators
* o remove duplicate ( adjacent ) separators
* o remove ' . ' ( unless path reduces to only ' . ' )
* o remove ' . ' ( unless path reduces to only ' . ' )
* o process ' . . ' ourselves , removing it if possible
* o process ' . . ' ourselves , removing it if possible
* Modifies path in - place .
*
* This comes in two variants : encoding - aware and not . The non - aware version
* is only safe to use on strings that are in a server - safe encoding .
*/
*/
void
void
canonicalize_path ( char * path )
canonicalize_path ( char * path )
{
/* All server-safe encodings are alike here, so just use PG_SQL_ASCII */
canonicalize_path_enc ( path , PG_SQL_ASCII ) ;
}
void
canonicalize_path_enc ( char * path , int encoding )
{
{
char * p ,
char * p ,
* to_p ;
* to_p ;
@ -278,17 +357,15 @@ canonicalize_path(char *path)
/*
/*
* The Windows command processor will accept suitably quoted paths with
* The Windows command processor will accept suitably quoted paths with
* forward slashes , but barfs badly with mixed forward and back slashes .
* forward slashes , but barfs badly with mixed forward and back slashes .
* Hence , start by converting all back slashes to forward slashes .
*/
*/
for ( p = path ; * p ; p + + )
debackslash_path ( path , encoding ) ;
{
if ( * p = = ' \\ ' )
* p = ' / ' ;
}
/*
/*
* In Win32 , if you do : prog . exe " a b " " \ c \ d \" the system will pass \ c \ d "
* In Win32 , if you do : prog . exe " a b " " \ c \ d \" the system will pass \ c \ d "
* as argv [ 2 ] , so trim off trailing quote .
* as argv [ 2 ] , so trim off trailing quote .
*/
*/
p = path + strlen ( path ) ;
if ( p > path & & * ( p - 1 ) = = ' " ' )
if ( p > path & & * ( p - 1 ) = = ' " ' )
* ( p - 1 ) = ' / ' ;
* ( p - 1 ) = ' / ' ;
# endif
# endif