Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ead629b

Browse files
committed
Issue 67: permission mask is not preserved by restore
1 parent 84c6fd4 commit ead629b

File tree

4 files changed

+159
-4
lines changed

4 files changed

+159
-4
lines changed

src/dir.c

+149-1
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,16 @@ pgFileComparePath(const void *f1, const void *f2)
340340
return strcmp(f1p->path, f2p->path);
341341
}
342342

343+
/* Compare two pgFile with their name in ascending order of ASCII code. */
344+
int
345+
pgFileCompareName(const void *f1, const void *f2)
346+
{
347+
pgFile *f1p = *(pgFile **)f1;
348+
pgFile *f2p = *(pgFile **)f2;
349+
350+
return strcmp(f1p->name, f2p->name);
351+
}
352+
343353
/*
344354
* Compare two pgFile with their path and external_dir_num
345355
* in ascending order of ASCII code.
@@ -1041,6 +1051,142 @@ opt_externaldir_map(ConfigOption *opt, const char *arg)
10411051
opt_path_map(opt, arg, &external_remap_list, "external directory");
10421052
}
10431053

1054+
/*
1055+
* Create backup directories from **backup_dir** to **data_dir**. Doesn't raise
1056+
* an error if target directories exist.
1057+
*
1058+
* If **extract_tablespaces** is true then try to extract tablespace data
1059+
* directories into their initial path using tablespace_map file.
1060+
*
1061+
* Enforce permissions from backup_content.control. The only
1062+
* problem now is with PGDATA itself, we must preserve PGDATA permissions
1063+
* somewhere.
1064+
*
1065+
* TODO: symlink handling. If user located symlink in PG_TBLSPC_DIR, it will
1066+
* be restored as directory.
1067+
*/
1068+
void
1069+
create_data_directories(parray *dest_files, const char *data_dir, const char *backup_dir,
1070+
bool extract_tablespaces, fio_location location)
1071+
{
1072+
int i;
1073+
parray *links = NULL;
1074+
mode_t pg_tablespace_mode;
1075+
char to_path[MAXPGPATH];
1076+
1077+
/* Ugly: get PG_TBLSPC_DIR pemission mask */
1078+
for (i = 0; i < parray_num(dest_files); i++)
1079+
{
1080+
pgFile *file = (pgFile *) parray_get(dest_files, i);
1081+
1082+
if (!S_ISDIR(file->mode))
1083+
continue;
1084+
1085+
if (strcmp(file->rel_path, PG_TBLSPC_DIR) == 0)
1086+
{
1087+
if (file->external_dir_num == 0)
1088+
{
1089+
pg_tablespace_mode = file->mode;
1090+
break;
1091+
}
1092+
}
1093+
}
1094+
1095+
/* get tablespace map */
1096+
if (extract_tablespaces)
1097+
{
1098+
links = parray_new();
1099+
read_tablespace_map(links, backup_dir);
1100+
/* Sort links by a link name */
1101+
parray_qsort(links, pgFileCompareName);
1102+
}
1103+
1104+
/* Fun part is that backup_content.control is from beginning
1105+
* of a backup, and tablespace_map is from the end
1106+
* of a backup.
1107+
* If we trust tablspace_map, we would have to we create first
1108+
* tablespaces from it, then the start creating directories and files
1109+
* from backup_content.
1110+
* The problem if that backup_content could contain files from
1111+
* deleted tablespaces and so would have to
1112+
* check every file and directory if it comes from tablespace,
1113+
* not presented in tablespace_map and skip it restoring if it
1114+
* is not.
1115+
* Trusting backup_content.control is safest way, there is no risk
1116+
* of not restoring something.
1117+
*/
1118+
1119+
elog(LOG, "Restore directories and symlinks...");
1120+
1121+
/* create directories */
1122+
for (i = 0; i < parray_num(dest_files); i++)
1123+
{
1124+
char parent_dir[MAXPGPATH];
1125+
pgFile *dir = (pgFile *) parray_get(dest_files, i);
1126+
1127+
if (!S_ISDIR(dir->mode))
1128+
continue;
1129+
1130+
/* skip external directory content */
1131+
if (dir->external_dir_num != 0)
1132+
continue;
1133+
1134+
/* tablespace_map exists */
1135+
if (links)
1136+
{
1137+
/* get parent dir of rel_path */
1138+
strncpy(parent_dir, dir->rel_path, MAXPGPATH);
1139+
get_parent_directory(parent_dir);
1140+
1141+
/* check if directory is actually link to tablespace */
1142+
if (strcmp(parent_dir, PG_TBLSPC_DIR) == 0)
1143+
{
1144+
/* this directory located in pg_tblspc
1145+
* check it against tablespace map
1146+
*/
1147+
pgFile **link = (pgFile **) parray_bsearch(links, dir, pgFileCompareName);
1148+
1149+
/* got match */
1150+
if (link)
1151+
{
1152+
const char *linked_path = get_tablespace_mapping((*link)->linked);
1153+
1154+
if (!is_absolute_path(linked_path))
1155+
elog(ERROR, "Tablespace directory is not an absolute path: %s\n",
1156+
linked_path);
1157+
1158+
join_path_components(to_path, data_dir, dir->rel_path);
1159+
1160+
elog(VERBOSE, "Create directory \"%s\" and symbolic link \"%s\"",
1161+
linked_path, to_path);
1162+
1163+
/* create tablespace directory */
1164+
fio_mkdir(linked_path, pg_tablespace_mode, location);
1165+
1166+
/* create link to linked_path */
1167+
if (fio_symlink(linked_path, to_path, location) < 0)
1168+
elog(ERROR, "Could not create symbolic link \"%s\": %s",
1169+
to_path, strerror(errno));
1170+
1171+
continue;
1172+
}
1173+
}
1174+
}
1175+
1176+
/* This is not symlink, create directory */
1177+
elog(INFO, "Create directory \"%s\"", dir->rel_path);
1178+
1179+
join_path_components(to_path, data_dir, dir->rel_path);
1180+
fio_mkdir(to_path, dir->mode, location);
1181+
}
1182+
1183+
if (extract_tablespaces)
1184+
{
1185+
parray_walk(links, pgFileFree);
1186+
parray_free(links);
1187+
}
1188+
}
1189+
10441190
/*
10451191
* Create backup directories from **backup_dir** to **data_dir**. Doesn't raise
10461192
* an error if target directories exist.
@@ -1049,7 +1195,7 @@ opt_externaldir_map(ConfigOption *opt, const char *arg)
10491195
* directories into their initial path using tablespace_map file.
10501196
*/
10511197
void
1052-
create_data_directories(const char *data_dir, const char *backup_dir,
1198+
create_data_directories_manual(const char *data_dir, const char *backup_dir,
10531199
bool extract_tablespaces, fio_location location)
10541200
{
10551201
parray *dirs,
@@ -1234,6 +1380,8 @@ read_tablespace_map(parray *files, const char *backup_dir)
12341380
file->path = pgut_malloc(strlen(link_name) + 1);
12351381
strcpy(file->path, link_name);
12361382

1383+
file->name = file->path;
1384+
12371385
file->linked = pgut_malloc(strlen(path) + 1);
12381386
strcpy(file->linked, path);
12391387

src/merge.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
255255
write_backup_status(to_backup, BACKUP_STATUS_MERGING);
256256
write_backup_status(from_backup, BACKUP_STATUS_MERGING);
257257

258-
create_data_directories(to_database_path, from_backup_path, false, FIO_BACKUP_HOST);
258+
create_data_directories(files, to_database_path, from_backup_path, false, FIO_BACKUP_HOST);
259259

260260
threads = (pthread_t *) palloc(sizeof(pthread_t) * num_threads);
261261
threads_args = (merge_files_arg *) palloc(sizeof(merge_files_arg) * num_threads);

src/pg_probackup.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -577,11 +577,17 @@ extern const char* deparse_compress_alg(int alg);
577577
extern void dir_list_file(parray *files, const char *root, bool exclude,
578578
bool omit_symlink, bool add_root, int external_dir_num, fio_location location);
579579

580-
extern void create_data_directories(const char *data_dir,
580+
extern void create_data_directories_manual(const char *data_dir,
581581
const char *backup_dir,
582582
bool extract_tablespaces,
583583
fio_location location);
584584

585+
extern void create_data_directories(parray *dest_files,
586+
const char *data_dir,
587+
const char *backup_dir,
588+
bool extract_tablespaces,
589+
fio_location location);
590+
585591
extern void read_tablespace_map(parray *files, const char *backup_dir);
586592
extern void opt_tablespace_map(ConfigOption *opt, const char *arg);
587593
extern void opt_externaldir_map(ConfigOption *opt, const char *arg);
@@ -614,6 +620,7 @@ extern void pgFileDelete(pgFile *file);
614620
extern void pgFileFree(void *file);
615621
extern pg_crc32 pgFileGetCRC(const char *file_path, bool use_crc32c,
616622
bool raise_on_deleted, size_t *bytes_read, fio_location location);
623+
extern int pgFileCompareName(const void *f1, const void *f2);
617624
extern int pgFileComparePath(const void *f1, const void *f2);
618625
extern int pgFileComparePathWithExternal(const void *f1, const void *f2);
619626
extern int pgFileCompareRelPathWithExternal(const void *f1, const void *f2);

src/restore.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
442442
*/
443443
pgBackupGetPath(dest_backup, dest_backup_path,
444444
lengthof(dest_backup_path), NULL);
445-
create_data_directories(instance_config.pgdata, dest_backup_path, true,
445+
create_data_directories(dest_files, instance_config.pgdata, dest_backup_path, true,
446446
FIO_DB_HOST);
447447

448448
/*

0 commit comments

Comments
 (0)