Repository: bitcoin/bitcoin
File: src/addrdb.cpp (C++)

Code before:
    fs::path pathTmp = gArgs.GetDataDirNet() / fs::u8path(tmpfn);
    FILE *file = fsbridge::fopen(pathTmp, "wb");
    AutoFile fileout{file};
    if (fileout.IsNull()) {
        fileout.fclose();
        remove(pathTmp);
        LogError("%s: Failed to open file %s\n", __func__, fs::PathToString(pathTmp));
        return false;
    }

    // Serialize
    if (!SerializeDB(fileout, data)) {
        fileout.fclose();
        remove(pathTmp);
        return false;
    }
    if (!fileout.Commit()) {
        fileout.fclose();
        remove(pathTmp);
        LogError("%s: Failed to flush file %s\n", __func__, fs::PathToString(pathTmp));
        return false;
    }
    fileout.fclose();

    // replace existing file, if any, with new file
    if (!RenameOver(pathTmp, path)) {
        remove(pathTmp);
        LogError("%s: Rename-into-place failed\n", __func__);
        return false;
    }

    return true;
}

template <typename Stream, typename Data>
void DeserializeDB(Stream& stream, Data&& data, bool fCheckSum = true)
{
    HashVerifier verifier{stream};
    // de-serialize file header (network specific magic number) and ..
    MessageStartChars pchMsgTmp;
    verifier >> pchMsgTmp;
    // ... verify the network matches ours
    if (pchMsgTmp != Params().MessageStart()) {
        throw std::runtime_error{"Invalid network magic number"};
    }

    // de-serialize data
    verifier >> data;

    // verify checksum
    if (fCheckSum) {

Review comment (bug):
not sure about this. Commit is stronger than fclose, so I fail to see how this could ever fail on a real and normal system.

Forcing devs to write verbose and dead code doesn't seem ideal. It would be better to just treat Commit as `m_was_written=false`.

Code after:
    // open temp output file
    fs::path pathTmp = gArgs.GetDataDirNet() / fs::u8path(tmpfn);
    FILE *file = fsbridge::fopen(pathTmp, "wb");
    AutoFile fileout{file};
    if (fileout.IsNull()) {
        remove(pathTmp);
        LogError("%s: Failed to open file %s\n", __func__, fs::PathToString(pathTmp));
        return false;
    }

    // Serialize
    if (!SerializeDB(fileout, data)) {
        (void)fileout.fclose();
        remove(pathTmp);
        return false;
    }
    if (!fileout.Commit()) {
        (void)fileout.fclose();
        remove(pathTmp);
        LogError("%s: Failed to flush file %s\n", __func__, fs::PathToString(pathTmp));
        return false;
    }
    if (fileout.fclose() != 0) {
        const int errno_save{errno};
        remove(pathTmp);
        LogError("Failed to close file %s after commit: %s", fs::PathToString(pathTmp), SysErrorString(errno_save));
        return false;
    }

    // replace existing file, if any, with new file
    if (!RenameOver(pathTmp, path)) {
        remove(pathTmp);
        LogError("%s: Rename-into-place failed\n", __func__);
        return false;
    }

    return true;
}

template <typename Stream, typename Data>
void DeserializeDB(Stream& stream, Data&& data, bool fCheckSum = true)
{
    HashVerifier verifier{stream};
    // de-serialize file header (network specific magic number) and ..
    MessageStartChars pchMsgTmp;
    verifier >> pchMsgTmp;
    // ... verify the network matches ours
    if (pchMsgTmp != Params().MessageStart()) {
        throw std::runtime_error{"Invalid network magic number"};
    }