// File: /workspace/github_c_makefile_star2_O1/zhou-yuxin[P]redis-aof-no-cow/src/redis-check-rdb.c
// Function: redis_check_rdb
int redis_check_rdb(char *rdbfilename) {
    uint64_t dbid;
    int type, rdbver;
    char buf[1024];
    long long expiretime, now = mstime();
    FILE *fp;
    rio rdb;

    if ((fp = fopen(rdbfilename,"r")) == NULL) return C_ERR;

    rioInitWithFile(&rdb,fp);
    rdbstate.rio = &rdb;
    rdb.update_cksum = rdbLoadProgressCallback;
    if (rioRead(&rdb,buf,9) == 0) goto eoferr;
    buf[9] = '\0';
    if (memcmp(buf,"REDIS",5) != 0) {
        rdbCheckError("Wrong signature trying to load DB from file");
        return 1;
    }
    rdbver = atoi(buf+5);
    if (rdbver < 1 || rdbver > RDB_VERSION) {
        rdbCheckError("Can't handle RDB format version %d",rdbver);
        return 1;
    }

    startLoading(fp);
    while(1) {
        robj *key, *val;
        expiretime = -1;

        /* Read type. */
        rdbstate.doing = RDB_CHECK_DOING_READ_TYPE;
        if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;

        /* Handle special types. */
        if (type == RDB_OPCODE_EXPIRETIME) {
            rdbstate.doing = RDB_CHECK_DOING_READ_EXPIRE;
            /* EXPIRETIME: load an expire associated with the next key
             * to load. Note that after loading an expire we need to
             * load the actual type, and continue. */
            if ((expiretime = rdbLoadTime(&rdb)) == -1) goto eoferr;
            /* We read the time so we need to read the object type again. */
            rdbstate.doing = RDB_CHECK_DOING_READ_TYPE;
            if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
            /* the EXPIRETIME opcode specifies time in seconds, so convert
             * into milliseconds. */
            expiretime *= 1000;
        } else if (type == RDB_OPCODE_EXPIRETIME_MS) {
            /* EXPIRETIME_MS: milliseconds precision expire times introduced
             * with RDB v3. Like EXPIRETIME but no with more precision. */
            rdbstate.doing = RDB_CHECK_DOING_READ_EXPIRE;
            if ((expiretime = rdbLoadMillisecondTime(&rdb)) == -1) goto eoferr;
            /* We read the time so we need to read the object type again. */
            rdbstate.doing = RDB_CHECK_DOING_READ_TYPE;
            if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
        } else if (type == RDB_OPCODE_EOF) {
            /* EOF: End of file, exit the main loop. */
            break;
        } else if (type == RDB_OPCODE_SELECTDB) {
            /* SELECTDB: Select the specified database. */
            rdbstate.doing = RDB_CHECK_DOING_READ_LEN;
            if ((dbid = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)
                goto eoferr;
            rdbCheckInfo("Selecting DB ID %d", dbid);
            continue; /* Read type again. */
        } else if (type == RDB_OPCODE_RESIZEDB) {
            /* RESIZEDB: Hint about the size of the keys in the currently
             * selected data base, in order to avoid useless rehashing. */
            uint64_t db_size, expires_size;
            rdbstate.doing = RDB_CHECK_DOING_READ_LEN;
            if ((db_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)
                goto eoferr;
            if ((expires_size = rdbLoadLen(&rdb,NULL)) == RDB_LENERR)
                goto eoferr;
            continue; /* Read type again. */
        } else if (type == RDB_OPCODE_AUX) {
            /* AUX: generic string-string fields. Use to add state to RDB
             * which is backward compatible. Implementations of RDB loading
             * are requierd to skip AUX fields they don't understand.
             *
             * An AUX field is composed of two strings: key and value. */
            robj *auxkey, *auxval;
            rdbstate.doing = RDB_CHECK_DOING_READ_AUX;
            if ((auxkey = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;
            if ((auxval = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;

            rdbCheckInfo("AUX FIELD %s = '%s'",
                (char*)auxkey->ptr, (char*)auxval->ptr);
            decrRefCount(auxkey);
            decrRefCount(auxval);
            continue; /* Read type again. */
        } else {
            if (!rdbIsObjectType(type)) {
                rdbCheckError("Invalid object type: %d", type);
                return 1;
            }
            rdbstate.key_type = type;
        }

        /* Read key */
        rdbstate.doing = RDB_CHECK_DOING_READ_KEY;
        if ((key = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;
        rdbstate.key = key;
        rdbstate.keys++;
        /* Read value */
        rdbstate.doing = RDB_CHECK_DOING_READ_OBJECT_VALUE;
        if ((val = rdbLoadObject(type,&rdb)) == NULL) goto eoferr;
        /* Check if the key already expired. This function is used when loading
         * an RDB file from disk, either at startup, or when an RDB was
         * received from the master. In the latter case, the master is
         * responsible for key expiry. If we would expire keys here, the
         * snapshot taken by the master may not be reflected on the slave. */
        if (server.masterhost == NULL && expiretime != -1 && expiretime < now)
            rdbstate.already_expired++;
        if (expiretime != -1) rdbstate.expires++;
        rdbstate.key = NULL;
        decrRefCount(key);
        decrRefCount(val);
        rdbstate.key_type = -1;
    }
    /* Verify the checksum if RDB version is >= 5 */
    if (rdbver >= 5 && server.rdb_checksum) {
        uint64_t cksum, expected = rdb.cksum;

        rdbstate.doing = RDB_CHECK_DOING_CHECK_SUM;
        if (rioRead(&rdb,&cksum,8) == 0) goto eoferr;
        memrev64ifbe(&cksum);
        if (cksum == 0) {
            rdbCheckInfo("RDB file was saved with checksum disabled: no check performed.");
        } else if (cksum != expected) {
            rdbCheckError("RDB CRC error");
        } else {
            rdbCheckInfo("Checksum OK");
        }
    }

    fclose(fp);
    return 0;

eoferr: /* unexpected end of file is handled here with a fatal exit */
    if (rdbstate.error_set) {
        rdbCheckError(rdbstate.error);
    } else {
        rdbCheckError("Unexpected EOF reading RDB file");
    }
    return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x498, %rsp            # imm = 0x498
movq %rdi, %rbx
callq 0x330c8
movq %rax, 0x18(%rsp)
leaq 0x3ecc6(%rip), %rsi     # 0xc29f5
movq %rbx, %rdi
callq 0x26af0
testq %rax, %rax
je 0x83e17
leaq 0x28(%rsp), %r15
movq %r15, %rdi
movq %rax, 0x8(%rsp)
movq %rax, %rsi
callq 0x76172
movq %r15, 0x97bdc(%rip)     # 0x11b938
leaq -0x36368(%rip), %rax    # 0x4d9fb
movq %rax, 0x20(%r15)
movl $0x9, %eax
leaq 0x90(%rsp), %r12
testq %rax, %rax
je 0x83deb
movq %rax, %rbx
movq 0x60(%rsp), %rax
cmpq %rbx, %rax
movq %rbx, %r13
cmovbq %rax, %r13
testq %rax, %rax
cmoveq %rbx, %r13
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq *0x28(%rsp)
movq %rax, %rbp
testq %rax, %rax
je 0x83dcc
movq 0x48(%rsp), %rax
testq %rax, %rax
je 0x83dbc
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq *%rax
addq %r13, %r12
movq %rbx, %rax
subq %r13, %rax
addq %r13, 0x58(%rsp)
jmp 0x83dcf
movq %rbx, %rax
testq %rbp, %rbp
jne 0x83d74
testq %rbx, %rbx
je 0x83deb
cmpl $0x0, 0x97b8c(%rip)     # 0x11b96c
je 0x83e45
leaq 0x97b87(%rip), %rdi     # 0x11b970
jmp 0x83e4c
movb $0x0, 0x99(%rsp)
movl $0x49444552, %eax       # imm = 0x49444552
xorl 0x90(%rsp), %eax
movzbl 0x94(%rsp), %ecx
xorl $0x53, %ecx
orl %eax, %ecx
je 0x83e1e
leaq 0x41e19(%rip), %rdi     # 0xc5c2e
jmp 0x83e4c
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x83e58
leaq 0x95(%rsp), %rdi
callq 0x26770
movl %eax, %esi
leal -0x8(%rsi), %eax
cmpl $-0x8, %eax
ja 0x83e6a
leaq 0x41e1e(%rip), %rdi     # 0xc5c5a
xorl %eax, %eax
callq 0x839c9
jmp 0x83e53
leaq 0x41f76(%rip), %rdi     # 0xc5dc2
xorl %eax, %eax
callq 0x839c9
movl $0x1, %eax
addq $0x498, %rsp            # imm = 0x498
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rsi, 0x10(%rsp)
movq 0x8(%rsp), %rdi
callq 0x4d949
leaq 0x28(%rsp), %r12
leaq 0x4e35f(%rip), %r14     # 0xd21e4
movl $0x1, 0x97ad9(%rip)     # 0x11b968
movq %r12, %rdi
callq 0x4ae06
movl %eax, %r13d
movl $0x2, %ebx
leal 0x1(%r13), %eax
cmpl $0xf, %eax
ja 0x83f8e
movl $0xfc3e, %ecx           # imm = 0xFC3E
btl %eax, %ecx
jae 0x83f8a
movl %r13d, 0x97a87(%rip)    # 0x11b948
movq $-0x1, %rbp
movl $0x3, 0x97a96(%rip)     # 0x11b968
movq %r12, %rdi
callq 0x4bccf
testq %rax, %rax
je 0x83f76
movq %rax, %r15
movq %rax, 0x97a53(%rip)     # 0x11b940
incq 0x97a5c(%rip)           # 0x11b950
movl $0x4, 0x97a6a(%rip)     # 0x11b968
movl %r13d, %edi
movq %r12, %rsi
callq 0x4cfb6
testq %rax, %rax
je 0x83f76
movq %rax, %r13
leaq 0x82940(%rip), %rax     # 0x106858
cmpq $0x0, 0x818(%rax)
sete %al
cmpq $-0x1, %rbp
setne %cl
cmpq 0x18(%rsp), %rbp
setl %dl
andb %cl, %dl
andb %al, %dl
cmpb $0x1, %dl
jne 0x83f42
incq 0x97a1e(%rip)           # 0x11b960
cmpq $-0x1, %rbp
je 0x83f4f
incq 0x97a09(%rip)           # 0x11b958
movq $0x0, 0x979e6(%rip) # 0x11b940
movq %r15, %rdi
callq 0x440f3
movq %r13, %rdi
callq 0x440f3
movl $0xffffffff, 0x979d4(%rip) # imm = 0xFFFFFFFF
xorl %ebx, %ebx
cmpl $0x4, %ebx
ja 0x83e53
movl %ebx, %eax
movslq (%r14,%rax,4), %rax
addq %r14, %rax
jmpq *%rax
testl %eax, %eax
je 0x83f76
movl %r13d, %eax
addl $0xffffff06, %eax       # imm = 0xFFFFFF06
cmpl $0x5, %eax
ja 0x84104
leaq 0x4e226(%rip), %rcx     # 0xd21cc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x7, 0x979af(%rip)     # 0x11b968
movq %r12, %rdi
callq 0x4bccf
testq %rax, %rax
je 0x83f76
movq %rax, %r15
movq %r12, %rdi
callq 0x4bccf
testq %rax, %rax
je 0x83f76
movq %rax, %r13
movq 0x8(%r15), %rsi
movq 0x8(%rax), %rdx
leaq 0x4e3e9(%rip), %rdi     # 0xd23d1
xorl %eax, %eax
callq 0x83b14
movq %r15, %rdi
callq 0x440f3
movq %r13, %rdi
callq 0x440f3
jmp 0x8402e
movl $0x6, 0x9795d(%rip)     # 0x11b968
movq %r12, %rdi
xorl %esi, %esi
callq 0x4b10c
cmpl $-0x1, %eax
je 0x83f76
movl %eax, %esi
leaq 0x4e397(%rip), %rdi     # 0xd23be
xorl %eax, %eax
callq 0x83b14
movl $0x3, %ebx
jmp 0x83f76
movl $0x2, 0x97926(%rip)     # 0x11b968
movq %r12, %rdi
callq 0x4afc4
cmpq $-0x1, %rax
je 0x83f76
movq %rax, %rbp
movl $0x1, 0x97907(%rip)     # 0x11b968
movq %r12, %rdi
callq 0x4ae06
cmpl $-0x1, %eax
je 0x83f76
movl %eax, %r13d
jmp 0x83ec8
movl $0x2, 0x978e4(%rip)     # 0x11b968
movq %r12, %rdi
callq 0x4af1b
cmpq $-0x1, %rax
je 0x83f76
movq %rax, %r15
movl $0x1, 0x978c5(%rip)     # 0x11b968
movq %r12, %rdi
callq 0x4ae06
cmpl $-0x1, %eax
je 0x83f76
movl %eax, %r13d
imulq $0x3e8, %r15, %rbp      # imm = 0x3E8
jmp 0x83ec8
movl $0x6, 0x9789b(%rip)     # 0x11b968
movq %r12, %rdi
xorl %esi, %esi
callq 0x4b10c
cmpl $-0x1, %eax
je 0x83f76
movq %r12, %rdi
xorl %esi, %esi
callq 0x4b10c
xorl %ebx, %ebx
cmpl $-0x1, %eax
sete %bl
xorl $0x3, %ebx
jmp 0x83f76
movl $0x4, %ebx
jmp 0x83f76
leaq 0x4e2da(%rip), %rdi     # 0xd23e5
movl %r13d, %esi
xorl %eax, %eax
callq 0x839c9
movl $0x1, %ebx
jmp 0x83f76
cmpl $0x5, 0x10(%rsp)
jl 0x841a3
leaq 0x8272b(%rip), %rax     # 0x106858
cmpl $0x0, 0x744(%rax)
je 0x841a3
leaq 0x28(%rsp), %rdi
movq 0x28(%rdi), %rbx
movl $0x5, 0x9781f(%rip)     # 0x11b968
leaq 0x20(%rsp), %rsi
movl $0x8, %edx
callq 0x841b4
testq %rax, %rax
je 0x83dd9
movq %rax, %r14
movq 0x20(%rsp), %rax
testq %rax, %rax
je 0x8417c
cmpq %rbx, %rax
jne 0x8418c
leaq 0x4e283(%rip), %rdi     # 0xd23fd
jmp 0x84183
leaq 0x41b8f(%rip), %rdi     # 0xc5d12
xorl %eax, %eax
callq 0x83b14
jmp 0x8419a
leaq 0x41be0(%rip), %rdi     # 0xc5d73
xorl %eax, %eax
callq 0x839c9
testq %r14, %r14
je 0x83dd9
movq 0x8(%rsp), %rdi
callq 0x26a20
xorl %eax, %eax
jmp 0x83e58