Skip to content

Commit eaf3b14

Browse files
committed
fix set_forkname
Fork detection were broken before set_forkname extraction, and its bug were copied into. Lets reimplement it to be like `parse_filename_for_nonetemp_relation` in PostgreSQL code.
1 parent 0c7c78b commit eaf3b14

File tree

3 files changed

+72
-35
lines changed

3 files changed

+72
-35
lines changed

src/catalog.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,18 @@ get_backup_filelist(pgBackup *backup, bool strict)
11391139
file->uncompressed_size = write_size;
11401140

11411141
if (file->external_dir_num == 0)
1142+
{
1143+
bool is_datafile = file->is_datafile;
11421144
set_forkname(file);
1145+
if (is_datafile != file->is_datafile)
1146+
{
1147+
elog(WARNING, "File '%s' was stored as datafile, but looks like it is not",
1148+
file->rel_path);
1149+
/* Lets fail in tests */
1150+
Assert(file->is_datafile == file->is_datafile);
1151+
file->is_datafile = is_datafile;
1152+
}
1153+
}
11431154

11441155
parray_append(files, file);
11451156
}

src/dir.c

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -631,20 +631,6 @@ dir_check_file(pgFile *file, bool backup_logs)
631631

632632
if (file->forkName == ptrack) /* Compatibility with left-overs from ptrack1 */
633633
return CHECK_FALSE;
634-
else if (file->forkName != none)
635-
return CHECK_TRUE;
636-
637-
/* Set is_datafile flag */
638-
{
639-
char suffix[MAXFNAMELEN];
640-
641-
/* check if file is datafile */
642-
sscanf_res = sscanf(file->name, "%u.%d.%s", &(file->relOid),
643-
&(file->segno), suffix);
644-
Assert(sscanf_res > 0); /* since first char is digit */
645-
if (sscanf_res == 1 || sscanf_res == 2)
646-
file->is_datafile = true;
647-
}
648634
}
649635
}
650636

@@ -1789,34 +1775,74 @@ pfilearray_clear_locks(parray *file_list)
17891775
}
17901776
}
17911777

1778+
static inline bool
1779+
is_forkname(char *name, size_t *pos, const char *forkname)
1780+
{
1781+
size_t fnlen = strlen(forkname);
1782+
if (strncmp(name + *pos, forkname, fnlen) != 0)
1783+
return false;
1784+
*pos += fnlen;
1785+
return true;
1786+
}
1787+
1788+
#define OIDCHARS 10
1789+
17921790
/* Set forkName if possible */
1793-
void
1791+
bool
17941792
set_forkname(pgFile *file)
17951793
{
1796-
int name_len = strlen(file->name);
1797-
1798-
/* Auxiliary fork of the relfile */
1799-
if (name_len > 3 && strcmp(file->name + name_len - 3, "_vm") == 0)
1800-
file->forkName = vm;
1794+
size_t i = 0;
1795+
uint64_t oid = 0; /* use 64bit to not check for overflow in a loop */
18011796

1802-
else if (name_len > 4 && strcmp(file->name + name_len - 4, "_fsm") == 0)
1803-
file->forkName = fsm;
1797+
/* pretend it is not relation file */
1798+
file->relOid = 0;
1799+
file->forkName = none;
1800+
file->is_datafile = false;
18041801

1805-
else if (name_len > 4 && strcmp(file->name + name_len - 4, ".cfm") == 0)
1806-
file->forkName = cfm;
1802+
for (i = 0; isdigit(file->name[i]); i++)
1803+
{
1804+
if (i == 0 && file->name[i] == '0')
1805+
return false;
1806+
oid = oid * 10 + file->name[i] - '0';
1807+
}
1808+
if (i == 0 || i > OIDCHARS || oid > UINT32_MAX)
1809+
return false;
18071810

1808-
else if (name_len > 5 && strcmp(file->name + name_len - 5, "_init") == 0)
1811+
/* usual fork name */
1812+
/* /^\d+_(vm|fsm|init|ptrack)$/ */
1813+
if (is_forkname(file->name, &i, "_vm"))
1814+
file->forkName = vm;
1815+
else if (is_forkname(file->name, &i, "_fsm"))
1816+
file->forkName = fsm;
1817+
else if (is_forkname(file->name, &i, "_init"))
18091818
file->forkName = init;
1810-
1811-
else if (name_len > 7 && strcmp(file->name + name_len - 7, "_ptrack") == 0)
1819+
else if (is_forkname(file->name, &i, "_ptrack"))
18121820
file->forkName = ptrack;
18131821

1814-
// extract relOid for certain forks
1822+
/* segment number */
1823+
/* /^\d+(_(vm|fsm|init|ptrack))?\.\d+$/ */
1824+
if (file->name[i] == '.' && isdigit(file->name[i+1]))
1825+
{
1826+
for (i++; isdigit(file->name[i]); i++)
1827+
;
1828+
}
1829+
1830+
/* CFS "fork name" */
1831+
if (file->forkName == none &&
1832+
is_forkname(file->name, &i, ".cfm"))
1833+
{
1834+
/* /^\d+(\.\d+)?.cfm$/ */
1835+
file->forkName = cfm;
1836+
}
1837+
1838+
/* If there are excess characters, it is not relation file */
1839+
if (file->name[i] != 0)
1840+
{
1841+
file->forkName = none;
1842+
return false;
1843+
}
18151844

1816-
if ((file->forkName == vm ||
1817-
file->forkName == fsm ||
1818-
file->forkName == init ||
1819-
file->forkName == cfm) &&
1820-
(sscanf(file->name, "%u*", &(file->relOid)) != 1))
1821-
file->relOid = 0;
1845+
file->relOid = oid;
1846+
file->is_datafile = file->forkName == none;
1847+
return true;
18221848
}

src/pg_probackup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ extern int pgCompareString(const void *str1, const void *str2);
10981098
extern int pgPrefixCompareString(const void *str1, const void *str2);
10991099
extern int pgCompareOid(const void *f1, const void *f2);
11001100
extern void pfilearray_clear_locks(parray *file_list);
1101-
extern void set_forkname(pgFile *file);
1101+
extern bool set_forkname(pgFile *file);
11021102

11031103
/* in data.c */
11041104
extern bool check_data_file(ConnectionArgs *arguments, pgFile *file,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy