You've already forked pgbackrest
							
							
				mirror of
				https://github.com/pgbackrest/pgbackrest.git
				synced 2025-10-30 23:37:45 +02:00 
			
		
		
		
	More config parsing in C in preparation for all config parsing in C.
This commit is contained in:
		| @@ -83,14 +83,17 @@ sub buildConfigParse | ||||
|                 "${strOptionPrefix}${iOptionIdx}-" . substr($strOption, length($strOptionPrefix) + 1) : $strOption; | ||||
|  | ||||
|             # Generate option value used for parsing (offset is added so options don't conflict with getopt_long return values) | ||||
|             my $strOptionVal = 'PARSE_OPTION_OFFSET + ' . $strOptionEnum . ($iOptionIdx > 1 ? " + " . ($iOptionIdx - 1) : ''); | ||||
|             my $strOptionFlag = 'PARSE_OPTION_FLAG |'; | ||||
|  | ||||
|             my $strOptionVal = | ||||
|                 ($iOptionIdx > 1 ? "(" : '') . $strOptionEnum . ($iOptionIdx > 1 ? " + " . ($iOptionIdx - 1) . ')' : ''); | ||||
|  | ||||
|             # Add option | ||||
|             $strBuildSource .= | ||||
|                 "    {\n" . | ||||
|                 "        .name = \"${strOptionName}\",\n" . | ||||
|                 $strOptionArg . | ||||
|                 "        .val = ${strOptionVal},\n" . | ||||
|                 "        .val = ${strOptionFlag} ${strOptionVal},\n" . | ||||
|                 "    },\n"; | ||||
|  | ||||
|             # Add negation when defined | ||||
| @@ -99,7 +102,7 @@ sub buildConfigParse | ||||
|                 $strBuildSource .= | ||||
|                     "    {\n" . | ||||
|                     "        .name = \"no-${strOptionName}\",\n" . | ||||
|                     "        .val = ${strOptionVal},\n" . | ||||
|                     "        .val = ${strOptionFlag} PARSE_NEGATE_FLAG | ${strOptionVal},\n" . | ||||
|                     "    },\n"; | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -54,6 +54,10 @@ | ||||
|                     <release-item> | ||||
|                         <p>Replace <code>cfgCommandTotal()</code>/<code>cfgOptionTotal()</code> functions with constants.  The constants are applicable in more cases and allow the compiler to optimize certain loops more efficiently.</p> | ||||
|                     </release-item> | ||||
|  | ||||
|                     <release-item> | ||||
|                         <p>More config parsing in C in preparation for all config parsing in C.</p> | ||||
|                     </release-item> | ||||
|                 </release-development-list> | ||||
|             </release-core-list> | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| CC=gcc | ||||
| CFLAGS=-I. -Wfatal-errors -Wall -Wextra -Wwrite-strings -Wno-clobbered -std=c99 -funroll-loops -ftree-vectorize | ||||
| CFLAGS=-I. -Wfatal-errors -Wall -Wextra -Wwrite-strings -Wno-clobbered -std=c99 -O2 -funroll-loops -ftree-vectorize | ||||
| DESTDIR= | ||||
|  | ||||
| pgbackrest: \ | ||||
|   | ||||
| @@ -31,6 +31,7 @@ Define errors | ||||
| ERROR_DEFINE(ERROR_CODE_MIN, AssertError, RuntimeError); | ||||
|  | ||||
| ERROR_DEFINE(ERROR_CODE_MIN + 04, FormatError, RuntimeError); | ||||
| ERROR_DEFINE(ERROR_CODE_MIN + 05, CommandRequiredError, FormatError); | ||||
| ERROR_DEFINE(ERROR_CODE_MIN + 23, CommandInvalidError, FormatError); | ||||
| ERROR_DEFINE(ERROR_CODE_MIN + 31, OptionInvalidError, FormatError); | ||||
| ERROR_DEFINE(ERROR_CODE_MIN + 69, MemoryError, RuntimeError); | ||||
|   | ||||
| @@ -17,6 +17,7 @@ typedef struct ErrorType ErrorType; | ||||
| ERROR_DECLARE(AssertError); | ||||
|  | ||||
| ERROR_DECLARE(FormatError); | ||||
| ERROR_DECLARE(CommandRequiredError); | ||||
| ERROR_DECLARE(CommandInvalidError); | ||||
| ERROR_DECLARE(OptionInvalidError); | ||||
| ERROR_DECLARE(MemoryError); | ||||
|   | ||||
| @@ -11,778 +11,778 @@ static const struct option optionList[] = | ||||
| { | ||||
|     { | ||||
|         .name = "archive-async", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptArchiveAsync, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptArchiveAsync, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-archive-async", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptArchiveAsync, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptArchiveAsync, | ||||
|     }, | ||||
|     { | ||||
|         .name = "archive-check", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptArchiveCheck, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptArchiveCheck, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-archive-check", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptArchiveCheck, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptArchiveCheck, | ||||
|     }, | ||||
|     { | ||||
|         .name = "archive-copy", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptArchiveCopy, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptArchiveCopy, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-archive-copy", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptArchiveCopy, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptArchiveCopy, | ||||
|     }, | ||||
|     { | ||||
|         .name = "archive-queue-max", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptArchiveQueueMax, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptArchiveQueueMax, | ||||
|     }, | ||||
|     { | ||||
|         .name = "archive-timeout", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptArchiveTimeout, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptArchiveTimeout, | ||||
|     }, | ||||
|     { | ||||
|         .name = "backup-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptBackupCmd, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptBackupCmd, | ||||
|     }, | ||||
|     { | ||||
|         .name = "backup-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptBackupConfig, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptBackupConfig, | ||||
|     }, | ||||
|     { | ||||
|         .name = "backup-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptBackupHost, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptBackupHost, | ||||
|     }, | ||||
|     { | ||||
|         .name = "backup-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptBackupSshPort, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptBackupSshPort, | ||||
|     }, | ||||
|     { | ||||
|         .name = "backup-standby", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptBackupStandby, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptBackupStandby, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-backup-standby", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptBackupStandby, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptBackupStandby, | ||||
|     }, | ||||
|     { | ||||
|         .name = "backup-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptBackupUser, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptBackupUser, | ||||
|     }, | ||||
|     { | ||||
|         .name = "buffer-size", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptBufferSize, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptBufferSize, | ||||
|     }, | ||||
|     { | ||||
|         .name = "checksum-page", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptChecksumPage, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptChecksumPage, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-checksum-page", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptChecksumPage, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptChecksumPage, | ||||
|     }, | ||||
|     { | ||||
|         .name = "cmd-ssh", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptCmdSsh, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptCmdSsh, | ||||
|     }, | ||||
|     { | ||||
|         .name = "command", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptCommand, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptCommand, | ||||
|     }, | ||||
|     { | ||||
|         .name = "compress", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptCompress, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptCompress, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-compress", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptCompress, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptCompress, | ||||
|     }, | ||||
|     { | ||||
|         .name = "compress-level", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptCompressLevel, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptCompressLevel, | ||||
|     }, | ||||
|     { | ||||
|         .name = "compress-level-network", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptCompressLevelNetwork, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptCompressLevelNetwork, | ||||
|     }, | ||||
|     { | ||||
|         .name = "config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptConfig, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptConfig, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-config", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptConfig, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptConfig, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbCmd, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbCmd, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db1-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbCmd, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbCmd, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db2-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 1, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbCmd + 1), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db3-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 2, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbCmd + 2), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db4-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 3, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbCmd + 3), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db5-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 4, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbCmd + 4), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db6-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 5, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbCmd + 5), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db7-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 6, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbCmd + 6), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db8-cmd", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbCmd + 7, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbCmd + 7), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbConfig, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbConfig, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db1-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbConfig, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbConfig, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db2-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 1, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbConfig + 1), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db3-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 2, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbConfig + 2), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db4-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 3, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbConfig + 3), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db5-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 4, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbConfig + 4), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db6-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 5, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbConfig + 5), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db7-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 6, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbConfig + 6), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db8-config", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbConfig + 7, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbConfig + 7), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbHost, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbHost, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db1-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbHost, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbHost, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db2-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbHost + 1, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbHost + 1), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db3-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbHost + 2, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbHost + 2), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db4-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbHost + 3, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbHost + 3), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db5-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbHost + 4, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbHost + 4), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db6-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbHost + 5, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbHost + 5), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db7-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbHost + 6, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbHost + 6), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db8-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbHost + 7, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbHost + 7), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-include", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbInclude, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbInclude, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPath, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbPath, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db1-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPath, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbPath, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db2-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPath + 1, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPath + 1), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db3-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPath + 2, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPath + 2), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db4-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPath + 3, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPath + 3), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db5-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPath + 4, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPath + 4), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db6-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPath + 5, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPath + 5), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db7-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPath + 6, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPath + 6), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db8-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPath + 7, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPath + 7), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPort, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbPort, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db1-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPort, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbPort, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db2-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPort + 1, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPort + 1), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db3-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPort + 2, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPort + 2), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db4-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPort + 3, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPort + 3), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db5-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPort + 4, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPort + 4), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db6-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPort + 5, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPort + 5), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db7-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPort + 6, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPort + 6), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db8-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbPort + 7, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbPort + 7), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-socket-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbSocketPath, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db1-socket-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbSocketPath, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db2-socket-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 1, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSocketPath + 1), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db3-socket-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 2, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSocketPath + 2), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db4-socket-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 3, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSocketPath + 3), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db5-socket-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 4, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSocketPath + 4), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db6-socket-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 5, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSocketPath + 5), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db7-socket-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 6, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSocketPath + 6), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db8-socket-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSocketPath + 7, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSocketPath + 7), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSshPort, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbSshPort, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db1-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSshPort, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbSshPort, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db2-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 1, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSshPort + 1), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db3-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 2, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSshPort + 2), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db4-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 3, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSshPort + 3), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db5-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 4, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSshPort + 4), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db6-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 5, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSshPort + 5), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db7-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 6, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSshPort + 6), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db8-ssh-port", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbSshPort + 7, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbSshPort + 7), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-timeout", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbTimeout, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbTimeout, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbUser, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbUser, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db1-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbUser, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDbUser, | ||||
|     }, | ||||
|     { | ||||
|         .name = "db2-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbUser + 1, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbUser + 1), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db3-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbUser + 2, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbUser + 2), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db4-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbUser + 3, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbUser + 3), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db5-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbUser + 4, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbUser + 4), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db6-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbUser + 5, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbUser + 5), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db7-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbUser + 6, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbUser + 6), | ||||
|     }, | ||||
|     { | ||||
|         .name = "db8-user", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDbUser + 7, | ||||
|         .val = PARSE_OPTION_FLAG | (cfgOptDbUser + 7), | ||||
|     }, | ||||
|     { | ||||
|         .name = "delta", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptDelta, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptDelta, | ||||
|     }, | ||||
|     { | ||||
|         .name = "force", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptForce, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptForce, | ||||
|     }, | ||||
|     { | ||||
|         .name = "hardlink", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptHardlink, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptHardlink, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-hardlink", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptHardlink, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptHardlink, | ||||
|     }, | ||||
|     { | ||||
|         .name = "host-id", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptHostId, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptHostId, | ||||
|     }, | ||||
|     { | ||||
|         .name = "link-all", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLinkAll, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptLinkAll, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-link-all", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLinkAll, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptLinkAll, | ||||
|     }, | ||||
|     { | ||||
|         .name = "link-map", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLinkMap, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptLinkMap, | ||||
|     }, | ||||
|     { | ||||
|         .name = "lock-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLockPath, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptLockPath, | ||||
|     }, | ||||
|     { | ||||
|         .name = "log-level-console", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLogLevelConsole, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptLogLevelConsole, | ||||
|     }, | ||||
|     { | ||||
|         .name = "log-level-file", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLogLevelFile, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptLogLevelFile, | ||||
|     }, | ||||
|     { | ||||
|         .name = "log-level-stderr", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLogLevelStderr, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptLogLevelStderr, | ||||
|     }, | ||||
|     { | ||||
|         .name = "log-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLogPath, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptLogPath, | ||||
|     }, | ||||
|     { | ||||
|         .name = "log-timestamp", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLogTimestamp, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptLogTimestamp, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-log-timestamp", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptLogTimestamp, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptLogTimestamp, | ||||
|     }, | ||||
|     { | ||||
|         .name = "manifest-save-threshold", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptManifestSaveThreshold, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptManifestSaveThreshold, | ||||
|     }, | ||||
|     { | ||||
|         .name = "neutral-umask", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptNeutralUmask, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptNeutralUmask, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-neutral-umask", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptNeutralUmask, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptNeutralUmask, | ||||
|     }, | ||||
|     { | ||||
|         .name = "online", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptOnline, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptOnline, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-online", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptOnline, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptOnline, | ||||
|     }, | ||||
|     { | ||||
|         .name = "output", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptOutput, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptOutput, | ||||
|     }, | ||||
|     { | ||||
|         .name = "process", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptProcess, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptProcess, | ||||
|     }, | ||||
|     { | ||||
|         .name = "process-max", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptProcessMax, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptProcessMax, | ||||
|     }, | ||||
|     { | ||||
|         .name = "protocol-timeout", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptProtocolTimeout, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptProtocolTimeout, | ||||
|     }, | ||||
|     { | ||||
|         .name = "recovery-option", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRecoveryOption, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRecoveryOption, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-cipher-pass", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoCipherPass, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoCipherPass, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-cipher-type", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoCipherType, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoCipherType, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoPath, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoPath, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-s3-bucket", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3Bucket, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoS3Bucket, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-s3-ca-file", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3CaFile, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoS3CaFile, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-s3-ca-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3CaPath, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoS3CaPath, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-s3-endpoint", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3Endpoint, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoS3Endpoint, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-s3-host", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3Host, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoS3Host, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-s3-key", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3Key, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoS3Key, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-s3-key-secret", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3KeySecret, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoS3KeySecret, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-s3-region", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3Region, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoS3Region, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-s3-verify-ssl", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3VerifySsl, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoS3VerifySsl, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-repo-s3-verify-ssl", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoS3VerifySsl, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptRepoS3VerifySsl, | ||||
|     }, | ||||
|     { | ||||
|         .name = "repo-type", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRepoType, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRepoType, | ||||
|     }, | ||||
|     { | ||||
|         .name = "resume", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptResume, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptResume, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-resume", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptResume, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptResume, | ||||
|     }, | ||||
|     { | ||||
|         .name = "retention-archive", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRetentionArchive, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRetentionArchive, | ||||
|     }, | ||||
|     { | ||||
|         .name = "retention-archive-type", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRetentionArchiveType, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRetentionArchiveType, | ||||
|     }, | ||||
|     { | ||||
|         .name = "retention-diff", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRetentionDiff, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRetentionDiff, | ||||
|     }, | ||||
|     { | ||||
|         .name = "retention-full", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptRetentionFull, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptRetentionFull, | ||||
|     }, | ||||
|     { | ||||
|         .name = "set", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptSet, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptSet, | ||||
|     }, | ||||
|     { | ||||
|         .name = "spool-path", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptSpoolPath, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptSpoolPath, | ||||
|     }, | ||||
|     { | ||||
|         .name = "stanza", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptStanza, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptStanza, | ||||
|     }, | ||||
|     { | ||||
|         .name = "start-fast", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptStartFast, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptStartFast, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-start-fast", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptStartFast, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptStartFast, | ||||
|     }, | ||||
|     { | ||||
|         .name = "stop-auto", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptStopAuto, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptStopAuto, | ||||
|     }, | ||||
|     { | ||||
|         .name = "no-stop-auto", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptStopAuto, | ||||
|         .val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptStopAuto, | ||||
|     }, | ||||
|     { | ||||
|         .name = "tablespace-map", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptTablespaceMap, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptTablespaceMap, | ||||
|     }, | ||||
|     { | ||||
|         .name = "tablespace-map-all", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptTablespaceMapAll, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptTablespaceMapAll, | ||||
|     }, | ||||
|     { | ||||
|         .name = "target", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptTarget, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptTarget, | ||||
|     }, | ||||
|     { | ||||
|         .name = "target-action", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptTargetAction, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptTargetAction, | ||||
|     }, | ||||
|     { | ||||
|         .name = "target-exclusive", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptTargetExclusive, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptTargetExclusive, | ||||
|     }, | ||||
|     { | ||||
|         .name = "target-timeline", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptTargetTimeline, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptTargetTimeline, | ||||
|     }, | ||||
|     { | ||||
|         .name = "test", | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptTest, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptTest, | ||||
|     }, | ||||
|     { | ||||
|         .name = "test-delay", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptTestDelay, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptTestDelay, | ||||
|     }, | ||||
|     { | ||||
|         .name = "test-point", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptTestPoint, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptTestPoint, | ||||
|     }, | ||||
|     { | ||||
|         .name = "type", | ||||
|         .has_arg = required_argument, | ||||
|         .val = PARSE_OPTION_OFFSET + cfgOptType, | ||||
|         .val = PARSE_OPTION_FLAG | cfgOptType, | ||||
|     }, | ||||
|     // Perl option is ignored by normal config parsing | ||||
|     { | ||||
|   | ||||
| @@ -1,26 +1,40 @@ | ||||
| /*********************************************************************************************************************************** | ||||
| Command and Option Configuration | ||||
| Command and Option Parse | ||||
| ***********************************************************************************************************************************/ | ||||
| #include <assert.h> | ||||
| #include <getopt.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "common/error.h" | ||||
| #include "config/config.h" | ||||
| #include "common/memContext.h" | ||||
| #include "config/parse.h" | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Include the automatically generated configuration data | ||||
| ***********************************************************************************************************************************/ | ||||
| // Offset the option values so they don't conflict with getopt_long return codes | ||||
| #define PARSE_OPTION_OFFSET                                         100000 | ||||
| #define PARSE_OPTION_FLAG                                         (1 << 31) | ||||
|  | ||||
| // Add a flag for negation rather than checking "-no-" | ||||
| #define PARSE_NEGATE_FLAG                                         (1 << 30) | ||||
|  | ||||
| // Mask to exclude all flags and get at the actual option id (only 12 bits allowed for option id, the rest reserved for flags) | ||||
| #define PARSE_OPTION_MASK                                         0xFFF | ||||
|  | ||||
| #include "parse.auto.c" | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Map command names to ids and vice versa | ||||
| Parse the command-line arguments and produce preliminary parse data | ||||
|  | ||||
| This function only checks for obvious errors.  Dependencies, types, etc, are checked later when data from the config file is | ||||
| available. | ||||
| ***********************************************************************************************************************************/ | ||||
| void | ||||
| configParse(int argListSize, const char *argList[]) | ||||
| ParseData * | ||||
| configParseArg(int argListSize, const char *argList[]) | ||||
| { | ||||
|     // Allocate memory for the parse data | ||||
|     ParseData *parseData = memNew(sizeof(ParseData)); | ||||
|  | ||||
|     // Reset optind to 1 in case getopt_long has been called before | ||||
|     optind = 1; | ||||
|  | ||||
| @@ -31,26 +45,33 @@ configParse(int argListSize, const char *argList[]) | ||||
|     bool commandSet = false; | ||||
|  | ||||
|     // Parse options | ||||
|     int option; | ||||
|     int optionIdx; | ||||
|     int option;                                                     // Code returned by getopt_long | ||||
|     int optionListIdx;                                              // Index of option is list (if an option was returned) | ||||
|     ConfigOption optionId;                                          // Option id extracted from option var | ||||
|     bool negate;                                                    // Option is being negated | ||||
|     bool argFound = false;                                          // Track args found to decide on error or help at the end | ||||
|  | ||||
|     while ((option = getopt_long(argListSize, (char **)argList, "-", optionList, &optionIdx)) != -1) | ||||
|     while ((option = getopt_long(argListSize, (char **)argList, "-:", optionList, &optionListIdx)) != -1) | ||||
|     { | ||||
|         switch (option) | ||||
|         { | ||||
|             // Perl options that should be ignored | ||||
|             // Add perl options (if any) to the list | ||||
|             case 0: | ||||
|                 if (parseData->perlOptionList == NULL) | ||||
|                     parseData->perlOptionList = strLstNew(); | ||||
|  | ||||
|                 strLstAdd(parseData->perlOptionList, strNew(optarg)); | ||||
|                 break; | ||||
|  | ||||
|             // Parse parameters that are not options, i.e. commands and parameters passed to commands | ||||
|             // Parse arguments that are not options, i.e. commands and parameters passed to commands | ||||
|             case 1: | ||||
|                 // The first parameter should be the command | ||||
|                 // The first argument should be the command | ||||
|                 if (!commandSet) | ||||
|                 { | ||||
|                     // Try getting the command from the valid command list | ||||
|                     TRY_BEGIN() | ||||
|                     { | ||||
|                         cfgCommandSet(cfgCommandId(argList[optind - 1])); | ||||
|                         parseData->command = cfgCommandId(argList[optind - 1]); | ||||
|                     } | ||||
|                     // Assert error means the command does not exist, which is correct for all usages but this one (since we don't | ||||
|                     // have any control over what the user passes), so modify the error code and message. | ||||
| @@ -60,19 +81,103 @@ configParse(int argListSize, const char *argList[]) | ||||
|                     } | ||||
|                     TRY_END(); | ||||
|                 } | ||||
|                 // Else implement additional parameters here for more complex commands | ||||
|                 // Additioal arguments are command arguments | ||||
|                 else | ||||
|                 { | ||||
|                     if (parseData->commandArgList == NULL) | ||||
|                         parseData->commandArgList = strLstNew(); | ||||
|  | ||||
|                     strLstAdd(parseData->commandArgList, strNew(argList[optind - 1])); | ||||
|                 } | ||||
|  | ||||
|                 commandSet = true; | ||||
|                 break; | ||||
|  | ||||
|             // If the option is unknown generate an error | ||||
|             // If the option is unknown then error | ||||
|             case '?': | ||||
|                 THROW(OptionInvalidError, "invalid option '%s'", argList[optind - 1]); | ||||
|                 break;                                              // {uncoverable - case statement does not return} | ||||
|  | ||||
|             // If the option is missing an argument then error | ||||
|             case ':': | ||||
|                 THROW(OptionInvalidError, "option '%s' requires argument", argList[optind - 1]); | ||||
|                 break;                                              // {uncoverable - case statement does not return} | ||||
|  | ||||
|             // Parse valid option | ||||
|             default: | ||||
|                 // Get option id and flags from the option code | ||||
|                 optionId = option & PARSE_OPTION_MASK; | ||||
|                 negate = option & PARSE_NEGATE_FLAG; | ||||
|  | ||||
|                 // Make sure the option id is valid | ||||
|                 assert(optionId < CFG_OPTION_TOTAL); | ||||
|  | ||||
|                 // If the the option has not been found yet then set it | ||||
|                 if (!parseData->parseOptionList[optionId].found) | ||||
|                 { | ||||
|                     parseData->parseOptionList[optionId].found = true; | ||||
|                     parseData->parseOptionList[optionId].negate = negate; | ||||
|  | ||||
|                     // Only set the argument if the option requires one | ||||
|                     if (optionList[optionListIdx].has_arg == required_argument) | ||||
|                         parseData->parseOptionList[optionId].valueList = strLstAdd(strLstNew(), strNew(optarg)); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // Make sure option is not negated more than once.  It probably wouldn't hurt anything to accept this case but | ||||
|                     // there's no point in allowing the user to be sloppy. | ||||
|                     if (parseData->parseOptionList[optionId].negate && negate) | ||||
|                         THROW(OptionInvalidError, "option '%s' is negated multiple times", cfgOptionName(optionId)); | ||||
|  | ||||
|                     // Don't allow an option to be both set and negated | ||||
|                     if (parseData->parseOptionList[optionId].negate != negate) | ||||
|                         THROW(OptionInvalidError, "option '%s' cannot be set and negated", cfgOptionName(optionId)); | ||||
|  | ||||
|                     // Error if this option does not allow multiple arguments (!!! IMPLEMENT THIS IN DEFINE.C) | ||||
|                     if (!(cfgDefOptionType(cfgOptionDefIdFromId(optionId)) == cfgDefOptTypeHash || | ||||
|                           cfgDefOptionType(cfgOptionDefIdFromId(optionId)) == cfgDefOptTypeList)) | ||||
|                     { | ||||
|                         THROW(OptionInvalidError, "option '%s' cannot have multiple arguments", cfgOptionName(optionId)); | ||||
|                     } | ||||
|  | ||||
|                     // Add the argument | ||||
|                     strLstAdd(parseData->parseOptionList[optionId].valueList, strNew(optarg)); | ||||
|                 } | ||||
|  | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         // Arg has been found | ||||
|         argFound = true; | ||||
|     } | ||||
|  | ||||
|     // Handle command not found | ||||
|     if (!commandSet) | ||||
|     { | ||||
|         // If there are args then error | ||||
|         if (argFound) | ||||
|             THROW(CommandRequiredError, "no command found"); | ||||
|  | ||||
|         // Otherwise set the comand to help | ||||
|         parseData->command = cfgCmdHelp; | ||||
|     } | ||||
|  | ||||
|     // Return the parse data | ||||
|     return parseData; | ||||
| } | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Parse the command-line arguments and config file to produce final config data | ||||
| ***********************************************************************************************************************************/ | ||||
| void | ||||
| configParse(int argListSize, const char *argList[]) | ||||
| { | ||||
|     // Parse the command line | ||||
|     ParseData *parseData = configParseArg(argListSize, argList); | ||||
|  | ||||
|     // Set the command | ||||
|     cfgCommandSet(parseData->command); | ||||
|  | ||||
|     // Free the parse data | ||||
|     memFree(parseData); | ||||
| } | ||||
|   | ||||
| @@ -4,9 +4,34 @@ Parse Configuration | ||||
| #ifndef CONFIG_PARSE_H | ||||
| #define CONFIG_PARSE_H | ||||
|  | ||||
| #include "config/config.h" | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Struct to hold options parsed from the command line (??? move back to parse.c once perl exec works on full config data) | ||||
| ***********************************************************************************************************************************/ | ||||
| typedef struct ParseOption | ||||
| { | ||||
|     bool found:1;                                                   // Was the option found on the command line? | ||||
|     bool negate:1;                                                  // Was the option negated on the command line? | ||||
|     StringList *valueList;                                          // List of values found | ||||
| } ParseOption; | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Struct to hold all parsed data  (??? move back to parse.c once perl exec works on full config data) | ||||
| ***********************************************************************************************************************************/ | ||||
| typedef struct ParseData | ||||
| { | ||||
|     ConfigCommand command;                                          // Command found | ||||
|     StringList *perlOptionList;                                     // List of perl options | ||||
|     StringList *commandArgList;                                     // List of command arguments | ||||
|     ParseOption parseOptionList[CFG_OPTION_TOTAL];               // List of parsed options | ||||
| } ParseData; | ||||
|  | ||||
| ParseData *configParseArg(int argListSize, const char *argList[]); | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Functions | ||||
| ***********************************************************************************************************************************/ | ||||
| void configParse(int argListSize, char *argList[]); | ||||
| void configParse(int argListSize, const char *argList[]); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -10,7 +10,7 @@ Main | ||||
| #include "perl/exec.h" | ||||
| #include "version.h" | ||||
|  | ||||
| int main(int argListSize, char *argList[]) | ||||
| int main(int argListSize, const char *argList[]) | ||||
| { | ||||
|     TRY_BEGIN() | ||||
|     { | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| Execute Perl for Legacy Functionality | ||||
| ***********************************************************************************************************************************/ | ||||
| #include <errno.h> | ||||
| #include <getopt.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| @@ -12,6 +11,7 @@ Execute Perl for Legacy Functionality | ||||
| #include "common/error.h" | ||||
| #include "common/memContext.h" | ||||
| #include "common/type.h" | ||||
| #include "config/parse.h" | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Constants used to build perl options | ||||
| @@ -20,7 +20,6 @@ Constants used to build perl options | ||||
| #define ENV_EXE                                                     "/usr/bin/env" | ||||
|  | ||||
| #define PARAM_PERL_OPTION                                           "perl-option" | ||||
| #define PARAM_PERL_OPTION_ID                                        1000 | ||||
|  | ||||
| #define PGBACKREST_MODULE                                           PGBACKREST_NAME "::Main" | ||||
| #define PGBACKREST_MAIN                                             PGBACKREST_MODULE "::main" | ||||
| @@ -28,65 +27,71 @@ Constants used to build perl options | ||||
| /*********************************************************************************************************************************** | ||||
| Build list of perl options to use for exec | ||||
| ***********************************************************************************************************************************/ | ||||
| StringList *perlCommand(int argListSize, char *argList[]) | ||||
| StringList *perlCommand(int argListSize, const char *argList[]) | ||||
| { | ||||
|     // Setup arg list for perl exec | ||||
|     ParseData *parseData = configParseArg(argListSize, argList); | ||||
|  | ||||
|     // Begin arg list for perl exec | ||||
|     StringList *perlArgList = strLstNew(); | ||||
|     strLstAdd(perlArgList, strNew(ENV_EXE)); | ||||
|     strLstAdd(perlArgList, strNew(PERL_EXE)); | ||||
|  | ||||
|     // Setup Perl main call | ||||
|     String *mainParamBuffer = strNew(""); | ||||
|     // Construct option list to pass to main | ||||
|     String *mainCallParam = strNew(""); | ||||
|  | ||||
|     // Setup pgbackrest bin | ||||
|     String *binParamBuffer = strNew(""); | ||||
|  | ||||
|     // Reset optind to 1 in case getopt_long has been called before | ||||
|     optind = 1; | ||||
|  | ||||
|     // Don't error on unknown options -- they are expected since we are passing options through to Perl | ||||
|     opterr = false; | ||||
|  | ||||
|     // Struct with all valid options | ||||
|     static struct option optionList[] = | ||||
|     for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++) | ||||
|     { | ||||
|         {PARAM_PERL_OPTION, required_argument, NULL, PARAM_PERL_OPTION_ID}, | ||||
|         {0, 0, NULL, 0}, | ||||
|     }; | ||||
|         ParseOption *option = &parseData->parseOptionList[optionId]; | ||||
|  | ||||
|     // Parse options | ||||
|     int option; | ||||
|     int optionIdx; | ||||
|  | ||||
|     while ((option = getopt_long(argListSize, argList, "-", optionList, &optionIdx)) != -1) | ||||
|     { | ||||
|         switch (option) | ||||
|         // If option was found | ||||
|         if (option->found) | ||||
|         { | ||||
|             case 1: | ||||
|             case '?': | ||||
|                 strCat(mainParamBuffer, ", "); | ||||
|                 strCatFmt(mainParamBuffer, "'%s'", argList[optind - 1]); | ||||
|                 break; | ||||
|  | ||||
|             case PARAM_PERL_OPTION_ID: | ||||
|                 strLstAdd(perlArgList, strNew(optarg)); | ||||
|  | ||||
|                 strCatFmt(binParamBuffer, " --" PARAM_PERL_OPTION "=\"%s\"", optarg); | ||||
|                 break; | ||||
|             // If option was negated | ||||
|             if (option->negate) | ||||
|                 strCatFmt(mainCallParam, ", '--no-%s\'", cfgOptionName(optionId)); | ||||
|             // Else option with no arguments | ||||
|             else if (option->valueList == NULL) | ||||
|                 strCatFmt(mainCallParam, ", '--%s'", cfgOptionName(optionId)); | ||||
|             // Else options with arguments | ||||
|             else | ||||
|             { | ||||
|                 for (unsigned int argIdx = 0; argIdx < strLstSize(option->valueList); argIdx++) | ||||
|                 { | ||||
|                     strCatFmt(mainCallParam, ", '--%s'", cfgOptionName(optionId)); | ||||
|                     strCatFmt(mainCallParam, ", '%s'", strPtr(strLstGet(option->valueList, argIdx))); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Finish Perl main call | ||||
|     String *mainBuffer = strNewFmt( | ||||
|         PGBACKREST_MAIN "('%s%s'%s)", argList[0], strPtr(binParamBuffer), strPtr(mainParamBuffer)); | ||||
|     // Add command to pass to main | ||||
|     strCatFmt(mainCallParam, ", '%s'", cfgCommandName(parseData->command)); | ||||
|  | ||||
|     strFree(binParamBuffer); | ||||
|     strFree(mainParamBuffer); | ||||
|     // Add command arguments to pass to main | ||||
|     if (parseData->commandArgList != NULL) | ||||
|         for (unsigned int argIdx = 0; argIdx < strLstSize(parseData->commandArgList); argIdx++) | ||||
|             strCatFmt(mainCallParam, ", '%s'", strPtr(strLstGet(parseData->commandArgList, argIdx))); | ||||
|  | ||||
|     // Finish arg list for perl exec | ||||
|     // Construct perl option list to add to bin | ||||
|     String *binPerlOption = strNew(""); | ||||
|  | ||||
|     if (parseData->perlOptionList != NULL) | ||||
|         for (unsigned int argIdx = 0; argIdx < strLstSize(parseData->perlOptionList); argIdx++) | ||||
|         { | ||||
|             // Add to bin option list | ||||
|             strCatFmt(binPerlOption, " --" PARAM_PERL_OPTION "=\"%s\"", strPtr(strLstGet(parseData->perlOptionList, argIdx))); | ||||
|  | ||||
|             // Add to list that will be passed to exec | ||||
|             strLstAdd(perlArgList, strLstGet(parseData->perlOptionList, argIdx)); | ||||
|         } | ||||
|  | ||||
|     // Construct Perl main call | ||||
|     String *mainCall = strNewFmt(PGBACKREST_MAIN "('%s%s'%s)", argList[0], strPtr(binPerlOption), strPtr(mainCallParam)); | ||||
|  | ||||
|     // End arg list for perl exec | ||||
|     strLstAdd(perlArgList, strNew("-M" PGBACKREST_MODULE)); | ||||
|     strLstAdd(perlArgList, strNew("-e")); | ||||
|     strLstAdd(perlArgList, mainBuffer); | ||||
|     strLstAdd(perlArgList, mainCall); | ||||
|     strLstAdd(perlArgList, NULL); | ||||
|  | ||||
|     return perlArgList; | ||||
|   | ||||
| @@ -9,7 +9,7 @@ Execute Perl for Legacy Functionality | ||||
| /*********************************************************************************************************************************** | ||||
| Functions | ||||
| ***********************************************************************************************************************************/ | ||||
| StringList *perlCommand(int argListSize, char *argList[]); | ||||
| StringList *perlCommand(int argListSize, const char *argList[]); | ||||
| void perlExec(StringList *perlArgList); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -329,7 +329,7 @@ my $oTestDef = | ||||
|                 }, | ||||
|                 { | ||||
|                     &TESTDEF_NAME => 'parse', | ||||
|                     &TESTDEF_TOTAL => 1, | ||||
|                     &TESTDEF_TOTAL => 2, | ||||
|                     &TESTDEF_C => true, | ||||
|  | ||||
|                     &TESTDEF_COVERAGE => | ||||
|   | ||||
| @@ -168,6 +168,27 @@ Test that a void statement returns and does not throw an error | ||||
|     TRY_END();                                                                                                                     \ | ||||
| } | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Test that a statement does not error and assign it to the specified variable if not | ||||
| ***********************************************************************************************************************************/ | ||||
| #define TEST_ASSIGN(lValue, statement, ...)                                                                                        \ | ||||
| {                                                                                                                                  \ | ||||
|     /* Output test info */                                                                                                         \ | ||||
|     TEST_RESULT_INFO(__VA_ARGS__);                                                                                                 \ | ||||
|                                                                                                                                    \ | ||||
|     TRY_BEGIN()                                                                                                                    \ | ||||
|     {                                                                                                                              \ | ||||
|         lValue = statement;                                                                                                        \ | ||||
|     }                                                                                                                              \ | ||||
|     /* Catch any errors */                                                                                                         \ | ||||
|     CATCH_ANY()                                                                                                                    \ | ||||
|     {                                                                                                                              \ | ||||
|         /* No errors were expected so error */                                                                                     \ | ||||
|         THROW(AssertError, "statement '%s' threw error %s, '%s' but result expected", #statement, errorName(), errorMessage());    \ | ||||
|     }                                                                                                                              \ | ||||
|     TRY_END();                                                                                                                     \ | ||||
| } | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Macros to ease the use of common data types | ||||
| ***********************************************************************************************************************************/ | ||||
|   | ||||
| @@ -4,7 +4,10 @@ Test Configuration Parse | ||||
|  | ||||
| #define TEST_BACKREST_EXE                                           "pgbackrest" | ||||
|  | ||||
| #define TEST_COMMAND_ARCHIVE_GET                                    "archive-get" | ||||
| #define TEST_COMMAND_BACKUP                                         "backup" | ||||
| #define TEST_COMMAND_HELP                                           "help" | ||||
| #define TEST_COMMAND_RESTORE                                        "restore" | ||||
| #define TEST_COMMAND_VERSION                                        "version" | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| @@ -13,40 +16,129 @@ Test run | ||||
| void testRun() | ||||
| { | ||||
|     // ----------------------------------------------------------------------------------------------------------------------------- | ||||
|     if (testBegin("configParse()")) | ||||
|     if (testBegin("configParseArg()")) | ||||
|     { | ||||
|         ParseData *parseData = NULL; | ||||
|  | ||||
|         StringList *argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), "exe only"); | ||||
|         TEST_ASSIGN(parseData, configParseArg(strLstSize(argList), strLstPtr(argList)), "no command, no args - set help command"); | ||||
|         TEST_RESULT_INT(parseData->command, cfgCmdHelp, "    command is " TEST_COMMAND_HELP); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         strLstAdd(argList, strNew("--online")); | ||||
|         TEST_ERROR(configParseArg(strLstSize(argList), strLstPtr(argList)), CommandRequiredError, "no command found"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         strLstAdd(argList, strNew(TEST_COMMAND_VERSION)); | ||||
|         TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), TEST_COMMAND_VERSION " command"); | ||||
|         TEST_RESULT_INT(cfgCommand(), cfgCmdVersion, "command is " TEST_COMMAND_VERSION); | ||||
|         TEST_ASSIGN(parseData, configParseArg(strLstSize(argList), strLstPtr(argList)), TEST_COMMAND_VERSION " command"); | ||||
|         TEST_RESULT_INT(parseData->command, cfgCmdVersion, "    command is " TEST_COMMAND_VERSION); | ||||
|         TEST_RESULT_PTR(parseData->perlOptionList, NULL, "    no perl options"); | ||||
|         TEST_RESULT_PTR(parseData->commandArgList, NULL, "    no command arguments"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         strLstAdd(argList, strNew("--perl-option=value")); | ||||
|         TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), "perl option"); | ||||
|         TEST_ASSIGN(parseData, configParseArg(strLstSize(argList), strLstPtr(argList)), "perl option"); | ||||
|         TEST_RESULT_STR(strPtr(strLstCat(parseData->perlOptionList, ",")), "value", "check perl option"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         strLstAdd(argList, strNewFmt("--%s", cfgOptionName(cfgOptDelta))); | ||||
|         TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), "delta option"); | ||||
|         TEST_ASSIGN(parseData, configParseArg(strLstSize(argList), strLstPtr(argList)), "delta option"); | ||||
|         TEST_RESULT_BOOL(parseData->parseOptionList[cfgOptDelta].found, true, "    option found"); | ||||
|         TEST_RESULT_BOOL(parseData->parseOptionList[cfgOptDelta].negate, false, "    option not negated"); | ||||
|         TEST_RESULT_PTR(parseData->parseOptionList[cfgOptDelta].valueList, NULL, "    no values"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         strLstAdd(argList, strNew("--" BOGUS_STR)); | ||||
|         TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList)), OptionInvalidError, "invalid option '--BOGUS'"); | ||||
|         TEST_ERROR(configParseArg(strLstSize(argList), strLstPtr(argList)), OptionInvalidError, "invalid option '--BOGUS'"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew("--no-archive-check")); | ||||
|         strLstAdd(argList, strNew(TEST_COMMAND_HELP)); | ||||
|         TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), TEST_COMMAND_HELP " command"); | ||||
|         TEST_ASSIGN(parseData, configParseArg(strLstSize(argList), strLstPtr(argList)), TEST_COMMAND_HELP " command"); | ||||
|         TEST_RESULT_BOOL(parseData->parseOptionList[cfgOptArchiveCheck].negate, true, "    option negated"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew(BOGUS_STR)); | ||||
|         TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList)), CommandInvalidError, "invalid command 'BOGUS'"); | ||||
|         TEST_ERROR(configParseArg(strLstSize(argList), strLstPtr(argList)), CommandInvalidError, "invalid command 'BOGUS'"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew("--no-online")); | ||||
|         strLstAdd(argList, strNew("--no-online")); | ||||
|         TEST_ERROR( | ||||
|             configParseArg(strLstSize(argList), strLstPtr(argList)), OptionInvalidError, | ||||
|             "option 'online' is negated multiple times"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew("--db-host")); | ||||
|         TEST_ERROR( | ||||
|             configParseArg(strLstSize(argList), strLstPtr(argList)), OptionInvalidError, "option '--db-host' requires argument"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew("--config=/etc/config")); | ||||
|         strLstAdd(argList, strNew("--no-config")); | ||||
|         TEST_ERROR( | ||||
|             configParseArg(strLstSize(argList), strLstPtr(argList)), OptionInvalidError, | ||||
|             "option 'config' cannot be set and negated"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew("--compress-level=3")); | ||||
|         strLstAdd(argList, strNew("--compress-level=3")); | ||||
|         TEST_ERROR( | ||||
|             configParseArg(strLstSize(argList), strLstPtr(argList)), OptionInvalidError, | ||||
|             "option 'compress-level' cannot have multiple arguments"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew(TEST_COMMAND_ARCHIVE_GET)); | ||||
|         strLstAdd(argList, strNew("000000010000000200000003")); | ||||
|         strLstAdd(argList, strNew("/path/to/wal/RECOVERYWAL")); | ||||
|         TEST_ASSIGN(parseData, configParseArg(strLstSize(argList), strLstPtr(argList)), "command arguments"); | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(parseData->commandArgList, "|")), "000000010000000200000003|/path/to/wal/RECOVERYWAL", | ||||
|             "    check command arguments"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew("--db-host=db1.test.org")); | ||||
|         strLstAdd(argList, strNew(TEST_COMMAND_BACKUP)); | ||||
|         TEST_ASSIGN(parseData, configParseArg(strLstSize(argList), strLstPtr(argList)), "single valid option"); | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(parseData->parseOptionList[cfgOptDbHost].valueList, "|")), "db1.test.org", "    check db-host option"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew("--link-map=ts1=/path/to/ts1")); | ||||
|         strLstAdd(argList, strNew("--link-map=ts2=/path/to/ts2")); | ||||
|         strLstAdd(argList, strNew(TEST_COMMAND_RESTORE)); | ||||
|         TEST_ASSIGN(parseData, configParseArg(strLstSize(argList), strLstPtr(argList)), "multiple valid options"); | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(parseData->parseOptionList[cfgOptLinkMap].valueList, "|")), "ts1=/path/to/ts1|ts2=/path/to/ts2", | ||||
|             "    check link-map options"); | ||||
|     } | ||||
|  | ||||
|     // ----------------------------------------------------------------------------------------------------------------------------- | ||||
|     if (testBegin("configParse()")) | ||||
|     { | ||||
|         StringList *argList = strLstNew(); | ||||
|         strLstAdd(argList, strNew(TEST_BACKREST_EXE)); | ||||
|         strLstAdd(argList, strNew(TEST_COMMAND_HELP)); | ||||
|         TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), TEST_COMMAND_HELP " command"); | ||||
|         TEST_RESULT_INT(cfgCommand(), cfgCmdHelp, "    command is " TEST_COMMAND_HELP); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -17,46 +17,68 @@ void testRun() | ||||
|     if (testBegin("perlCommand()")) | ||||
|     { | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         char *cmdLineParam[128]; | ||||
|         const char *cmdLineParam[128]; | ||||
|         int cmdLineParamSize = 0; | ||||
|  | ||||
|         cmdLineParam[cmdLineParamSize++] = (char *)TEST_BACKREST_EXE; | ||||
|         cmdLineParam[cmdLineParamSize++] = TEST_BACKREST_EXE; | ||||
|         cmdLineParam[cmdLineParamSize++] = "backup"; | ||||
|  | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(perlCommand(cmdLineParamSize, cmdLineParam), "|")), | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|" TEST_PERL_MAIN "')|[NULL]", "simple command"); | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|" TEST_PERL_MAIN "', 'backup')|[NULL]", "simple command"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         cmdLineParam[cmdLineParamSize++] = (char *)"--option"; | ||||
|         cmdLineParam[cmdLineParamSize++] = "--compress"; | ||||
|  | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(perlCommand(cmdLineParamSize, cmdLineParam), "|")), | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|" TEST_PERL_MAIN "', '--option')|[NULL]", "simple option"); | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|" TEST_PERL_MAIN "', '--compress', 'backup')|[NULL]", "simple option"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         cmdLineParam[cmdLineParamSize++] = (char *)"--option2=value"; | ||||
|         cmdLineParam[cmdLineParamSize++] = "--db-host=db1"; | ||||
|  | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(perlCommand(cmdLineParamSize, cmdLineParam), "|")), | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|" TEST_PERL_MAIN "', '--option', '--option2=value')|[NULL]", | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|" TEST_PERL_MAIN "', '--compress', '--db1-host', 'db1', 'backup')|[NULL]", | ||||
|             "option with = before value"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         cmdLineParam[cmdLineParamSize++] = (char *)"--option3"; | ||||
|         cmdLineParam[cmdLineParamSize++] = (char *)"value"; | ||||
|         cmdLineParam[cmdLineParamSize++] = "--db-user"; | ||||
|         cmdLineParam[cmdLineParamSize++] = "postgres"; | ||||
|  | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(perlCommand(cmdLineParamSize, cmdLineParam), "|")), | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|" TEST_PERL_MAIN "', '--option', '--option2=value', '--option3', 'value')|[NULL]", | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|" TEST_PERL_MAIN | ||||
|                 "', '--compress', '--db1-host', 'db1', '--db1-user', 'postgres', 'backup')|[NULL]", | ||||
|             "option with space before value"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         cmdLineParam[cmdLineParamSize++] = (char *)"--perl-option=-I."; | ||||
|         cmdLineParam[cmdLineParamSize++] = "--perl-option=-I."; | ||||
|  | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(perlCommand(cmdLineParamSize, cmdLineParam), "|")), | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|-I.|" TEST_PERL_MAIN " --perl-option=\"-I.\"', '--option', '--option2=value', " | ||||
|                 "'--option3', 'value')|[NULL]", | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|-I.|" TEST_PERL_MAIN | ||||
|                 " --perl-option=\"-I.\"', '--compress', '--db1-host', 'db1', '--db1-user', 'postgres', 'backup')|[NULL]", | ||||
|             "perl option"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         cmdLineParam[cmdLineParamSize++] = "--no-online"; | ||||
|  | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(perlCommand(cmdLineParamSize, cmdLineParam), "|")), | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|-I.|" TEST_PERL_MAIN | ||||
|                 " --perl-option=\"-I.\"', '--compress', '--db1-host', 'db1', '--db1-user', 'postgres', '--no-online'," | ||||
|                 " 'backup')|[NULL]", | ||||
|             "perl option"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         cmdLineParam[cmdLineParamSize++] = "cmdarg1"; | ||||
|  | ||||
|         TEST_RESULT_STR( | ||||
|             strPtr(strLstCat(perlCommand(cmdLineParamSize, cmdLineParam), "|")), | ||||
|             TEST_ENV_EXE "|" TEST_PERL_EXE "|-I.|" TEST_PERL_MAIN | ||||
|                 " --perl-option=\"-I.\"', '--compress', '--db1-host', 'db1', '--db1-user', 'postgres', '--no-online', 'backup'," | ||||
|                 " 'cmdarg1')|[NULL]", | ||||
|             "perl option"); | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user