@ -87,6 +87,7 @@
/* GUC variables */
char * default_tablespace = NULL ;
char * temp_tablespaces = NULL ;
bool allow_in_place_tablespaces = false ;
static void create_tablespace_directories ( const char * location ,
@ -241,6 +242,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
char * location ;
Oid ownerId ;
Datum newOptions ;
bool in_place ;
/* Must be superuser */
if ( ! superuser ( ) )
@ -266,12 +268,15 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
( errcode ( ERRCODE_INVALID_NAME ) ,
errmsg ( " tablespace location cannot contain single quotes " ) ) ) ;
in_place = allow_in_place_tablespaces & & strlen ( location ) = = 0 ;
/*
* Allowing relative paths seems risky
*
* this also helps us ensure that location is not empty or whitespace
* This also helps us ensure that location is not empty or whitespace ,
* unless specifying a developer - only in - place tablespace .
*/
if ( ! is_absolute_path ( location ) )
if ( ! in_place & & ! i s_absolute_path ( location ) )
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_OBJECT_DEFINITION ) ,
errmsg ( " tablespace location must be an absolute path " ) ) ) ;
@ -590,16 +595,36 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
char * linkloc ;
char * location_with_version_dir ;
struct stat st ;
bool in_place ;
linkloc = psprintf ( " pg_tblspc/%u " , tablespaceoid ) ;
location_with_version_dir = psprintf ( " %s/%s " , location ,
/*
* If we ' re asked to make an ' in place ' tablespace , create the directory
* directly where the symlink would normally go . This is a developer - only
* option for now , to facilitate regression testing .
*/
in_place = strlen ( location ) = = 0 ;
if ( in_place )
{
if ( MakePGDirectory ( linkloc ) < 0 & & errno ! = EEXIST )
ereport ( ERROR ,
( errcode_for_file_access ( ) ,
errmsg ( " could not create directory \" %s \" : %m " ,
linkloc ) ) ) ;
}
location_with_version_dir = psprintf ( " %s/%s " , in_place ? linkloc : location ,
TABLESPACE_VERSION_DIRECTORY ) ;
/*
* Attempt to coerce target directory to safe permissions . If this fails ,
* it doesn ' t exist or has the wrong owner .
* it doesn ' t exist or has the wrong owner . Not needed for in - place mode ,
* because in that case we created the directory with the desired
* permissions .
*/
if ( chmod ( location , pg_dir_create_mode ) ! = 0 )
if ( ! in_place & & chmod ( location , pg_dir_create_mode ) ! = 0 )
{
if ( errno = = ENOENT )
ereport ( ERROR ,
@ -648,13 +673,13 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
/*
* In recovery , remove old symlink , in case it points to the wrong place .
*/
if ( InRecovery )
if ( ! in_place & & InRecovery )
remove_tablespace_symlink ( linkloc ) ;
/*
* Create the symlink under PGDATA
*/
if ( symlink ( location , linkloc ) < 0 )
if ( ! in_place & & symlink ( location , linkloc ) < 0 )
ereport ( ERROR ,
( errcode_for_file_access ( ) ,
errmsg ( " could not create symbolic link \" %s \" : %m " ,