mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-08 12:18:31 +00:00
Add torture test for zipos file descriptors
This change hardens the code for opening /zip/ files using the system call interface. Thread safety and signal safety has been improved for file descriptors in general. We now document fixed addresses that are needed for low level allocations.
This commit is contained in:
parent
579080cd4c
commit
e466dd0553
44 changed files with 2981 additions and 307 deletions
|
@ -16,19 +16,20 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/zip.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Closes compressed object.
|
||||
*
|
||||
* @param fd is vetted by close()
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
int __zipos_close(int fd) {
|
||||
int rc;
|
||||
|
@ -40,8 +41,7 @@ int __zipos_close(int fd) {
|
|||
rc = 0; /* no system file descriptor needed on nt */
|
||||
}
|
||||
if (!__vforked) {
|
||||
free(h->freeme);
|
||||
free(h);
|
||||
__zipos_free(__zipos_get(), h);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
40
libc/zipos/free.c
Normal file
40
libc/zipos/free.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/asancodes.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Frees ZipOS handle.
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
*/
|
||||
void __zipos_free(struct Zipos *z, struct ZiposHandle *h) {
|
||||
if (IsAsan()) {
|
||||
__asan_poison((char *)h + sizeof(struct ZiposHandle),
|
||||
h->mapsize - sizeof(struct ZiposHandle), kAsanHeapFree);
|
||||
}
|
||||
__zipos_lock();
|
||||
do h->next = z->freelist;
|
||||
while (!_cmpxchg(&z->freelist, h->next, h));
|
||||
__zipos_unlock();
|
||||
}
|
|
@ -16,27 +16,15 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/zip.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
|
@ -63,52 +51,52 @@ static void __zipos_munmap_unneeded(const uint8_t *base, const uint8_t *cdir,
|
|||
|
||||
/**
|
||||
* Returns pointer to zip central directory of current executable.
|
||||
* @asyncsignalsafe (TODO: verify this)
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
*/
|
||||
struct Zipos *__zipos_get(void) {
|
||||
int fd;
|
||||
char *path;
|
||||
ssize_t size;
|
||||
const char *msg;
|
||||
static bool once;
|
||||
sigset_t neu, old;
|
||||
struct Zipos *res;
|
||||
const char *progpath;
|
||||
static struct Zipos zipos;
|
||||
uint8_t *map, *base, *cdir;
|
||||
static pthread_mutex_t lock;
|
||||
pthread_mutex_lock(&lock);
|
||||
if (_cmpxchg(&once, false, true)) {
|
||||
sigfillset(&neu);
|
||||
if (!once) {
|
||||
__zipos_lock();
|
||||
progpath = GetProgramExecutableName();
|
||||
if ((fd = open(progpath, O_RDONLY)) != -1) {
|
||||
if ((size = getfiledescriptorsize(fd)) != SIZE_MAX &&
|
||||
if ((size = getfiledescriptorsize(fd)) != -1ul &&
|
||||
(map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) {
|
||||
if ((base = FindEmbeddedApe(map, size))) {
|
||||
size -= base - map;
|
||||
} else {
|
||||
base = map;
|
||||
}
|
||||
if ((cdir = GetZipCdir(base, size))) {
|
||||
if ((cdir = GetZipCdir(base, size)) && _cmpxchg(&zipos.map, 0, base)) {
|
||||
__zipos_munmap_unneeded(base, cdir, map);
|
||||
zipos.map = base;
|
||||
zipos.cdir = cdir;
|
||||
STRACE("__zipos_get(%#s)", progpath);
|
||||
msg = "ok";
|
||||
} else {
|
||||
munmap(map, size);
|
||||
STRACE("__zipos_get(%#s) → eocd not found", progpath);
|
||||
msg = "eocd not found";
|
||||
}
|
||||
} else {
|
||||
msg = "map failed";
|
||||
}
|
||||
close(fd);
|
||||
} else {
|
||||
STRACE("__zipos_get(%#s) → open failed %m", progpath);
|
||||
msg = "open failed";
|
||||
}
|
||||
once = true;
|
||||
__zipos_unlock();
|
||||
STRACE("__zipos_get(%#s) → %s% m", progpath, msg);
|
||||
}
|
||||
if (zipos.cdir) {
|
||||
res = &zipos;
|
||||
} else {
|
||||
res = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
return res;
|
||||
}
|
||||
|
|
30
libc/zipos/lock.c
Normal file
30
libc/zipos/lock.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
static pthread_mutex_t __zipos_lock_obj;
|
||||
|
||||
void(__zipos_lock)(void) {
|
||||
pthread_mutex_lock(&__zipos_lock_obj);
|
||||
}
|
||||
|
||||
void(__zipos_unlock)(void) {
|
||||
pthread_mutex_unlock(&__zipos_lock_obj);
|
||||
}
|
|
@ -16,24 +16,26 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/relocations.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/bits/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/lockcmpxchg.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
@ -41,64 +43,164 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zip.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
#include "third_party/zlib/zlib.h"
|
||||
|
||||
static int __zipos_inflate(struct ZiposHandle *h, uint8_t *data, size_t size) {
|
||||
return !__inflate(h->freeme, h->size, data, size) ? 0 : eio();
|
||||
static volatile size_t maptotal;
|
||||
|
||||
static pureconst size_t __zipos_granularity(void) {
|
||||
return (IsWindows() ? FRAMESIZE : PAGESIZE) * (IsAsan() ? 8 : 1);
|
||||
}
|
||||
|
||||
static void *__zipos_mmap(size_t mapsize) {
|
||||
size_t offset;
|
||||
int prot, flags;
|
||||
struct DirectMap dm;
|
||||
uint64_t addr, addr2;
|
||||
do offset = maptotal;
|
||||
while (!_cmpxchg(&maptotal, offset, maptotal + mapsize));
|
||||
if (offset + mapsize <= kMemtrackZiposSize) {
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
|
||||
addr = kMemtrackZiposStart + offset;
|
||||
if ((dm = sys_mmap((void *)addr, mapsize, prot, flags, -1, 0)).addr !=
|
||||
MAP_FAILED) {
|
||||
TrackMemoryInterval(&_mmi, addr >> 16, (addr + mapsize - 1) >> 16,
|
||||
dm.maphandle, prot, flags, false, false, 0, mapsize);
|
||||
if (IsAsan()) {
|
||||
addr2 = (addr >> 3) + 0x7fff8000;
|
||||
dm = sys_mmap((void *)addr2, mapsize >> 3, prot, flags, -1, 0);
|
||||
TrackMemoryInterval(&_mmi, addr2 >> 16,
|
||||
(addr2 + (mapsize >> 3) - 1) >> 16, dm.maphandle,
|
||||
prot, flags, false, false, 0, mapsize >> 3);
|
||||
}
|
||||
return (void *)addr;
|
||||
}
|
||||
}
|
||||
enomem();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ZiposHandle *__zipos_alloc(struct Zipos *zipos, size_t size) {
|
||||
size_t mapsize;
|
||||
struct ZiposHandle *h, **ph;
|
||||
__zipos_lock();
|
||||
mapsize = sizeof(struct ZiposHandle) + size;
|
||||
mapsize = ROUNDUP(mapsize, __zipos_granularity());
|
||||
StartOver:
|
||||
ph = &zipos->freelist;
|
||||
while ((h = *ph)) {
|
||||
if (h->mapsize >= mapsize) {
|
||||
if (!_cmpxchg(ph, h, h->next)) goto StartOver;
|
||||
h->next = 0;
|
||||
break;
|
||||
}
|
||||
ph = &h->next;
|
||||
}
|
||||
if (!h) {
|
||||
h = __zipos_mmap(mapsize);
|
||||
}
|
||||
__zipos_unlock();
|
||||
if (IsAsan()) {
|
||||
__asan_unpoison((char *)h, sizeof(struct ZiposHandle) + size);
|
||||
__asan_poison((char *)h + sizeof(struct ZiposHandle) + size,
|
||||
mapsize - (sizeof(struct ZiposHandle) + size),
|
||||
kAsanHeapOverrun);
|
||||
}
|
||||
if (h) {
|
||||
h->size = size;
|
||||
h->mapsize = mapsize;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
static int __zipos_mkfd(int minfd) {
|
||||
int e, fd;
|
||||
static bool demodernize;
|
||||
if (!demodernize) {
|
||||
e = errno;
|
||||
if ((fd = __sys_fcntl(2, F_DUPFD_CLOEXEC, minfd)) != -1) {
|
||||
return fd;
|
||||
} else if (errno == EINVAL) {
|
||||
demodernize = true;
|
||||
errno = e;
|
||||
} else {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
if ((fd = __sys_fcntl(2, F_DUPFD, minfd)) != -1) {
|
||||
__sys_fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int __zipos_setfd(int fd, struct ZiposHandle *h, unsigned flags,
|
||||
int mode) {
|
||||
_cmpxchg(&g_fds.f, fd, fd + 1);
|
||||
g_fds.p[fd].kind = kFdZip;
|
||||
g_fds.p[fd].handle = (intptr_t)h;
|
||||
g_fds.p[fd].flags = flags | O_CLOEXEC;
|
||||
g_fds.p[fd].mode = mode;
|
||||
g_fds.p[fd].extra = 0;
|
||||
__fds_unlock();
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags,
|
||||
int mode) {
|
||||
size_t lf;
|
||||
int rc, fd;
|
||||
size_t size;
|
||||
uint8_t *data;
|
||||
int rc, fd, minfd;
|
||||
struct ZiposHandle *h;
|
||||
lf = GetZipCfileOffset(zipos->map + cf);
|
||||
if (!IsTiny() &&
|
||||
(ZIP_LFILE_MAGIC(zipos->map + lf) != kZipLfileHdrMagic ||
|
||||
(ZIP_LFILE_COMPRESSIONMETHOD(zipos->map + lf) != kZipCompressionNone &&
|
||||
ZIP_LFILE_COMPRESSIONMETHOD(zipos->map + lf) !=
|
||||
kZipCompressionDeflate))) {
|
||||
return eio();
|
||||
}
|
||||
if (!(h = calloc(1, sizeof(*h)))) return -1;
|
||||
h->cfile = cf;
|
||||
h->size = GetZipLfileUncompressedSize(zipos->map + lf);
|
||||
if (ZIP_LFILE_COMPRESSIONMETHOD(zipos->map + lf)) {
|
||||
if ((h->freeme = malloc(h->size))) {
|
||||
data = ZIP_LFILE_CONTENT(zipos->map + lf);
|
||||
size = GetZipLfileCompressedSize(zipos->map + lf);
|
||||
if ((rc = __zipos_inflate(h, data, size)) != -1) {
|
||||
h->mem = h->freeme;
|
||||
assert((ZIP_LFILE_MAGIC(zipos->map + lf) == kZipLfileHdrMagic));
|
||||
size = GetZipLfileUncompressedSize(zipos->map + lf);
|
||||
switch (ZIP_LFILE_COMPRESSIONMETHOD(zipos->map + lf)) {
|
||||
case kZipCompressionNone:
|
||||
if (!(h = __zipos_alloc(zipos, 0))) return -1;
|
||||
h->mem = ZIP_LFILE_CONTENT(zipos->map + lf);
|
||||
break;
|
||||
case kZipCompressionDeflate:
|
||||
if (!(h = __zipos_alloc(zipos, size))) return -1;
|
||||
if (!__inflate(h->data, size, ZIP_LFILE_CONTENT(zipos->map + lf),
|
||||
GetZipLfileCompressedSize(zipos->map + lf))) {
|
||||
h->mem = h->data;
|
||||
} else {
|
||||
h->mem = 0;
|
||||
eio();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
h->mem = ZIP_LFILE_CONTENT(zipos->map + lf);
|
||||
break;
|
||||
default:
|
||||
return eio();
|
||||
}
|
||||
h->pos = 0;
|
||||
h->cfile = cf;
|
||||
h->size = size;
|
||||
if (!IsTiny() && h->mem &&
|
||||
crc32_z(0, h->mem, h->size) != ZIP_LFILE_CRC32(zipos->map + lf)) {
|
||||
errno = EIO;
|
||||
h->mem = NULL;
|
||||
h->mem = 0;
|
||||
eio();
|
||||
}
|
||||
if (h->mem) {
|
||||
if ((fd = IsWindows() ? __reservefd(-1) : dup(2)) != -1) {
|
||||
if (__ensurefds(fd) != -1) {
|
||||
__fds_lock();
|
||||
h->handle = g_fds.p[fd].handle;
|
||||
g_fds.p[fd].kind = kFdZip;
|
||||
g_fds.p[fd].handle = (intptr_t)h;
|
||||
g_fds.p[fd].flags = flags | O_CLOEXEC;
|
||||
g_fds.p[fd].mode = mode;
|
||||
g_fds.p[fd].extra = 0;
|
||||
__fds_unlock();
|
||||
return fd;
|
||||
minfd = 3;
|
||||
__fds_lock();
|
||||
TryAgain:
|
||||
if (IsWindows()) {
|
||||
if ((fd = __reservefd_unlocked(-1)) != -1) {
|
||||
return __zipos_setfd(fd, h, flags, mode);
|
||||
}
|
||||
close(fd);
|
||||
} else if ((fd = __zipos_mkfd(minfd)) != -1) {
|
||||
if (__ensurefds_unlocked(fd) != -1) {
|
||||
if (g_fds.p[fd].kind) {
|
||||
sys_close(fd);
|
||||
minfd = fd + 1;
|
||||
goto TryAgain;
|
||||
}
|
||||
return __zipos_setfd(fd, h, flags, mode);
|
||||
}
|
||||
sys_close(fd);
|
||||
}
|
||||
__fds_unlock();
|
||||
}
|
||||
free(h->freeme);
|
||||
free(h);
|
||||
__zipos_free(zipos, h);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -106,12 +208,12 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags,
|
|||
* Loads compressed file from αcτµαlly pδrταblε εxεcµταblε object store.
|
||||
*
|
||||
* @param uri is obtained via __zipos_parseuri()
|
||||
* @note don't call open() from signal handlers
|
||||
* @asyncsignalsafe (todo)
|
||||
* @threadsafe
|
||||
*/
|
||||
int __zipos_open(const struct ZiposUri *name, unsigned flags, int mode) {
|
||||
int rc;
|
||||
ssize_t cf;
|
||||
sigset_t oldmask;
|
||||
struct Zipos *zipos;
|
||||
if ((flags & O_ACCMODE) == O_RDONLY) {
|
||||
if ((zipos = __zipos_get())) {
|
||||
|
|
|
@ -1,33 +1,40 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_
|
||||
#define COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/nopl.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct stat;
|
||||
struct iovec;
|
||||
|
||||
struct Zipos {
|
||||
uint8_t *map;
|
||||
uint8_t *cdir;
|
||||
};
|
||||
|
||||
struct ZiposUri {
|
||||
const char *path;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
struct ZiposHandle {
|
||||
uint8_t *mem; /* uncompressed file memory */
|
||||
size_t size; /* byte length of file memory */
|
||||
struct ZiposHandle *next;
|
||||
size_t size; /* byte length of `mem` */
|
||||
size_t mapsize; /* total size of this struct */
|
||||
size_t pos; /* read/write byte offset state */
|
||||
uint32_t cfile; /* central directory entry rva */
|
||||
int64_t handle;
|
||||
uint8_t *freeme;
|
||||
uint8_t *mem; /* points to inflated data or uncompressed image */
|
||||
uint8_t data[]; /* uncompressed file memory */
|
||||
};
|
||||
|
||||
struct Zipos {
|
||||
uint8_t *map;
|
||||
uint8_t *cdir;
|
||||
struct ZiposHandle *freelist;
|
||||
};
|
||||
|
||||
void __zipos_lock(void) hidden;
|
||||
void __zipos_unlock(void) hidden;
|
||||
int __zipos_close(int) hidden;
|
||||
struct Zipos *__zipos_get(void) pureconst hidden;
|
||||
void __zipos_free(struct Zipos *, struct ZiposHandle *) hidden;
|
||||
ssize_t __zipos_parseuri(const char *, struct ZiposUri *) hidden;
|
||||
ssize_t __zipos_find(struct Zipos *, const struct ZiposUri *);
|
||||
int __zipos_open(const struct ZiposUri *, unsigned, int) hidden;
|
||||
|
@ -42,6 +49,14 @@ int64_t __zipos_lseek(struct ZiposHandle *, int64_t, unsigned) hidden;
|
|||
int __zipos_fcntl(int, int, uintptr_t) hidden;
|
||||
int __zipos_notat(int, const char *) hidden;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__llvm__) && !defined(__STRICT_ANSI__)
|
||||
#define __zipos_lock() _NOPL0("__threadcalls", __zipos_lock)
|
||||
#define __zipos_unlock() _NOPL0("__threadcalls", __zipos_unlock)
|
||||
#else
|
||||
#define __zipos_lock() (__threaded ? __zipos_lock() : 0)
|
||||
#define __zipos_unlock() (__threaded ? __zipos_unlock() : 0)
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue