mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
Change struct tablespaceinfo's oid member from 'char *' to 'Oid'
This shouldn't change behavior except in the unusual case where there are file in the tablespace directory that have entirely numeric names but are nevertheless not possible names for a tablespace directory, either because their names have leading zeroes that shouldn't be there, or the value is actually zero, or because the value is too large to represent as an OID. In those cases, the directory would previously have made it into the list of tablespaceinfo objects and no longer will. Thus, base backups will now ignore such directories, instead of treating them as legitimate tablespace directories. Similarly, if entries for such tablespaces occur in a tablespace_map file, they will now be rejected as erroneous, instead of being honored. This is infrastructure for future work that wants to be able to know the tablespace of each relation that is part of a backup *as an OID*. By strengthening the up-front validation, we don't have to worry about weird cases later, and can more easily avoid repeated string->integer conversions. Patch by me, reviewed by David Steele. Discussion: http://postgr.es/m/CA+TgmoZNVeBzoqDL8xvr-nkaepq815jtDR4nJzPew7=3iEuM1g@mail.gmail.com
This commit is contained in:
@ -8579,9 +8579,22 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
|
|||||||
char *relpath = NULL;
|
char *relpath = NULL;
|
||||||
char *s;
|
char *s;
|
||||||
PGFileType de_type;
|
PGFileType de_type;
|
||||||
|
char *badp;
|
||||||
|
Oid tsoid;
|
||||||
|
|
||||||
/* Skip anything that doesn't look like a tablespace */
|
/*
|
||||||
if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
|
* Try to parse the directory name as an unsigned integer.
|
||||||
|
*
|
||||||
|
* Tablespace directories should be positive integers that can be
|
||||||
|
* represented in 32 bits, with no leading zeroes or trailing
|
||||||
|
* garbage. If we come across a name that doesn't meet those
|
||||||
|
* criteria, skip it.
|
||||||
|
*/
|
||||||
|
if (de->d_name[0] < '1' || de->d_name[1] > '9')
|
||||||
|
continue;
|
||||||
|
errno = 0;
|
||||||
|
tsoid = strtoul(de->d_name, &badp, 10);
|
||||||
|
if (*badp != '\0' || errno == EINVAL || errno == ERANGE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
|
snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
|
||||||
@ -8656,7 +8669,7 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ti = palloc(sizeof(tablespaceinfo));
|
ti = palloc(sizeof(tablespaceinfo));
|
||||||
ti->oid = pstrdup(de->d_name);
|
ti->oid = tsoid;
|
||||||
ti->path = pstrdup(linkpath);
|
ti->path = pstrdup(linkpath);
|
||||||
ti->rpath = relpath;
|
ti->rpath = relpath;
|
||||||
ti->size = -1;
|
ti->size = -1;
|
||||||
|
@ -678,7 +678,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
|
|||||||
tablespaceinfo *ti = lfirst(lc);
|
tablespaceinfo *ti = lfirst(lc);
|
||||||
char *linkloc;
|
char *linkloc;
|
||||||
|
|
||||||
linkloc = psprintf("pg_tblspc/%s", ti->oid);
|
linkloc = psprintf("pg_tblspc/%u", ti->oid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the existing symlink if any and Create the symlink
|
* Remove the existing symlink if any and Create the symlink
|
||||||
@ -692,7 +692,6 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
|
|||||||
errmsg("could not create symbolic link \"%s\": %m",
|
errmsg("could not create symbolic link \"%s\": %m",
|
||||||
linkloc)));
|
linkloc)));
|
||||||
|
|
||||||
pfree(ti->oid);
|
|
||||||
pfree(ti->path);
|
pfree(ti->path);
|
||||||
pfree(ti);
|
pfree(ti);
|
||||||
}
|
}
|
||||||
@ -1341,6 +1340,8 @@ read_tablespace_map(List **tablespaces)
|
|||||||
{
|
{
|
||||||
if (!was_backslash && (ch == '\n' || ch == '\r'))
|
if (!was_backslash && (ch == '\n' || ch == '\r'))
|
||||||
{
|
{
|
||||||
|
char *endp;
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
continue; /* \r immediately followed by \n */
|
continue; /* \r immediately followed by \n */
|
||||||
|
|
||||||
@ -1360,7 +1361,12 @@ read_tablespace_map(List **tablespaces)
|
|||||||
str[n++] = '\0';
|
str[n++] = '\0';
|
||||||
|
|
||||||
ti = palloc0(sizeof(tablespaceinfo));
|
ti = palloc0(sizeof(tablespaceinfo));
|
||||||
ti->oid = pstrdup(str);
|
errno = 0;
|
||||||
|
ti->oid = strtoul(str, &endp, 10);
|
||||||
|
if (*endp != '\0' || errno == EINVAL || errno == ERANGE)
|
||||||
|
ereport(FATAL,
|
||||||
|
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||||
|
errmsg("invalid data in file \"%s\"", TABLESPACE_MAP)));
|
||||||
ti->path = pstrdup(str + n);
|
ti->path = pstrdup(str + n);
|
||||||
*tablespaces = lappend(*tablespaces, ti);
|
*tablespaces = lappend(*tablespaces, ti);
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ FreeBackupManifest(backup_manifest_info *manifest)
|
|||||||
* Add an entry to the backup manifest for a file.
|
* Add an entry to the backup manifest for a file.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
AddFileToBackupManifest(backup_manifest_info *manifest, const char *spcoid,
|
AddFileToBackupManifest(backup_manifest_info *manifest, Oid spcoid,
|
||||||
const char *pathname, size_t size, pg_time_t mtime,
|
const char *pathname, size_t size, pg_time_t mtime,
|
||||||
pg_checksum_context *checksum_ctx)
|
pg_checksum_context *checksum_ctx)
|
||||||
{
|
{
|
||||||
@ -114,9 +114,9 @@ AddFileToBackupManifest(backup_manifest_info *manifest, const char *spcoid,
|
|||||||
* pathname relative to the data directory (ignoring the intermediate
|
* pathname relative to the data directory (ignoring the intermediate
|
||||||
* symlink traversal).
|
* symlink traversal).
|
||||||
*/
|
*/
|
||||||
if (spcoid != NULL)
|
if (OidIsValid(spcoid))
|
||||||
{
|
{
|
||||||
snprintf(pathbuf, sizeof(pathbuf), "pg_tblspc/%s/%s", spcoid,
|
snprintf(pathbuf, sizeof(pathbuf), "pg_tblspc/%u/%s", spcoid,
|
||||||
pathname);
|
pathname);
|
||||||
pathname = pathbuf;
|
pathname = pathbuf;
|
||||||
}
|
}
|
||||||
|
@ -75,14 +75,15 @@ typedef struct
|
|||||||
pg_checksum_type manifest_checksum_type;
|
pg_checksum_type manifest_checksum_type;
|
||||||
} basebackup_options;
|
} basebackup_options;
|
||||||
|
|
||||||
static int64 sendTablespace(bbsink *sink, char *path, char *spcoid, bool sizeonly,
|
static int64 sendTablespace(bbsink *sink, char *path, Oid spcoid, bool sizeonly,
|
||||||
struct backup_manifest_info *manifest);
|
struct backup_manifest_info *manifest);
|
||||||
static int64 sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
|
static int64 sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
|
||||||
List *tablespaces, bool sendtblspclinks,
|
List *tablespaces, bool sendtblspclinks,
|
||||||
backup_manifest_info *manifest, const char *spcoid);
|
backup_manifest_info *manifest, Oid spcoid);
|
||||||
static bool sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
|
static bool sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
|
||||||
struct stat *statbuf, bool missing_ok, Oid dboid,
|
struct stat *statbuf, bool missing_ok,
|
||||||
backup_manifest_info *manifest, const char *spcoid);
|
Oid dboid, Oid spcoid,
|
||||||
|
backup_manifest_info *manifest);
|
||||||
static off_t read_file_data_into_buffer(bbsink *sink,
|
static off_t read_file_data_into_buffer(bbsink *sink,
|
||||||
const char *readfilename, int fd,
|
const char *readfilename, int fd,
|
||||||
off_t offset, size_t length,
|
off_t offset, size_t length,
|
||||||
@ -305,7 +306,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
|
|||||||
|
|
||||||
if (tmp->path == NULL)
|
if (tmp->path == NULL)
|
||||||
tmp->size = sendDir(sink, ".", 1, true, state.tablespaces,
|
tmp->size = sendDir(sink, ".", 1, true, state.tablespaces,
|
||||||
true, NULL, NULL);
|
true, NULL, InvalidOid);
|
||||||
else
|
else
|
||||||
tmp->size = sendTablespace(sink, tmp->path, tmp->oid, true,
|
tmp->size = sendTablespace(sink, tmp->path, tmp->oid, true,
|
||||||
NULL);
|
NULL);
|
||||||
@ -346,7 +347,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
|
|||||||
|
|
||||||
/* Then the bulk of the files... */
|
/* Then the bulk of the files... */
|
||||||
sendDir(sink, ".", 1, false, state.tablespaces,
|
sendDir(sink, ".", 1, false, state.tablespaces,
|
||||||
sendtblspclinks, &manifest, NULL);
|
sendtblspclinks, &manifest, InvalidOid);
|
||||||
|
|
||||||
/* ... and pg_control after everything else. */
|
/* ... and pg_control after everything else. */
|
||||||
if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
|
if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
|
||||||
@ -355,11 +356,11 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
|
|||||||
errmsg("could not stat file \"%s\": %m",
|
errmsg("could not stat file \"%s\": %m",
|
||||||
XLOG_CONTROL_FILE)));
|
XLOG_CONTROL_FILE)));
|
||||||
sendFile(sink, XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf,
|
sendFile(sink, XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf,
|
||||||
false, InvalidOid, &manifest, NULL);
|
false, InvalidOid, InvalidOid, &manifest);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *archive_name = psprintf("%s.tar", ti->oid);
|
char *archive_name = psprintf("%u.tar", ti->oid);
|
||||||
|
|
||||||
bbsink_begin_archive(sink, archive_name);
|
bbsink_begin_archive(sink, archive_name);
|
||||||
|
|
||||||
@ -623,8 +624,8 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
|
|||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
errmsg("could not stat file \"%s\": %m", pathbuf)));
|
errmsg("could not stat file \"%s\": %m", pathbuf)));
|
||||||
|
|
||||||
sendFile(sink, pathbuf, pathbuf, &statbuf, false, InvalidOid,
|
sendFile(sink, pathbuf, pathbuf, &statbuf, false,
|
||||||
&manifest, NULL);
|
InvalidOid, InvalidOid, &manifest);
|
||||||
|
|
||||||
/* unconditionally mark file as archived */
|
/* unconditionally mark file as archived */
|
||||||
StatusFilePath(pathbuf, fname, ".done");
|
StatusFilePath(pathbuf, fname, ".done");
|
||||||
@ -1087,7 +1088,7 @@ sendFileWithContent(bbsink *sink, const char *filename, const char *content,
|
|||||||
|
|
||||||
_tarWritePadding(sink, len);
|
_tarWritePadding(sink, len);
|
||||||
|
|
||||||
AddFileToBackupManifest(manifest, NULL, filename, len,
|
AddFileToBackupManifest(manifest, InvalidOid, filename, len,
|
||||||
(pg_time_t) statbuf.st_mtime, &checksum_ctx);
|
(pg_time_t) statbuf.st_mtime, &checksum_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1099,7 +1100,7 @@ sendFileWithContent(bbsink *sink, const char *filename, const char *content,
|
|||||||
* Only used to send auxiliary tablespaces, not PGDATA.
|
* Only used to send auxiliary tablespaces, not PGDATA.
|
||||||
*/
|
*/
|
||||||
static int64
|
static int64
|
||||||
sendTablespace(bbsink *sink, char *path, char *spcoid, bool sizeonly,
|
sendTablespace(bbsink *sink, char *path, Oid spcoid, bool sizeonly,
|
||||||
backup_manifest_info *manifest)
|
backup_manifest_info *manifest)
|
||||||
{
|
{
|
||||||
int64 size;
|
int64 size;
|
||||||
@ -1154,7 +1155,7 @@ sendTablespace(bbsink *sink, char *path, char *spcoid, bool sizeonly,
|
|||||||
static int64
|
static int64
|
||||||
sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
|
sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
|
||||||
List *tablespaces, bool sendtblspclinks, backup_manifest_info *manifest,
|
List *tablespaces, bool sendtblspclinks, backup_manifest_info *manifest,
|
||||||
const char *spcoid)
|
Oid spcoid)
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *de;
|
struct dirent *de;
|
||||||
@ -1416,8 +1417,8 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
|
|||||||
|
|
||||||
if (!sizeonly)
|
if (!sizeonly)
|
||||||
sent = sendFile(sink, pathbuf, pathbuf + basepathlen + 1, &statbuf,
|
sent = sendFile(sink, pathbuf, pathbuf + basepathlen + 1, &statbuf,
|
||||||
true, isDbDir ? atooid(lastDir + 1) : InvalidOid,
|
true, isDbDir ? atooid(lastDir + 1) : InvalidOid, spcoid,
|
||||||
manifest, spcoid);
|
manifest);
|
||||||
|
|
||||||
if (sent || sizeonly)
|
if (sent || sizeonly)
|
||||||
{
|
{
|
||||||
@ -1486,8 +1487,8 @@ is_checksummed_file(const char *fullpath, const char *filename)
|
|||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
|
sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
|
||||||
struct stat *statbuf, bool missing_ok, Oid dboid,
|
struct stat *statbuf, bool missing_ok, Oid dboid, Oid spcoid,
|
||||||
backup_manifest_info *manifest, const char *spcoid)
|
backup_manifest_info *manifest)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
BlockNumber blkno = 0;
|
BlockNumber blkno = 0;
|
||||||
|
@ -407,7 +407,7 @@ SendTablespaceList(List *tablespaces)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
values[0] = ObjectIdGetDatum(strtoul(ti->oid, NULL, 10));
|
values[0] = ObjectIdGetDatum(ti->oid);
|
||||||
values[1] = CStringGetTextDatum(ti->path);
|
values[1] = CStringGetTextDatum(ti->path);
|
||||||
}
|
}
|
||||||
if (ti->size >= 0)
|
if (ti->size >= 0)
|
||||||
|
@ -39,7 +39,7 @@ extern void InitializeBackupManifest(backup_manifest_info *manifest,
|
|||||||
backup_manifest_option want_manifest,
|
backup_manifest_option want_manifest,
|
||||||
pg_checksum_type manifest_checksum_type);
|
pg_checksum_type manifest_checksum_type);
|
||||||
extern void AddFileToBackupManifest(backup_manifest_info *manifest,
|
extern void AddFileToBackupManifest(backup_manifest_info *manifest,
|
||||||
const char *spcoid,
|
Oid spcoid,
|
||||||
const char *pathname, size_t size,
|
const char *pathname, size_t size,
|
||||||
pg_time_t mtime,
|
pg_time_t mtime,
|
||||||
pg_checksum_context *checksum_ctx);
|
pg_checksum_context *checksum_ctx);
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char *oid; /* tablespace's OID, as a decimal string */
|
Oid oid; /* tablespace's OID */
|
||||||
char *path; /* full path to tablespace's directory */
|
char *path; /* full path to tablespace's directory */
|
||||||
char *rpath; /* relative path if it's within PGDATA, else
|
char *rpath; /* relative path if it's within PGDATA, else
|
||||||
* NULL */
|
* NULL */
|
||||||
|
Reference in New Issue
Block a user