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; }