/* * Copyright 2023 Xavier Del Campo Romero * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include struct secret_file { FILE *f; const void *buf; long offset, sz; int eof, error; }; FILE *__wrap_fopen(const char *restrict const pathname, const char *restrict const flags) { FILE *__real_fopen(const char *, const char *); struct secret_file *const s = malloc(sizeof *s); if (!s) return NULL; *s = (const struct secret_file){0}; for (size_t i = 0; i < fswrap_entries->n; i++) { const struct fswrap_entry *const e = &fswrap_entries->entries[i]; if (!strcmp(pathname, e->pathname)) { if (strcmp(flags, "r") && strcmp(flags, "rb")) { fprintf(stderr, "%s: unsupported flags %s\n", __func__, flags); return NULL; } s->buf = e->buf; s->sz = e->sz; return (FILE *)s; } } if (!(s->f = __real_fopen(pathname, flags))) goto failure; return (FILE *)s; failure: free(s); return NULL; } int __wrap_fclose(FILE *const f) { int ret; int __real_fclose(FILE *); struct secret_file *const s = (struct secret_file *)f; if (s->f) ret = __real_fclose(s->f); free(s); return ret; } static int read_item(void *restrict *const ptr, const size_t size, struct secret_file *restrict const s) { if (size > s->sz - s->offset) { s->eof = 1; return -1; } memcpy(*ptr, &((const char *restrict)(s->buf))[s->offset], size); *ptr = (char *restrict)*ptr + size; s->offset += size; return 0; } size_t __wrap_fread(void *restrict ptr, const size_t size, const size_t nitems, FILE *restrict const stream) { size_t __real_fread(void *restrict, size_t, size_t, FILE *restrict); if (((struct secret_file *restrict )stream)->f) return __real_fread(ptr, size, nitems, ((struct secret_file *restrict)stream)->f); for (size_t i = 0; i < nitems; i++) if (read_item(&ptr, size, (struct secret_file *restrict)stream)) return i; return nitems; } int __wrap_feof(FILE *const stream) { int __real_feof(FILE *); struct secret_file *const s = (struct secret_file *)stream; if (s->f) return __real_feof(s->f); return s->eof; } int __wrap_ferror(FILE *const stream) { int __real_ferror(FILE *); struct secret_file *const s = (struct secret_file *)stream; if (s->f) return __real_ferror(s->f); return s->error; } static int file_seek(struct secret_file *const s, const long offset, const int whence) { switch (whence) { case SEEK_SET: if (offset < 0) { errno = EINVAL; return -1; } s->offset = offset; break; case SEEK_CUR: if (offset > LONG_MAX - s->offset) { errno = EOVERFLOW; return -1; } else if (offset < -s->offset) { errno = EINVAL; return -1; } s->offset += offset; break; case SEEK_END: if (offset > LONG_MAX - s->sz) { errno = EOVERFLOW; return -1; } else if (offset < -s->sz) { errno = EINVAL; return -1; } s->offset = s->sz + offset; break; default: errno = EINVAL; return -1; } s->eof = 0; return 0; } int __wrap_fseek(FILE *const stream, const long offset, const int whence) { int __real_fseek(FILE *, long, int); struct secret_file *const s = (struct secret_file *)stream; if (s->f) return __real_fseek(stream, offset, whence); return file_seek(s, offset, whence); } void __wrap_clearerr(FILE *const stream) { int __real_clearerr(FILE *); struct secret_file *const s = (struct secret_file *)stream; if (s->f) __real_clearerr(s->f); else s->eof = s->error = 0; } int __wrap_access(const char *const pathname, const int mode) { return -1; }