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 /* declared in assfile_impl.h */
27 int ass_mod_url_max_threads;
28 char ass_mod_url_cachedir[512];
31 static int add_fop(const char *prefix, int type, struct ass_fileops *fop);
32 static const char *match_prefix(const char *str, const char *prefix);
33 static void upd_verbose_flag(void);
35 #define DEF_FLAGS (1 << ASS_OPEN_FALLTHROUGH)
37 static unsigned int assflags = DEF_FLAGS;
38 static struct mount *mlist;
40 void ass_set_option(int opt, int val)
45 assflags &= ~(1 << opt);
49 int ass_get_option(int opt)
51 return assflags & (1 << opt);
54 int ass_add_path(const char *prefix, const char *path)
56 return add_fop(prefix, MOD_PATH, ass_alloc_path(path));
59 int ass_add_archive(const char *prefix, const char *arfile)
61 return add_fop(prefix, MOD_ARCHIVE, ass_alloc_archive(arfile));
64 int ass_add_url(const char *prefix, const char *url)
66 return add_fop(prefix, MOD_URL, ass_alloc_url(url));
69 int ass_add_user(const char *prefix, struct ass_fileops *fop)
71 return add_fop(prefix, MOD_USER, fop);
74 static int add_fop(const char *prefix, int type, struct ass_fileops *fop)
81 fprintf(stderr, "assfile: failed to allocate asset source\n");
85 if(!(m = malloc(sizeof *m))) {
86 perror("assfile: failed to allocate mount node");
90 if(!(m->prefix = malloc(strlen(prefix) + 1))) {
94 strcpy(m->prefix, prefix);
109 struct mount *m = mlist;
114 ass_free_path(m->fop);
117 ass_free_archive(m->fop);
120 ass_free_url(m->fop);
131 ass_file *ass_fopen(const char *fname, const char *mode)
137 const char *after_prefix;
143 if((after_prefix = match_prefix(fname, m->prefix))) {
144 while(*after_prefix && (*after_prefix == '/' || *after_prefix == '\\')) {
147 if((mfile = m->fop->open(after_prefix, m->fop->udata))) {
148 if(!(file = malloc(sizeof *file))) {
149 perror("assfile: ass_fopen failed to allocate file structure");
150 m->fop->close(mfile, m->fop->udata);
157 if(!(assflags & (1 << ASS_OPEN_FALLTHROUGH))) {
165 /* nothing matched, or failed to open, try the filesystem */
166 if((fp = fopen(fname, mode))) {
167 if(!(file = malloc(sizeof *file))) {
169 perror("assfile: ass_fopen failed to allocate file structure");
181 static const char *match_prefix(const char *str, const char *prefix)
183 if(!prefix || !*prefix) return str; /* match on null or empty prefix */
186 if(*prefix++ != *str++) {
193 void ass_fclose(ass_file *fp)
196 fp->fop->close(fp->file, fp->fop->udata);
203 long ass_fseek(ass_file *fp, long offs, int whence)
206 return fp->fop->seek(fp->file, offs, whence, fp->fop->udata);
209 if(fseek(fp->file, offs, whence) == -1) {
212 return ftell(fp->file);
215 long ass_ftell(ass_file *fp)
217 return ass_fseek(fp, 0, SEEK_CUR);
220 size_t ass_fread(void *buf, size_t size, size_t count, ass_file *fp)
223 long res = fp->fop->read(fp->file, buf, size * count, fp->fop->udata);
224 if(res <= 0) return 0;
228 return fread(buf, size, count, fp->file);
232 /* --- convenience functions --- */
234 int ass_fgetc(ass_file *fp)
238 if(ass_fread(&c, 1, 1, fp) < 1) {
244 char *ass_fgets(char *s, int size, ass_file *fp)
251 for(i=0; i<size - 1; i++) {
252 if((c = ass_fgetc(fp)) == -1) {
260 return ptr == s ? 0 : s;
264 static void upd_verbose_flag(void)
268 if((env = getenv("ASSFILE_VERBOSE"))) {
269 ass_verbose = atoi(env);