// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/redis-check-aof.c
// Function: main
int main(int argc, char **argv) {
    char *filename;
    int fix = 0;

    // 选项，如果不带 --fix 就只检查，不进行修复
    if (argc < 2) {
        printf("Usage: %s [--fix] <file.aof>\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(filename,"r+");
    if (fp == NULL) {
        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", filename);
        exit(1);
    }

    // 取出文件的大小
    off_t size = sb.st_size;
    if (size == 0) {
        printf("Empty file: %s\n", filename);
        exit(1);
    }

    // 如果文件出错，那么这个偏移量指向：
    // 1） 第一个不符合格式的位置
    // 2） 第一个没有 EXEC 对应的 MULTI 的位置
    // 如果文件没有出错，那么这个偏移量指向：
    // 3） 文件末尾
    off_t pos = process(fp);
    // 计算偏移量距离文件末尾有多远
    off_t diff = size-pos;
    printf("AOF analyzed: size=%lld, ok_up_to=%lld, diff=%lld\n",
        (long long) size, (long long) pos, (long long) diff);

    // 大于 0 表示未到达文件末尾，出错
    if (diff > 0) {

        // fix 模式：尝试修复文件
        if (fix) {

            // 尝试从出错的位置开始，一直删除到文件的末尾
            char buf[2];
            printf("This will shrink the AOF from %lld bytes, with %lld bytes, to %lld bytes\n",(long long)size,(long long)diff,(long long)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");
            }

        // 非 fix 模式：只报告文件不合法
        } else {
            printf("AOF is not valid\n");
            exit(1);
        }

    // 等于 0 表示文件已经顺利读完，无错
    } else {
        printf("AOF is valid\n");
    }

    // 关闭文件
    fclose(fp);

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x98, %rsp
movq %rsi, %rbx
cmpl $0x1, %edi
jle 0x17ab
movl %edi, %ebp
cmpl $0x2, %edi
jne 0x1661
pushq $0x8
jmp 0x1687
cmpl $0x3, %ebp
jne 0x17e4
movq 0x8(%rbx), %r14
leaq 0xa77(%rip), %rsi       # 0x20ec
movq %r14, %rdi
callq 0x10b0
testl %eax, %eax
jne 0x17f2
pushq $0x10
popq %rax
movq (%rbx,%rax), %r14
leaq 0xa75(%rip), %rsi       # 0x2108
movq %r14, %rdi
callq 0x10d0
testq %rax, %rax
je 0x17b7
movq %rax, %rbx
movq %rax, %rdi
callq 0x10f0
leaq 0x8(%rsp), %rsi
movl %eax, %edi
callq 0x1150
cmpl $-0x1, %eax
je 0x17c0
movq 0x38(%rsp), %r15
testq %r15, %r15
je 0x17c9
movq %rbx, %rdi
callq 0x147a
movq %rax, %r14
leaq 0xa63(%rip), %rdi       # 0x2147
movq %r15, %rcx
subq %rax, %rcx
movq %r15, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x1080
movq %r15, %rdx
subq %r14, %rdx
jle 0x177e
cmpl $0x2, %ebp
je 0x17d2
leaq 0xa6b(%rip), %rdi       # 0x217a
movq %r15, %rsi
movq %r14, %rcx
xorl %eax, %eax
callq 0x1080
leaq 0xaa1(%rip), %rdi       # 0x21c4
xorl %eax, %eax
callq 0x1080
movq 0x28af(%rip), %rax      # 0x3fe0
movq (%rax), %rdx
leaq 0x6(%rsp), %rdi
pushq $0x2
popq %rsi
callq 0x10a0
testq %rax, %rax
je 0x17a2
leaq 0xa89(%rip), %rsi       # 0x21d6
leaq 0x6(%rsp), %rdi
pushq $0x1
popq %rdx
callq 0x1110
testl %eax, %eax
jne 0x17a2
movq %rbx, %rdi
callq 0x10f0
movl %eax, %edi
movq %r14, %rsi
callq 0x1120
cmpl $-0x1, %eax
je 0x17db
leaq 0xa8c(%rip), %rdi       # 0x2208
jmp 0x1785
leaq 0xa65(%rip), %rdi       # 0x21ea
callq 0x1050
movq %rbx, %rdi
callq 0x1070
xorl %eax, %eax
addq $0x98, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
leaq 0xa91(%rip), %rdi       # 0x223a
jmp 0x17eb
movq (%rbx), %rsi
leaq 0x919(%rip), %rdi       # 0x20ce
jmp 0x17fc
leaq 0x94d(%rip), %rdi       # 0x210b
jmp 0x17f9
leaq 0x95a(%rip), %rdi       # 0x2121
jmp 0x17f9
leaq 0x967(%rip), %rdi       # 0x2137
jmp 0x17f9
leaq 0xa1e(%rip), %rdi       # 0x21f7
jmp 0x17eb
leaq 0xa41(%rip), %rdi       # 0x2223
jmp 0x17eb
leaq 0x9ed(%rip), %rdi       # 0x21d8
callq 0x1050
jmp 0x1803
leaq 0x8f9(%rip), %rdi       # 0x20f2
movq %r14, %rsi
xorl %eax, %eax
callq 0x1080
pushq $0x1
popq %rdi
callq 0x1140