Bug Summary

File:src/config.c
Warning:line 1238, column 17
Array access (via field 'lines') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name config.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D REDIS_STATIC= -I ../deps/hiredis -I ../deps/linenoise -I ../deps/lua/src -I ../deps/hdr_histogram -D USE_JEMALLOC -I ../deps/jemalloc/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-c11-extensions -Wno-missing-field-initializers -std=c11 -fdebug-compilation-dir /home/netto/Desktop/redis-6.2.1/src -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-03-14-133648-8817-1 -x c config.c
1/* Configuration file parsing and CONFIG GET/SET commands implementation.
2 *
3 * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of Redis nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without
16 * specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "server.h"
32#include "cluster.h"
33
34#include <fcntl.h>
35#include <sys/stat.h>
36
37/*-----------------------------------------------------------------------------
38 * Config file name-value maps.
39 *----------------------------------------------------------------------------*/
40
41typedef struct configEnum {
42 const char *name;
43 const int val;
44} configEnum;
45
46configEnum maxmemory_policy_enum[] = {
47 {"volatile-lru", MAXMEMORY_VOLATILE_LRU((0<<8)|(1<<0))},
48 {"volatile-lfu", MAXMEMORY_VOLATILE_LFU((1<<8)|(1<<1))},
49 {"volatile-random",MAXMEMORY_VOLATILE_RANDOM(3<<8)},
50 {"volatile-ttl",MAXMEMORY_VOLATILE_TTL(2<<8)},
51 {"allkeys-lru",MAXMEMORY_ALLKEYS_LRU((4<<8)|(1<<0)|(1<<2))},
52 {"allkeys-lfu",MAXMEMORY_ALLKEYS_LFU((5<<8)|(1<<1)|(1<<2))},
53 {"allkeys-random",MAXMEMORY_ALLKEYS_RANDOM((6<<8)|(1<<2))},
54 {"noeviction",MAXMEMORY_NO_EVICTION(7<<8)},
55 {NULL((void*)0), 0}
56};
57
58configEnum syslog_facility_enum[] = {
59 {"user", LOG_USER(1<<3)},
60 {"local0", LOG_LOCAL0(16<<3)},
61 {"local1", LOG_LOCAL1(17<<3)},
62 {"local2", LOG_LOCAL2(18<<3)},
63 {"local3", LOG_LOCAL3(19<<3)},
64 {"local4", LOG_LOCAL4(20<<3)},
65 {"local5", LOG_LOCAL5(21<<3)},
66 {"local6", LOG_LOCAL6(22<<3)},
67 {"local7", LOG_LOCAL7(23<<3)},
68 {NULL((void*)0), 0}
69};
70
71configEnum loglevel_enum[] = {
72 {"debug", LL_DEBUG0},
73 {"verbose", LL_VERBOSE1},
74 {"notice", LL_NOTICE2},
75 {"warning", LL_WARNING3},
76 {NULL((void*)0),0}
77};
78
79configEnum supervised_mode_enum[] = {
80 {"upstart", SUPERVISED_UPSTART3},
81 {"systemd", SUPERVISED_SYSTEMD2},
82 {"auto", SUPERVISED_AUTODETECT1},
83 {"no", SUPERVISED_NONE0},
84 {NULL((void*)0), 0}
85};
86
87configEnum aof_fsync_enum[] = {
88 {"everysec", AOF_FSYNC_EVERYSEC2},
89 {"always", AOF_FSYNC_ALWAYS1},
90 {"no", AOF_FSYNC_NO0},
91 {NULL((void*)0), 0}
92};
93
94configEnum repl_diskless_load_enum[] = {
95 {"disabled", REPL_DISKLESS_LOAD_DISABLED0},
96 {"on-empty-db", REPL_DISKLESS_LOAD_WHEN_DB_EMPTY1},
97 {"swapdb", REPL_DISKLESS_LOAD_SWAPDB2},
98 {NULL((void*)0), 0}
99};
100
101configEnum tls_auth_clients_enum[] = {
102 {"no", TLS_CLIENT_AUTH_NO0},
103 {"yes", TLS_CLIENT_AUTH_YES1},
104 {"optional", TLS_CLIENT_AUTH_OPTIONAL2},
105 {NULL((void*)0), 0}
106};
107
108configEnum oom_score_adj_enum[] = {
109 {"no", OOM_SCORE_ADJ_NO0},
110 {"yes", OOM_SCORE_RELATIVE1},
111 {"relative", OOM_SCORE_RELATIVE1},
112 {"absolute", OOM_SCORE_ADJ_ABSOLUTE2},
113 {NULL((void*)0), 0}
114};
115
116configEnum acl_pubsub_default_enum[] = {
117 {"allchannels", USER_FLAG_ALLCHANNELS(1<<5)},
118 {"resetchannels", 0},
119 {NULL((void*)0), 0}
120};
121
122configEnum sanitize_dump_payload_enum[] = {
123 {"no", SANITIZE_DUMP_NO0},
124 {"yes", SANITIZE_DUMP_YES1},
125 {"clients", SANITIZE_DUMP_CLIENTS2},
126 {NULL((void*)0), 0}
127};
128
129/* Output buffer limits presets. */
130clientBufferLimitsConfig clientBufferLimitsDefaults[CLIENT_TYPE_OBUF_COUNT3] = {
131 {0, 0, 0}, /* normal */
132 {1024*1024*256, 1024*1024*64, 60}, /* slave */
133 {1024*1024*32, 1024*1024*8, 60} /* pubsub */
134};
135
136/* OOM Score defaults */
137int configOOMScoreAdjValuesDefaults[CONFIG_OOM_COUNT3] = { 0, 200, 800 };
138
139/* Generic config infrastructure function pointers
140 * int is_valid_fn(val, err)
141 * Return 1 when val is valid, and 0 when invalid.
142 * Optionally set err to a static error string.
143 * int update_fn(val, prev, err)
144 * This function is called only for CONFIG SET command (not at config file parsing)
145 * It is called after the actual config is applied,
146 * Return 1 for success, and 0 for failure.
147 * Optionally set err to a static error string.
148 * On failure the config change will be reverted.
149 */
150
151/* Configuration values that require no special handling to set, get, load or
152 * rewrite. */
153typedef struct boolConfigData {
154 int *config; /* The pointer to the server config this value is stored in */
155 const int default_value; /* The default value of the config on rewrite */
156 int (*is_valid_fn)(int val, const char **err); /* Optional function to check validity of new value (generic doc above) */
157 int (*update_fn)(int val, int prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
158} boolConfigData;
159
160typedef struct stringConfigData {
161 char **config; /* Pointer to the server config this value is stored in. */
162 const char *default_value; /* Default value of the config on rewrite. */
163 int (*is_valid_fn)(char* val, const char **err); /* Optional function to check validity of new value (generic doc above) */
164 int (*update_fn)(char* val, char* prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
165 int convert_empty_to_null; /* Boolean indicating if empty strings should
166 be stored as a NULL value. */
167} stringConfigData;
168
169typedef struct sdsConfigData {
170 sds *config; /* Pointer to the server config this value is stored in. */
171 const char *default_value; /* Default value of the config on rewrite. */
172 int (*is_valid_fn)(sds val, const char **err); /* Optional function to check validity of new value (generic doc above) */
173 int (*update_fn)(sds val, sds prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
174 int convert_empty_to_null; /* Boolean indicating if empty SDS strings should
175 be stored as a NULL value. */
176} sdsConfigData;
177
178typedef struct enumConfigData {
179 int *config; /* The pointer to the server config this value is stored in */
180 configEnum *enum_value; /* The underlying enum type this data represents */
181 const int default_value; /* The default value of the config on rewrite */
182 int (*is_valid_fn)(int val, const char **err); /* Optional function to check validity of new value (generic doc above) */
183 int (*update_fn)(int val, int prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
184} enumConfigData;
185
186typedef enum numericType {
187 NUMERIC_TYPE_INT,
188 NUMERIC_TYPE_UINT,
189 NUMERIC_TYPE_LONG,
190 NUMERIC_TYPE_ULONG,
191 NUMERIC_TYPE_LONG_LONG,
192 NUMERIC_TYPE_ULONG_LONG,
193 NUMERIC_TYPE_SIZE_T,
194 NUMERIC_TYPE_SSIZE_T,
195 NUMERIC_TYPE_OFF_T,
196 NUMERIC_TYPE_TIME_T,
197} numericType;
198
199typedef struct numericConfigData {
200 union {
201 int *i;
202 unsigned int *ui;
203 long *l;
204 unsigned long *ul;
205 long long *ll;
206 unsigned long long *ull;
207 size_t *st;
208 ssize_t *sst;
209 off_t *ot;
210 time_t *tt;
211 } config; /* The pointer to the numeric config this value is stored in */
212 int is_memory; /* Indicates if this value can be loaded as a memory value */
213 numericType numeric_type; /* An enum indicating the type of this value */
214 long long lower_bound; /* The lower bound of this numeric value */
215 long long upper_bound; /* The upper bound of this numeric value */
216 const long long default_value; /* The default value of the config on rewrite */
217 int (*is_valid_fn)(long long val, const char **err); /* Optional function to check validity of new value (generic doc above) */
218 int (*update_fn)(long long val, long long prev, const char **err); /* Optional function to apply new value at runtime (generic doc above) */
219} numericConfigData;
220
221typedef union typeData {
222 boolConfigData yesno;
223 stringConfigData string;
224 sdsConfigData sds;
225 enumConfigData enumd;
226 numericConfigData numeric;
227} typeData;
228
229typedef struct typeInterface {
230 /* Called on server start, to init the server with default value */
231 void (*init)(typeData data);
232 /* Called on server start, should return 1 on success, 0 on error and should set err */
233 int (*load)(typeData data, sds *argc, int argv, const char **err);
234 /* Called on server startup and CONFIG SET, returns 1 on success, 0 on error
235 * and can set a verbose err string, update is true when called from CONFIG SET */
236 int (*set)(typeData data, sds value, int update, const char **err);
237 /* Called on CONFIG GET, required to add output to the client */
238 void (*get)(client *c, typeData data);
239 /* Called on CONFIG REWRITE, required to rewrite the config state */
240 void (*rewrite)(typeData data, const char *name, struct rewriteConfigState *state);
241} typeInterface;
242
243typedef struct standardConfig {
244 const char *name; /* The user visible name of this config */
245 const char *alias; /* An alias that can also be used for this config */
246 const int modifiable; /* Can this value be updated by CONFIG SET? */
247 typeInterface interface; /* The function pointers that define the type interface */
248 typeData data; /* The type specific data exposed used by the interface */
249} standardConfig;
250
251standardConfig configs[];
252
253/*-----------------------------------------------------------------------------
254 * Enum access functions
255 *----------------------------------------------------------------------------*/
256
257/* Get enum value from name. If there is no match INT_MIN is returned. */
258int configEnumGetValue(configEnum *ce, char *name) {
259 while(ce->name != NULL((void*)0)) {
260 if (!strcasecmp(ce->name,name)) return ce->val;
261 ce++;
262 }
263 return INT_MIN(-2147483647 -1);
264}
265
266/* Get enum name from value. If no match is found NULL is returned. */
267const char *configEnumGetName(configEnum *ce, int val) {
268 while(ce->name != NULL((void*)0)) {
269 if (ce->val == val) return ce->name;
270 ce++;
271 }
272 return NULL((void*)0);
273}
274
275/* Wrapper for configEnumGetName() returning "unknown" instead of NULL if
276 * there is no match. */
277const char *configEnumGetNameOrUnknown(configEnum *ce, int val) {
278 const char *name = configEnumGetName(ce,val);
279 return name ? name : "unknown";
280}
281
282/* Used for INFO generation. */
283const char *evictPolicyToString(void) {
284 return configEnumGetNameOrUnknown(maxmemory_policy_enum,server.maxmemory_policy);
285}
286
287/*-----------------------------------------------------------------------------
288 * Config file parsing
289 *----------------------------------------------------------------------------*/
290
291int yesnotoi(char *s) {
292 if (!strcasecmp(s,"yes")) return 1;
293 else if (!strcasecmp(s,"no")) return 0;
294 else return -1;
295}
296
297void appendServerSaveParams(time_t seconds, int changes) {
298 server.saveparams = zrealloc(server.saveparams,sizeof(struct saveparam)*(server.saveparamslen+1));
299 server.saveparams[server.saveparamslen].seconds = seconds;
300 server.saveparams[server.saveparamslen].changes = changes;
301 server.saveparamslen++;
302}
303
304void resetServerSaveParams(void) {
305 zfree(server.saveparams);
306 server.saveparams = NULL((void*)0);
307 server.saveparamslen = 0;
308}
309
310void queueLoadModule(sds path, sds *argv, int argc) {
311 int i;
312 struct moduleLoadQueueEntry *loadmod;
313
314 loadmod = zmalloc(sizeof(struct moduleLoadQueueEntry));
315 loadmod->argv = zmalloc(sizeof(robj*)*argc);
316 loadmod->path = sdsnew(path);
317 loadmod->argc = argc;
318 for (i = 0; i < argc; i++) {
319 loadmod->argv[i] = createRawStringObject(argv[i],sdslen(argv[i]));
320 }
321 listAddNodeTail(server.loadmodule_queue,loadmod);
322}
323
324/* Parse an array of CONFIG_OOM_COUNT sds strings, validate and populate
325 * server.oom_score_adj_values if valid.
326 */
327
328static int updateOOMScoreAdjValues(sds *args, const char **err, int apply) {
329 int i;
330 int values[CONFIG_OOM_COUNT3];
331
332 for (i = 0; i < CONFIG_OOM_COUNT3; i++) {
333 char *eptr;
334 long long val = strtoll(args[i], &eptr, 10);
335
336 if (*eptr != '\0' || val < -2000 || val > 2000) {
337 if (err) *err = "Invalid oom-score-adj-values, elements must be between -2000 and 2000.";
338 return C_ERR-1;
339 }
340
341 values[i] = val;
342 }
343
344 /* Verify that the values make sense. If they don't omit a warning but
345 * keep the configuration, which may still be valid for privileged processes.
346 */
347
348 if (values[CONFIG_OOM_REPLICA1] < values[CONFIG_OOM_MASTER0] ||
349 values[CONFIG_OOM_BGCHILD2] < values[CONFIG_OOM_REPLICA1]) {
350 serverLog(LOG_WARNING4,
351 "The oom-score-adj-values configuration may not work for non-privileged processes! "
352 "Please consult the documentation.");
353 }
354
355 /* Store values, retain previous config for rollback in case we fail. */
356 int old_values[CONFIG_OOM_COUNT3];
357 for (i = 0; i < CONFIG_OOM_COUNT3; i++) {
358 old_values[i] = server.oom_score_adj_values[i];
359 server.oom_score_adj_values[i] = values[i];
360 }
361
362 /* When parsing the config file, we want to apply only when all is done. */
363 if (!apply)
364 return C_OK0;
365
366 /* Update */
367 if (setOOMScoreAdj(-1) == C_ERR-1) {
368 /* Roll back */
369 for (i = 0; i < CONFIG_OOM_COUNT3; i++)
370 server.oom_score_adj_values[i] = old_values[i];
371
372 if (err)
373 *err = "Failed to apply oom-score-adj-values configuration, check server logs.";
374
375 return C_ERR-1;
376 }
377
378 return C_OK0;
379}
380
381void initConfigValues() {
382 for (standardConfig *config = configs; config->name != NULL((void*)0); config++) {
383 config->interface.init(config->data);
384 }
385}
386
387void loadServerConfigFromString(char *config) {
388 const char *err = NULL((void*)0);
389 int linenum = 0, totlines, i;
390 int slaveof_linenum = 0;
391 sds *lines;
392 int save_loaded = 0;
393
394 lines = sdssplitlen(config,strlen(config),"\n",1,&totlines);
395
396 for (i = 0; i < totlines; i++) {
397 sds *argv;
398 int argc;
399
400 linenum = i+1;
401 lines[i] = sdstrim(lines[i]," \t\r\n");
402
403 /* Skip comments and blank lines */
404 if (lines[i][0] == '#' || lines[i][0] == '\0') continue;
405
406 /* Split into arguments */
407 argv = sdssplitargs(lines[i],&argc);
408 if (argv == NULL((void*)0)) {
409 err = "Unbalanced quotes in configuration line";
410 goto loaderr;
411 }
412
413 /* Skip this line if the resulting command vector is empty. */
414 if (argc == 0) {
415 sdsfreesplitres(argv,argc);
416 continue;
417 }
418 sdstolower(argv[0]);
419
420 /* Iterate the configs that are standard */
421 int match = 0;
422 for (standardConfig *config = configs; config->name != NULL((void*)0); config++) {
423 if ((!strcasecmp(argv[0],config->name) ||
424 (config->alias && !strcasecmp(argv[0],config->alias))))
425 {
426 if (argc != 2) {
427 err = "wrong number of arguments";
428 goto loaderr;
429 }
430 if (!config->interface.set(config->data, argv[1], 0, &err)) {
431 goto loaderr;
432 }
433
434 match = 1;
435 break;
436 }
437 }
438
439 if (match) {
440 sdsfreesplitres(argv,argc);
441 continue;
442 }
443
444 /* Execute config directives */
445 if (!strcasecmp(argv[0],"bind") && argc >= 2) {
446 int j, addresses = argc-1;
447
448 if (addresses > CONFIG_BINDADDR_MAX16) {
449 err = "Too many bind addresses specified"; goto loaderr;
450 }
451 /* Free old bind addresses */
452 for (j = 0; j < server.bindaddr_count; j++) {
453 zfree(server.bindaddr[j]);
454 }
455 for (j = 0; j < addresses; j++)
456 server.bindaddr[j] = zstrdup(argv[j+1]);
457 server.bindaddr_count = addresses;
458 } else if (!strcasecmp(argv[0],"unixsocketperm") && argc == 2) {
459 errno(*__errno_location ()) = 0;
460 server.unixsocketperm = (mode_t)strtol(argv[1], NULL((void*)0), 8);
461 if (errno(*__errno_location ()) || server.unixsocketperm > 0777) {
462 err = "Invalid socket file permissions"; goto loaderr;
463 }
464 } else if (!strcasecmp(argv[0],"save")) {
465 /* We don't reset save params before loading, because if they're not part
466 * of the file the defaults should be used.
467 */
468 if (!save_loaded) {
469 save_loaded = 1;
470 resetServerSaveParams();
471 }
472
473 if (argc == 3) {
474 int seconds = atoi(argv[1]);
475 int changes = atoi(argv[2]);
476 if (seconds < 1 || changes < 0) {
477 err = "Invalid save parameters"; goto loaderr;
478 }
479 appendServerSaveParams(seconds,changes);
480 } else if (argc == 2 && !strcasecmp(argv[1],"")) {
481 resetServerSaveParams();
482 }
483 } else if (!strcasecmp(argv[0],"dir") && argc == 2) {
484 if (chdir(argv[1]) == -1) {
485 serverLog(LL_WARNING3,"Can't chdir to '%s': %s",
486 argv[1], strerror(errno(*__errno_location ())));
487 exit(1);
488 }
489 } else if (!strcasecmp(argv[0],"logfile") && argc == 2) {
490 FILE *logfp;
491
492 zfree(server.logfile);
493 server.logfile = zstrdup(argv[1]);
494 if (server.logfile[0] != '\0') {
495 /* Test if we are able to open the file. The server will not
496 * be able to abort just for this problem later... */
497 logfp = fopen(server.logfile,"a");
498 if (logfp == NULL((void*)0)) {
499 err = sdscatprintf(sdsempty(),
500 "Can't open the log file: %s", strerror(errno(*__errno_location ())));
501 goto loaderr;
502 }
503 fclose(logfp);
504 }
505 } else if (!strcasecmp(argv[0],"include") && argc == 2) {
506 loadServerConfig(argv[1], 0, NULL((void*)0));
507 } else if ((!strcasecmp(argv[0],"slaveof") ||
508 !strcasecmp(argv[0],"replicaof")) && argc == 3) {
509 slaveof_linenum = linenum;
510 sdsfree(server.masterhost);
511 if (!strcasecmp(argv[1], "no") && !strcasecmp(argv[2], "one")) {
512 server.masterhost = NULL((void*)0);
513 continue;
514 }
515 server.masterhost = sdsnew(argv[1]);
516 char *ptr;
517 server.masterport = strtol(argv[2], &ptr, 10);
518 if (server.masterport < 0 || server.masterport > 65535 || *ptr != '\0') {
519 err = "Invalid master port"; goto loaderr;
520 }
521 server.repl_state = REPL_STATE_CONNECT;
522 } else if (!strcasecmp(argv[0],"list-max-ziplist-entries") && argc == 2){
523 /* DEAD OPTION */
524 } else if (!strcasecmp(argv[0],"list-max-ziplist-value") && argc == 2) {
525 /* DEAD OPTION */
526 } else if (!strcasecmp(argv[0],"rename-command") && argc == 3) {
527 struct redisCommand *cmd = lookupCommand(argv[1]);
528 int retval;
529
530 if (!cmd) {
531 err = "No such command in rename-command";
532 goto loaderr;
533 }
534
535 /* If the target command name is the empty string we just
536 * remove it from the command table. */
537 retval = dictDelete(server.commands, argv[1]);
538 serverAssert(retval == DICT_OK)((retval == 0)?(void)0 : (_serverAssert("retval == DICT_OK","config.c"
,538),__builtin_unreachable()))
;
539
540 /* Otherwise we re-add the command under a different name. */
541 if (sdslen(argv[2]) != 0) {
542 sds copy = sdsdup(argv[2]);
543
544 retval = dictAdd(server.commands, copy, cmd);
545 if (retval != DICT_OK0) {
546 sdsfree(copy);
547 err = "Target command name already exists"; goto loaderr;
548 }
549 }
550 } else if (!strcasecmp(argv[0],"cluster-config-file") && argc == 2) {
551 zfree(server.cluster_configfile);
552 server.cluster_configfile = zstrdup(argv[1]);
553 } else if (!strcasecmp(argv[0],"client-output-buffer-limit") &&
554 argc == 5)
555 {
556 int class = getClientTypeByName(argv[1]);
557 unsigned long long hard, soft;
558 int soft_seconds;
559
560 if (class == -1 || class == CLIENT_TYPE_MASTER3) {
561 err = "Unrecognized client limit class: the user specified "
562 "an invalid one, or 'master' which has no buffer limits.";
563 goto loaderr;
564 }
565 hard = memtoll(argv[2],NULL((void*)0));
566 soft = memtoll(argv[3],NULL((void*)0));
567 soft_seconds = atoi(argv[4]);
568 if (soft_seconds < 0) {
569 err = "Negative number of seconds in soft limit is invalid";
570 goto loaderr;
571 }
572 server.client_obuf_limits[class].hard_limit_bytes = hard;
573 server.client_obuf_limits[class].soft_limit_bytes = soft;
574 server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;
575 } else if (!strcasecmp(argv[0],"oom-score-adj-values") && argc == 1 + CONFIG_OOM_COUNT3) {
576 if (updateOOMScoreAdjValues(&argv[1], &err, 0) == C_ERR-1) goto loaderr;
577 } else if (!strcasecmp(argv[0],"notify-keyspace-events") && argc == 2) {
578 int flags = keyspaceEventsStringToFlags(argv[1]);
579
580 if (flags == -1) {
581 err = "Invalid event class character. Use 'g$lshzxeA'.";
582 goto loaderr;
583 }
584 server.notify_keyspace_events = flags;
585 } else if (!strcasecmp(argv[0],"user") && argc >= 2) {
586 int argc_err;
587 if (ACLAppendUserForLoading(argv,argc,&argc_err) == C_ERR-1) {
588 char buf[1024];
589 const char *errmsg = ACLSetUserStringError();
590 snprintf(buf,sizeof(buf),"Error in user declaration '%s': %s",
591 argv[argc_err],errmsg);
592 err = buf;
593 goto loaderr;
594 }
595 } else if (!strcasecmp(argv[0],"loadmodule") && argc >= 2) {
596 queueLoadModule(argv[1],&argv[2],argc-2);
597 } else if (!strcasecmp(argv[0],"sentinel")) {
598 /* argc == 1 is handled by main() as we need to enter the sentinel
599 * mode ASAP. */
600 if (argc != 1) {
601 if (!server.sentinel_mode) {
602 err = "sentinel directive while not in sentinel mode";
603 goto loaderr;
604 }
605 queueSentinelConfig(argv+1,argc-1,linenum,lines[i]);
606 }
607 } else {
608 err = "Bad directive or wrong number of arguments"; goto loaderr;
609 }
610 sdsfreesplitres(argv,argc);
611 }
612
613 /* Sanity checks. */
614 if (server.cluster_enabled && server.masterhost) {
615 linenum = slaveof_linenum;
616 i = linenum-1;
617 err = "replicaof directive not allowed in cluster mode";
618 goto loaderr;
619 }
620
621 sdsfreesplitres(lines,totlines);
622 return;
623
624loaderr:
625 fprintf(stderrstderr, "\n*** FATAL CONFIG FILE ERROR (Redis %s) ***\n",
626 REDIS_VERSION"6.2.1");
627 fprintf(stderrstderr, "Reading the configuration file, at line %d\n", linenum);
628 fprintf(stderrstderr, ">>> '%s'\n", lines[i]);
629 fprintf(stderrstderr, "%s\n", err);
630 exit(1);
631}
632
633/* Load the server configuration from the specified filename.
634 * The function appends the additional configuration directives stored
635 * in the 'options' string to the config file before loading.
636 *
637 * Both filename and options can be NULL, in such a case are considered
638 * empty. This way loadServerConfig can be used to just load a file or
639 * just load a string. */
640void loadServerConfig(char *filename, char config_from_stdin, char *options) {
641 sds config = sdsempty();
642 char buf[CONFIG_MAX_LINE1024+1];
643 FILE *fp;
644
645 /* Load the file content */
646 if (filename) {
647 if ((fp = fopen(filename,"r")) == NULL((void*)0)) {
648 serverLog(LL_WARNING3,
649 "Fatal error, can't open config file '%s': %s",
650 filename, strerror(errno(*__errno_location ())));
651 exit(1);
652 }
653 while(fgets(buf,CONFIG_MAX_LINE1024+1,fp) != NULL((void*)0))
654 config = sdscat(config,buf);
655 fclose(fp);
656 }
657 /* Append content from stdin */
658 if (config_from_stdin) {
659 serverLog(LL_WARNING3,"Reading config from stdin");
660 fp = stdinstdin;
661 while(fgets(buf,CONFIG_MAX_LINE1024+1,fp) != NULL((void*)0))
662 config = sdscat(config,buf);
663 }
664
665 /* Append the additional options */
666 if (options) {
667 config = sdscat(config,"\n");
668 config = sdscat(config,options);
669 }
670 loadServerConfigFromString(config);
671 sdsfree(config);
672}
673
674/*-----------------------------------------------------------------------------
675 * CONFIG SET implementation
676 *----------------------------------------------------------------------------*/
677
678#define config_set_bool_field(_name,_var)} else if (!strcasecmp(c->argv[2]->ptr,_name)) { int yn
= yesnotoi(o->ptr); if (yn == -1) goto badfmt; _var = yn;
\
679 } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \
680 int yn = yesnotoi(o->ptr); \
681 if (yn == -1) goto badfmt; \
682 _var = yn;
683
684#define config_set_numerical_field(_name,_var,min,max)} else if (!strcasecmp(c->argv[2]->ptr,_name)) { if (getLongLongFromObject
(o,&ll) == -1) goto badfmt; if (min != (-9223372036854775807LL
-1LL) && ll < min) goto badfmt; if (max != 9223372036854775807LL
&& ll > max) goto badfmt; _var = ll;
\
685 } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \
686 if (getLongLongFromObject(o,&ll) == C_ERR-1) goto badfmt; \
687 if (min != LLONG_MIN(-9223372036854775807LL -1LL) && ll < min) goto badfmt; \
688 if (max != LLONG_MAX9223372036854775807LL && ll > max) goto badfmt; \
689 _var = ll;
690
691#define config_set_memory_field(_name,_var)} else if (!strcasecmp(c->argv[2]->ptr,_name)) { ll = memtoll
(o->ptr,&err); if (err || ll < 0) goto badfmt; _var
= ll;
\
692 } else if (!strcasecmp(c->argv[2]->ptr,_name)) { \
693 ll = memtoll(o->ptr,&err); \
694 if (err || ll < 0) goto badfmt; \
695 _var = ll;
696
697#define config_set_special_field(_name)} else if (!strcasecmp(c->argv[2]->ptr,_name)) { \
698 } else if (!strcasecmp(c->argv[2]->ptr,_name)) {
699
700#define config_set_special_field_with_alias(_name1,_name2)} else if (!strcasecmp(c->argv[2]->ptr,_name1) || !strcasecmp
(c->argv[2]->ptr,_name2)) {
\
701 } else if (!strcasecmp(c->argv[2]->ptr,_name1) || \
702 !strcasecmp(c->argv[2]->ptr,_name2)) {
703
704#define config_set_else} else } else
705
706void configSetCommand(client *c) {
707 robj *o;
708 long long ll;
709 int err;
710 const char *errstr = NULL((void*)0);
711 serverAssertWithInfo(c,c->argv[2],sdsEncodedObject(c->argv[2]))(((c->argv[2]->encoding == 0 || c->argv[2]->encoding
== 8))?(void)0 : (_serverAssertWithInfo(c,c->argv[2],"sdsEncodedObject(c->argv[2])"
,"config.c",711),__builtin_unreachable()))
;
712 serverAssertWithInfo(c,c->argv[3],sdsEncodedObject(c->argv[3]))(((c->argv[3]->encoding == 0 || c->argv[3]->encoding
== 8))?(void)0 : (_serverAssertWithInfo(c,c->argv[3],"sdsEncodedObject(c->argv[3])"
,"config.c",712),__builtin_unreachable()))
;
713 o = c->argv[3];
714
715 /* Iterate the configs that are standard */
716 for (standardConfig *config = configs; config->name != NULL((void*)0); config++) {
717 if(config->modifiable && (!strcasecmp(c->argv[2]->ptr,config->name) ||
718 (config->alias && !strcasecmp(c->argv[2]->ptr,config->alias))))
719 {
720 if (!config->interface.set(config->data,o->ptr,1,&errstr)) {
721 goto badfmt;
722 }
723 addReply(c,shared.ok);
724 return;
725 }
726 }
727
728 if (0) { /* this starts the config_set macros else-if chain. */
729
730 /* Special fields that can't be handled with general macros. */
731 config_set_special_field("bind")} else if (!strcasecmp(c->argv[2]->ptr,"bind")) { {
732 int vlen;
733 sds *v = sdssplitlen(o->ptr,sdslen(o->ptr)," ",1,&vlen);
734
735 if (vlen < 1 || vlen > CONFIG_BINDADDR_MAX16) {
736 addReplyError(c, "Too many bind addresses specified.");
737 sdsfreesplitres(v, vlen);
738 return;
739 }
740
741 if (changeBindAddr(v, vlen) == C_ERR-1) {
742 addReplyError(c, "Failed to bind to specified addresses.");
743 sdsfreesplitres(v, vlen);
744 return;
745 }
746 sdsfreesplitres(v, vlen);
747 } config_set_special_field("save")} else if (!strcasecmp(c->argv[2]->ptr,"save")) { {
748 int vlen, j;
749 sds *v = sdssplitlen(o->ptr,sdslen(o->ptr)," ",1,&vlen);
750
751 /* Perform sanity check before setting the new config:
752 * - Even number of args
753 * - Seconds >= 1, changes >= 0 */
754 if (vlen & 1) {
755 sdsfreesplitres(v,vlen);
756 goto badfmt;
757 }
758 for (j = 0; j < vlen; j++) {
759 char *eptr;
760 long val;
761
762 val = strtoll(v[j], &eptr, 10);
763 if (eptr[0] != '\0' ||
764 ((j & 1) == 0 && val < 1) ||
765 ((j & 1) == 1 && val < 0)) {
766 sdsfreesplitres(v,vlen);
767 goto badfmt;
768 }
769 }
770 /* Finally set the new config */
771 resetServerSaveParams();
772 for (j = 0; j < vlen; j += 2) {
773 time_t seconds;
774 int changes;
775
776 seconds = strtoll(v[j],NULL((void*)0),10);
777 changes = strtoll(v[j+1],NULL((void*)0),10);
778 appendServerSaveParams(seconds, changes);
779 }
780 sdsfreesplitres(v,vlen);
781 } config_set_special_field("dir")} else if (!strcasecmp(c->argv[2]->ptr,"dir")) { {
782 if (chdir((char*)o->ptr) == -1) {
783 addReplyErrorFormat(c,"Changing directory: %s", strerror(errno(*__errno_location ())));
784 return;
785 }
786 } config_set_special_field("client-output-buffer-limit")} else if (!strcasecmp(c->argv[2]->ptr,"client-output-buffer-limit"
)) {
{
787 int vlen, j;
788 sds *v = sdssplitlen(o->ptr,sdslen(o->ptr)," ",1,&vlen);
789
790 /* We need a multiple of 4: <class> <hard> <soft> <soft_seconds> */
791 if (vlen % 4) {
792 sdsfreesplitres(v,vlen);
793 goto badfmt;
794 }
795
796 /* Sanity check of single arguments, so that we either refuse the
797 * whole configuration string or accept it all, even if a single
798 * error in a single client class is present. */
799 for (j = 0; j < vlen; j++) {
800 long val;
801
802 if ((j % 4) == 0) {
803 int class = getClientTypeByName(v[j]);
804 if (class == -1 || class == CLIENT_TYPE_MASTER3) {
805 sdsfreesplitres(v,vlen);
806 goto badfmt;
807 }
808 } else {
809 val = memtoll(v[j], &err);
810 if (err || val < 0) {
811 sdsfreesplitres(v,vlen);
812 goto badfmt;
813 }
814 }
815 }
816 /* Finally set the new config */
817 for (j = 0; j < vlen; j += 4) {
818 int class;
819 unsigned long long hard, soft;
820 int soft_seconds;
821
822 class = getClientTypeByName(v[j]);
823 hard = memtoll(v[j+1],NULL((void*)0));
824 soft = memtoll(v[j+2],NULL((void*)0));
825 soft_seconds = strtoll(v[j+3],NULL((void*)0),10);
826
827 server.client_obuf_limits[class].hard_limit_bytes = hard;
828 server.client_obuf_limits[class].soft_limit_bytes = soft;
829 server.client_obuf_limits[class].soft_limit_seconds = soft_seconds;
830 }
831 sdsfreesplitres(v,vlen);
832 } config_set_special_field("oom-score-adj-values")} else if (!strcasecmp(c->argv[2]->ptr,"oom-score-adj-values"
)) {
{
833 int vlen;
834 int success = 1;
835
836 sds *v = sdssplitlen(o->ptr, sdslen(o->ptr), " ", 1, &vlen);
837 if (vlen != CONFIG_OOM_COUNT3 || updateOOMScoreAdjValues(v, &errstr, 1) == C_ERR-1)
838 success = 0;
839
840 sdsfreesplitres(v, vlen);
841 if (!success)
842 goto badfmt;
843 } config_set_special_field("notify-keyspace-events")} else if (!strcasecmp(c->argv[2]->ptr,"notify-keyspace-events"
)) {
{
844 int flags = keyspaceEventsStringToFlags(o->ptr);
845
846 if (flags == -1) goto badfmt;
847 server.notify_keyspace_events = flags;
848 /* Numerical fields.
849 * config_set_numerical_field(name,var,min,max) */
850 } config_set_numerical_field(} else if (!strcasecmp(c->argv[2]->ptr,"watchdog-period"
)) { if (getLongLongFromObject(o,&ll) == -1) goto badfmt;
if (0 != (-9223372036854775807LL -1LL) && ll < 0)
goto badfmt; if (2147483647 != 9223372036854775807LL &&
ll > 2147483647) goto badfmt; ll = ll;
851 "watchdog-period",ll,0,INT_MAX)} else if (!strcasecmp(c->argv[2]->ptr,"watchdog-period"
)) { if (getLongLongFromObject(o,&ll) == -1) goto badfmt;
if (0 != (-9223372036854775807LL -1LL) && ll < 0)
goto badfmt; if (2147483647 != 9223372036854775807LL &&
ll > 2147483647) goto badfmt; ll = ll;
{
852 if (ll)
853 enableWatchdog(ll);
854 else
855 disableWatchdog();
856 /* Everything else is an error... */
857 } config_set_else} else {
858 addReplyErrorFormat(c,"Unsupported CONFIG parameter: %s",
859 (char*)c->argv[2]->ptr);
860 return;
861 }
862
863 /* On success we just return a generic OK for all the options. */
864 addReply(c,shared.ok);
865 return;
866
867badfmt: /* Bad format errors */
868 if (errstr) {
869 addReplyErrorFormat(c,"Invalid argument '%s' for CONFIG SET '%s' - %s",
870 (char*)o->ptr,
871 (char*)c->argv[2]->ptr,
872 errstr);
873 } else {
874 addReplyErrorFormat(c,"Invalid argument '%s' for CONFIG SET '%s'",
875 (char*)o->ptr,
876 (char*)c->argv[2]->ptr);
877 }
878}
879
880/*-----------------------------------------------------------------------------
881 * CONFIG GET implementation
882 *----------------------------------------------------------------------------*/
883
884#define config_get_string_field(_name,_var)do { if (stringmatch(pattern,_name,1)) { addReplyBulkCString(
c,_name); addReplyBulkCString(c,_var ? _var : ""); matches++;
} } while(0)
do { \
885 if (stringmatch(pattern,_name,1)) { \
886 addReplyBulkCString(c,_name); \
887 addReplyBulkCString(c,_var ? _var : ""); \
888 matches++; \
889 } \
890} while(0)
891
892#define config_get_bool_field(_name,_var)do { if (stringmatch(pattern,_name,1)) { addReplyBulkCString(
c,_name); addReplyBulkCString(c,_var ? "yes" : "no"); matches
++; } } while(0)
do { \
893 if (stringmatch(pattern,_name,1)) { \
894 addReplyBulkCString(c,_name); \
895 addReplyBulkCString(c,_var ? "yes" : "no"); \
896 matches++; \
897 } \
898} while(0)
899
900#define config_get_numerical_field(_name,_var)do { if (stringmatch(pattern,_name,1)) { ll2string(buf,sizeof
(buf),_var); addReplyBulkCString(c,_name); addReplyBulkCString
(c,buf); matches++; } } while(0)
do { \
901 if (stringmatch(pattern,_name,1)) { \
902 ll2string(buf,sizeof(buf),_var); \
903 addReplyBulkCString(c,_name); \
904 addReplyBulkCString(c,buf); \
905 matches++; \
906 } \
907} while(0)
908
909void configGetCommand(client *c) {
910 robj *o = c->argv[2];
911 void *replylen = addReplyDeferredLen(c);
912 char *pattern = o->ptr;
913 char buf[128];
914 int matches = 0;
915 serverAssertWithInfo(c,o,sdsEncodedObject(o))(((o->encoding == 0 || o->encoding == 8))?(void)0 : (_serverAssertWithInfo
(c,o,"sdsEncodedObject(o)","config.c",915),__builtin_unreachable
()))
;
916
917 /* Iterate the configs that are standard */
918 for (standardConfig *config = configs; config->name != NULL((void*)0); config++) {
919 if (stringmatch(pattern,config->name,1)) {
920 addReplyBulkCString(c,config->name);
921 config->interface.get(c,config->data);
922 matches++;
923 }
924 if (config->alias && stringmatch(pattern,config->alias,1)) {
925 addReplyBulkCString(c,config->alias);
926 config->interface.get(c,config->data);
927 matches++;
928 }
929 }
930
931 /* String values */
932 config_get_string_field("logfile",server.logfile)do { if (stringmatch(pattern,"logfile",1)) { addReplyBulkCString
(c,"logfile"); addReplyBulkCString(c,server.logfile ? server.
logfile : ""); matches++; } } while(0)
;
933
934 /* Numerical values */
935 config_get_numerical_field("watchdog-period",server.watchdog_period)do { if (stringmatch(pattern,"watchdog-period",1)) { ll2string
(buf,sizeof(buf),server.watchdog_period); addReplyBulkCString
(c,"watchdog-period"); addReplyBulkCString(c,buf); matches++;
} } while(0)
;
936
937 /* Everything we can't handle with macros follows. */
938
939 if (stringmatch(pattern,"dir",1)) {
940 char buf[1024];
941
942 if (getcwd(buf,sizeof(buf)) == NULL((void*)0))
943 buf[0] = '\0';
944
945 addReplyBulkCString(c,"dir");
946 addReplyBulkCString(c,buf);
947 matches++;
948 }
949 if (stringmatch(pattern,"save",1)) {
950 sds buf = sdsempty();
951 int j;
952
953 for (j = 0; j < server.saveparamslen; j++) {
954 buf = sdscatprintf(buf,"%jd %d",
955 (intmax_t)server.saveparams[j].seconds,
956 server.saveparams[j].changes);
957 if (j != server.saveparamslen-1)
958 buf = sdscatlen(buf," ",1);
959 }
960 addReplyBulkCString(c,"save");
961 addReplyBulkCString(c,buf);
962 sdsfree(buf);
963 matches++;
964 }
965 if (stringmatch(pattern,"client-output-buffer-limit",1)) {
966 sds buf = sdsempty();
967 int j;
968
969 for (j = 0; j < CLIENT_TYPE_OBUF_COUNT3; j++) {
970 buf = sdscatprintf(buf,"%s %llu %llu %ld",
971 getClientTypeName(j),
972 server.client_obuf_limits[j].hard_limit_bytes,
973 server.client_obuf_limits[j].soft_limit_bytes,
974 (long) server.client_obuf_limits[j].soft_limit_seconds);
975 if (j != CLIENT_TYPE_OBUF_COUNT3-1)
976 buf = sdscatlen(buf," ",1);
977 }
978 addReplyBulkCString(c,"client-output-buffer-limit");
979 addReplyBulkCString(c,buf);
980 sdsfree(buf);
981 matches++;
982 }
983 if (stringmatch(pattern,"unixsocketperm",1)) {
984 char buf[32];
985 snprintf(buf,sizeof(buf),"%lo",(unsigned long) server.unixsocketperm);
986 addReplyBulkCString(c,"unixsocketperm");
987 addReplyBulkCString(c,buf);
988 matches++;
989 }
990 if (stringmatch(pattern,"slaveof",1) ||
991 stringmatch(pattern,"replicaof",1))
992 {
993 char *optname = stringmatch(pattern,"slaveof",1) ?
994 "slaveof" : "replicaof";
995 char buf[256];
996
997 addReplyBulkCString(c,optname);
998 if (server.masterhost)
999 snprintf(buf,sizeof(buf),"%s %d",
1000 server.masterhost, server.masterport);
1001 else
1002 buf[0] = '\0';
1003 addReplyBulkCString(c,buf);
1004 matches++;
1005 }
1006 if (stringmatch(pattern,"notify-keyspace-events",1)) {
1007 sds flags = keyspaceEventsFlagsToString(server.notify_keyspace_events);
1008
1009 addReplyBulkCString(c,"notify-keyspace-events");
1010 addReplyBulkSds(c,flags);
1011 matches++;
1012 }
1013 if (stringmatch(pattern,"bind",1)) {
1014 sds aux = sdsjoin(server.bindaddr,server.bindaddr_count," ");
1015
1016 addReplyBulkCString(c,"bind");
1017 addReplyBulkCString(c,aux);
1018 sdsfree(aux);
1019 matches++;
1020 }
1021
1022 if (stringmatch(pattern,"oom-score-adj-values",0)) {
1023 sds buf = sdsempty();
1024 int j;
1025
1026 for (j = 0; j < CONFIG_OOM_COUNT3; j++) {
1027 buf = sdscatprintf(buf,"%d", server.oom_score_adj_values[j]);
1028 if (j != CONFIG_OOM_COUNT3-1)
1029 buf = sdscatlen(buf," ",1);
1030 }
1031
1032 addReplyBulkCString(c,"oom-score-adj-values");
1033 addReplyBulkCString(c,buf);
1034 sdsfree(buf);
1035 matches++;
1036 }
1037
1038 setDeferredMapLen(c,replylen,matches);
1039}
1040
1041/*-----------------------------------------------------------------------------
1042 * CONFIG REWRITE implementation
1043 *----------------------------------------------------------------------------*/
1044
1045#define REDIS_CONFIG_REWRITE_SIGNATURE"# Generated by CONFIG REWRITE" "# Generated by CONFIG REWRITE"
1046
1047/* We use the following dictionary type to store where a configuration
1048 * option is mentioned in the old configuration file, so it's
1049 * like "maxmemory" -> list of line numbers (first line is zero). */
1050uint64_t dictSdsCaseHash(const void *key);
1051int dictSdsKeyCaseCompare(void *privdata, const void *key1, const void *key2);
1052void dictSdsDestructor(void *privdata, void *val);
1053void dictListDestructor(void *privdata, void *val);
1054
1055/* Sentinel config rewriting is implemented inside sentinel.c by
1056 * rewriteConfigSentinelOption(). */
1057void rewriteConfigSentinelOption(struct rewriteConfigState *state);
1058
1059dictType optionToLineDictType = {
1060 dictSdsCaseHash, /* hash function */
1061 NULL((void*)0), /* key dup */
1062 NULL((void*)0), /* val dup */
1063 dictSdsKeyCaseCompare, /* key compare */
1064 dictSdsDestructor, /* key destructor */
1065 dictListDestructor, /* val destructor */
1066 NULL((void*)0) /* allow to expand */
1067};
1068
1069dictType optionSetDictType = {
1070 dictSdsCaseHash, /* hash function */
1071 NULL((void*)0), /* key dup */
1072 NULL((void*)0), /* val dup */
1073 dictSdsKeyCaseCompare, /* key compare */
1074 dictSdsDestructor, /* key destructor */
1075 NULL((void*)0), /* val destructor */
1076 NULL((void*)0) /* allow to expand */
1077};
1078
1079/* The config rewrite state. */
1080struct rewriteConfigState {
1081 dict *option_to_line; /* Option -> list of config file lines map */
1082 dict *rewritten; /* Dictionary of already processed options */
1083 int numlines; /* Number of lines in current config */
1084 sds *lines; /* Current lines as an array of sds strings */
1085 int has_tail; /* True if we already added directives that were
1086 not present in the original config file. */
1087 int force_all; /* True if we want all keywords to be force
1088 written. Currently only used for testing. */
1089};
1090
1091/* Append the new line to the current configuration state. */
1092void rewriteConfigAppendLine(struct rewriteConfigState *state, sds line) {
1093 state->lines = zrealloc(state->lines, sizeof(char*) * (state->numlines+1));
1094 state->lines[state->numlines++] = line;
1095}
1096
1097/* Populate the option -> list of line numbers map. */
1098void rewriteConfigAddLineNumberToOption(struct rewriteConfigState *state, sds option, int linenum) {
1099 list *l = dictFetchValue(state->option_to_line,option);
1100
1101 if (l == NULL((void*)0)) {
1102 l = listCreate();
1103 dictAdd(state->option_to_line,sdsdup(option),l);
1104 }
1105 listAddNodeTail(l,(void*)(long)linenum);
1106}
1107
1108/* Add the specified option to the set of processed options.
1109 * This is useful as only unused lines of processed options will be blanked
1110 * in the config file, while options the rewrite process does not understand
1111 * remain untouched. */
1112void rewriteConfigMarkAsProcessed(struct rewriteConfigState *state, const char *option) {
1113 sds opt = sdsnew(option);
1114
1115 if (dictAdd(state->rewritten,opt,NULL((void*)0)) != DICT_OK0) sdsfree(opt);
28
Assuming the condition is false
29
Taking false branch
1116}
30
Returning without writing to 'state->lines'
1117
1118/* Read the old file, split it into lines to populate a newly created
1119 * config rewrite state, and return it to the caller.
1120 *
1121 * If it is impossible to read the old file, NULL is returned.
1122 * If the old file does not exist at all, an empty state is returned. */
1123struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {
1124 FILE *fp = fopen(path,"r");
1125 if (fp == NULL((void*)0) && errno(*__errno_location ()) != ENOENT2) return NULL((void*)0);
13
Assuming 'fp' is equal to NULL
14
Assuming the condition is false
15
Taking false branch
1126
1127 char buf[CONFIG_MAX_LINE1024+1];
1128 int linenum = -1;
1129 struct rewriteConfigState *state = zmalloc(sizeof(*state));
1130 state->option_to_line = dictCreate(&optionToLineDictType,NULL((void*)0));
1131 state->rewritten = dictCreate(&optionSetDictType,NULL((void*)0));
1132 state->numlines = 0;
1133 state->lines = NULL((void*)0);
16
Null pointer value stored to field 'lines'
1134 state->has_tail = 0;
1135 state->force_all = 0;
1136 if (fp
16.1
'fp' is equal to NULL
== NULL((void*)0)) return state;
17
Taking true branch
1137
1138 /* Read the old file line by line, populate the state. */
1139 while(fgets(buf,CONFIG_MAX_LINE1024+1,fp) != NULL((void*)0)) {
1140 int argc;
1141 sds *argv;
1142 sds line = sdstrim(sdsnew(buf),"\r\n\t ");
1143
1144 linenum++; /* Zero based, so we init at -1 */
1145
1146 /* Handle comments and empty lines. */
1147 if (line[0] == '#' || line[0] == '\0') {
1148 if (!state->has_tail && !strcmp(line,REDIS_CONFIG_REWRITE_SIGNATURE"# Generated by CONFIG REWRITE"))
1149 state->has_tail = 1;
1150 rewriteConfigAppendLine(state,line);
1151 continue;
1152 }
1153
1154 /* Not a comment, split into arguments. */
1155 argv = sdssplitargs(line,&argc);
1156 if (argv == NULL((void*)0)) {
1157 /* Apparently the line is unparsable for some reason, for
1158 * instance it may have unbalanced quotes. Load it as a
1159 * comment. */
1160 sds aux = sdsnew("# ??? ");
1161 aux = sdscatsds(aux,line);
1162 sdsfree(line);
1163 rewriteConfigAppendLine(state,aux);
1164 continue;
1165 }
1166
1167 sdstolower(argv[0]); /* We only want lowercase config directives. */
1168
1169 /* Now we populate the state according to the content of this line.
1170 * Append the line and populate the option -> line numbers map. */
1171 rewriteConfigAppendLine(state,line);
1172
1173 /* Translate options using the word "slave" to the corresponding name
1174 * "replica", before adding such option to the config name -> lines
1175 * mapping. */
1176 char *p = strstr(argv[0],"slave");
1177 if (p) {
1178 sds alt = sdsempty();
1179 alt = sdscatlen(alt,argv[0],p-argv[0]);
1180 alt = sdscatlen(alt,"replica",7);
1181 alt = sdscatlen(alt,p+5,strlen(p+5));
1182 sdsfree(argv[0]);
1183 argv[0] = alt;
1184 }
1185 /* If this is sentinel config, we use sentinel "sentinel <config>" as option
1186 to avoid messing up the sequence. */
1187 if (server.sentinel_mode && argc > 1 && !strcasecmp(argv[0],"sentinel")) {
1188 sds sentinelOption = sdsempty();
1189 sentinelOption = sdscatfmt(sentinelOption,"%S %S",argv[0],argv[1]);
1190 rewriteConfigAddLineNumberToOption(state,sentinelOption,linenum);
1191 sdsfree(sentinelOption);
1192 } else {
1193 rewriteConfigAddLineNumberToOption(state,argv[0],linenum);
1194 }
1195 sdsfreesplitres(argv,argc);
1196 }
1197 fclose(fp);
1198 return state;
1199}
1200
1201/* Rewrite the specified configuration option with the new "line".
1202 * It progressively uses lines of the file that were already used for the same
1203 * configuration option in the old version of the file, removing that line from
1204 * the map of options -> line numbers.
1205 *
1206 * If there are lines associated with a given configuration option and
1207 * "force" is non-zero, the line is appended to the configuration file.
1208 * Usually "force" is true when an option has not its default value, so it
1209 * must be rewritten even if not present previously.
1210 *
1211 * The first time a line is appended into a configuration file, a comment
1212 * is added to show that starting from that point the config file was generated
1213 * by CONFIG REWRITE.
1214 *
1215 * "line" is either used, or freed, so the caller does not need to free it
1216 * in any way. */
1217void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force) {
1218 sds o = sdsnew(option);
1219 list *l = dictFetchValue(state->option_to_line,o);
1220
1221 rewriteConfigMarkAsProcessed(state,option);
27
Calling 'rewriteConfigMarkAsProcessed'
31
Returning from 'rewriteConfigMarkAsProcessed'
1222
1223 if (!l && !force && !state->force_all) {
32
Assuming 'l' is non-null
1224 /* Option not used previously, and we are not forced to use it. */
1225 sdsfree(line);
1226 sdsfree(o);
1227 return;
1228 }
1229
1230 if (l
32.1
'l' is non-null
) {
33
Taking true branch
1231 listNode *ln = listFirst(l)((l)->head);
1232 int linenum = (long) ln->value;
1233
1234 /* There are still lines in the old configuration file we can reuse
1235 * for this option. Replace the line with the new one. */
1236 listDelNode(l,ln);
1237 if (listLength(l)((l)->len) == 0) dictDelete(state->option_to_line,o);
34
Assuming field 'len' is not equal to 0
35
Taking false branch
1238 sdsfree(state->lines[linenum]);
36
Array access (via field 'lines') results in a null pointer dereference
1239 state->lines[linenum] = line;
1240 } else {
1241 /* Append a new line. */
1242 if (!state->has_tail) {
1243 rewriteConfigAppendLine(state,
1244 sdsnew(REDIS_CONFIG_REWRITE_SIGNATURE"# Generated by CONFIG REWRITE"));
1245 state->has_tail = 1;
1246 }
1247 rewriteConfigAppendLine(state,line);
1248 }
1249 sdsfree(o);
1250}
1251
1252/* Write the long long 'bytes' value as a string in a way that is parsable
1253 * inside redis.conf. If possible uses the GB, MB, KB notation. */
1254int rewriteConfigFormatMemory(char *buf, size_t len, long long bytes) {
1255 int gb = 1024*1024*1024;
1256 int mb = 1024*1024;
1257 int kb = 1024;
1258
1259 if (bytes && (bytes % gb) == 0) {
1260 return snprintf(buf,len,"%lldgb",bytes/gb);
1261 } else if (bytes && (bytes % mb) == 0) {
1262 return snprintf(buf,len,"%lldmb",bytes/mb);
1263 } else if (bytes && (bytes % kb) == 0) {
1264 return snprintf(buf,len,"%lldkb",bytes/kb);
1265 } else {
1266 return snprintf(buf,len,"%lld",bytes);
1267 }
1268}
1269
1270/* Rewrite a simple "option-name <bytes>" configuration option. */
1271void rewriteConfigBytesOption(struct rewriteConfigState *state, const char *option, long long value, long long defvalue) {
1272 char buf[64];
1273 int force = value != defvalue;
1274 sds line;
1275
1276 rewriteConfigFormatMemory(buf,sizeof(buf),value);
1277 line = sdscatprintf(sdsempty(),"%s %s",option,buf);
1278 rewriteConfigRewriteLine(state,option,line,force);
1279}
1280
1281/* Rewrite a yes/no option. */
1282void rewriteConfigYesNoOption(struct rewriteConfigState *state, const char *option, int value, int defvalue) {
1283 int force = value != defvalue;
1284 sds line = sdscatprintf(sdsempty(),"%s %s",option,
1285 value ? "yes" : "no");
1286
1287 rewriteConfigRewriteLine(state,option,line,force);
1288}
1289
1290/* Rewrite a string option. */
1291void rewriteConfigStringOption(struct rewriteConfigState *state, const char *option, char *value, const char *defvalue) {
1292 int force = 1;
1293 sds line;
1294
1295 /* String options set to NULL need to be not present at all in the
1296 * configuration file to be set to NULL again at the next reboot. */
1297 if (value == NULL((void*)0)) {
1298 rewriteConfigMarkAsProcessed(state,option);
1299 return;
1300 }
1301
1302 /* Set force to zero if the value is set to its default. */
1303 if (defvalue && strcmp(value,defvalue) == 0) force = 0;
1304
1305 line = sdsnew(option);
1306 line = sdscatlen(line, " ", 1);
1307 line = sdscatrepr(line, value, strlen(value));
1308
1309 rewriteConfigRewriteLine(state,option,line,force);
1310}
1311
1312/* Rewrite a SDS string option. */
1313void rewriteConfigSdsOption(struct rewriteConfigState *state, const char *option, sds value, const sds defvalue) {
1314 int force = 1;
1315 sds line;
1316
1317 /* If there is no value set, we don't want the SDS option
1318 * to be present in the configuration at all. */
1319 if (value == NULL((void*)0)) {
1320 rewriteConfigMarkAsProcessed(state, option);
1321 return;
1322 }
1323
1324 /* Set force to zero if the value is set to its default. */
1325 if (defvalue && sdscmp(value, defvalue) == 0) force = 0;
1326
1327 line = sdsnew(option);
1328 line = sdscatlen(line, " ", 1);
1329 line = sdscatrepr(line, value, sdslen(value));
1330
1331 rewriteConfigRewriteLine(state, option, line, force);
1332}
1333
1334/* Rewrite a numerical (long long range) option. */
1335void rewriteConfigNumericalOption(struct rewriteConfigState *state, const char *option, long long value, long long defvalue) {
1336 int force = value != defvalue;
1337 sds line = sdscatprintf(sdsempty(),"%s %lld",option,value);
1338
1339 rewriteConfigRewriteLine(state,option,line,force);
1340}
1341
1342/* Rewrite an octal option. */
1343void rewriteConfigOctalOption(struct rewriteConfigState *state, char *option, int value, int defvalue) {
1344 int force = value != defvalue;
1345 sds line = sdscatprintf(sdsempty(),"%s %o",option,value);
1346
1347 rewriteConfigRewriteLine(state,option,line,force);
1348}
1349
1350/* Rewrite an enumeration option. It takes as usually state and option name,
1351 * and in addition the enumeration array and the default value for the
1352 * option. */
1353void rewriteConfigEnumOption(struct rewriteConfigState *state, const char *option, int value, configEnum *ce, int defval) {
1354 sds line;
1355 const char *name = configEnumGetNameOrUnknown(ce,value);
1356 int force = value != defval;
1357
1358 line = sdscatprintf(sdsempty(),"%s %s",option,name);
1359 rewriteConfigRewriteLine(state,option,line,force);
1360}
1361
1362/* Rewrite the save option. */
1363void rewriteConfigSaveOption(struct rewriteConfigState *state) {
1364 int j;
1365 sds line;
1366
1367 /* In Sentinel mode we don't need to rewrite the save parameters */
1368 if (server.sentinel_mode) {
1369 rewriteConfigMarkAsProcessed(state,"save");
1370 return;
1371 }
1372
1373 /* Note that if there are no save parameters at all, all the current
1374 * config line with "save" will be detected as orphaned and deleted,
1375 * resulting into no RDB persistence as expected. */
1376 for (j = 0; j < server.saveparamslen; j++) {
1377 line = sdscatprintf(sdsempty(),"save %ld %d",
1378 (long) server.saveparams[j].seconds, server.saveparams[j].changes);
1379 rewriteConfigRewriteLine(state,"save",line,1);
1380 }
1381 /* Mark "save" as processed in case server.saveparamslen is zero. */
1382 rewriteConfigMarkAsProcessed(state,"save");
1383}
1384
1385/* Rewrite the user option. */
1386void rewriteConfigUserOption(struct rewriteConfigState *state) {
1387 /* If there is a user file defined we just mark this configuration
1388 * directive as processed, so that all the lines containing users
1389 * inside the config file gets discarded. */
1390 if (server.acl_filename[0] != '\0') {
1391 rewriteConfigMarkAsProcessed(state,"user");
1392 return;
1393 }
1394
1395 /* Otherwise scan the list of users and rewrite every line. Note that
1396 * in case the list here is empty, the effect will just be to comment
1397 * all the users directive inside the config file. */
1398 raxIterator ri;
1399 raxStart(&ri,Users);
1400 raxSeek(&ri,"^",NULL((void*)0),0);
1401 while(raxNext(&ri)) {
1402 user *u = ri.data;
1403 sds line = sdsnew("user ");
1404 line = sdscatsds(line,u->name);
1405 line = sdscatlen(line," ",1);
1406 sds descr = ACLDescribeUser(u);
1407 line = sdscatsds(line,descr);
1408 sdsfree(descr);
1409 rewriteConfigRewriteLine(state,"user",line,1);
1410 }
1411 raxStop(&ri);
1412
1413 /* Mark "user" as processed in case there are no defined users. */
1414 rewriteConfigMarkAsProcessed(state,"user");
1415}
1416
1417/* Rewrite the dir option, always using absolute paths.*/
1418void rewriteConfigDirOption(struct rewriteConfigState *state) {
1419 char cwd[1024];
1420
1421 if (getcwd(cwd,sizeof(cwd)) == NULL((void*)0)) {
1422 rewriteConfigMarkAsProcessed(state,"dir");
1423 return; /* no rewrite on error. */
1424 }
1425 rewriteConfigStringOption(state,"dir",cwd,NULL((void*)0));
1426}
1427
1428/* Rewrite the slaveof option. */
1429void rewriteConfigSlaveofOption(struct rewriteConfigState *state, char *option) {
1430 sds line;
1431
1432 /* If this is a master, we want all the slaveof config options
1433 * in the file to be removed. Note that if this is a cluster instance
1434 * we don't want a slaveof directive inside redis.conf. */
1435 if (server.cluster_enabled || server.masterhost == NULL((void*)0)) {
1436 rewriteConfigMarkAsProcessed(state,option);
1437 return;
1438 }
1439 line = sdscatprintf(sdsempty(),"%s %s %d", option,
1440 server.masterhost, server.masterport);
1441 rewriteConfigRewriteLine(state,option,line,1);
1442}
1443
1444/* Rewrite the notify-keyspace-events option. */
1445void rewriteConfigNotifykeyspaceeventsOption(struct rewriteConfigState *state) {
1446 int force = server.notify_keyspace_events != 0;
1447 char *option = "notify-keyspace-events";
1448 sds line, flags;
1449
1450 flags = keyspaceEventsFlagsToString(server.notify_keyspace_events);
1451 line = sdsnew(option);
1452 line = sdscatlen(line, " ", 1);
1453 line = sdscatrepr(line, flags, sdslen(flags));
1454 sdsfree(flags);
1455 rewriteConfigRewriteLine(state,option,line,force);
1456}
1457
1458/* Rewrite the client-output-buffer-limit option. */
1459void rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state) {
1460 int j;
1461 char *option = "client-output-buffer-limit";
1462
1463 for (j = 0; j < CLIENT_TYPE_OBUF_COUNT3; j++) {
1464 int force = (server.client_obuf_limits[j].hard_limit_bytes !=
1465 clientBufferLimitsDefaults[j].hard_limit_bytes) ||
1466 (server.client_obuf_limits[j].soft_limit_bytes !=
1467 clientBufferLimitsDefaults[j].soft_limit_bytes) ||
1468 (server.client_obuf_limits[j].soft_limit_seconds !=
1469 clientBufferLimitsDefaults[j].soft_limit_seconds);
1470 sds line;
1471 char hard[64], soft[64];
1472
1473 rewriteConfigFormatMemory(hard,sizeof(hard),
1474 server.client_obuf_limits[j].hard_limit_bytes);
1475 rewriteConfigFormatMemory(soft,sizeof(soft),
1476 server.client_obuf_limits[j].soft_limit_bytes);
1477
1478 char *typename = getClientTypeName(j);
1479 if (!strcmp(typename,"slave")) typename = "replica";
1480 line = sdscatprintf(sdsempty(),"%s %s %s %s %ld",
1481 option, typename, hard, soft,
1482 (long) server.client_obuf_limits[j].soft_limit_seconds);
1483 rewriteConfigRewriteLine(state,option,line,force);
1484 }
1485}
1486
1487/* Rewrite the oom-score-adj-values option. */
1488void rewriteConfigOOMScoreAdjValuesOption(struct rewriteConfigState *state) {
1489 int force = 0;
1490 int j;
1491 char *option = "oom-score-adj-values";
1492 sds line;
1493
1494 line = sdsnew(option);
1495 line = sdscatlen(line, " ", 1);
1496 for (j = 0; j < CONFIG_OOM_COUNT3; j++) {
1497 if (server.oom_score_adj_values[j] != configOOMScoreAdjValuesDefaults[j])
1498 force = 1;
1499
1500 line = sdscatprintf(line, "%d", server.oom_score_adj_values[j]);
1501 if (j+1 != CONFIG_OOM_COUNT3)
1502 line = sdscatlen(line, " ", 1);
1503 }
1504 rewriteConfigRewriteLine(state,option,line,force);
1505}
1506
1507/* Rewrite the bind option. */
1508void rewriteConfigBindOption(struct rewriteConfigState *state) {
1509 int force = 1;
1510 sds line, addresses;
1511 char *option = "bind";
1512
1513 /* Nothing to rewrite if we don't have bind addresses. */
1514 if (server.bindaddr_count == 0) {
24
Assuming field 'bindaddr_count' is not equal to 0
25
Taking false branch
1515 rewriteConfigMarkAsProcessed(state,option);
1516 return;
1517 }
1518
1519 /* Rewrite as bind <addr1> <addr2> ... <addrN> */
1520 addresses = sdsjoin(server.bindaddr,server.bindaddr_count," ");
1521 line = sdsnew(option);
1522 line = sdscatlen(line, " ", 1);
1523 line = sdscatsds(line, addresses);
1524 sdsfree(addresses);
1525
1526 rewriteConfigRewriteLine(state,option,line,force);
26
Calling 'rewriteConfigRewriteLine'
1527}
1528
1529/* Glue together the configuration lines in the current configuration
1530 * rewrite state into a single string, stripping multiple empty lines. */
1531sds rewriteConfigGetContentFromState(struct rewriteConfigState *state) {
1532 sds content = sdsempty();
1533 int j, was_empty = 0;
1534
1535 for (j = 0; j < state->numlines; j++) {
1536 /* Every cluster of empty lines is turned into a single empty line. */
1537 if (sdslen(state->lines[j]) == 0) {
1538 if (was_empty) continue;
1539 was_empty = 1;
1540 } else {
1541 was_empty = 0;
1542 }
1543 content = sdscatsds(content,state->lines[j]);
1544 content = sdscatlen(content,"\n",1);
1545 }
1546 return content;
1547}
1548
1549/* Free the configuration rewrite state. */
1550void rewriteConfigReleaseState(struct rewriteConfigState *state) {
1551 sdsfreesplitres(state->lines,state->numlines);
1552 dictRelease(state->option_to_line);
1553 dictRelease(state->rewritten);
1554 zfree(state);
1555}
1556
1557/* At the end of the rewrite process the state contains the remaining
1558 * map between "option name" => "lines in the original config file".
1559 * Lines used by the rewrite process were removed by the function
1560 * rewriteConfigRewriteLine(), all the other lines are "orphaned" and
1561 * should be replaced by empty lines.
1562 *
1563 * This function does just this, iterating all the option names and
1564 * blanking all the lines still associated. */
1565void rewriteConfigRemoveOrphaned(struct rewriteConfigState *state) {
1566 dictIterator *di = dictGetIterator(state->option_to_line);
1567 dictEntry *de;
1568
1569 while((de = dictNext(di)) != NULL((void*)0)) {
1570 list *l = dictGetVal(de)((de)->v.val);
1571 sds option = dictGetKey(de)((de)->key);
1572
1573 /* Don't blank lines about options the rewrite process
1574 * don't understand. */
1575 if (dictFind(state->rewritten,option) == NULL((void*)0)) {
1576 serverLog(LL_DEBUG0,"Not rewritten option: %s", option);
1577 continue;
1578 }
1579
1580 while(listLength(l)((l)->len)) {
1581 listNode *ln = listFirst(l)((l)->head);
1582 int linenum = (long) ln->value;
1583
1584 sdsfree(state->lines[linenum]);
1585 state->lines[linenum] = sdsempty();
1586 listDelNode(l,ln);
1587 }
1588 }
1589 dictReleaseIterator(di);
1590}
1591
1592/* This function replaces the old configuration file with the new content
1593 * in an atomic manner.
1594 *
1595 * The function returns 0 on success, otherwise -1 is returned and errno
1596 * is set accordingly. */
1597int rewriteConfigOverwriteFile(char *configfile, sds content) {
1598 int fd = -1;
1599 int retval = -1;
1600 char tmp_conffile[PATH_MAX4096];
1601 const char *tmp_suffix = ".XXXXXX";
1602 size_t offset = 0;
1603 ssize_t written_bytes = 0;
1604
1605 int tmp_path_len = snprintf(tmp_conffile, sizeof(tmp_conffile), "%s%s", configfile, tmp_suffix);
1606 if (tmp_path_len <= 0 || (unsigned int)tmp_path_len >= sizeof(tmp_conffile)) {
1607 serverLog(LL_WARNING3, "Config file full path is too long");
1608 errno(*__errno_location ()) = ENAMETOOLONG36;
1609 return retval;
1610 }
1611
1612#ifdef _GNU_SOURCE
1613 fd = mkostemp(tmp_conffile, O_CLOEXEC02000000);
1614#else
1615 /* There's a theoretical chance here to leak the FD if a module thread forks & execv in the middle */
1616 fd = mkstemp(tmp_conffile);
1617#endif
1618
1619 if (fd == -1) {
1620 serverLog(LL_WARNING3, "Could not create tmp config file (%s)", strerror(errno(*__errno_location ())));
1621 return retval;
1622 }
1623
1624 while (offset < sdslen(content)) {
1625 written_bytes = write(fd, content + offset, sdslen(content) - offset);
1626 if (written_bytes <= 0) {
1627 if (errno(*__errno_location ()) == EINTR4) continue; /* FD is blocking, no other retryable errors */
1628 serverLog(LL_WARNING3, "Failed after writing (%zd) bytes to tmp config file (%s)", offset, strerror(errno(*__errno_location ())));
1629 goto cleanup;
1630 }
1631 offset+=written_bytes;
1632 }
1633
1634 if (fsync(fd))
1635 serverLog(LL_WARNING3, "Could not sync tmp config file to disk (%s)", strerror(errno(*__errno_location ())));
1636 else if (fchmod(fd, 0644 & ~server.umask) == -1)
1637 serverLog(LL_WARNING3, "Could not chmod config file (%s)", strerror(errno(*__errno_location ())));
1638 else if (rename(tmp_conffile, configfile) == -1)
1639 serverLog(LL_WARNING3, "Could not rename tmp config file (%s)", strerror(errno(*__errno_location ())));
1640 else {
1641 retval = 0;
1642 serverLog(LL_DEBUG0, "Rewritten config file (%s) successfully", configfile);
1643 }
1644
1645cleanup:
1646 close(fd);
1647 if (retval) unlink(tmp_conffile);
1648 return retval;
1649}
1650
1651/* Rewrite the configuration file at "path".
1652 * If the configuration file already exists, we try at best to retain comments
1653 * and overall structure.
1654 *
1655 * Configuration parameters that are at their default value, unless already
1656 * explicitly included in the old configuration file, are not rewritten.
1657 * The force_all flag overrides this behavior and forces everything to be
1658 * written. This is currently only used for testing purposes.
1659 *
1660 * On error -1 is returned and errno is set accordingly, otherwise 0. */
1661int rewriteConfig(char *path, int force_all) {
1662 struct rewriteConfigState *state;
1663 sds newcontent;
1664 int retval;
1665
1666 /* Step 1: read the old config into our rewrite state. */
1667 if ((state = rewriteConfigReadOldFile(path)) == NULL((void*)0)) return -1;
12
Calling 'rewriteConfigReadOldFile'
18
Returning from 'rewriteConfigReadOldFile'
19
Taking false branch
1668 if (force_all
19.1
'force_all' is 0
) state->force_all = 1;
20
Taking false branch
1669
1670 /* Step 2: rewrite every single option, replacing or appending it inside
1671 * the rewrite state. */
1672
1673 /* Iterate the configs that are standard */
1674 for (standardConfig *config = configs; config->name != NULL((void*)0); config++) {
21
Assuming field 'name' is equal to NULL
22
Loop condition is false. Execution continues on line 1678
1675 config->interface.rewrite(config->data, config->name, state);
1676 }
1677
1678 rewriteConfigBindOption(state);
23
Calling 'rewriteConfigBindOption'
1679 rewriteConfigOctalOption(state,"unixsocketperm",server.unixsocketperm,CONFIG_DEFAULT_UNIX_SOCKET_PERM0);
1680 rewriteConfigStringOption(state,"logfile",server.logfile,CONFIG_DEFAULT_LOGFILE"");
1681 rewriteConfigSaveOption(state);
1682 rewriteConfigUserOption(state);
1683 rewriteConfigDirOption(state);
1684 rewriteConfigSlaveofOption(state,"replicaof");
1685 rewriteConfigStringOption(state,"cluster-config-file",server.cluster_configfile,CONFIG_DEFAULT_CLUSTER_CONFIG_FILE"nodes.conf");
1686 rewriteConfigNotifykeyspaceeventsOption(state);
1687 rewriteConfigClientoutputbufferlimitOption(state);
1688 rewriteConfigOOMScoreAdjValuesOption(state);
1689
1690 /* Rewrite Sentinel config if in Sentinel mode. */
1691 if (server.sentinel_mode) rewriteConfigSentinelOption(state);
1692
1693 /* Step 3: remove all the orphaned lines in the old file, that is, lines
1694 * that were used by a config option and are no longer used, like in case
1695 * of multiple "save" options or duplicated options. */
1696 rewriteConfigRemoveOrphaned(state);
1697
1698 /* Step 4: generate a new configuration file from the modified state
1699 * and write it into the original file. */
1700 newcontent = rewriteConfigGetContentFromState(state);
1701 retval = rewriteConfigOverwriteFile(server.configfile,newcontent);
1702
1703 sdsfree(newcontent);
1704 rewriteConfigReleaseState(state);
1705 return retval;
1706}
1707
1708/*-----------------------------------------------------------------------------
1709 * Configs that fit one of the major types and require no special handling
1710 *----------------------------------------------------------------------------*/
1711#define LOADBUF_SIZE256 256
1712static char loadbuf[LOADBUF_SIZE256];
1713
1714#define MODIFIABLE_CONFIG1 1
1715#define IMMUTABLE_CONFIG0 0
1716
1717#define embedCommonConfig(config_name, config_alias, is_modifiable).name = (config_name), .alias = (config_alias), .modifiable =
(is_modifiable),
\
1718 .name = (config_name), \
1719 .alias = (config_alias), \
1720 .modifiable = (is_modifiable),
1721
1722#define embedConfigInterface(initfn, setfn, getfn, rewritefn).interface = { .init = (initfn), .set = (setfn), .get = (getfn
), .rewrite = (rewritefn) },
.interface = { \
1723 .init = (initfn), \
1724 .set = (setfn), \
1725 .get = (getfn), \
1726 .rewrite = (rewritefn) \
1727},
1728
1729/* What follows is the generic config types that are supported. To add a new
1730 * config with one of these types, add it to the standardConfig table with
1731 * the creation macro for each type.
1732 *
1733 * Each type contains the following:
1734 * * A function defining how to load this type on startup.
1735 * * A function defining how to update this type on CONFIG SET.
1736 * * A function defining how to serialize this type on CONFIG SET.
1737 * * A function defining how to rewrite this type on CONFIG REWRITE.
1738 * * A Macro defining how to create this type.
1739 */
1740
1741/* Bool Configs */
1742static void boolConfigInit(typeData data) {
1743 *data.yesno.config = data.yesno.default_value;
1744}
1745
1746static int boolConfigSet(typeData data, sds value, int update, const char **err) {
1747 int yn = yesnotoi(value);
1748 if (yn == -1) {
1749 *err = "argument must be 'yes' or 'no'";
1750 return 0;
1751 }
1752 if (data.yesno.is_valid_fn && !data.yesno.is_valid_fn(yn, err))
1753 return 0;
1754 int prev = *(data.yesno.config);
1755 *(data.yesno.config) = yn;
1756 if (update && data.yesno.update_fn && !data.yesno.update_fn(yn, prev, err)) {
1757 *(data.yesno.config) = prev;
1758 return 0;
1759 }
1760 return 1;
1761}
1762
1763static void boolConfigGet(client *c, typeData data) {
1764 addReplyBulkCString(c, *data.yesno.config ? "yes" : "no");
1765}
1766
1767static void boolConfigRewrite(typeData data, const char *name, struct rewriteConfigState *state) {
1768 rewriteConfigYesNoOption(state, name,*(data.yesno.config), data.yesno.default_value);
1769}
1770
1771#define createBoolConfig(name, alias, modifiable, config_addr, default, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(config_addr), .default_value =
(default), .is_valid_fn = (is_valid), .update_fn = (update),
} }
{ \
1772 embedCommonConfig(name, alias, modifiable).name = (name), .alias = (alias), .modifiable = (modifiable), \
1773 embedConfigInterface(boolConfigInit, boolConfigSet, boolConfigGet, boolConfigRewrite).interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) },
\
1774 .data.yesno = { \
1775 .config = &(config_addr), \
1776 .default_value = (default), \
1777 .is_valid_fn = (is_valid), \
1778 .update_fn = (update), \
1779 } \
1780}
1781
1782/* String Configs */
1783static void stringConfigInit(typeData data) {
1784 *data.string.config = (data.string.convert_empty_to_null && !data.string.default_value) ? NULL((void*)0) : zstrdup(data.string.default_value);
1785}
1786
1787static int stringConfigSet(typeData data, sds value, int update, const char **err) {
1788 if (data.string.is_valid_fn && !data.string.is_valid_fn(value, err))
1789 return 0;
1790 char *prev = *data.string.config;
1791 *data.string.config = (data.string.convert_empty_to_null && !value[0]) ? NULL((void*)0) : zstrdup(value);
1792 if (update && data.string.update_fn && !data.string.update_fn(*data.string.config, prev, err)) {
1793 zfree(*data.string.config);
1794 *data.string.config = prev;
1795 return 0;
1796 }
1797 zfree(prev);
1798 return 1;
1799}
1800
1801static void stringConfigGet(client *c, typeData data) {
1802 addReplyBulkCString(c, *data.string.config ? *data.string.config : "");
1803}
1804
1805static void stringConfigRewrite(typeData data, const char *name, struct rewriteConfigState *state) {
1806 rewriteConfigStringOption(state, name,*(data.string.config), data.string.default_value);
1807}
1808
1809/* SDS Configs */
1810static void sdsConfigInit(typeData data) {
1811 *data.sds.config = (data.sds.convert_empty_to_null && !data.sds.default_value) ? NULL((void*)0): sdsnew(data.sds.default_value);
1812}
1813
1814static int sdsConfigSet(typeData data, sds value, int update, const char **err) {
1815 if (data.sds.is_valid_fn && !data.sds.is_valid_fn(value, err))
1816 return 0;
1817 sds prev = *data.sds.config;
1818 *data.sds.config = (data.sds.convert_empty_to_null && (sdslen(value) == 0)) ? NULL((void*)0) : sdsdup(value);
1819 if (update && data.sds.update_fn && !data.sds.update_fn(*data.sds.config, prev, err)) {
1820 sdsfree(*data.sds.config);
1821 *data.sds.config = prev;
1822 return 0;
1823 }
1824 sdsfree(prev);
1825 return 1;
1826}
1827
1828static void sdsConfigGet(client *c, typeData data) {
1829 if (*data.sds.config) {
1830 addReplyBulkSds(c, sdsdup(*data.sds.config));
1831 } else {
1832 addReplyBulkCString(c, "");
1833 }
1834}
1835
1836static void sdsConfigRewrite(typeData data, const char *name, struct rewriteConfigState *state) {
1837 rewriteConfigSdsOption(state, name, *(data.sds.config), data.sds.default_value ? sdsnew(data.sds.default_value) : NULL((void*)0));
1838}
1839
1840
1841#define ALLOW_EMPTY_STRING0 0
1842#define EMPTY_STRING_IS_NULL1 1
1843
1844#define createStringConfig(name, alias, modifiable, empty_to_null, config_addr, default, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(config_addr), .default_value
= (default), .is_valid_fn = (is_valid), .update_fn = (update
), .convert_empty_to_null = (empty_to_null), } }
{ \
1845 embedCommonConfig(name, alias, modifiable).name = (name), .alias = (alias), .modifiable = (modifiable), \
1846 embedConfigInterface(stringConfigInit, stringConfigSet, stringConfigGet, stringConfigRewrite).interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
},
\
1847 .data.string = { \
1848 .config = &(config_addr), \
1849 .default_value = (default), \
1850 .is_valid_fn = (is_valid), \
1851 .update_fn = (update), \
1852 .convert_empty_to_null = (empty_to_null), \
1853 } \
1854}
1855
1856#define createSDSConfig(name, alias, modifiable, empty_to_null, config_addr, default, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (sdsConfigInit), .set = (sdsConfigSet
), .get = (sdsConfigGet), .rewrite = (sdsConfigRewrite) }, .data
.sds = { .config = &(config_addr), .default_value = (default
), .is_valid_fn = (is_valid), .update_fn = (update), .convert_empty_to_null
= (empty_to_null), } }
{ \
1857 embedCommonConfig(name, alias, modifiable).name = (name), .alias = (alias), .modifiable = (modifiable), \
1858 embedConfigInterface(sdsConfigInit, sdsConfigSet, sdsConfigGet, sdsConfigRewrite).interface = { .init = (sdsConfigInit), .set = (sdsConfigSet)
, .get = (sdsConfigGet), .rewrite = (sdsConfigRewrite) },
\
1859 .data.sds = { \
1860 .config = &(config_addr), \
1861 .default_value = (default), \
1862 .is_valid_fn = (is_valid), \
1863 .update_fn = (update), \
1864 .convert_empty_to_null = (empty_to_null), \
1865 } \
1866}
1867
1868/* Enum configs */
1869static void enumConfigInit(typeData data) {
1870 *data.enumd.config = data.enumd.default_value;
1871}
1872
1873static int enumConfigSet(typeData data, sds value, int update, const char **err) {
1874 int enumval = configEnumGetValue(data.enumd.enum_value, value);
1875 if (enumval == INT_MIN(-2147483647 -1)) {
1876 sds enumerr = sdsnew("argument must be one of the following: ");
1877 configEnum *enumNode = data.enumd.enum_value;
1878 while(enumNode->name != NULL((void*)0)) {
1879 enumerr = sdscatlen(enumerr, enumNode->name,
1880 strlen(enumNode->name));
1881 enumerr = sdscatlen(enumerr, ", ", 2);
1882 enumNode++;
1883 }
1884 sdsrange(enumerr,0,-3); /* Remove final ", ". */
1885
1886 strncpy(loadbuf, enumerr, LOADBUF_SIZE256);
1887 loadbuf[LOADBUF_SIZE256 - 1] = '\0';
1888
1889 sdsfree(enumerr);
1890 *err = loadbuf;
1891 return 0;
1892 }
1893 if (data.enumd.is_valid_fn && !data.enumd.is_valid_fn(enumval, err))
1894 return 0;
1895 int prev = *(data.enumd.config);
1896 *(data.enumd.config) = enumval;
1897 if (update && data.enumd.update_fn && !data.enumd.update_fn(enumval, prev, err)) {
1898 *(data.enumd.config) = prev;
1899 return 0;
1900 }
1901 return 1;
1902}
1903
1904static void enumConfigGet(client *c, typeData data) {
1905 addReplyBulkCString(c, configEnumGetNameOrUnknown(data.enumd.enum_value,*data.enumd.config));
1906}
1907
1908static void enumConfigRewrite(typeData data, const char *name, struct rewriteConfigState *state) {
1909 rewriteConfigEnumOption(state, name,*(data.enumd.config), data.enumd.enum_value, data.enumd.default_value);
1910}
1911
1912#define createEnumConfig(name, alias, modifiable, enum, config_addr, default, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(config_addr), .default_value =
(default), .is_valid_fn = (is_valid), .update_fn = (update),
.enum_value = (enum), } }
{ \
1913 embedCommonConfig(name, alias, modifiable).name = (name), .alias = (alias), .modifiable = (modifiable), \
1914 embedConfigInterface(enumConfigInit, enumConfigSet, enumConfigGet, enumConfigRewrite).interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) },
\
1915 .data.enumd = { \
1916 .config = &(config_addr), \
1917 .default_value = (default), \
1918 .is_valid_fn = (is_valid), \
1919 .update_fn = (update), \
1920 .enum_value = (enum), \
1921 } \
1922}
1923
1924/* Gets a 'long long val' and sets it into the union, using a macro to get
1925 * compile time type check. */
1926#define SET_NUMERIC_TYPE(val)if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { *(data.numeric
.config.i) = (int) val; } else if (data.numeric.numeric_type ==
NUMERIC_TYPE_UINT) { *(data.numeric.config.ui) = (unsigned int
) val; } else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG
) { *(data.numeric.config.l) = (long) val; } else if (data.numeric
.numeric_type == NUMERIC_TYPE_ULONG) { *(data.numeric.config.
ul) = (unsigned long) val; } else if (data.numeric.numeric_type
== NUMERIC_TYPE_LONG_LONG) { *(data.numeric.config.ll) = (long
long) val; } else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG
) { *(data.numeric.config.ull) = (unsigned long long) val; } else
if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) { *(data
.numeric.config.st) = (size_t) val; } else if (data.numeric.numeric_type
== NUMERIC_TYPE_SSIZE_T) { *(data.numeric.config.sst) = (ssize_t
) val; } else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T
) { *(data.numeric.config.ot) = (off_t) val; } else if (data.
numeric.numeric_type == NUMERIC_TYPE_TIME_T) { *(data.numeric
.config.tt) = (time_t) val; }
\
1927 if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { \
1928 *(data.numeric.config.i) = (int) val; \
1929 } else if (data.numeric.numeric_type == NUMERIC_TYPE_UINT) { \
1930 *(data.numeric.config.ui) = (unsigned int) val; \
1931 } else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG) { \
1932 *(data.numeric.config.l) = (long) val; \
1933 } else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG) { \
1934 *(data.numeric.config.ul) = (unsigned long) val; \
1935 } else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) { \
1936 *(data.numeric.config.ll) = (long long) val; \
1937 } else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG) { \
1938 *(data.numeric.config.ull) = (unsigned long long) val; \
1939 } else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) { \
1940 *(data.numeric.config.st) = (size_t) val; \
1941 } else if (data.numeric.numeric_type == NUMERIC_TYPE_SSIZE_T) { \
1942 *(data.numeric.config.sst) = (ssize_t) val; \
1943 } else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T) { \
1944 *(data.numeric.config.ot) = (off_t) val; \
1945 } else if (data.numeric.numeric_type == NUMERIC_TYPE_TIME_T) { \
1946 *(data.numeric.config.tt) = (time_t) val; \
1947 }
1948
1949/* Gets a 'long long val' and sets it with the value from the union, using a
1950 * macro to get compile time type check. */
1951#define GET_NUMERIC_TYPE(val)if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { val = *(
data.numeric.config.i); } else if (data.numeric.numeric_type ==
NUMERIC_TYPE_UINT) { val = *(data.numeric.config.ui); } else
if (data.numeric.numeric_type == NUMERIC_TYPE_LONG) { val = *
(data.numeric.config.l); } else if (data.numeric.numeric_type
== NUMERIC_TYPE_ULONG) { val = *(data.numeric.config.ul); } else
if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) { val
= *(data.numeric.config.ll); } else if (data.numeric.numeric_type
== NUMERIC_TYPE_ULONG_LONG) { val = *(data.numeric.config.ull
); } else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T
) { val = *(data.numeric.config.st); } else if (data.numeric.
numeric_type == NUMERIC_TYPE_SSIZE_T) { val = *(data.numeric.
config.sst); } else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T
) { val = *(data.numeric.config.ot); } else if (data.numeric.
numeric_type == NUMERIC_TYPE_TIME_T) { val = *(data.numeric.config
.tt); }
\
1952 if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { \
1953 val = *(data.numeric.config.i); \
1954 } else if (data.numeric.numeric_type == NUMERIC_TYPE_UINT) { \
1955 val = *(data.numeric.config.ui); \
1956 } else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG) { \
1957 val = *(data.numeric.config.l); \
1958 } else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG) { \
1959 val = *(data.numeric.config.ul); \
1960 } else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG) { \
1961 val = *(data.numeric.config.ll); \
1962 } else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG) { \
1963 val = *(data.numeric.config.ull); \
1964 } else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) { \
1965 val = *(data.numeric.config.st); \
1966 } else if (data.numeric.numeric_type == NUMERIC_TYPE_SSIZE_T) { \
1967 val = *(data.numeric.config.sst); \
1968 } else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T) { \
1969 val = *(data.numeric.config.ot); \
1970 } else if (data.numeric.numeric_type == NUMERIC_TYPE_TIME_T) { \
1971 val = *(data.numeric.config.tt); \
1972 }
1973
1974/* Numeric configs */
1975static void numericConfigInit(typeData data) {
1976 SET_NUMERIC_TYPE(data.numeric.default_value)if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { *(data.numeric
.config.i) = (int) data.numeric.default_value; } else if (data
.numeric.numeric_type == NUMERIC_TYPE_UINT) { *(data.numeric.
config.ui) = (unsigned int) data.numeric.default_value; } else
if (data.numeric.numeric_type == NUMERIC_TYPE_LONG) { *(data
.numeric.config.l) = (long) data.numeric.default_value; } else
if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG) { *(data
.numeric.config.ul) = (unsigned long) data.numeric.default_value
; } else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG
) { *(data.numeric.config.ll) = (long long) data.numeric.default_value
; } else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG
) { *(data.numeric.config.ull) = (unsigned long long) data.numeric
.default_value; } else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T
) { *(data.numeric.config.st) = (size_t) data.numeric.default_value
; } else if (data.numeric.numeric_type == NUMERIC_TYPE_SSIZE_T
) { *(data.numeric.config.sst) = (ssize_t) data.numeric.default_value
; } else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T)
{ *(data.numeric.config.ot) = (off_t) data.numeric.default_value
; } else if (data.numeric.numeric_type == NUMERIC_TYPE_TIME_T
) { *(data.numeric.config.tt) = (time_t) data.numeric.default_value
; }
1977}
1978
1979static int numericBoundaryCheck(typeData data, long long ll, const char **err) {
1980 if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG ||
1981 data.numeric.numeric_type == NUMERIC_TYPE_UINT ||
1982 data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) {
1983 /* Boundary check for unsigned types */
1984 unsigned long long ull = ll;
1985 unsigned long long upper_bound = data.numeric.upper_bound;
1986 unsigned long long lower_bound = data.numeric.lower_bound;
1987 if (ull > upper_bound || ull < lower_bound) {
1988 snprintf(loadbuf, LOADBUF_SIZE256,
1989 "argument must be between %llu and %llu inclusive",
1990 lower_bound,
1991 upper_bound);
1992 *err = loadbuf;
1993 return 0;
1994 }
1995 } else {
1996 /* Boundary check for signed types */
1997 if (ll > data.numeric.upper_bound || ll < data.numeric.lower_bound) {
1998 snprintf(loadbuf, LOADBUF_SIZE256,
1999 "argument must be between %lld and %lld inclusive",
2000 data.numeric.lower_bound,
2001 data.numeric.upper_bound);
2002 *err = loadbuf;
2003 return 0;
2004 }
2005 }
2006 return 1;
2007}
2008
2009static int numericConfigSet(typeData data, sds value, int update, const char **err) {
2010 long long ll, prev = 0;
2011 if (data.numeric.is_memory) {
2012 int memerr;
2013 ll = memtoll(value, &memerr);
2014 if (memerr || ll < 0) {
2015 *err = "argument must be a memory value";
2016 return 0;
2017 }
2018 } else {
2019 if (!string2ll(value, sdslen(value),&ll)) {
2020 *err = "argument couldn't be parsed into an integer" ;
2021 return 0;
2022 }
2023 }
2024
2025 if (!numericBoundaryCheck(data, ll, err))
2026 return 0;
2027
2028 if (data.numeric.is_valid_fn && !data.numeric.is_valid_fn(ll, err))
2029 return 0;
2030
2031 GET_NUMERIC_TYPE(prev)if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { prev = *
(data.numeric.config.i); } else if (data.numeric.numeric_type
== NUMERIC_TYPE_UINT) { prev = *(data.numeric.config.ui); } else
if (data.numeric.numeric_type == NUMERIC_TYPE_LONG) { prev =
*(data.numeric.config.l); } else if (data.numeric.numeric_type
== NUMERIC_TYPE_ULONG) { prev = *(data.numeric.config.ul); }
else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG
) { prev = *(data.numeric.config.ll); } else if (data.numeric
.numeric_type == NUMERIC_TYPE_ULONG_LONG) { prev = *(data.numeric
.config.ull); } else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T
) { prev = *(data.numeric.config.st); } else if (data.numeric
.numeric_type == NUMERIC_TYPE_SSIZE_T) { prev = *(data.numeric
.config.sst); } else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T
) { prev = *(data.numeric.config.ot); } else if (data.numeric
.numeric_type == NUMERIC_TYPE_TIME_T) { prev = *(data.numeric
.config.tt); }
2032 SET_NUMERIC_TYPE(ll)if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { *(data.numeric
.config.i) = (int) ll; } else if (data.numeric.numeric_type ==
NUMERIC_TYPE_UINT) { *(data.numeric.config.ui) = (unsigned int
) ll; } else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG
) { *(data.numeric.config.l) = (long) ll; } else if (data.numeric
.numeric_type == NUMERIC_TYPE_ULONG) { *(data.numeric.config.
ul) = (unsigned long) ll; } else if (data.numeric.numeric_type
== NUMERIC_TYPE_LONG_LONG) { *(data.numeric.config.ll) = (long
long) ll; } else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG
) { *(data.numeric.config.ull) = (unsigned long long) ll; } else
if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) { *(data
.numeric.config.st) = (size_t) ll; } else if (data.numeric.numeric_type
== NUMERIC_TYPE_SSIZE_T) { *(data.numeric.config.sst) = (ssize_t
) ll; } else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T
) { *(data.numeric.config.ot) = (off_t) ll; } else if (data.numeric
.numeric_type == NUMERIC_TYPE_TIME_T) { *(data.numeric.config
.tt) = (time_t) ll; }
2033
2034 if (update && data.numeric.update_fn && !data.numeric.update_fn(ll, prev, err)) {
2035 SET_NUMERIC_TYPE(prev)if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { *(data.numeric
.config.i) = (int) prev; } else if (data.numeric.numeric_type
== NUMERIC_TYPE_UINT) { *(data.numeric.config.ui) = (unsigned
int) prev; } else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG
) { *(data.numeric.config.l) = (long) prev; } else if (data.numeric
.numeric_type == NUMERIC_TYPE_ULONG) { *(data.numeric.config.
ul) = (unsigned long) prev; } else if (data.numeric.numeric_type
== NUMERIC_TYPE_LONG_LONG) { *(data.numeric.config.ll) = (long
long) prev; } else if (data.numeric.numeric_type == NUMERIC_TYPE_ULONG_LONG
) { *(data.numeric.config.ull) = (unsigned long long) prev; }
else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T) {
*(data.numeric.config.st) = (size_t) prev; } else if (data.numeric
.numeric_type == NUMERIC_TYPE_SSIZE_T) { *(data.numeric.config
.sst) = (ssize_t) prev; } else if (data.numeric.numeric_type ==
NUMERIC_TYPE_OFF_T) { *(data.numeric.config.ot) = (off_t) prev
; } else if (data.numeric.numeric_type == NUMERIC_TYPE_TIME_T
) { *(data.numeric.config.tt) = (time_t) prev; }
2036 return 0;
2037 }
2038 return 1;
2039}
2040
2041static void numericConfigGet(client *c, typeData data) {
2042 char buf[128];
2043 long long value = 0;
2044
2045 GET_NUMERIC_TYPE(value)if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { value = *
(data.numeric.config.i); } else if (data.numeric.numeric_type
== NUMERIC_TYPE_UINT) { value = *(data.numeric.config.ui); }
else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG) { value
= *(data.numeric.config.l); } else if (data.numeric.numeric_type
== NUMERIC_TYPE_ULONG) { value = *(data.numeric.config.ul); }
else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG
) { value = *(data.numeric.config.ll); } else if (data.numeric
.numeric_type == NUMERIC_TYPE_ULONG_LONG) { value = *(data.numeric
.config.ull); } else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T
) { value = *(data.numeric.config.st); } else if (data.numeric
.numeric_type == NUMERIC_TYPE_SSIZE_T) { value = *(data.numeric
.config.sst); } else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T
) { value = *(data.numeric.config.ot); } else if (data.numeric
.numeric_type == NUMERIC_TYPE_TIME_T) { value = *(data.numeric
.config.tt); }
2046
2047 ll2string(buf, sizeof(buf), value);
2048 addReplyBulkCString(c, buf);
2049}
2050
2051static void numericConfigRewrite(typeData data, const char *name, struct rewriteConfigState *state) {
2052 long long value = 0;
2053
2054 GET_NUMERIC_TYPE(value)if (data.numeric.numeric_type == NUMERIC_TYPE_INT) { value = *
(data.numeric.config.i); } else if (data.numeric.numeric_type
== NUMERIC_TYPE_UINT) { value = *(data.numeric.config.ui); }
else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG) { value
= *(data.numeric.config.l); } else if (data.numeric.numeric_type
== NUMERIC_TYPE_ULONG) { value = *(data.numeric.config.ul); }
else if (data.numeric.numeric_type == NUMERIC_TYPE_LONG_LONG
) { value = *(data.numeric.config.ll); } else if (data.numeric
.numeric_type == NUMERIC_TYPE_ULONG_LONG) { value = *(data.numeric
.config.ull); } else if (data.numeric.numeric_type == NUMERIC_TYPE_SIZE_T
) { value = *(data.numeric.config.st); } else if (data.numeric
.numeric_type == NUMERIC_TYPE_SSIZE_T) { value = *(data.numeric
.config.sst); } else if (data.numeric.numeric_type == NUMERIC_TYPE_OFF_T
) { value = *(data.numeric.config.ot); } else if (data.numeric
.numeric_type == NUMERIC_TYPE_TIME_T) { value = *(data.numeric
.config.tt); }
2055
2056 if (data.numeric.is_memory) {
2057 rewriteConfigBytesOption(state, name, value, data.numeric.default_value);
2058 } else {
2059 rewriteConfigNumericalOption(state, name, value, data.numeric.default_value);
2060 }
2061}
2062
2063#define INTEGER_CONFIG0 0
2064#define MEMORY_CONFIG1 1
2065
2066#define embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
{ \
2067 embedCommonConfig(name, alias, modifiable).name = (name), .alias = (alias), .modifiable = (modifiable), \
2068 embedConfigInterface(numericConfigInit, numericConfigSet, numericConfigGet, numericConfigRewrite).interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) },
\
2069 .data.numeric = { \
2070 .lower_bound = (lower), \
2071 .upper_bound = (upper), \
2072 .default_value = (default), \
2073 .is_valid_fn = (is_valid), \
2074 .update_fn = (update), \
2075 .is_memory = (memory),
2076
2077#define createIntConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_INT, .config.i = &(config_addr) } }
\
2078 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2079 .numeric_type = NUMERIC_TYPE_INT, \
2080 .config.i = &(config_addr) \
2081 } \
2082}
2083
2084#define createUIntConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_UINT, .config.ui = &(config_addr) } }
\
2085 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2086 .numeric_type = NUMERIC_TYPE_UINT, \
2087 .config.ui = &(config_addr) \
2088 } \
2089}
2090
2091#define createLongConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_LONG, .config.l = &(config_addr) } }
\
2092 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2093 .numeric_type = NUMERIC_TYPE_LONG, \
2094 .config.l = &(config_addr) \
2095 } \
2096}
2097
2098#define createULongConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_ULONG, .config.ul = &(config_addr) } }
\
2099 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2100 .numeric_type = NUMERIC_TYPE_ULONG, \
2101 .config.ul = &(config_addr) \
2102 } \
2103}
2104
2105#define createLongLongConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_LONG_LONG, .config.ll = &(config_addr) } }
\
2106 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2107 .numeric_type = NUMERIC_TYPE_LONG_LONG, \
2108 .config.ll = &(config_addr) \
2109 } \
2110}
2111
2112#define createULongLongConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_ULONG_LONG, .config.ull = &(config_addr) }
}
\
2113 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2114 .numeric_type = NUMERIC_TYPE_ULONG_LONG, \
2115 .config.ull = &(config_addr) \
2116 } \
2117}
2118
2119#define createSizeTConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_SIZE_T, .config.st = &(config_addr) } }
\
2120 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2121 .numeric_type = NUMERIC_TYPE_SIZE_T, \
2122 .config.st = &(config_addr) \
2123 } \
2124}
2125
2126#define createSSizeTConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_SSIZE_T, .config.sst = &(config_addr) } }
\
2127 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2128 .numeric_type = NUMERIC_TYPE_SSIZE_T, \
2129 .config.sst = &(config_addr) \
2130 } \
2131}
2132
2133#define createTimeTConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_TIME_T, .config.tt = &(config_addr) } }
\
2134 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2135 .numeric_type = NUMERIC_TYPE_TIME_T, \
2136 .config.tt = &(config_addr) \
2137 } \
2138}
2139
2140#define createOffTConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory), .numeric_type
= NUMERIC_TYPE_OFF_T, .config.ot = &(config_addr) } }
\
2141 embedCommonNumericalConfig(name, alias, modifiable, lower, upper, config_addr, default, memory, is_valid, update){ .name = (name), .alias = (alias), .modifiable = (modifiable
), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (lower), .upper_bound =
(upper), .default_value = (default), .is_valid_fn = (is_valid
), .update_fn = (update), .is_memory = (memory),
\
2142 .numeric_type = NUMERIC_TYPE_OFF_T, \
2143 .config.ot = &(config_addr) \
2144 } \
2145}
2146
2147static int isValidActiveDefrag(int val, const char **err) {
2148#ifndef HAVE_DEFRAG
2149 if (val) {
2150 *err = "Active defragmentation cannot be enabled: it "
2151 "requires a Redis server compiled with a modified Jemalloc "
2152 "like the one shipped by default with the Redis source "
2153 "distribution";
2154 return 0;
2155 }
2156#else
2157 UNUSED(val)((void) val);
2158 UNUSED(err)((void) err);
2159#endif
2160 return 1;
2161}
2162
2163static int isValidDBfilename(char *val, const char **err) {
2164 if (!pathIsBaseName(val)) {
2165 *err = "dbfilename can't be a path, just a filename";
2166 return 0;
2167 }
2168 return 1;
2169}
2170
2171static int isValidAOFfilename(char *val, const char **err) {
2172 if (!pathIsBaseName(val)) {
2173 *err = "appendfilename can't be a path, just a filename";
2174 return 0;
2175 }
2176 return 1;
2177}
2178
2179/* Validate specified string is a valid proc-title-template */
2180static int isValidProcTitleTemplate(char *val, const char **err) {
2181 if (!validateProcTitleTemplate(val)) {
2182 *err = "template format is invalid or contains unknown variables";
2183 return 0;
2184 }
2185 return 1;
2186}
2187
2188static int updateProcTitleTemplate(char *val, char *prev, const char **err) {
2189 UNUSED(val)((void) val);
2190 UNUSED(prev)((void) prev);
2191 if (redisSetProcTitle(NULL((void*)0)) == C_ERR-1) {
2192 *err = "failed to set process title";
2193 return 0;
2194 }
2195 return 1;
2196}
2197
2198static int updateHZ(long long val, long long prev, const char **err) {
2199 UNUSED(prev)((void) prev);
2200 UNUSED(err)((void) err);
2201 /* Hz is more a hint from the user, so we accept values out of range
2202 * but cap them to reasonable values. */
2203 server.config_hz = val;
2204 if (server.config_hz < CONFIG_MIN_HZ1) server.config_hz = CONFIG_MIN_HZ1;
2205 if (server.config_hz > CONFIG_MAX_HZ500) server.config_hz = CONFIG_MAX_HZ500;
2206 server.hz = server.config_hz;
2207 return 1;
2208}
2209
2210static int updatePort(long long val, long long prev, const char **err) {
2211 /* Do nothing if port is unchanged */
2212 if (val == prev) {
2213 return 1;
2214 }
2215
2216 if (changeListenPort(val, &server.ipfd, acceptTcpHandler) == C_ERR-1) {
2217 *err = "Unable to listen on this port. Check server logs.";
2218 return 0;
2219 }
2220
2221 return 1;
2222}
2223
2224static int updateJemallocBgThread(int val, int prev, const char **err) {
2225 UNUSED(prev)((void) prev);
2226 UNUSED(err)((void) err);
2227 set_jemalloc_bg_thread(val);
2228 return 1;
2229}
2230
2231static int updateReplBacklogSize(long long val, long long prev, const char **err) {
2232 /* resizeReplicationBacklog sets server.repl_backlog_size, and relies on
2233 * being able to tell when the size changes, so restore prev before calling it. */
2234 UNUSED(err)((void) err);
2235 server.repl_backlog_size = prev;
2236 resizeReplicationBacklog(val);
2237 return 1;
2238}
2239
2240static int updateMaxmemory(long long val, long long prev, const char **err) {
2241 UNUSED(prev)((void) prev);
2242 UNUSED(err)((void) err);
2243 if (val) {
2244 size_t used = zmalloc_used_memory()-freeMemoryGetNotCountedMemory();
2245 if ((unsigned long long)val < used) {
2246 serverLog(LL_WARNING3,"WARNING: the new maxmemory value set via CONFIG SET (%llu) is smaller than the current memory usage (%zu). This will result in key eviction and/or the inability to accept new write commands depending on the maxmemory-policy.", server.maxmemory, used);
2247 }
2248 performEvictions();
2249 }
2250 return 1;
2251}
2252
2253static int updateGoodSlaves(long long val, long long prev, const char **err) {
2254 UNUSED(val)((void) val);
2255 UNUSED(prev)((void) prev);
2256 UNUSED(err)((void) err);
2257 refreshGoodSlavesCount();
2258 return 1;
2259}
2260
2261static int updateAppendonly(int val, int prev, const char **err) {
2262 UNUSED(prev)((void) prev);
2263 if (val == 0 && server.aof_state != AOF_OFF0) {
2264 stopAppendOnly();
2265 } else if (val && server.aof_state == AOF_OFF0) {
2266 if (startAppendOnly() == C_ERR-1) {
2267 *err = "Unable to turn on AOF. Check server logs.";
2268 return 0;
2269 }
2270 }
2271 return 1;
2272}
2273
2274static int updateSighandlerEnabled(int val, int prev, const char **err) {
2275 UNUSED(err)((void) err);
2276 UNUSED(prev)((void) prev);
2277 if (val)
2278 setupSignalHandlers();
2279 else
2280 removeSignalHandlers();
2281 return 1;
2282}
2283
2284static int updateMaxclients(long long val, long long prev, const char **err) {
2285 /* Try to check if the OS is capable of supporting so many FDs. */
2286 if (val > prev) {
2287 adjustOpenFilesLimit();
2288 if (server.maxclients != val) {
2289 static char msg[128];
2290 sprintf(msg, "The operating system is not able to handle the specified number of clients, try with %d", server.maxclients);
2291 *err = msg;
2292 if (server.maxclients > prev) {
2293 server.maxclients = prev;
2294 adjustOpenFilesLimit();
2295 }
2296 return 0;
2297 }
2298 if ((unsigned int) aeGetSetSize(server.el) <
2299 server.maxclients + CONFIG_FDSET_INCR(32 +96))
2300 {
2301 if (aeResizeSetSize(server.el,
2302 server.maxclients + CONFIG_FDSET_INCR(32 +96)) == AE_ERR-1)
2303 {
2304 *err = "The event loop API used by Redis is not able to handle the specified number of clients";
2305 return 0;
2306 }
2307 }
2308 }
2309 return 1;
2310}
2311
2312static int updateOOMScoreAdj(int val, int prev, const char **err) {
2313 UNUSED(prev)((void) prev);
2314
2315 if (val) {
2316 if (setOOMScoreAdj(-1) == C_ERR-1) {
2317 *err = "Failed to set current oom_score_adj. Check server logs.";
2318 return 0;
2319 }
2320 }
2321
2322 return 1;
2323}
2324
2325
2326int updateRequirePass(sds val, sds prev, const char **err) {
2327 UNUSED(prev)((void) prev);
2328 UNUSED(err)((void) err);
2329 /* The old "requirepass" directive just translates to setting
2330 * a password to the default user. The only thing we do
2331 * additionally is to remember the cleartext password in this
2332 * case, for backward compatibility with Redis <= 5. */
2333 ACLUpdateDefaultUserPassword(val);
2334 return 1;
2335}
2336
2337#ifdef USE_OPENSSL
2338static int updateTlsCfg(char *val, char *prev, const char **err) {
2339 UNUSED(val)((void) val);
2340 UNUSED(prev)((void) prev);
2341 UNUSED(err)((void) err);
2342
2343 /* If TLS is enabled, try to configure OpenSSL. */
2344 if ((server.tls_port || server.tls_replication || server.tls_cluster)
2345 && tlsConfigure(&server.tls_ctx_config) == C_ERR-1) {
2346 *err = "Unable to update TLS configuration. Check server logs.";
2347 return 0;
2348 }
2349 return 1;
2350}
2351static int updateTlsCfgBool(int val, int prev, const char **err) {
2352 UNUSED(val)((void) val);
2353 UNUSED(prev)((void) prev);
2354 return updateTlsCfg(NULL((void*)0), NULL((void*)0), err);
2355}
2356
2357static int updateTlsCfgInt(long long val, long long prev, const char **err) {
2358 UNUSED(val)((void) val);
2359 UNUSED(prev)((void) prev);
2360 return updateTlsCfg(NULL((void*)0), NULL((void*)0), err);
2361}
2362
2363static int updateTLSPort(long long val, long long prev, const char **err) {
2364 /* Do nothing if port is unchanged */
2365 if (val == prev) {
2366 return 1;
2367 }
2368
2369 /* Configure TLS if tls is enabled */
2370 if (prev == 0 && tlsConfigure(&server.tls_ctx_config) == C_ERR-1) {
2371 *err = "Unable to update TLS configuration. Check server logs.";
2372 return 0;
2373 }
2374
2375 if (changeListenPort(val, &server.tlsfd, acceptTLSHandler) == C_ERR-1) {
2376 *err = "Unable to listen on this port. Check server logs.";
2377 return 0;
2378 }
2379
2380 return 1;
2381}
2382
2383#endif /* USE_OPENSSL */
2384
2385standardConfig configs[] = {
2386 /* Bool configs */
2387 createBoolConfig("rdbchecksum", NULL, IMMUTABLE_CONFIG, server.rdb_checksum, 1, NULL, NULL){ .name = ("rdbchecksum"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.rdb_checksum), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2388 createBoolConfig("daemonize", NULL, IMMUTABLE_CONFIG, server.daemonize, 0, NULL, NULL){ .name = ("daemonize"), .alias = (((void*)0)), .modifiable =
(0), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.daemonize), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2389 createBoolConfig("io-threads-do-reads", NULL, IMMUTABLE_CONFIG, server.io_threads_do_reads, 0,NULL, NULL){ .name = ("io-threads-do-reads"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.io_threads_do_reads), .
default_value = (0), .is_valid_fn = (((void*)0)), .update_fn =
(((void*)0)), } }
, /* Read + parse from threads? */
2390 createBoolConfig("lua-replicate-commands", NULL, MODIFIABLE_CONFIG, server.lua_always_replicate_commands, 1, NULL, NULL){ .name = ("lua-replicate-commands"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (boolConfigInit), .set
= (boolConfigSet), .get = (boolConfigGet), .rewrite = (boolConfigRewrite
) }, .data.yesno = { .config = &(server.lua_always_replicate_commands
), .default_value = (1), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), } }
,
2391 createBoolConfig("always-show-logo", NULL, IMMUTABLE_CONFIG, server.always_show_logo, 0, NULL, NULL){ .name = ("always-show-logo"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.always_show_logo), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2392 createBoolConfig("protected-mode", NULL, MODIFIABLE_CONFIG, server.protected_mode, 1, NULL, NULL){ .name = ("protected-mode"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.protected_mode), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2393 createBoolConfig("rdbcompression", NULL, MODIFIABLE_CONFIG, server.rdb_compression, 1, NULL, NULL){ .name = ("rdbcompression"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.rdb_compression), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2394 createBoolConfig("rdb-del-sync-files", NULL, MODIFIABLE_CONFIG, server.rdb_del_sync_files, 0, NULL, NULL){ .name = ("rdb-del-sync-files"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.rdb_del_sync_files), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2395 createBoolConfig("activerehashing", NULL, MODIFIABLE_CONFIG, server.activerehashing, 1, NULL, NULL){ .name = ("activerehashing"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.activerehashing), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2396 createBoolConfig("stop-writes-on-bgsave-error", NULL, MODIFIABLE_CONFIG, server.stop_writes_on_bgsave_err, 1, NULL, NULL){ .name = ("stop-writes-on-bgsave-error"), .alias = (((void*)
0)), .modifiable = (1), .interface = { .init = (boolConfigInit
), .set = (boolConfigSet), .get = (boolConfigGet), .rewrite =
(boolConfigRewrite) }, .data.yesno = { .config = &(server
.stop_writes_on_bgsave_err), .default_value = (1), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
,
2397 createBoolConfig("set-proc-title", NULL, IMMUTABLE_CONFIG, server.set_proc_title, 1, NULL, NULL){ .name = ("set-proc-title"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.set_proc_title), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
, /* Should setproctitle be used? */
2398 createBoolConfig("dynamic-hz", NULL, MODIFIABLE_CONFIG, server.dynamic_hz, 1, NULL, NULL){ .name = ("dynamic-hz"), .alias = (((void*)0)), .modifiable =
(1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.dynamic_hz), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
, /* Adapt hz to # of clients.*/
2399 createBoolConfig("lazyfree-lazy-eviction", NULL, MODIFIABLE_CONFIG, server.lazyfree_lazy_eviction, 0, NULL, NULL){ .name = ("lazyfree-lazy-eviction"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (boolConfigInit), .set
= (boolConfigSet), .get = (boolConfigGet), .rewrite = (boolConfigRewrite
) }, .data.yesno = { .config = &(server.lazyfree_lazy_eviction
), .default_value = (0), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), } }
,
2400 createBoolConfig("lazyfree-lazy-expire", NULL, MODIFIABLE_CONFIG, server.lazyfree_lazy_expire, 0, NULL, NULL){ .name = ("lazyfree-lazy-expire"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.lazyfree_lazy_expire), .
default_value = (0), .is_valid_fn = (((void*)0)), .update_fn =
(((void*)0)), } }
,
2401 createBoolConfig("lazyfree-lazy-server-del", NULL, MODIFIABLE_CONFIG, server.lazyfree_lazy_server_del, 0, NULL, NULL){ .name = ("lazyfree-lazy-server-del"), .alias = (((void*)0))
, .modifiable = (1), .interface = { .init = (boolConfigInit),
.set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
lazyfree_lazy_server_del), .default_value = (0), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
,
2402 createBoolConfig("lazyfree-lazy-user-del", NULL, MODIFIABLE_CONFIG, server.lazyfree_lazy_user_del , 0, NULL, NULL){ .name = ("lazyfree-lazy-user-del"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (boolConfigInit), .set
= (boolConfigSet), .get = (boolConfigGet), .rewrite = (boolConfigRewrite
) }, .data.yesno = { .config = &(server.lazyfree_lazy_user_del
), .default_value = (0), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), } }
,
2403 createBoolConfig("lazyfree-lazy-user-flush", NULL, MODIFIABLE_CONFIG, server.lazyfree_lazy_user_flush , 0, NULL, NULL){ .name = ("lazyfree-lazy-user-flush"), .alias = (((void*)0))
, .modifiable = (1), .interface = { .init = (boolConfigInit),
.set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
lazyfree_lazy_user_flush), .default_value = (0), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
,
2404 createBoolConfig("repl-disable-tcp-nodelay", NULL, MODIFIABLE_CONFIG, server.repl_disable_tcp_nodelay, 0, NULL, NULL){ .name = ("repl-disable-tcp-nodelay"), .alias = (((void*)0))
, .modifiable = (1), .interface = { .init = (boolConfigInit),
.set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
repl_disable_tcp_nodelay), .default_value = (0), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
,
2405 createBoolConfig("repl-diskless-sync", NULL, MODIFIABLE_CONFIG, server.repl_diskless_sync, 0, NULL, NULL){ .name = ("repl-diskless-sync"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.repl_diskless_sync), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2406 createBoolConfig("gopher-enabled", NULL, MODIFIABLE_CONFIG, server.gopher_enabled, 0, NULL, NULL){ .name = ("gopher-enabled"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.gopher_enabled), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2407 createBoolConfig("aof-rewrite-incremental-fsync", NULL, MODIFIABLE_CONFIG, server.aof_rewrite_incremental_fsync, 1, NULL, NULL){ .name = ("aof-rewrite-incremental-fsync"), .alias = (((void
*)0)), .modifiable = (1), .interface = { .init = (boolConfigInit
), .set = (boolConfigSet), .get = (boolConfigGet), .rewrite =
(boolConfigRewrite) }, .data.yesno = { .config = &(server
.aof_rewrite_incremental_fsync), .default_value = (1), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
,
2408 createBoolConfig("no-appendfsync-on-rewrite", NULL, MODIFIABLE_CONFIG, server.aof_no_fsync_on_rewrite, 0, NULL, NULL){ .name = ("no-appendfsync-on-rewrite"), .alias = (((void*)0)
), .modifiable = (1), .interface = { .init = (boolConfigInit)
, .set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
aof_no_fsync_on_rewrite), .default_value = (0), .is_valid_fn =
(((void*)0)), .update_fn = (((void*)0)), } }
,
2409 createBoolConfig("cluster-require-full-coverage", NULL, MODIFIABLE_CONFIG, server.cluster_require_full_coverage, 1, NULL, NULL){ .name = ("cluster-require-full-coverage"), .alias = (((void
*)0)), .modifiable = (1), .interface = { .init = (boolConfigInit
), .set = (boolConfigSet), .get = (boolConfigGet), .rewrite =
(boolConfigRewrite) }, .data.yesno = { .config = &(server
.cluster_require_full_coverage), .default_value = (1), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
,
2410 createBoolConfig("rdb-save-incremental-fsync", NULL, MODIFIABLE_CONFIG, server.rdb_save_incremental_fsync, 1, NULL, NULL){ .name = ("rdb-save-incremental-fsync"), .alias = (((void*)0
)), .modifiable = (1), .interface = { .init = (boolConfigInit
), .set = (boolConfigSet), .get = (boolConfigGet), .rewrite =
(boolConfigRewrite) }, .data.yesno = { .config = &(server
.rdb_save_incremental_fsync), .default_value = (1), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
,
2411 createBoolConfig("aof-load-truncated", NULL, MODIFIABLE_CONFIG, server.aof_load_truncated, 1, NULL, NULL){ .name = ("aof-load-truncated"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.aof_load_truncated), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2412 createBoolConfig("aof-use-rdb-preamble", NULL, MODIFIABLE_CONFIG, server.aof_use_rdb_preamble, 1, NULL, NULL){ .name = ("aof-use-rdb-preamble"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.aof_use_rdb_preamble), .
default_value = (1), .is_valid_fn = (((void*)0)), .update_fn =
(((void*)0)), } }
,
2413 createBoolConfig("cluster-replica-no-failover", "cluster-slave-no-failover", MODIFIABLE_CONFIG, server.cluster_slave_no_failover, 0, NULL, NULL){ .name = ("cluster-replica-no-failover"), .alias = ("cluster-slave-no-failover"
), .modifiable = (1), .interface = { .init = (boolConfigInit)
, .set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
cluster_slave_no_failover), .default_value = (0), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
, /* Failover by default. */
2414 createBoolConfig("replica-lazy-flush", "slave-lazy-flush", MODIFIABLE_CONFIG, server.repl_slave_lazy_flush, 0, NULL, NULL){ .name = ("replica-lazy-flush"), .alias = ("slave-lazy-flush"
), .modifiable = (1), .interface = { .init = (boolConfigInit)
, .set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
repl_slave_lazy_flush), .default_value = (0), .is_valid_fn = (
((void*)0)), .update_fn = (((void*)0)), } }
,
2415 createBoolConfig("replica-serve-stale-data", "slave-serve-stale-data", MODIFIABLE_CONFIG, server.repl_serve_stale_data, 1, NULL, NULL){ .name = ("replica-serve-stale-data"), .alias = ("slave-serve-stale-data"
), .modifiable = (1), .interface = { .init = (boolConfigInit)
, .set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
repl_serve_stale_data), .default_value = (1), .is_valid_fn = (
((void*)0)), .update_fn = (((void*)0)), } }
,
2416 createBoolConfig("replica-read-only", "slave-read-only", MODIFIABLE_CONFIG, server.repl_slave_ro, 1, NULL, NULL){ .name = ("replica-read-only"), .alias = ("slave-read-only")
, .modifiable = (1), .interface = { .init = (boolConfigInit),
.set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
repl_slave_ro), .default_value = (1), .is_valid_fn = (((void*
)0)), .update_fn = (((void*)0)), } }
,
2417 createBoolConfig("replica-ignore-maxmemory", "slave-ignore-maxmemory", MODIFIABLE_CONFIG, server.repl_slave_ignore_maxmemory, 1, NULL, NULL){ .name = ("replica-ignore-maxmemory"), .alias = ("slave-ignore-maxmemory"
), .modifiable = (1), .interface = { .init = (boolConfigInit)
, .set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
repl_slave_ignore_maxmemory), .default_value = (1), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
,
2418 createBoolConfig("jemalloc-bg-thread", NULL, MODIFIABLE_CONFIG, server.jemalloc_bg_thread, 1, NULL, updateJemallocBgThread){ .name = ("jemalloc-bg-thread"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.jemalloc_bg_thread), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (updateJemallocBgThread
), } }
,
2419 createBoolConfig("activedefrag", NULL, MODIFIABLE_CONFIG, server.active_defrag_enabled, 0, isValidActiveDefrag, NULL){ .name = ("activedefrag"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.active_defrag_enabled),
.default_value = (0), .is_valid_fn = (isValidActiveDefrag), .
update_fn = (((void*)0)), } }
,
2420 createBoolConfig("syslog-enabled", NULL, IMMUTABLE_CONFIG, server.syslog_enabled, 0, NULL, NULL){ .name = ("syslog-enabled"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.syslog_enabled), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2421 createBoolConfig("cluster-enabled", NULL, IMMUTABLE_CONFIG, server.cluster_enabled, 0, NULL, NULL){ .name = ("cluster-enabled"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.cluster_enabled), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2422 createBoolConfig("appendonly", NULL, MODIFIABLE_CONFIG, server.aof_enabled, 0, NULL, updateAppendonly){ .name = ("appendonly"), .alias = (((void*)0)), .modifiable =
(1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.aof_enabled), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (updateAppendonly
), } }
,
2423 createBoolConfig("cluster-allow-reads-when-down", NULL, MODIFIABLE_CONFIG, server.cluster_allow_reads_when_down, 0, NULL, NULL){ .name = ("cluster-allow-reads-when-down"), .alias = (((void
*)0)), .modifiable = (1), .interface = { .init = (boolConfigInit
), .set = (boolConfigSet), .get = (boolConfigGet), .rewrite =
(boolConfigRewrite) }, .data.yesno = { .config = &(server
.cluster_allow_reads_when_down), .default_value = (0), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), } }
,
2424 createBoolConfig("crash-log-enabled", NULL, MODIFIABLE_CONFIG, server.crashlog_enabled, 1, NULL, updateSighandlerEnabled){ .name = ("crash-log-enabled"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.crashlog_enabled), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (updateSighandlerEnabled
), } }
,
2425 createBoolConfig("crash-memcheck-enabled", NULL, MODIFIABLE_CONFIG, server.memcheck_enabled, 1, NULL, NULL){ .name = ("crash-memcheck-enabled"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (boolConfigInit), .set
= (boolConfigSet), .get = (boolConfigGet), .rewrite = (boolConfigRewrite
) }, .data.yesno = { .config = &(server.memcheck_enabled)
, .default_value = (1), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), } }
,
2426 createBoolConfig("use-exit-on-panic", NULL, MODIFIABLE_CONFIG, server.use_exit_on_panic, 0, NULL, NULL){ .name = ("use-exit-on-panic"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.use_exit_on_panic), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2427 createBoolConfig("disable-thp", NULL, MODIFIABLE_CONFIG, server.disable_thp, 1, NULL, NULL){ .name = ("disable-thp"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.disable_thp), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), } }
,
2428
2429 /* String Configs */
2430 createStringConfig("aclfile", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, server.acl_filename, "", NULL, NULL){ .name = ("aclfile"), .alias = (((void*)0)), .modifiable = (
0), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.acl_filename), .default_value
= (""), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0
)), .convert_empty_to_null = (0), } }
,
2431 createStringConfig("unixsocket", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.unixsocket, NULL, NULL, NULL){ .name = ("unixsocket"), .alias = (((void*)0)), .modifiable =
(0), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.unixsocket), .default_value
= (((void*)0)), .is_valid_fn = (((void*)0)), .update_fn = ((
(void*)0)), .convert_empty_to_null = (1), } }
,
2432 createStringConfig("pidfile", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.pidfile, NULL, NULL, NULL){ .name = ("pidfile"), .alias = (((void*)0)), .modifiable = (
0), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.pidfile), .default_value
= (((void*)0)), .is_valid_fn = (((void*)0)), .update_fn = ((
(void*)0)), .convert_empty_to_null = (1), } }
,
2433 createStringConfig("replica-announce-ip", "slave-announce-ip", MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.slave_announce_ip, NULL, NULL, NULL){ .name = ("replica-announce-ip"), .alias = ("slave-announce-ip"
), .modifiable = (1), .interface = { .init = (stringConfigInit
), .set = (stringConfigSet), .get = (stringConfigGet), .rewrite
= (stringConfigRewrite) }, .data.string = { .config = &(
server.slave_announce_ip), .default_value = (((void*)0)), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .convert_empty_to_null
= (1), } }
,
2434 createStringConfig("masteruser", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.masteruser, NULL, NULL, NULL){ .name = ("masteruser"), .alias = (((void*)0)), .modifiable =
(1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.masteruser), .default_value
= (((void*)0)), .is_valid_fn = (((void*)0)), .update_fn = ((
(void*)0)), .convert_empty_to_null = (1), } }
,
2435 createStringConfig("cluster-announce-ip", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.cluster_announce_ip, NULL, NULL, NULL){ .name = ("cluster-announce-ip"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.cluster_announce_ip
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (((void*)0)), .convert_empty_to_null = (1), } }
,
2436 createStringConfig("syslog-ident", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, server.syslog_ident, "redis", NULL, NULL){ .name = ("syslog-ident"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.syslog_ident), .default_value
= ("redis"), .is_valid_fn = (((void*)0)), .update_fn = (((void
*)0)), .convert_empty_to_null = (0), } }
,
2437 createStringConfig("dbfilename", NULL, MODIFIABLE_CONFIG, ALLOW_EMPTY_STRING, server.rdb_filename, "dump.rdb", isValidDBfilename, NULL){ .name = ("dbfilename"), .alias = (((void*)0)), .modifiable =
(1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.rdb_filename), .default_value
= ("dump.rdb"), .is_valid_fn = (isValidDBfilename), .update_fn
= (((void*)0)), .convert_empty_to_null = (0), } }
,
2438 createStringConfig("appendfilename", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, server.aof_filename, "appendonly.aof", isValidAOFfilename, NULL){ .name = ("appendfilename"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.aof_filename), .default_value
= ("appendonly.aof"), .is_valid_fn = (isValidAOFfilename), .
update_fn = (((void*)0)), .convert_empty_to_null = (0), } }
,
2439 createStringConfig("server_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.server_cpulist, NULL, NULL, NULL){ .name = ("server_cpulist"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.server_cpulist), .
default_value = (((void*)0)), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .convert_empty_to_null = (1), } }
,
2440 createStringConfig("bio_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.bio_cpulist, NULL, NULL, NULL){ .name = ("bio_cpulist"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.bio_cpulist), .default_value
= (((void*)0)), .is_valid_fn = (((void*)0)), .update_fn = ((
(void*)0)), .convert_empty_to_null = (1), } }
,
2441 createStringConfig("aof_rewrite_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.aof_rewrite_cpulist, NULL, NULL, NULL){ .name = ("aof_rewrite_cpulist"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.aof_rewrite_cpulist
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (((void*)0)), .convert_empty_to_null = (1), } }
,
2442 createStringConfig("bgsave_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.bgsave_cpulist, NULL, NULL, NULL){ .name = ("bgsave_cpulist"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.bgsave_cpulist), .
default_value = (((void*)0)), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .convert_empty_to_null = (1), } }
,
2443 createStringConfig("ignore-warnings", NULL, MODIFIABLE_CONFIG, ALLOW_EMPTY_STRING, server.ignore_warnings, "", NULL, NULL){ .name = ("ignore-warnings"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.ignore_warnings),
.default_value = (""), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .convert_empty_to_null = (0), } }
,
2444 createStringConfig("proc-title-template", NULL, MODIFIABLE_CONFIG, ALLOW_EMPTY_STRING, server.proc_title_template, CONFIG_DEFAULT_PROC_TITLE_TEMPLATE, isValidProcTitleTemplate, updateProcTitleTemplate){ .name = ("proc-title-template"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.proc_title_template
), .default_value = ("{title} {listen-addr} {server-mode}"), .
is_valid_fn = (isValidProcTitleTemplate), .update_fn = (updateProcTitleTemplate
), .convert_empty_to_null = (0), } }
,
2445
2446 /* SDS Configs */
2447 createSDSConfig("masterauth", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.masterauth, NULL, NULL, NULL){ .name = ("masterauth"), .alias = (((void*)0)), .modifiable =
(1), .interface = { .init = (sdsConfigInit), .set = (sdsConfigSet
), .get = (sdsConfigGet), .rewrite = (sdsConfigRewrite) }, .data
.sds = { .config = &(server.masterauth), .default_value =
(((void*)0)), .is_valid_fn = (((void*)0)), .update_fn = (((void
*)0)), .convert_empty_to_null = (1), } }
,
2448 createSDSConfig("requirepass", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.requirepass, NULL, NULL, updateRequirePass){ .name = ("requirepass"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (sdsConfigInit), .set = (sdsConfigSet
), .get = (sdsConfigGet), .rewrite = (sdsConfigRewrite) }, .data
.sds = { .config = &(server.requirepass), .default_value =
(((void*)0)), .is_valid_fn = (((void*)0)), .update_fn = (updateRequirePass
), .convert_empty_to_null = (1), } }
,
2449
2450 /* Enum Configs */
2451 createEnumConfig("supervised", NULL, IMMUTABLE_CONFIG, supervised_mode_enum, server.supervised_mode, SUPERVISED_NONE, NULL, NULL){ .name = ("supervised"), .alias = (((void*)0)), .modifiable =
(0), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(server.supervised_mode), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), .enum_value = (supervised_mode_enum), } }
,
2452 createEnumConfig("syslog-facility", NULL, IMMUTABLE_CONFIG, syslog_facility_enum, server.syslog_facility, LOG_LOCAL0, NULL, NULL){ .name = ("syslog-facility"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(server.syslog_facility), .default_value
= ((16<<3)), .is_valid_fn = (((void*)0)), .update_fn =
(((void*)0)), .enum_value = (syslog_facility_enum), } }
,
2453 createEnumConfig("repl-diskless-load", NULL, MODIFIABLE_CONFIG, repl_diskless_load_enum, server.repl_diskless_load, REPL_DISKLESS_LOAD_DISABLED, NULL, NULL){ .name = ("repl-diskless-load"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(server.repl_diskless_load), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), .enum_value = (repl_diskless_load_enum), } }
,
2454 createEnumConfig("loglevel", NULL, MODIFIABLE_CONFIG, loglevel_enum, server.verbosity, LL_NOTICE, NULL, NULL){ .name = ("loglevel"), .alias = (((void*)0)), .modifiable = (
1), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(server.verbosity), .default_value
= (2), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), .enum_value = (loglevel_enum), } }
,
2455 createEnumConfig("maxmemory-policy", NULL, MODIFIABLE_CONFIG, maxmemory_policy_enum, server.maxmemory_policy, MAXMEMORY_NO_EVICTION, NULL, NULL){ .name = ("maxmemory-policy"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(server.maxmemory_policy), .default_value
= ((7<<8)), .is_valid_fn = (((void*)0)), .update_fn = (
((void*)0)), .enum_value = (maxmemory_policy_enum), } }
,
2456 createEnumConfig("appendfsync", NULL, MODIFIABLE_CONFIG, aof_fsync_enum, server.aof_fsync, AOF_FSYNC_EVERYSEC, NULL, NULL){ .name = ("appendfsync"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(server.aof_fsync), .default_value
= (2), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), .enum_value = (aof_fsync_enum), } }
,
2457 createEnumConfig("oom-score-adj", NULL, MODIFIABLE_CONFIG, oom_score_adj_enum, server.oom_score_adj, OOM_SCORE_ADJ_NO, NULL, updateOOMScoreAdj){ .name = ("oom-score-adj"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(server.oom_score_adj), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (updateOOMScoreAdj
), .enum_value = (oom_score_adj_enum), } }
,
2458 createEnumConfig("acl-pubsub-default", NULL, MODIFIABLE_CONFIG, acl_pubsub_default_enum, server.acl_pubusub_default, USER_FLAG_ALLCHANNELS, NULL, NULL){ .name = ("acl-pubsub-default"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(server.acl_pubusub_default), .
default_value = ((1<<5)), .is_valid_fn = (((void*)0)), .
update_fn = (((void*)0)), .enum_value = (acl_pubsub_default_enum
), } }
,
2459 createEnumConfig("sanitize-dump-payload", NULL, MODIFIABLE_CONFIG, sanitize_dump_payload_enum, server.sanitize_dump_payload, SANITIZE_DUMP_NO, NULL, NULL){ .name = ("sanitize-dump-payload"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (enumConfigInit), .set
= (enumConfigSet), .get = (enumConfigGet), .rewrite = (enumConfigRewrite
) }, .data.enumd = { .config = &(server.sanitize_dump_payload
), .default_value = (0), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .enum_value = (sanitize_dump_payload_enum), }
}
,
2460
2461 /* Integer configs */
2462 createIntConfig("databases", NULL, IMMUTABLE_CONFIG, 1, INT_MAX, server.dbnum, 16, INTEGER_CONFIG, NULL, NULL){ .name = ("databases"), .alias = (((void*)0)), .modifiable =
(0), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (1), .upper_bound = (2147483647
), .default_value = (16), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.dbnum) } }
,
2463 createIntConfig("port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.port, 6379, INTEGER_CONFIG, NULL, updatePort){ .name = ("port"), .alias = (((void*)0)), .modifiable = (1),
.interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (65535
), .default_value = (6379), .is_valid_fn = (((void*)0)), .update_fn
= (updatePort), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.port) } }
, /* TCP port. */
2464 createIntConfig("io-threads", NULL, IMMUTABLE_CONFIG, 1, 128, server.io_threads_num, 1, INTEGER_CONFIG, NULL, NULL){ .name = ("io-threads"), .alias = (((void*)0)), .modifiable =
(0), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (1), .upper_bound = (128
), .default_value = (1), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.io_threads_num) } }
, /* Single threaded by default */
2465 createIntConfig("auto-aof-rewrite-percentage", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.aof_rewrite_perc, 100, INTEGER_CONFIG, NULL, NULL){ .name = ("auto-aof-rewrite-percentage"), .alias = (((void*)
0)), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (2147483647), .default_value = (100), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.aof_rewrite_perc
) } }
,
2466 createIntConfig("cluster-replica-validity-factor", "cluster-slave-validity-factor", MODIFIABLE_CONFIG, 0, INT_MAX, server.cluster_slave_validity_factor, 10, INTEGER_CONFIG, NULL, NULL){ .name = ("cluster-replica-validity-factor"), .alias = ("cluster-slave-validity-factor"
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (2147483647), .default_value = (10), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.cluster_slave_validity_factor
) } }
, /* Slave max data age factor. */
2467 createIntConfig("list-max-ziplist-size", NULL, MODIFIABLE_CONFIG, INT_MIN, INT_MAX, server.list_max_ziplist_size, -2, INTEGER_CONFIG, NULL, NULL){ .name = ("list-max-ziplist-size"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (numericConfigInit),
.set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
((-2147483647 -1)), .upper_bound = (2147483647), .default_value
= (-2), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0
)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT, .config
.i = &(server.list_max_ziplist_size) } }
,
2468 createIntConfig("tcp-keepalive", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.tcpkeepalive, 300, INTEGER_CONFIG, NULL, NULL){ .name = ("tcp-keepalive"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (2147483647
), .default_value = (300), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.tcpkeepalive) } }
,
2469 createIntConfig("cluster-migration-barrier", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.cluster_migration_barrier, 1, INTEGER_CONFIG, NULL, NULL){ .name = ("cluster-migration-barrier"), .alias = (((void*)0)
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (2147483647), .default_value = (1), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.cluster_migration_barrier
) } }
,
2470 createIntConfig("active-defrag-cycle-min", NULL, MODIFIABLE_CONFIG, 1, 99, server.active_defrag_cycle_min, 1, INTEGER_CONFIG, NULL, NULL){ .name = ("active-defrag-cycle-min"), .alias = (((void*)0)),
.modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(1), .upper_bound = (99), .default_value = (1), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.active_defrag_cycle_min
) } }
, /* Default: 1% CPU min (at lower threshold) */
2471 createIntConfig("active-defrag-cycle-max", NULL, MODIFIABLE_CONFIG, 1, 99, server.active_defrag_cycle_max, 25, INTEGER_CONFIG, NULL, NULL){ .name = ("active-defrag-cycle-max"), .alias = (((void*)0)),
.modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(1), .upper_bound = (99), .default_value = (25), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.active_defrag_cycle_max
) } }
, /* Default: 25% CPU max (at upper threshold) */
2472 createIntConfig("active-defrag-threshold-lower", NULL, MODIFIABLE_CONFIG, 0, 1000, server.active_defrag_threshold_lower, 10, INTEGER_CONFIG, NULL, NULL){ .name = ("active-defrag-threshold-lower"), .alias = (((void
*)0)), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (1000), .default_value = (10), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.active_defrag_threshold_lower
) } }
, /* Default: don't defrag when fragmentation is below 10% */
2473 createIntConfig("active-defrag-threshold-upper", NULL, MODIFIABLE_CONFIG, 0, 1000, server.active_defrag_threshold_upper, 100, INTEGER_CONFIG, NULL, NULL){ .name = ("active-defrag-threshold-upper"), .alias = (((void
*)0)), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (1000), .default_value = (100), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.active_defrag_threshold_upper
) } }
, /* Default: maximum defrag force at 100% fragmentation */
2474 createIntConfig("lfu-log-factor", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.lfu_log_factor, 10, INTEGER_CONFIG, NULL, NULL){ .name = ("lfu-log-factor"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (2147483647
), .default_value = (10), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.lfu_log_factor) } }
,
2475 createIntConfig("lfu-decay-time", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.lfu_decay_time, 1, INTEGER_CONFIG, NULL, NULL){ .name = ("lfu-decay-time"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (2147483647
), .default_value = (1), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.lfu_decay_time) } }
,
2476 createIntConfig("replica-priority", "slave-priority", MODIFIABLE_CONFIG, 0, INT_MAX, server.slave_priority, 100, INTEGER_CONFIG, NULL, NULL){ .name = ("replica-priority"), .alias = ("slave-priority"), .
modifiable = (1), .interface = { .init = (numericConfigInit),
.set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (2147483647), .default_value = (100), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.slave_priority
) } }
,
2477 createIntConfig("repl-diskless-sync-delay", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.repl_diskless_sync_delay, 5, INTEGER_CONFIG, NULL, NULL){ .name = ("repl-diskless-sync-delay"), .alias = (((void*)0))
, .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (2147483647), .default_value = (5), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.repl_diskless_sync_delay
) } }
,
2478 createIntConfig("maxmemory-samples", NULL, MODIFIABLE_CONFIG, 1, INT_MAX, server.maxmemory_samples, 5, INTEGER_CONFIG, NULL, NULL){ .name = ("maxmemory-samples"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (1), .upper_bound = (2147483647
), .default_value = (5), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.maxmemory_samples) } }
,
2479 createIntConfig("maxmemory-eviction-tenacity", NULL, MODIFIABLE_CONFIG, 0, 100, server.maxmemory_eviction_tenacity, 10, INTEGER_CONFIG, NULL, NULL){ .name = ("maxmemory-eviction-tenacity"), .alias = (((void*)
0)), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (100), .default_value = (10), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.maxmemory_eviction_tenacity
) } }
,
2480 createIntConfig("timeout", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.maxidletime, 0, INTEGER_CONFIG, NULL, NULL){ .name = ("timeout"), .alias = (((void*)0)), .modifiable = (
1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (2147483647
), .default_value = (0), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.maxidletime) } }
, /* Default client timeout: infinite */
2481 createIntConfig("replica-announce-port", "slave-announce-port", MODIFIABLE_CONFIG, 0, 65535, server.slave_announce_port, 0, INTEGER_CONFIG, NULL, NULL){ .name = ("replica-announce-port"), .alias = ("slave-announce-port"
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (65535), .default_value = (0), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.slave_announce_port
) } }
,
2482 createIntConfig("tcp-backlog", NULL, IMMUTABLE_CONFIG, 0, INT_MAX, server.tcp_backlog, 511, INTEGER_CONFIG, NULL, NULL){ .name = ("tcp-backlog"), .alias = (((void*)0)), .modifiable
= (0), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (2147483647
), .default_value = (511), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.tcp_backlog) } }
, /* TCP listen backlog. */
2483 createIntConfig("cluster-announce-bus-port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.cluster_announce_bus_port, 0, INTEGER_CONFIG, NULL, NULL){ .name = ("cluster-announce-bus-port"), .alias = (((void*)0)
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (65535), .default_value = (0), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.cluster_announce_bus_port
) } }
, /* Default: Use +10000 offset. */
2484 createIntConfig("cluster-announce-port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.cluster_announce_port, 0, INTEGER_CONFIG, NULL, NULL){ .name = ("cluster-announce-port"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (numericConfigInit),
.set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (65535), .default_value = (0), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.cluster_announce_port
) } }
, /* Use server.port */
2485 createIntConfig("repl-timeout", NULL, MODIFIABLE_CONFIG, 1, INT_MAX, server.repl_timeout, 60, INTEGER_CONFIG, NULL, NULL){ .name = ("repl-timeout"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (1), .upper_bound = (2147483647
), .default_value = (60), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.repl_timeout) } }
,
2486 createIntConfig("repl-ping-replica-period", "repl-ping-slave-period", MODIFIABLE_CONFIG, 1, INT_MAX, server.repl_ping_slave_period, 10, INTEGER_CONFIG, NULL, NULL){ .name = ("repl-ping-replica-period"), .alias = ("repl-ping-slave-period"
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(1), .upper_bound = (2147483647), .default_value = (10), .is_valid_fn
= (((void*)0)), .update_fn = (((void*)0)), .is_memory = (0),
.numeric_type = NUMERIC_TYPE_INT, .config.i = &(server.repl_ping_slave_period
) } }
,
2487 createIntConfig("list-compress-depth", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.list_compress_depth, 0, INTEGER_CONFIG, NULL, NULL){ .name = ("list-compress-depth"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (2147483647
), .default_value = (0), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.list_compress_depth) } }
,
2488 createIntConfig("rdb-key-save-delay", NULL, MODIFIABLE_CONFIG, INT_MIN, INT_MAX, server.rdb_key_save_delay, 0, INTEGER_CONFIG, NULL, NULL){ .name = ("rdb-key-save-delay"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = ((-2147483647 -1)), .upper_bound
= (2147483647), .default_value = (0), .is_valid_fn = (((void
*)0)), .update_fn = (((void*)0)), .is_memory = (0), .numeric_type
= NUMERIC_TYPE_INT, .config.i = &(server.rdb_key_save_delay
) } }
,
2489 createIntConfig("key-load-delay", NULL, MODIFIABLE_CONFIG, INT_MIN, INT_MAX, server.key_load_delay, 0, INTEGER_CONFIG, NULL, NULL){ .name = ("key-load-delay"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = ((-2147483647 -1)), .upper_bound
= (2147483647), .default_value = (0), .is_valid_fn = (((void
*)0)), .update_fn = (((void*)0)), .is_memory = (0), .numeric_type
= NUMERIC_TYPE_INT, .config.i = &(server.key_load_delay)
} }
,
2490 createIntConfig("active-expire-effort", NULL, MODIFIABLE_CONFIG, 1, 10, server.active_expire_effort, 1, INTEGER_CONFIG, NULL, NULL){ .name = ("active-expire-effort"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (1), .upper_bound = (10
), .default_value = (1), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.active_expire_effort) } }
, /* From 1 to 10. */
2491 createIntConfig("hz", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.config_hz, CONFIG_DEFAULT_HZ, INTEGER_CONFIG, NULL, updateHZ){ .name = ("hz"), .alias = (((void*)0)), .modifiable = (1), .
interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (2147483647
), .default_value = (10), .is_valid_fn = (((void*)0)), .update_fn
= (updateHZ), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.config_hz) } }
,
2492 createIntConfig("min-replicas-to-write", "min-slaves-to-write", MODIFIABLE_CONFIG, 0, INT_MAX, server.repl_min_slaves_to_write, 0, INTEGER_CONFIG, NULL, updateGoodSlaves){ .name = ("min-replicas-to-write"), .alias = ("min-slaves-to-write"
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (2147483647), .default_value = (0), .is_valid_fn
= (((void*)0)), .update_fn = (updateGoodSlaves), .is_memory =
(0), .numeric_type = NUMERIC_TYPE_INT, .config.i = &(server
.repl_min_slaves_to_write) } }
,
2493 createIntConfig("min-replicas-max-lag", "min-slaves-max-lag", MODIFIABLE_CONFIG, 0, INT_MAX, server.repl_min_slaves_max_lag, 10, INTEGER_CONFIG, NULL, updateGoodSlaves){ .name = ("min-replicas-max-lag"), .alias = ("min-slaves-max-lag"
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (2147483647), .default_value = (10), .is_valid_fn
= (((void*)0)), .update_fn = (updateGoodSlaves), .is_memory =
(0), .numeric_type = NUMERIC_TYPE_INT, .config.i = &(server
.repl_min_slaves_max_lag) } }
,
2494
2495 /* Unsigned int configs */
2496 createUIntConfig("maxclients", NULL, MODIFIABLE_CONFIG, 1, UINT_MAX, server.maxclients, 10000, INTEGER_CONFIG, NULL, updateMaxclients){ .name = ("maxclients"), .alias = (((void*)0)), .modifiable =
(1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (1), .upper_bound = ((2147483647
*2U +1U)), .default_value = (10000), .is_valid_fn = (((void*
)0)), .update_fn = (updateMaxclients), .is_memory = (0), .numeric_type
= NUMERIC_TYPE_UINT, .config.ui = &(server.maxclients) }
}
,
2497
2498 /* Unsigned Long configs */
2499 createULongConfig("active-defrag-max-scan-fields", NULL, MODIFIABLE_CONFIG, 1, LONG_MAX, server.active_defrag_max_scan_fields, 1000, INTEGER_CONFIG, NULL, NULL){ .name = ("active-defrag-max-scan-fields"), .alias = (((void
*)0)), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(1), .upper_bound = (9223372036854775807L), .default_value =
(1000), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0
)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_ULONG, .config
.ul = &(server.active_defrag_max_scan_fields) } }
, /* Default: keys with more than 1000 fields will be processed separately */
2500 createULongConfig("slowlog-max-len", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.slowlog_max_len, 128, INTEGER_CONFIG, NULL, NULL){ .name = ("slowlog-max-len"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (9223372036854775807L
), .default_value = (128), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_ULONG
, .config.ul = &(server.slowlog_max_len) } }
,
2501 createULongConfig("acllog-max-len", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.acllog_max_len, 128, INTEGER_CONFIG, NULL, NULL){ .name = ("acllog-max-len"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (9223372036854775807L
), .default_value = (128), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_ULONG
, .config.ul = &(server.acllog_max_len) } }
,
2502
2503 /* Long Long configs */
2504 createLongLongConfig("lua-time-limit", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.lua_time_limit, 5000, INTEGER_CONFIG, NULL, NULL){ .name = ("lua-time-limit"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (9223372036854775807L
), .default_value = (5000), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_LONG_LONG
, .config.ll = &(server.lua_time_limit) } }
,/* milliseconds */
2505 createLongLongConfig("cluster-node-timeout", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, server.cluster_node_timeout, 15000, INTEGER_CONFIG, NULL, NULL){ .name = ("cluster-node-timeout"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (9223372036854775807LL
), .default_value = (15000), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_LONG_LONG
, .config.ll = &(server.cluster_node_timeout) } }
,
2506 createLongLongConfig("slowlog-log-slower-than", NULL, MODIFIABLE_CONFIG, -1, LLONG_MAX, server.slowlog_log_slower_than, 10000, INTEGER_CONFIG, NULL, NULL){ .name = ("slowlog-log-slower-than"), .alias = (((void*)0)),
.modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(-1), .upper_bound = (9223372036854775807LL), .default_value
= (10000), .is_valid_fn = (((void*)0)), .update_fn = (((void
*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_LONG_LONG
, .config.ll = &(server.slowlog_log_slower_than) } }
,
2507 createLongLongConfig("latency-monitor-threshold", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, server.latency_monitor_threshold, 0, INTEGER_CONFIG, NULL, NULL){ .name = ("latency-monitor-threshold"), .alias = (((void*)0)
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807LL), .default_value =
(0), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)),
.is_memory = (0), .numeric_type = NUMERIC_TYPE_LONG_LONG, .config
.ll = &(server.latency_monitor_threshold) } }
,
2508 createLongLongConfig("proto-max-bulk-len", NULL, MODIFIABLE_CONFIG, 1024*1024, LONG_MAX, server.proto_max_bulk_len, 512ll*1024*1024, MEMORY_CONFIG, NULL, NULL){ .name = ("proto-max-bulk-len"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (1024*1024), .upper_bound
= (9223372036854775807L), .default_value = (512ll*1024*1024)
, .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)), .is_memory
= (1), .numeric_type = NUMERIC_TYPE_LONG_LONG, .config.ll = &
(server.proto_max_bulk_len) } }
, /* Bulk request max size */
2509 createLongLongConfig("stream-node-max-entries", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, server.stream_node_max_entries, 100, INTEGER_CONFIG, NULL, NULL){ .name = ("stream-node-max-entries"), .alias = (((void*)0)),
.modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807LL), .default_value =
(100), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), .is_memory = (0), .numeric_type = NUMERIC_TYPE_LONG_LONG, .
config.ll = &(server.stream_node_max_entries) } }
,
2510 createLongLongConfig("repl-backlog-size", NULL, MODIFIABLE_CONFIG, 1, LLONG_MAX, server.repl_backlog_size, 1024*1024, MEMORY_CONFIG, NULL, updateReplBacklogSize){ .name = ("repl-backlog-size"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (1), .upper_bound = (9223372036854775807LL
), .default_value = (1024*1024), .is_valid_fn = (((void*)0)),
.update_fn = (updateReplBacklogSize), .is_memory = (1), .numeric_type
= NUMERIC_TYPE_LONG_LONG, .config.ll = &(server.repl_backlog_size
) } }
, /* Default: 1mb */
2511
2512 /* Unsigned Long Long configs */
2513 createULongLongConfig("maxmemory", NULL, MODIFIABLE_CONFIG, 0, ULLONG_MAX, server.maxmemory, 0, MEMORY_CONFIG, NULL, updateMaxmemory){ .name = ("maxmemory"), .alias = (((void*)0)), .modifiable =
(1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = ((9223372036854775807LL
*2ULL+1ULL)), .default_value = (0), .is_valid_fn = (((void*)0
)), .update_fn = (updateMaxmemory), .is_memory = (1), .numeric_type
= NUMERIC_TYPE_ULONG_LONG, .config.ull = &(server.maxmemory
) } }
,
2514
2515 /* Size_t configs */
2516 createSizeTConfig("hash-max-ziplist-entries", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.hash_max_ziplist_entries, 512, INTEGER_CONFIG, NULL, NULL){ .name = ("hash-max-ziplist-entries"), .alias = (((void*)0))
, .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807L), .default_value =
(512), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), .is_memory = (0), .numeric_type = NUMERIC_TYPE_SIZE_T, .config
.st = &(server.hash_max_ziplist_entries) } }
,
2517 createSizeTConfig("set-max-intset-entries", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.set_max_intset_entries, 512, INTEGER_CONFIG, NULL, NULL){ .name = ("set-max-intset-entries"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (numericConfigInit),
.set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807L), .default_value =
(512), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), .is_memory = (0), .numeric_type = NUMERIC_TYPE_SIZE_T, .config
.st = &(server.set_max_intset_entries) } }
,
2518 createSizeTConfig("zset-max-ziplist-entries", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.zset_max_ziplist_entries, 128, INTEGER_CONFIG, NULL, NULL){ .name = ("zset-max-ziplist-entries"), .alias = (((void*)0))
, .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807L), .default_value =
(128), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), .is_memory = (0), .numeric_type = NUMERIC_TYPE_SIZE_T, .config
.st = &(server.zset_max_ziplist_entries) } }
,
2519 createSizeTConfig("active-defrag-ignore-bytes", NULL, MODIFIABLE_CONFIG, 1, LLONG_MAX, server.active_defrag_ignore_bytes, 100<<20, MEMORY_CONFIG, NULL, NULL){ .name = ("active-defrag-ignore-bytes"), .alias = (((void*)0
)), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(1), .upper_bound = (9223372036854775807LL), .default_value =
(100<<20), .is_valid_fn = (((void*)0)), .update_fn = (
((void*)0)), .is_memory = (1), .numeric_type = NUMERIC_TYPE_SIZE_T
, .config.st = &(server.active_defrag_ignore_bytes) } }
, /* Default: don't defrag if frag overhead is below 100mb */
2520 createSizeTConfig("hash-max-ziplist-value", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.hash_max_ziplist_value, 64, MEMORY_CONFIG, NULL, NULL){ .name = ("hash-max-ziplist-value"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (numericConfigInit),
.set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807L), .default_value =
(64), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0))
, .is_memory = (1), .numeric_type = NUMERIC_TYPE_SIZE_T, .config
.st = &(server.hash_max_ziplist_value) } }
,
2521 createSizeTConfig("stream-node-max-bytes", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.stream_node_max_bytes, 4096, MEMORY_CONFIG, NULL, NULL){ .name = ("stream-node-max-bytes"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (numericConfigInit),
.set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807L), .default_value =
(4096), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0
)), .is_memory = (1), .numeric_type = NUMERIC_TYPE_SIZE_T, .config
.st = &(server.stream_node_max_bytes) } }
,
2522 createSizeTConfig("zset-max-ziplist-value", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.zset_max_ziplist_value, 64, MEMORY_CONFIG, NULL, NULL){ .name = ("zset-max-ziplist-value"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (numericConfigInit),
.set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807L), .default_value =
(64), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0))
, .is_memory = (1), .numeric_type = NUMERIC_TYPE_SIZE_T, .config
.st = &(server.zset_max_ziplist_value) } }
,
2523 createSizeTConfig("hll-sparse-max-bytes", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.hll_sparse_max_bytes, 3000, MEMORY_CONFIG, NULL, NULL){ .name = ("hll-sparse-max-bytes"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (9223372036854775807L
), .default_value = (3000), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (1), .numeric_type = NUMERIC_TYPE_SIZE_T
, .config.st = &(server.hll_sparse_max_bytes) } }
,
2524 createSizeTConfig("tracking-table-max-keys", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.tracking_table_max_keys, 1000000, INTEGER_CONFIG, NULL, NULL){ .name = ("tracking-table-max-keys"), .alias = (((void*)0)),
.modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807L), .default_value =
(1000000), .is_valid_fn = (((void*)0)), .update_fn = (((void
*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_SIZE_T,
.config.st = &(server.tracking_table_max_keys) } }
, /* Default: 1 million keys max. */
2525 createSizeTConfig("client-query-buffer-limit", NULL, MODIFIABLE_CONFIG, 1024*1024, LONG_MAX, server.client_max_querybuf_len, 1024*1024*1024, MEMORY_CONFIG, NULL, NULL){ .name = ("client-query-buffer-limit"), .alias = (((void*)0)
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(1024*1024), .upper_bound = (9223372036854775807L), .default_value
= (1024*1024*1024), .is_valid_fn = (((void*)0)), .update_fn =
(((void*)0)), .is_memory = (1), .numeric_type = NUMERIC_TYPE_SIZE_T
, .config.st = &(server.client_max_querybuf_len) } }
, /* Default: 1GB max query buffer. */
2526
2527 /* Other configs */
2528 createTimeTConfig("repl-backlog-ttl", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.repl_backlog_time_limit, 60*60, INTEGER_CONFIG, NULL, NULL){ .name = ("repl-backlog-ttl"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (9223372036854775807L
), .default_value = (60*60), .is_valid_fn = (((void*)0)), .update_fn
= (((void*)0)), .is_memory = (0), .numeric_type = NUMERIC_TYPE_TIME_T
, .config.tt = &(server.repl_backlog_time_limit) } }
, /* Default: 1 hour */
2529 createOffTConfig("auto-aof-rewrite-min-size", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, server.aof_rewrite_min_size, 64*1024*1024, MEMORY_CONFIG, NULL, NULL){ .name = ("auto-aof-rewrite-min-size"), .alias = (((void*)0)
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (9223372036854775807LL), .default_value =
(64*1024*1024), .is_valid_fn = (((void*)0)), .update_fn = ((
(void*)0)), .is_memory = (1), .numeric_type = NUMERIC_TYPE_OFF_T
, .config.ot = &(server.aof_rewrite_min_size) } }
,
2530
2531#ifdef USE_OPENSSL
2532 createIntConfig("tls-port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.tls_port, 0, INTEGER_CONFIG, NULL, updateTLSPort){ .name = ("tls-port"), .alias = (((void*)0)), .modifiable = (
1), .interface = { .init = (numericConfigInit), .set = (numericConfigSet
), .get = (numericConfigGet), .rewrite = (numericConfigRewrite
) }, .data.numeric = { .lower_bound = (0), .upper_bound = (65535
), .default_value = (0), .is_valid_fn = (((void*)0)), .update_fn
= (updateTLSPort), .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT
, .config.i = &(server.tls_port) } }
, /* TCP port. */
2533 createIntConfig("tls-session-cache-size", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.tls_ctx_config.session_cache_size, 20*1024, INTEGER_CONFIG, NULL, updateTlsCfgInt){ .name = ("tls-session-cache-size"), .alias = (((void*)0)), .
modifiable = (1), .interface = { .init = (numericConfigInit),
.set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (2147483647), .default_value = (20*1024)
, .is_valid_fn = (((void*)0)), .update_fn = (updateTlsCfgInt)
, .is_memory = (0), .numeric_type = NUMERIC_TYPE_INT, .config
.i = &(server.tls_ctx_config.session_cache_size) } }
,
2534 createIntConfig("tls-session-cache-timeout", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.tls_ctx_config.session_cache_timeout, 300, INTEGER_CONFIG, NULL, updateTlsCfgInt){ .name = ("tls-session-cache-timeout"), .alias = (((void*)0)
), .modifiable = (1), .interface = { .init = (numericConfigInit
), .set = (numericConfigSet), .get = (numericConfigGet), .rewrite
= (numericConfigRewrite) }, .data.numeric = { .lower_bound =
(0), .upper_bound = (2147483647), .default_value = (300), .is_valid_fn
= (((void*)0)), .update_fn = (updateTlsCfgInt), .is_memory =
(0), .numeric_type = NUMERIC_TYPE_INT, .config.i = &(server
.tls_ctx_config.session_cache_timeout) } }
,
2535 createBoolConfig("tls-cluster", NULL, MODIFIABLE_CONFIG, server.tls_cluster, 0, NULL, updateTlsCfgBool){ .name = ("tls-cluster"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.tls_cluster), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (updateTlsCfgBool
), } }
,
2536 createBoolConfig("tls-replication", NULL, MODIFIABLE_CONFIG, server.tls_replication, 0, NULL, updateTlsCfgBool){ .name = ("tls-replication"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.tls_replication), .default_value
= (0), .is_valid_fn = (((void*)0)), .update_fn = (updateTlsCfgBool
), } }
,
2537 createEnumConfig("tls-auth-clients", NULL, MODIFIABLE_CONFIG, tls_auth_clients_enum, server.tls_auth_clients, TLS_CLIENT_AUTH_YES, NULL, NULL){ .name = ("tls-auth-clients"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (enumConfigInit), .set = (enumConfigSet
), .get = (enumConfigGet), .rewrite = (enumConfigRewrite) }, .
data.enumd = { .config = &(server.tls_auth_clients), .default_value
= (1), .is_valid_fn = (((void*)0)), .update_fn = (((void*)0)
), .enum_value = (tls_auth_clients_enum), } }
,
2538 createBoolConfig("tls-prefer-server-ciphers", NULL, MODIFIABLE_CONFIG, server.tls_ctx_config.prefer_server_ciphers, 0, NULL, updateTlsCfgBool){ .name = ("tls-prefer-server-ciphers"), .alias = (((void*)0)
), .modifiable = (1), .interface = { .init = (boolConfigInit)
, .set = (boolConfigSet), .get = (boolConfigGet), .rewrite = (
boolConfigRewrite) }, .data.yesno = { .config = &(server.
tls_ctx_config.prefer_server_ciphers), .default_value = (0), .
is_valid_fn = (((void*)0)), .update_fn = (updateTlsCfgBool), }
}
,
2539 createBoolConfig("tls-session-caching", NULL, MODIFIABLE_CONFIG, server.tls_ctx_config.session_caching, 1, NULL, updateTlsCfgBool){ .name = ("tls-session-caching"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (boolConfigInit), .set = (boolConfigSet
), .get = (boolConfigGet), .rewrite = (boolConfigRewrite) }, .
data.yesno = { .config = &(server.tls_ctx_config.session_caching
), .default_value = (1), .is_valid_fn = (((void*)0)), .update_fn
= (updateTlsCfgBool), } }
,
2540 createStringConfig("tls-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.cert_file, NULL, NULL, updateTlsCfg){ .name = ("tls-cert-file"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.cert_file
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2541 createStringConfig("tls-key-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.key_file, NULL, NULL, updateTlsCfg){ .name = ("tls-key-file"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.key_file
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2542 createStringConfig("tls-client-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.client_cert_file, NULL, NULL, updateTlsCfg){ .name = ("tls-client-cert-file"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.client_cert_file
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2543 createStringConfig("tls-client-key-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.client_key_file, NULL, NULL, updateTlsCfg){ .name = ("tls-client-key-file"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.client_key_file
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2544 createStringConfig("tls-dh-params-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.dh_params_file, NULL, NULL, updateTlsCfg){ .name = ("tls-dh-params-file"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.dh_params_file
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2545 createStringConfig("tls-ca-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ca_cert_file, NULL, NULL, updateTlsCfg){ .name = ("tls-ca-cert-file"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.ca_cert_file
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2546 createStringConfig("tls-ca-cert-dir", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ca_cert_dir, NULL, NULL, updateTlsCfg){ .name = ("tls-ca-cert-dir"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.ca_cert_dir
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2547 createStringConfig("tls-protocols", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.protocols, NULL, NULL, updateTlsCfg){ .name = ("tls-protocols"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.protocols
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2548 createStringConfig("tls-ciphers", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ciphers, NULL, NULL, updateTlsCfg){ .name = ("tls-ciphers"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.ciphers
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2549 createStringConfig("tls-ciphersuites", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ciphersuites, NULL, NULL, updateTlsCfg){ .name = ("tls-ciphersuites"), .alias = (((void*)0)), .modifiable
= (1), .interface = { .init = (stringConfigInit), .set = (stringConfigSet
), .get = (stringConfigGet), .rewrite = (stringConfigRewrite)
}, .data.string = { .config = &(server.tls_ctx_config.ciphersuites
), .default_value = (((void*)0)), .is_valid_fn = (((void*)0))
, .update_fn = (updateTlsCfg), .convert_empty_to_null = (1), }
}
,
2550#endif
2551
2552 /* NULL Terminator */
2553 {NULL((void*)0)}
2554};
2555
2556/*-----------------------------------------------------------------------------
2557 * CONFIG command entry point
2558 *----------------------------------------------------------------------------*/
2559
2560void configCommand(client *c) {
2561 /* Only allow CONFIG GET while loading. */
2562 if (server.loading && strcasecmp(c->argv[1]->ptr,"get")) {
1
Assuming field 'loading' is 0
2563 addReplyError(c,"Only CONFIG GET is allowed during loading");
2564 return;
2565 }
2566
2567 if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"help")) {
2
Assuming field 'argc' is equal to 2
3
Assuming the condition is false
4
Taking false branch
2568 const char *help[] = {
2569"GET <pattern>",
2570" Return parameters matching the glob-like <pattern> and their values.",
2571"SET <directive> <value>",
2572" Set the configuration <directive> to <value>.",
2573"RESETSTAT",
2574" Reset statistics reported by the INFO command.",
2575"REWRITE",
2576" Rewrite the configuration file.",
2577NULL((void*)0)
2578 };
2579
2580 addReplyHelp(c, help);
2581 } else if (!strcasecmp(c->argv[1]->ptr,"set") && c->argc == 4) {
5
Assuming the condition is false
2582 configSetCommand(c);
2583 } else if (!strcasecmp(c->argv[1]->ptr,"get") && c->argc == 3) {
6
Assuming the condition is false
2584 configGetCommand(c);
2585 } else if (!strcasecmp(c->argv[1]->ptr,"resetstat") && c->argc == 2) {
7
Assuming the condition is false
2586 resetServerStats();
2587 resetCommandTableStats();
2588 resetErrorTableStats();
2589 addReply(c,shared.ok);
2590 } else if (!strcasecmp(c->argv[1]->ptr,"rewrite") && c->argc
7.1
Field 'argc' is equal to 2
== 2) {
8
Taking true branch
2591 if (server.configfile == NULL((void*)0)) {
9
Assuming field 'configfile' is not equal to NULL
10
Taking false branch
2592 addReplyError(c,"The server is running without a config file");
2593 return;
2594 }
2595 if (rewriteConfig(server.configfile, 0) == -1) {
11
Calling 'rewriteConfig'
2596 serverLog(LL_WARNING3,"CONFIG REWRITE failed: %s", strerror(errno(*__errno_location ())));
2597 addReplyErrorFormat(c,"Rewriting config file: %s", strerror(errno(*__errno_location ())));
2598 } else {
2599 serverLog(LL_WARNING3,"CONFIG REWRITE executed with success.");
2600 addReply(c,shared.ok);
2601 }
2602 } else {
2603 addReplySubcommandSyntaxError(c);
2604 return;
2605 }
2606}