// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0xe0, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0x1c(%rbp)
cmpl $0x2, -0x8(%rbp)
jge 0x17f5
movq -0x10(%rbp), %rax
movq (%rax), %rsi
leaq 0x8ed(%rip), %rdi       # 0x20d1
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1150
cmpl $0x2, -0x8(%rbp)
jne 0x1809
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
jmp 0x1877
cmpl $0x3, -0x8(%rbp)
jne 0x185d
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
leaq 0x8d1(%rip), %rsi       # 0x20ef
callq 0x10c0
cmpl $0x0, %eax
je 0x1848
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq 0x8be(%rip), %rdi       # 0x20f5
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1150
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x18(%rbp)
movl $0x1, -0x1c(%rbp)
jmp 0x1875
leaq 0x8a7(%rip), %rdi       # 0x210b
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1150
jmp 0x1877
jmp 0x1879
movq -0x18(%rbp), %rdi
leaq 0x89a(%rip), %rsi       # 0x211e
callq 0x10e0
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x18b0
movq -0x18(%rbp), %rsi
leaq 0x882(%rip), %rdi       # 0x2121
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1150
movq -0x28(%rbp), %rdi
callq 0x1100
movl %eax, %edi
leaq -0xb8(%rbp), %rsi
callq 0x1160
cmpl $-0x1, %eax
jne 0x18e8
movq -0x18(%rbp), %rsi
leaq 0x860(%rip), %rdi       # 0x2137
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1150
movq -0x88(%rbp), %rax
movq %rax, -0xc0(%rbp)
cmpq $0x0, -0xc0(%rbp)
jne 0x191c
movq -0x18(%rbp), %rsi
leaq 0x842(%rip), %rdi       # 0x214d
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1150
movq -0x28(%rbp), %rdi
callq 0x15a0
movq %rax, -0xc8(%rbp)
movq -0xc0(%rbp), %rax
subq -0xc8(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0xc0(%rbp), %rsi
movq -0xc8(%rbp), %rdx
movq -0xd0(%rbp), %rcx
leaq 0x800(%rip), %rdi       # 0x215d
movb $0x0, %al
callq 0x1090
cmpq $0x0, -0xd0(%rbp)
jle 0x1a61
cmpl $0x0, -0x1c(%rbp)
je 0x1a47
movq -0xc0(%rbp), %rsi
movq -0xd0(%rbp), %rdx
movq -0xc8(%rbp), %rcx
leaq 0x7f8(%rip), %rdi       # 0x2190
movb $0x0, %al
callq 0x1090
leaq 0x834(%rip), %rdi       # 0x21da
movb $0x0, %al
callq 0x1090
leaq -0xd2(%rbp), %rdi
movq 0x2625(%rip), %rax      # 0x3fe0
movq (%rax), %rdx
movl $0x2, %esi
callq 0x10b0
cmpq $0x0, %rax
je 0x19eb
leaq -0xd2(%rbp), %rdi
leaq 0x810(%rip), %rsi       # 0x21ec
movl $0x1, %edx
callq 0x1120
cmpl $0x0, %eax
je 0x1a03
leaq 0x7fc(%rip), %rdi       # 0x21ee
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1150
movq -0x28(%rbp), %rdi
callq 0x1100
movl %eax, %edi
movq -0xc8(%rbp), %rsi
callq 0x1130
cmpl $-0x1, %eax
jne 0x1a37
leaq 0x7d5(%rip), %rdi       # 0x21fb
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1150
leaq 0x7d5(%rip), %rdi       # 0x2213
movb $0x0, %al
callq 0x1090
jmp 0x1a5f
leaq 0x7e1(%rip), %rdi       # 0x222f
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1150
jmp 0x1a6f
leaq 0x7d9(%rip), %rdi       # 0x2241
movb $0x0, %al
callq 0x1090
movq -0x28(%rbp), %rdi
callq 0x1070
xorl %eax, %eax
addq $0xe0, %rsp
popq %rbp
retq