// File: /workspace/github_c_makefile_star2_O1/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 0x181d
movl %edi, %ebp
movl $0x8, %ecx
cmpl $0x2, %edi
je 0x16f2
cmpl $0x3, %ebp
jne 0x1856
movq 0x8(%rbx), %r14
leaq 0xa12(%rip), %rsi       # 0x20ef
movq %r14, %rdi
callq 0x10c0
movl $0x10, %ecx
testl %eax, %eax
jne 0x1864
movq (%rbx,%rcx), %r14
leaq 0xa0e(%rip), %rsi       # 0x210b
movq %r14, %rdi
callq 0x10e0
testq %rax, %rax
je 0x1829
movq %rax, %rbx
movq %rax, %rdi
callq 0x1100
leaq 0x8(%rsp), %rsi
movl %eax, %edi
callq 0x1160
cmpl $-0x1, %eax
je 0x1832
movq 0x38(%rsp), %r15
testq %r15, %r15
je 0x183b
movq %rbx, %rdi
callq 0x14aa
movq %rax, %r14
leaq 0x9fc(%rip), %rdi       # 0x214a
movq %r15, %rcx
subq %rax, %rcx
movq %r15, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x1090
movq %r15, %rdx
subq %r14, %rdx
jle 0x17f0
cmpl $0x2, %ebp
je 0x1844
leaq 0xa00(%rip), %rdi       # 0x217d
movq %r15, %rsi
movq %r14, %rcx
xorl %eax, %eax
callq 0x1090
leaq 0xa36(%rip), %rdi       # 0x21c7
xorl %eax, %eax
callq 0x1090
movq 0x2841(%rip), %rax      # 0x3fe0
movq (%rax), %rdx
leaq 0x6(%rsp), %rdi
movl $0x2, %esi
callq 0x10b0
testq %rax, %rax
je 0x1814
leaq 0xa1c(%rip), %rsi       # 0x21d9
leaq 0x6(%rsp), %rdi
movl $0x1, %edx
callq 0x1120
testl %eax, %eax
jne 0x1814
movq %rbx, %rdi
callq 0x1100
movl %eax, %edi
movq %r14, %rsi
callq 0x1130
cmpl $-0x1, %eax
je 0x184d
leaq 0xa1d(%rip), %rdi       # 0x220b
jmp 0x17f7
leaq 0x9f6(%rip), %rdi       # 0x21ed
callq 0x1060
movq %rbx, %rdi
callq 0x1080
xorl %eax, %eax
addq $0x98, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
leaq 0xa22(%rip), %rdi       # 0x223d
jmp 0x185d
movq (%rbx), %rsi
leaq 0x8aa(%rip), %rdi       # 0x20d1
jmp 0x186e
leaq 0x8de(%rip), %rdi       # 0x210e
jmp 0x186b
leaq 0x8eb(%rip), %rdi       # 0x2124
jmp 0x186b
leaq 0x8f8(%rip), %rdi       # 0x213a
jmp 0x186b
leaq 0x9af(%rip), %rdi       # 0x21fa
jmp 0x185d
leaq 0x9d2(%rip), %rdi       # 0x2226
jmp 0x185d
leaq 0x97e(%rip), %rdi       # 0x21db
callq 0x1060
jmp 0x1875
leaq 0x88a(%rip), %rdi       # 0x20f5
movq %r14, %rsi
xorl %eax, %eax
callq 0x1090
movl $0x1, %edi
callq 0x1150