/* * 2ooM: The Master of Orion II Reverse Engineering Project * Default file operations structures for liblbx. * Copyright © 2010, 2014 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include "misc.h" #include "error.h" #include "lbx.h" /* Default I/O operations for ordinary files. */ static size_t file_read(void *buf, size_t size, void *handle) { size_t rc = fread(buf, 1, size, (FILE *)handle); if (rc < size && ferror((FILE *)handle)) lbx_error_raise(-errno); return rc; } static int file_seek(void *handle, long offset, int whence) { if (fseek((FILE *)handle, offset, whence) == -1) { lbx_error_raise(-errno); return -1; } return 0; } static int file_eof(void *handle) { return feof((FILE *)handle); } const struct lbx_file_ops lbx_default_fops = { .read = file_read, .seek = file_seek, .eof = file_eof, }; /* Read function for pipes that tracks the number of bytes read. */ static size_t pipe_read(void *buf, size_t size, void *handle) { struct lbx_pipe_state *state = handle; size_t rc; rc = file_read(buf, size, state->f); state->offset += rc; return rc; } /* Seek function for pipes that reads data into the void. */ static int pipe_seek(void *handle, long offset, int whence) { struct lbx_pipe_state *state = handle; long distance; switch (whence) { case SEEK_SET: distance = offset - state->offset; break; case SEEK_CUR: distance = offset; break; case SEEK_END: distance = -1; break; default: assert(0); } if (distance < 0) return -1; while (distance > 0) { static unsigned char oblivion[1024]; size_t rc, amount = MIN(sizeof oblivion, distance); rc = pipe_read(oblivion, amount, handle); distance -= rc; if (rc < amount) return -1; } clearerr(state->f); return 0; } static int pipe_eof(void *handle) { struct lbx_pipe_state *state = handle; return feof(state->f); } const struct lbx_file_ops lbx_pipe_fops = { .read = pipe_read, .seek = pipe_seek, .eof = pipe_eof, }; static size_t lbx_read(void *buf, size_t size, void *handle) { return lbx_file_read(handle, buf, size); } static int lbx_seek(void *handle, long offset, int whence) { return lbx_file_seek(handle, offset, whence); } static int lbx_eof(void *handle) { return lbx_file_eof(handle); } const struct lbx_file_ops lbx_arch_fops = { .read = lbx_read, .seek = lbx_seek, .eof = lbx_eof, };