2 assfile - library for accessing assets with an fopen/fread-like interface
3 Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
22 #include "assfile_impl.h"
26 struct tar_entry *tarent;
31 static void *fop_open(const char *fname, void *udata);
32 static void fop_close(void *fp, void *udata);
33 static long fop_seek(void *fp, long offs, int whence, void *udata);
34 static long fop_read(void *fp, void *buf, long size, void *udata);
37 struct ass_fileops *ass_alloc_archive(const char *fname)
39 struct ass_fileops *fop;
42 if(!(tar = malloc(sizeof *tar))) {
45 if(load_tar(tar, fname) == -1) {
50 if(!(fop = malloc(sizeof *fop))) {
55 fop->close = fop_close;
61 void ass_free_archive(struct ass_fileops *fop)
63 close_tar(fop->udata);
68 static void *fop_open(const char *fname, void *udata)
71 struct file_info *file;
72 struct tar *tar = udata;
74 for(i=0; i<tar->num_files; i++) {
75 if(strcmp(fname, tar->files[i].path) == 0) {
76 if(!(file = malloc(sizeof *file))) {
80 file->tarent = tar->files + i;
91 static void fop_close(void *fp, void *udata)
96 static long fop_seek(void *fp, long offs, int whence, void *udata)
99 struct file_info *file = fp;
107 newoffs = file->roffs + offs;
111 newoffs = file->tarent->size + offs;
125 file->roffs = newoffs;
129 static long fop_read(void *fp, void *buf, long size, void *udata)
131 struct tar *tar = udata;
132 struct file_info *file = fp;
133 long newoffs = file->roffs + size;
136 if(file->roffs >= file->tarent->size) {
141 if(newoffs > file->tarent->size) {
142 size = file->tarent->size - file->roffs;
143 newoffs = file->tarent->size;
146 if(fseek(tar->fp, file->tarent->offset + file->roffs, SEEK_SET) == -1) {
147 fprintf(stderr, "assfile mod_archive: fop_read failed to seek to %ld (%ld + %ld)\n",
148 file->tarent->offset + file->roffs, file->tarent->offset, file->roffs);
151 if((rdbytes = fread(buf, 1, size, tar->fp)) < size) {
152 fprintf(stderr, "assfile mod_archive: fop_read unexpected EOF while trying to read %ld bytes\n", size);
155 file->roffs = newoffs;