/** * @file file.c * @author Karim Vergnes * @copyright GPLv2 * @brief Functions to read and write UMDiff files * * The functions defined here control reading and writing UMDiff files from * in-memory structure @ref umdiff_File. */ #include "umdiff.h" #include #include #include typedef union { char data[sizeof(umdiff_Header)]; umdiff_Header hdr; } _impl_umdiff_RawHeader; #define _impl_umdiff_alignSector$(x) \ ( x + ISO_SECTOR_SIZE - (x % ISO_SECTOR_SIZE) ) void _impl_umdiff_Header_rectify(umdiff_Header *hdr) { long len_preamble = sizeof(umdiff_Header) + (sizeof(umdiff_Command) * hdr->cmd_count); strncpy(hdr->magic, umdiff_File_$MAGIC, 7); hdr->version = umdiff_File_$VERSION; hdr->data_start = _impl_umdiff_alignSector$(len_preamble); } int umdiff_File_load(umdiff_File *file, int fd, umdiff_FileFlags flags) { _impl_umdiff_RawHeader rheader; int ret; if (!file) return 1; ret = read(fd, &rheader.data, sizeof(umdiff_Header)); file->hdr = rheader.hdr; if (strncmp(file->hdr.magic, umdiff_File_$MAGIC, 7)) return 1; if (file->hdr.version != umdiff_File_$VERSION) return 1; if (flags >= umdiff_FileFlags_HEADER_AND_COMMANDS) { ret = read(fd, file->commands, sizeof(umdiff_Command) * file->hdr.cmd_count); } if (flags == umdiff_FileFlags_LOAD_FULL) { file->data_len = lseek(fd, 0, SEEK_END) - file->hdr.data_start; ret = lseek(fd, file->hdr.data_start, SEEK_SET); ret = read(fd, file->data, file->data_len); } return 0; } int umdiff_File_write(umdiff_File *file, int outfd) { _impl_umdiff_RawHeader rheader; int ret; if (!file || file->mode != umdiff_FileFlags_LOAD_FULL || !file->commands || !file->data || !file->hdr.cmd_count || !file->hdr.index[0]) return 1; rheader.hdr = file->hdr; _impl_umdiff_Header_rectify(&rheader.hdr); ret = write(outfd, rheader.data, sizeof(umdiff_Header)); ret = write(outfd, file->commands, sizeof(umdiff_Command) * rheader.hdr.cmd_count); ret = lseek(outfd, rheader.hdr.data_start, SEEK_SET); ret = write(outfd, file->data, file->data_len); return 0; }