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

Code before:
void AutoFile::seek(int64_t offset, int origin)
{
    if (IsNull()) {
        throw std::ios_base::failure("AutoFile::seek: file handle is nullptr");
    }
    if (std::fseek(m_file, offset, origin) != 0) {
        throw std::ios_base::failure(feof() ? "AutoFile::seek: end of file" : "AutoFile::seek: fseek failed");
    }
}

int64_t AutoFile::tell()
{
    if (IsNull()) {
        throw std::ios_base::failure("AutoFile::tell: file handle is nullptr");
    }
    int64_t r{std::ftell(m_file)};
    if (r < 0) {
        throw std::ios_base::failure("AutoFile::tell: ftell failed");
    }
    return r;
}

void AutoFile::read(Span<std::byte> dst)
{
    if (detail_fread(dst) != dst.size()) {
        throw std::ios_base::failure(feof() ? "AutoFile::read: end of file" : "AutoFile::read: fread failed");
    }
}

void AutoFile::ignore(size_t nSize)
{
    if (!m_file) throw std::ios_base::failure("AutoFile::ignore: file handle is nullptr");
    unsigned char data[4096];
    while (nSize > 0) {
        size_t nNow = std::min<size_t>(nSize, sizeof(data));
        if (std::fread(data, 1, nNow, m_file) != nNow) {
            throw std::ios_base::failure(feof() ? "AutoFile::ignore: end of file" : "AutoFile::ignore: fread failed");
        }
        nSize -= nNow;
    }
}

void AutoFile::write(Span<const std::byte> src)
{
    if (!m_file) throw std::ios_base::failure("AutoFile::write: file handle is nullptr");
    if (m_xor.empty()) {
        if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) {
            throw std::ios_base::failure("AutoFile::write: write failed");
        }
    } else {
        auto current_pos{std::ftell(m_file)};

Review comment (suggestion):
Only commenting because I struggled with this for a bit:

This makes sense since the only present possibility for this else branch is that `origin == SEEK_END`, in which case the only way for `fseek` to have returned zero is if `offset` is a negative number indicating how far from the end of the file to seek to,  and `m_position = length_of_file + negative_offset`

But, in order to get the length of the file you need to `fseek(m_file, 0, SEEK_END)` and `ftell(m_file)`.

So, just `ftell` here is the best way to get the new `m_position`.

Code after:
    if (!m_xor.empty()) {
        if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::read: position unknown");
        util::Xor(dst.subspan(0, ret), m_xor, *m_position);
    }
    if (m_position.has_value()) *m_position += ret;
    return ret;
}

void AutoFile::seek(int64_t offset, int origin)
{
    if (IsNull()) {
        throw std::ios_base::failure("AutoFile::seek: file handle is nullptr");
    }
    if (std::fseek(m_file, offset, origin) != 0) {
        throw std::ios_base::failure(feof() ? "AutoFile::seek: end of file" : "AutoFile::seek: fseek failed");
    }
    if (origin == SEEK_SET) {
        m_position = offset;
    } else if (origin == SEEK_CUR && m_position.has_value()) {
        *m_position += offset;
    } else {
        int64_t r{std::ftell(m_file)};
        if (r < 0) {
            throw std::ios_base::failure("AutoFile::seek: ftell failed");
        }
        m_position = r;
    }
}

int64_t AutoFile::tell()
{
    if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::tell: position unknown");
    return *m_position;
}

void AutoFile::read(Span<std::byte> dst)
{
    if (detail_fread(dst) != dst.size()) {
        throw std::ios_base::failure(feof() ? "AutoFile::read: end of file" : "AutoFile::read: fread failed");
    }
}

void AutoFile::ignore(size_t nSize)
{
    if (!m_file) throw std::ios_base::failure("AutoFile::ignore: file handle is nullptr");
    unsigned char data[4096];
    while (nSize > 0) {
        size_t nNow = std::min<size_t>(nSize, sizeof(data));
        if (std::fread(data, 1, nNow, m_file) != nNow) {
            throw std::ios_base::failure(feof() ? "AutoFile::ignore: end of file" : "AutoFile::ignore: fread failed");
        }