Switch pg_verify_checksums back to a blacklist
authorMichael Paquier
Fri, 30 Nov 2018 01:15:06 +0000 (10:15 +0900)
committerMichael Paquier
Fri, 30 Nov 2018 01:15:06 +0000 (10:15 +0900)
This basically reverts commit d55241af705667d4503638e3f77d3689fd6be31,
leaving around a portion of the regression tests still adapted with
empty relation files, and corrupted cases.  This is also proving to be
failing to check properly relation files located in a non-default
tablespace path.

Per discussion with various folks, including Stephen Frost, David
Steele, Andres Freund, Michael Banck and myself.

Reported-by: Michael Banck
Discussion: https://postgr.es/m/20181021134206[email protected]
Backpatch-through: 11

src/bin/pg_verify_checksums/pg_verify_checksums.c

index 36d11ab5638ba4bdf0375c435ae9443e221aef8e..589a3cc58988f2716041efa5519a608196824e4f 100644 (file)
@@ -15,7 +15,6 @@
 
 #include "catalog/pg_control.h"
 #include "common/controldata_utils.h"
-#include "common/relpath.h"
 #include "getopt_long.h"
 #include "pg_getopt.h"
 #include "storage/bufpage.h"
@@ -50,69 +49,27 @@ usage(void)
    printf(_("Report bugs to .\n"));
 }
 
-/*
- * isRelFileName
- *
- * Check if the given file name is authorized for checksum verification.
- */
+static const char *const skip[] = {
+   "pg_control",
+   "pg_filenode.map",
+   "pg_internal.init",
+   "PG_VERSION",
+   NULL,
+};
+
 static bool
-isRelFileName(const char *fn)
+skipfile(const char *fn)
 {
-   int         pos;
-
-   /*----------
-    * Only files including data checksums are authorized for verification.
-    * This is guessed based on the file name by reverse-engineering
-    * GetRelationPath() so make sure to update both code paths if any
-    * updates are done.  The following file name formats are allowed:
-    * 
-    * .
-    * _
-    * _.
-    *
-    * Note that temporary files, beginning with 't', are also skipped.
-    *
-    *----------
-    */
-
-   /* A non-empty string of digits should follow */
-   for (pos = 0; isdigit((unsigned char) fn[pos]); ++pos)
-       ;
-   /* leave if no digits */
-   if (pos == 0)
-       return false;
-   /* good to go if only digits */
-   if (fn[pos] == '\0')
-       return true;
-
-   /* Authorized fork files can be scanned */
-   if (fn[pos] == '_')
-   {
-       int         forkchar = forkname_chars(&fn[pos + 1], NULL);
-
-       if (forkchar <= 0)
-           return false;
+   const char *const *f;
 
-       pos += forkchar + 1;
-   }
-
-   /* Check for an optional segment number */
-   if (fn[pos] == '.')
-   {
-       int         segchar;
-
-       for (segchar = 1; isdigit((unsigned char) fn[pos + segchar]); ++segchar)
-           ;
-
-       if (segchar <= 1)
-           return false;
-       pos += segchar;
-   }
+   if (strcmp(fn, ".") == 0 ||
+       strcmp(fn, "..") == 0)
+       return true;
 
-   /* Now this should be the end */
-   if (fn[pos] != '\0')
-       return false;
-   return true;
+   for (f = skip; *f; f++)
+       if (strcmp(*f, fn) == 0)
+           return true;
+   return false;
 }
 
 static void
@@ -189,7 +146,7 @@ scan_directory(const char *basedir, const char *subdir)
        char        fn[MAXPGPATH];
        struct stat st;
 
-       if (!isRelFileName(de->d_name))
+       if (skipfile(de->d_name))
            continue;
 
        snprintf(fn, sizeof(fn), "%s/%s", path, de->d_name);