pg_waldump: Allow hexadecimal values for -t/--timeline option
authorPeter Eisentraut <peter@eisentraut.org>
Tue, 21 Mar 2023 07:01:12 +0000 (08:01 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Tue, 21 Mar 2023 07:05:23 +0000 (08:05 +0100)
This makes it easier to specify values taken directly from WAL file
names.

The option parsing is arranged in the style of option_parse_int() (but
we need to parse unsigned int), to allow future refactoring in the
same manner.

Reviewed-by: Sébastien Lardière <sebastien@lardiere.net>
Discussion: https://www.postgresql.org/message-id/flat/8fef346e-2541-76c3-d768-6536ae052993@lardiere.net

doc/src/sgml/ref/pg_waldump.sgml
src/bin/pg_waldump/pg_waldump.c

index 343f0482a9f6999c29f853634108ea6cac7a6c4e..7685d3d15b98ff8504fc96f75874a8e23f809aee 100644 (file)
@@ -215,7 +215,8 @@ PostgreSQL documentation
        <para>
         Timeline from which to read WAL records. The default is to use the
         value in <replaceable>startseg</replaceable>, if that is specified; otherwise, the
-        default is 1.
+        default is 1.  The value can be specified in decimal or hexadecimal,
+        for example <literal>17</literal> or <literal>0x11</literal>.
        </para>
       </listitem>
      </varlistentry>
index 44b5c8726e653d1e8378b8f5d27886e464722c92..8630000ef0b6c23a66d73415cbe7c3df20e4e4dc 100644 (file)
@@ -13,6 +13,7 @@
 #include "postgres.h"
 
 #include <dirent.h>
+#include <limits.h>
 #include <signal.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -1007,12 +1008,40 @@ main(int argc, char **argv)
                                        private.startptr = (uint64) xlogid << 32 | xrecoff;
                                break;
                        case 't':
-                               if (sscanf(optarg, "%u", &private.timeline) != 1)
+
+                               /*
+                                * This is like option_parse_int() but needs to handle
+                                * unsigned 32-bit int.  Also, we accept both decimal and
+                                * hexadecimal specifications here.
+                                */
                                {
-                                       pg_log_error("invalid timeline specification: \"%s\"", optarg);
-                                       goto bad_argument;
+                                       char       *endptr;
+                                       unsigned long val;
+
+                                       errno = 0;
+                                       val = strtoul(optarg, &endptr, 0);
+
+                                       while (*endptr != '\0' && isspace((unsigned char) *endptr))
+                                               endptr++;
+
+                                       if (*endptr != '\0')
+                                       {
+                                               pg_log_error("invalid value \"%s\" for option %s",
+                                                                        optarg, "-t/--timeline");
+                                               goto bad_argument;
+                                       }
+
+                                       if (errno == ERANGE || val < 1 || val > UINT_MAX)
+                                       {
+                                               pg_log_error("%s must be in range %u..%u",
+                                                                        "-t/--timeline", 1, UINT_MAX);
+                                               goto bad_argument;
+                                       }
+
+                                       private.timeline = val;
+
+                                       break;
                                }
-                               break;
                        case 'w':
                                config.filter_by_fpw = true;
                                break;