Exemple #1
0
static int _loki_write_loki_header(MbBiWriter *biw, MbFile *file,
                                   const LokiHeader *lhdr)
{
    LokiHeader dup = *lhdr;
    size_t n;
    int ret;

    loki_fix_header_byte_order(&dup);

    ret = mb_file_seek(file, LOKI_MAGIC_OFFSET, SEEK_SET, nullptr);
    if (ret != MB_FILE_OK) {
        mb_bi_writer_set_error(biw, mb_file_error(file),
                               "Failed to seek to Loki header offset: %s",
                               mb_file_error_string(file));
        return ret == MB_FILE_FATAL ? MB_BI_FATAL : MB_BI_FAILED;
    }

    ret = mb_file_write_fully(file, &dup, sizeof(dup), &n);
    if (ret != MB_FILE_OK) {
        mb_bi_writer_set_error(biw, mb_file_error(file),
                               "Failed to write Loki header: %s",
                               mb_file_error_string(file));
        return ret == MB_FILE_FATAL ? MB_BI_FATAL : MB_BI_FAILED;
    } else if (n != sizeof(dup)) {
        mb_bi_writer_set_error(biw, MB_BI_ERROR_FILE_FORMAT,
                               "Unexpected EOF when writing Loki header: %s",
                               mb_file_error_string(file));
        return MB_BI_FAILED;
    }

    return MB_BI_OK;
}
/*!
 * \brief Find and read Loki boot image header
 *
 * \note The integral fields in the header will be converted to the host's byte
 *       order.
 *
 * \pre The file position can be at any offset prior to calling this function.
 *
 * \post The file pointer position is undefined after this function returns.
 *       Use File::seek() to return to a known position.
 *
 * \param[in] reader Reader
 * \param[in] file File handle
 * \param[out] header_out Pointer to store header
 * \param[out] offset_out Pointer to store header offset
 *
 * \return
 *   * Nothing if the header is found
 *   * A LokiError if the header is not found
 *   * A specified error code if any file operation fails
 */
oc::result<void> LokiFormatReader::find_loki_header(Reader &reader, File &file,
                                                    LokiHeader &header_out,
                                                    uint64_t &offset_out)
{
    LokiHeader header;

    auto seek_ret = file.seek(LOKI_MAGIC_OFFSET, SEEK_SET);
    if (!seek_ret) {
        if (file.is_fatal()) { reader.set_fatal(); }
        return seek_ret.as_failure();
    }

    auto ret = file_read_exact(file, &header, sizeof(header));
    if (!ret) {
        if (ret.error() == FileError::UnexpectedEof) {
            return LokiError::LokiHeaderTooSmall;
        } else {
            if (file.is_fatal()) { reader.set_fatal(); }
            return ret.as_failure();
        }
    }

    if (memcmp(header.magic, LOKI_MAGIC, LOKI_MAGIC_SIZE) != 0) {
        return LokiError::InvalidLokiMagic;
    }

    loki_fix_header_byte_order(header);
    header_out = header;
    offset_out = LOKI_MAGIC_OFFSET;

    return oc::success();
}
MB_BEGIN_C_DECLS

/*!
 * \brief Find and read Loki boot image header
 *
 * \note The integral fields in the header will be converted to the host's byte
 *       order.
 *
 * \pre The file position can be at any offset prior to calling this function.
 *
 * \post The file pointer position is undefined after this function returns.
 *       Use mb_file_seek() to return to a known position.
 *
 * \param[in] bir MbBiReader
 * \param[in] file MbFile handle
 * \param[out] header_out Pointer to store header
 * \param[out] offset_out Pointer to store header offset
 *
 * \return
 *   * #MB_BI_OK if the header is found
 *   * #MB_BI_WARN if the header is not found
 *   * #MB_BI_FAILED if any file operation fails non-fatally
 *   * #MB_BI_FATAL if any file operation fails fatally
 */
int find_loki_header(MbBiReader *bir, MbFile *file,
                     LokiHeader *header_out, uint64_t *offset_out)
{
    LokiHeader header;
    size_t n;
    int ret;

    ret = mb_file_seek(file, LOKI_MAGIC_OFFSET, SEEK_SET, nullptr);
    if (ret < 0) {
        mb_bi_reader_set_error(bir, mb_file_error(file),
                               "Loki magic not found: %s",
                               mb_file_error_string(file));
        return ret == MB_FILE_FATAL ? MB_BI_FATAL : MB_BI_WARN;
    }

    ret = mb_file_read_fully(file, &header, sizeof(header), &n);
    if (ret < 0) {
        mb_bi_reader_set_error(bir, mb_file_error(file),
                               "Failed to read header: %s",
                               mb_file_error_string(file));
        return ret == MB_FILE_FATAL ? MB_BI_FATAL : MB_BI_FAILED;
    } else if (n != sizeof(header)) {
        mb_bi_reader_set_error(bir, MB_BI_ERROR_FILE_FORMAT,
                               "Too small to be Loki image");
        return MB_BI_WARN;
    }

    if (memcmp(header.magic, LOKI_MAGIC, LOKI_MAGIC_SIZE) != 0) {
        mb_bi_reader_set_error(bir, MB_BI_ERROR_FILE_FORMAT,
                               "Invalid loki magic");
        return MB_BI_WARN;
    }

    loki_fix_header_byte_order(&header);
    *header_out = header;
    *offset_out = LOKI_MAGIC_OFFSET;

    return MB_BI_OK;
}