X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/b4bd05241da2772f457d0552d807e7cfd4dc8f33..4e538759c4125a2379fd625e5a92c72347017b7f:/redis-check-aof.c diff --git a/redis-check-aof.c b/redis-check-aof.c index 3be60781..ff0d1f82 100644 --- a/redis-check-aof.c +++ b/redis-check-aof.c @@ -1,6 +1,8 @@ +#include "fmacros.h" #include #include #include +#include #include #include "config.h" @@ -57,13 +59,9 @@ int readString(FILE *fp, char** target) { len += 2; *target = (char*)malloc(len); if (!readBytes(fp,*target,len)) { - free(*target); - *target = NULL; return 0; } if (!consumeNewline(*target+len-2)) { - free(*target); - *target = NULL; return 0; } (*target)[len-2] = '\0'; @@ -81,14 +79,10 @@ long process(FILE *fp) { while(1) { if (!multi) pos = ftell(fp); - if (!readArgc(fp, &argc)) { - break; - } + if (!readArgc(fp, &argc)) break; for (i = 0; i < argc; i++) { - if (!readString(fp,&str)) { - break; - } + if (!readString(fp,&str)) break; if (i == 0) { if (strcasecmp(str, "multi") == 0) { if (multi++) { @@ -105,7 +99,7 @@ long process(FILE *fp) { free(str); } - /* Check if loop was finished */ + /* Stop if the loop did not finish */ if (i < argc) { if (str) free(str); break; @@ -115,45 +109,75 @@ long process(FILE *fp) { if (feof(fp) && multi && strlen(error) == 0) { ERROR("Reached EOF before reading EXEC for MULTI"); } - if (strlen(error) > 0) { printf("%s\n", error); } - return pos; } int main(int argc, char **argv) { - /* expect the first argument to be the dump file */ - if (argc <= 1) { - printf("Usage: %s \n", argv[0]); - exit(0); + char *filename; + int fix = 0; + + if (argc < 2) { + printf("Usage: %s [--fix] \n", argv[0]); + exit(1); + } else if (argc == 2) { + filename = argv[1]; + } else if (argc == 3) { + if (strcmp(argv[1],"--fix") != 0) { + printf("Invalid argument: %s\n", argv[1]); + exit(1); + } + filename = argv[2]; + fix = 1; + } else { + printf("Invalid arguments\n"); + exit(1); } - FILE *fp = fopen(argv[1],"r"); + FILE *fp = fopen(filename,"r+"); if (fp == NULL) { - printf("Cannot open file: %s\n", argv[1]); + printf("Cannot open file: %s\n", filename); exit(1); } struct redis_stat sb; if (redis_fstat(fileno(fp),&sb) == -1) { - printf("Cannot stat file: %s\n", argv[1]); + printf("Cannot stat file: %s\n", filename); exit(1); } long size = sb.st_size; if (size == 0) { - printf("Empty file: %s\n", argv[1]); + printf("Empty file: %s\n", filename); exit(1); } long pos = process(fp); - if (pos < size) { - printf("First invalid operation at offset %ld.\n", pos); - exit(1); + long diff = size-pos; + if (diff > 0) { + if (fix) { + char buf[2]; + printf("This will shrink the AOF from %ld bytes, with %ld bytes, to %ld bytes\n",size,diff,pos); + printf("Continue? [y/N]: "); + if (fgets(buf,sizeof(buf),stdin) == NULL || + strncasecmp(buf,"y",1) != 0) { + printf("Aborting...\n"); + exit(1); + } + if (ftruncate(fileno(fp), pos) == -1) { + printf("Failed to truncate AOF\n"); + exit(1); + } else { + printf("Successfully truncated AOF\n"); + } + } else { + printf("AOF is not valid\n"); + exit(1); + } } else { - printf("AOF is valid.\n"); + printf("AOF is valid\n"); } fclose(fp);