From d10e2eab346c34bf50b6be5865f8422159154371 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 | 66 +++++++++++----- src/bin/pg_basebackup/streamutil.c | 57 ++++++++------ src/bin/pg_basebackup/streamutil.h | 11 +++ src/bin/pg_basebackup/t/010_pg_basebackup.pl | 82 +++++++++++++++++++- 9 files changed, 288 insertions(+), 44 deletions(-) diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index d66b860cbd..9437c42256 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -2397,7 +2397,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 @@ -2507,6 +2507,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 c4f3950e5b..6b7a81c900 100644 --- a/doc/src/sgml/ref/pg_basebackup.sgml +++ b/doc/src/sgml/ref/pg_basebackup.sgml @@ -535,6 +535,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. + + + + + + + @@ -735,6 +782,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 537f09e342..23b7a05489 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 '