| 90 | /* Helper to extract Redis version information. Aborts on any failure. */ |
| 91 | #define REDIS_VERSION_FIELD "redis_version:" |
| 92 | void get_redis_version(redisContext *c, int *majorptr, int *minorptr) { |
| 93 | redisReply *reply; |
| 94 | char *eptr, *s, *e; |
| 95 | int major, minor; |
| 96 | |
| 97 | reply = redisCommand(c, "INFO"); |
| 98 | if (reply == NULL || c->err || reply->type != REDIS_REPLY_STRING) |
| 99 | goto abort; |
| 100 | if ((s = strstr(reply->str, REDIS_VERSION_FIELD)) == NULL) |
| 101 | goto abort; |
| 102 | |
| 103 | s += strlen(REDIS_VERSION_FIELD); |
| 104 | |
| 105 | /* We need a field terminator and at least 'x.y.z' (5) bytes of data */ |
| 106 | if ((e = strstr(s, "\r\n")) == NULL || (e - s) < 5) |
| 107 | goto abort; |
| 108 | |
| 109 | /* Extract version info */ |
| 110 | major = strtol(s, &eptr, 10); |
| 111 | if (*eptr != '.') goto abort; |
| 112 | minor = strtol(eptr+1, NULL, 10); |
| 113 | |
| 114 | /* Push info the caller wants */ |
| 115 | if (majorptr) *majorptr = major; |
| 116 | if (minorptr) *minorptr = minor; |
| 117 | |
| 118 | freeReplyObject(reply); |
| 119 | return; |
| 120 | |
| 121 | abort: |
| 122 | freeReplyObject(reply); |
| 123 | fprintf(stderr, "Error: Cannot determine Redis version, aborting\n"); |
| 124 | exit(1); |
| 125 | } |
| 126 | |
| 127 | static redisContext *select_database(redisContext *c) { |
| 128 | redisReply *reply; |
no test coverage detected