From 870435b9215901de59b651812f3af5af2bfad93a Mon Sep 17 00:00:00 2001 From: Hari Babu Date: Tue, 12 Feb 2019 17:55:53 +1100 Subject: [PATCH] New pg_basebackup -g option to control the group access permissions By default, pg_basebackup follows the backup file permissions same as source instance, but with this option, user can control the behavior. --group-mode = inherit (default) (same permissions are source instance) --group-mode = none (no group access permissions) --group-mode = group (group access permissions) The same applies to the database directory that is already present. To support group access permissions for the tar mode, the BASE BACKUP protocol is enhanced to support new option "GROUP_MODE" with options "none" and "group". These options will be sent to the server whenever user wants control the group access mode permissions other than default. --- doc/src/sgml/protocol.sgml | 13 +++- doc/src/sgml/ref/pg_basebackup.sgml | 48 ++++++++++++ src/backend/replication/basebackup.c | 46 +++++++++++ src/backend/replication/repl_gram.y | 8 +- src/backend/replication/repl_scanner.l | 1 + src/bin/pg_basebackup/pg_basebackup.c | 65 +++++++++++----- src/bin/pg_basebackup/streamutil.c | 53 +++++++------ src/bin/pg_basebackup/streamutil.h | 11 +++ src/bin/pg_basebackup/t/010_pg_basebackup.pl | 82 +++++++++++++++++++- 9 files changed, 284 insertions(+), 43 deletions(-) diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index b20f1690a7..c3611c53cf 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -2466,7 +2466,7 @@ The commands accepted in replication mode are: - BASE_BACKUP [ LABEL 'label' ] [ PROGRESS ] [ FAST ] [ WAL ] [ NOWAIT ] [ MAX_RATE rate ] [ TABLESPACE_MAP ] [ NOVERIFY_CHECKSUMS ] + BASE_BACKUP [ LABEL 'label' ] [ PROGRESS ] [ FAST ] [ WAL ] [ NOWAIT ] [ MAX_RATE rate ] [ TABLESPACE_MAP ] [ NOVERIFY_CHECKSUMS ] [ GROUP_MODE 'mode' ] BASE_BACKUP @@ -2576,6 +2576,17 @@ The commands accepted in replication mode are: + + + GROUP_MODE 'mode' + + + By default, the group access permissions will be same as source instance. If none is specified, + the backup files doesn't contains group access permissions. If group is specified, the backup + files should contains group access permissions. + + + diff --git a/doc/src/sgml/ref/pg_basebackup.sgml b/doc/src/sgml/ref/pg_basebackup.sgml index fc9e222f8d..89cf9895c8 100644 --- a/doc/src/sgml/ref/pg_basebackup.sgml +++ b/doc/src/sgml/ref/pg_basebackup.sgml @@ -536,6 +536,53 @@ PostgreSQL documentation + + + + + + + Controls the group permissions of the file in the backup. This option is ignored + on Windows as it does not support POSIX-style + group permissions. The following methods are available to control the group permissions: + + + + n + none + + + Don't include group access permissions in the backup. + + + + + + i + inherit + + + Follow the same access permissions of the source instance. + + + This value is the default. + + + + + + g + group + + + Include group access permissions for all the backup files. + + + + + + + @@ -742,6 +789,7 @@ PostgreSQL documentation or an older major version, down to 9.1. However, WAL streaming mode (-X stream) only works with server version 9.3 and later, and tar format mode (--format=tar) of the current version only works with server version 9.5 + or later. (-g) of the current version only works with server version 12 or later. diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c index c2978a949a..713c00d46d 100644 --- a/src/backend/replication/basebackup.c +++ b/src/backend/replication/basebackup.c @@ -54,6 +54,8 @@ typedef struct bool sendtblspcmapfile; } basebackup_options; +static int backup_dir_create_mode = 0; +static int backup_file_create_mode = 0; static int64 sendDir(const char *path, int basepathlen, bool sizeonly, List *tablespaces, bool sendtblspclinks); @@ -650,6 +652,7 @@ parse_basebackup_options(List *options, basebackup_options *opt) bool o_maxrate = false; bool o_tablespace_map = false; bool o_noverify_checksums = false; + bool o_group_mode = false; MemSet(opt, 0, sizeof(*opt)); foreach(lopt, options) @@ -738,6 +741,30 @@ parse_basebackup_options(List *options, basebackup_options *opt) noverify_checksums = true; o_noverify_checksums = true; } + else if (strcmp(defel->defname, "group_mode") == 0) + { + if (o_group_mode) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("duplicate option \"%s\"", defel->defname))); + + if (strcmp(strVal(defel->arg), "none") == 0) + { + backup_dir_create_mode = PG_DIR_MODE_OWNER; + backup_file_create_mode = PG_FILE_MODE_OWNER; + } + else if (strcmp(strVal(defel->arg), "group") == 0) + { + backup_dir_create_mode = PG_DIR_MODE_GROUP; + backup_file_create_mode = PG_FILE_MODE_GROUP; + } + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("Invalid option for group_mode \"%s\"", defel->defname))); + + o_group_mode = true; + } else elog(ERROR, "option \"%s\" not recognized", defel->defname); @@ -1602,6 +1629,25 @@ _tarWriteHeader(const char *filename, const char *linktarget, if (!sizeonly) { + /* + * Adjust the mode of the file according to the backup request, ignore + * it for tablespace links. + */ + if (!linktarget && backup_file_create_mode) + { + if (S_ISDIR(statbuf->st_mode)) + { + statbuf->st_mode &= ~(pg_dir_create_mode); + statbuf->st_mode |= backup_dir_create_mode; + } + else + { + statbuf->st_mode &= ~(pg_file_create_mode); + statbuf->st_mode |= backup_file_create_mode; + } + + } + rc = tarCreateHeader(h, filename, linktarget, statbuf->st_size, statbuf->st_mode, statbuf->st_uid, statbuf->st_gid, statbuf->st_mtime); diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y index c4e11cc4e8..44059e299b 100644 --- a/src/backend/replication/repl_gram.y +++ b/src/backend/replication/repl_gram.y @@ -78,6 +78,7 @@ static SQLCmd *make_sqlcmd(void); %token K_WAL %token K_TABLESPACE_MAP %token K_NOVERIFY_CHECKSUMS +%token K_GROUP_MODE %token K_TIMELINE %token K_PHYSICAL %token K_LOGICAL @@ -155,7 +156,7 @@ var_name: IDENT { $$ = $1; } /* * BASE_BACKUP [LABEL '