mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 08:18:30 +00:00
Improve redbean plus code size optimizations
This change turns symbol table compression back on using Puff, which noticeably reduces the size of programs like redbean and Python. The redbean web server receives some minor API additions for controlling things like SSL in addition to filling gaps in the documentation.
This commit is contained in:
parent
425ff5dff0
commit
13ee75150c
58 changed files with 2077 additions and 589 deletions
|
@ -2,8 +2,20 @@
|
|||
#define COSMOPOLITAN_LIBC_BITS_LIKELY_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
|
||||
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
|
||||
#define LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#if __GNUC__ + 0 >= 9 && !defined(__chibicc__)
|
||||
#define VERY_LIKELY(x) __builtin_expect_with_probability(!!(x), 1, 0.999)
|
||||
#else
|
||||
#define VERY_LIKELY(x) LIKELY(x)
|
||||
#endif
|
||||
|
||||
#if __GNUC__ + 0 >= 9 && !defined(__chibicc__)
|
||||
#define VERY_UNLIKELY(x) __builtin_expect_with_probability(!!(x), 0, 0.999)
|
||||
#else
|
||||
#define VERY_UNLIKELY(x) UNLIKELY(x)
|
||||
#endif
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_BITS_LIKELY_H_ */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
|
@ -50,7 +51,7 @@ int execve(const char *prog, char *const argv[], char *const envp[]) {
|
|||
rc = efault();
|
||||
} else {
|
||||
#ifdef SYSDEBUG
|
||||
if (__strace > 0) {
|
||||
if (UNLIKELY(__strace > 0)) {
|
||||
kprintf(STRACE_PROLOGUE "execve(%#s, {", prog);
|
||||
for (i = 0; argv[i]; ++i) {
|
||||
if (i) kprintf(", ");
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -82,7 +83,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
|
|||
}
|
||||
|
||||
#if defined(SYSDEBUG) && _POLLTRACE
|
||||
if (__strace > 0) {
|
||||
if (UNLIKELY(__strace > 0)) {
|
||||
kprintf(STRACE_PROLOGUE "poll(");
|
||||
if ((!IsAsan() && kisdangerous(fds)) ||
|
||||
(IsAsan() && !__asan_is_valid(fds, nfds * sizeof(struct pollfd)))) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
|
@ -115,7 +116,7 @@ ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
|||
ssize_t rc;
|
||||
rc = Preadv(fd, iov, iovlen, off);
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (UNLIKELY(__strace > 0)) {
|
||||
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
|
||||
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf("], %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
|
@ -119,7 +120,7 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
|
|||
ssize_t rc;
|
||||
rc = Pwritev(fd, iov, iovlen, off);
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (UNLIKELY(__strace > 0)) {
|
||||
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
|
||||
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf(", %d, %'ld) → %'ld% m\n", iovlen, off, rc);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
|
@ -68,7 +69,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
|||
rc = einval();
|
||||
}
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (UNLIKELY(__strace > 0)) {
|
||||
if (rc == -1 && errno == EFAULT) {
|
||||
STRACE("readv(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
|
@ -19,7 +20,7 @@ COSMOPOLITAN_C_START_
|
|||
#ifdef SYSDEBUG
|
||||
#define STRACE(FMT, ...) \
|
||||
do { \
|
||||
if (__strace > 0) { \
|
||||
if (UNLIKELY(__strace > 0)) { \
|
||||
__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
|
@ -75,7 +76,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
|||
}
|
||||
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (UNLIKELY(__strace > 0)) {
|
||||
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
|
||||
DescribeIov(iov, iovlen, rc != -1 ? rc : 0);
|
||||
kprintf(", %d) → %'ld% m\n", iovlen, rc);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern unsigned long long __kbirth;
|
||||
|
||||
void kprintf(const char *, ...);
|
||||
size_t ksnprintf(char *, size_t, const char *, ...);
|
||||
size_t kusnprintf(char *, size_t, const char *, ...);
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
STATIC_YOINK("_check_sigchld");
|
||||
|
||||
extern int64_t __wincrashearly;
|
||||
extern unsigned long long __kbirth;
|
||||
extern unsigned char __data_start[]; /* αpε */
|
||||
extern unsigned char __data_end[]; /* αpε */
|
||||
extern unsigned char __bss_start[]; /* αpε */
|
||||
|
|
|
@ -22,13 +22,14 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/undeflate.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/zip.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
#include "third_party/zlib/puff.h"
|
||||
|
||||
static int g_lock;
|
||||
hidden struct SymbolTable *__symtab; // for kprintf
|
||||
|
@ -56,9 +57,8 @@ static ssize_t FindSymtabInZip(struct Zipos *zipos) {
|
|||
* @note This code can't depend on dlmalloc()
|
||||
*/
|
||||
static struct SymbolTable *GetSymbolTableFromZip(struct Zipos *zipos) {
|
||||
ssize_t rc, cf, lf;
|
||||
size_t size, size2;
|
||||
struct DeflateState ds;
|
||||
ssize_t rc, cf, lf;
|
||||
struct SymbolTable *res = 0;
|
||||
if ((cf = FindSymtabInZip(zipos)) != -1) {
|
||||
lf = GetZipCfileOffset(zipos->map + cf);
|
||||
|
@ -69,17 +69,14 @@ static struct SymbolTable *GetSymbolTableFromZip(struct Zipos *zipos) {
|
|||
case kZipCompressionNone:
|
||||
memcpy(res, (void *)ZIP_LFILE_CONTENT(zipos->map + lf), size);
|
||||
break;
|
||||
#if 0
|
||||
// TODO(jart): fix me
|
||||
case kZipCompressionDeflate:
|
||||
rc = undeflate(res, size, (void *)ZIP_LFILE_CONTENT(zipos->map + lf),
|
||||
GetZipLfileCompressedSize(zipos->map + lf), &ds);
|
||||
if (rc == -1) {
|
||||
if (__inflate((void *)res, size,
|
||||
(void *)ZIP_LFILE_CONTENT(zipos->map + lf),
|
||||
GetZipLfileCompressedSize(zipos->map + lf))) {
|
||||
munmap(res, size2);
|
||||
res = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
munmap(res, size2);
|
||||
res = 0;
|
||||
|
|
63
libc/runtime/inflate.c
Normal file
63
libc/runtime/inflate.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*-*- 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/bits/weaken.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "third_party/zlib/puff.h"
|
||||
#include "third_party/zlib/zlib.h"
|
||||
|
||||
/**
|
||||
* Decompresses raw deflate data.
|
||||
*
|
||||
* This uses puff by default since it has a 2kb footprint. If zlib
|
||||
* proper is linked, then we favor that instead, since it's faster.
|
||||
*
|
||||
* @param outsize needs to be known ahead of time by some other means
|
||||
* @return 0 on success or nonzero on failure
|
||||
*/
|
||||
int __inflate(void *out, size_t outsize, const void *in, size_t insize) {
|
||||
int rc;
|
||||
z_stream zs;
|
||||
if (weaken(inflateInit2) && weaken(inflate) && weaken(inflateEnd)) {
|
||||
zs.next_in = in;
|
||||
zs.avail_in = insize;
|
||||
zs.total_in = insize;
|
||||
zs.next_out = out;
|
||||
zs.avail_out = outsize;
|
||||
zs.total_out = outsize;
|
||||
zs.zalloc = Z_NULL;
|
||||
zs.zfree = Z_NULL;
|
||||
if ((rc = weaken(inflateInit2)(&zs, -MAX_WBITS)) == Z_OK &&
|
||||
(rc = weaken(inflate)(&zs, Z_FINISH)) == Z_STREAM_END &&
|
||||
(rc = weaken(inflateEnd)(&zs)) == Z_OK) {
|
||||
rc = 0;
|
||||
} else if (rc == Z_OK) {
|
||||
rc = Z_STREAM_END; // coerce to nonzero
|
||||
} else {
|
||||
rc = rc;
|
||||
}
|
||||
} else {
|
||||
rc = puff(out, &outsize, in, &insize);
|
||||
}
|
||||
STRACE("inflate([%#.*hhs%s], %'zu, %#.*hhs%s, %'zu) → %d", MIN(40, outsize),
|
||||
out, outsize > 40 ? "..." : "", outsize, MIN(40, insize), in,
|
||||
insize > 40 ? "..." : "", insize, rc);
|
||||
return rc;
|
||||
}
|
|
@ -38,6 +38,7 @@ Elf64_Ehdr *MapElfRead(const char *, struct MappedFile *) hidden;
|
|||
int GetDosEnviron(const char16_t *, char *, size_t, char **, size_t);
|
||||
bool __intercept_flag(int *, char *[], const char *);
|
||||
int sys_mprotect_nt(void *, size_t, int) hidden;
|
||||
int __inflate(void *, size_t, const void *, size_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -176,14 +176,14 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
|
|||
int fd, int64_t off, int f, int x, int n) {
|
||||
struct DirectMap dm;
|
||||
dm = sys_mmap(addr, size, prot, f, fd, off);
|
||||
if (UNLIKELY(dm.addr == MAP_FAILED)) {
|
||||
if (VERY_UNLIKELY(dm.addr == MAP_FAILED)) {
|
||||
if (IsWindows() && (flags & MAP_FIXED)) {
|
||||
OnUnrecoverableMmapError(
|
||||
"can't recover from MAP_FIXED errors on Windows");
|
||||
}
|
||||
return MAP_FAILED;
|
||||
}
|
||||
if (UNLIKELY(dm.addr != addr)) {
|
||||
if (VERY_UNLIKELY(dm.addr != addr)) {
|
||||
OnUnrecoverableMmapError("KERNEL DIDN'T RESPECT MAP_FIXED");
|
||||
}
|
||||
return FinishMemory(addr, size, prot, flags, fd, off, f, x, n, dm);
|
||||
|
@ -248,42 +248,42 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
bool needguard, clashes;
|
||||
size_t virtualused, virtualneed;
|
||||
|
||||
if (UNLIKELY(!size)) {
|
||||
if (VERY_UNLIKELY(!size)) {
|
||||
STRACE("size=0");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(!IsLegalPointer(p))) {
|
||||
if (VERY_UNLIKELY(!IsLegalPointer(p))) {
|
||||
STRACE("p isn't 48-bit");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(!ALIGNED(p))) {
|
||||
if (VERY_UNLIKELY(!ALIGNED(p))) {
|
||||
STRACE("p isn't 64kb aligned");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(fd < -1)) {
|
||||
if (VERY_UNLIKELY(fd < -1)) {
|
||||
STRACE("mmap(%.12p, %'zu, fd=%d) EBADF", p, size, fd);
|
||||
return VIP(ebadf());
|
||||
}
|
||||
|
||||
if (UNLIKELY(!((fd != -1) ^ !!(flags & MAP_ANONYMOUS)))) {
|
||||
if (VERY_UNLIKELY(!((fd != -1) ^ !!(flags & MAP_ANONYMOUS)))) {
|
||||
STRACE("fd anonymous mismatch");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(!(!!(flags & MAP_PRIVATE) ^ !!(flags & MAP_SHARED)))) {
|
||||
if (VERY_UNLIKELY(!(!!(flags & MAP_PRIVATE) ^ !!(flags & MAP_SHARED)))) {
|
||||
STRACE("MAP_SHARED ^ MAP_PRIVATE");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(off < 0)) {
|
||||
if (VERY_UNLIKELY(off < 0)) {
|
||||
STRACE("neg off");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(!ALIGNED(off))) {
|
||||
if (VERY_UNLIKELY(!ALIGNED(off))) {
|
||||
STRACE("p isn't 64kb aligned");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
@ -298,12 +298,12 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(!IsLegalSize(size))) {
|
||||
if (VERY_UNLIKELY(!IsLegalSize(size))) {
|
||||
STRACE("size isn't 48-bit");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(INT64_MAX - size < off)) {
|
||||
if (VERY_UNLIKELY(INT64_MAX - size < off)) {
|
||||
STRACE("too large");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
|
|
@ -127,23 +127,23 @@ static noasan int Munmap(char *p, size_t n) {
|
|||
intptr_t a, b, x, y;
|
||||
assert(!__vforked);
|
||||
if (UNLIKELY(!n)) {
|
||||
STRACE("munmap(%.12p, %'zu) EINVAL (n=0)", p, n);
|
||||
STRACE("n=0");
|
||||
return einval();
|
||||
}
|
||||
if (UNLIKELY(!IsLegalSize(n))) {
|
||||
STRACE("munmap(%.12p, %'zu) EINVAL (n isn't 48-bit)", p, n);
|
||||
STRACE("n isn't 48-bit");
|
||||
return einval();
|
||||
}
|
||||
if (UNLIKELY(!IsLegalPointer(p))) {
|
||||
STRACE("munmap(%.12p, %'zu) EINVAL (p isn't 48-bit)", p, n);
|
||||
STRACE("p isn't 48-bit");
|
||||
return einval();
|
||||
}
|
||||
if (UNLIKELY(!IsLegalPointer(p + (n - 1)))) {
|
||||
STRACE("munmap(%.12p, %'zu) EINVAL (p+(n-1) isn't 48-bit)", p, n);
|
||||
STRACE("p+(n-1) isn't 48-bit");
|
||||
return einval();
|
||||
}
|
||||
if (UNLIKELY(!ALIGNED(p))) {
|
||||
STRACE("munmap(%.12p, %'zu) EINVAL (p isn't 64kb aligned)", p, n);
|
||||
STRACE("p isn't 64kb aligned");
|
||||
return einval();
|
||||
}
|
||||
MunmapImpl(p, n);
|
||||
|
|
|
@ -44,6 +44,7 @@ LIBC_RUNTIME_A_DIRECTDEPS = \
|
|||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_XED
|
||||
|
||||
LIBC_RUNTIME_A_DEPS := \
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/undeflate.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
@ -43,47 +43,8 @@
|
|||
#include "libc/zipos/zipos.internal.h"
|
||||
#include "third_party/zlib/zlib.h"
|
||||
|
||||
static int __zipos_inflate_fast(struct ZiposHandle *h, uint8_t *data,
|
||||
size_t size) {
|
||||
int rc;
|
||||
z_stream zs;
|
||||
zs.opaque = &h;
|
||||
zs.next_in = data;
|
||||
zs.avail_in = size;
|
||||
zs.total_in = size;
|
||||
zs.next_out = h->freeme;
|
||||
zs.avail_out = h->size;
|
||||
zs.total_out = h->size;
|
||||
zs.zfree = Z_NULL;
|
||||
zs.zalloc = Z_NULL;
|
||||
if (inflateInit2(&zs, -MAX_WBITS) == Z_OK) {
|
||||
switch (inflate(&zs, Z_NO_FLUSH)) {
|
||||
case Z_STREAM_END:
|
||||
rc = 0;
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
rc = enomem();
|
||||
break;
|
||||
case Z_DATA_ERROR:
|
||||
rc = eio();
|
||||
break;
|
||||
case Z_NEED_DICT:
|
||||
rc = enotsup(); /* TODO(jart): Z_NEED_DICT */
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
inflateEnd(&zs);
|
||||
} else {
|
||||
rc = enomem();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __zipos_inflate_tiny(struct ZiposHandle *h, uint8_t *data,
|
||||
size_t size) {
|
||||
struct DeflateState ds;
|
||||
return undeflate(h->freeme, h->size, data, size, &ds) != -1 ? 0 : eio();
|
||||
static int __zipos_inflate(struct ZiposHandle *h, uint8_t *data, size_t size) {
|
||||
return !__inflate(h->freeme, h->size, data, size) ? 0 : eio();
|
||||
}
|
||||
|
||||
static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags,
|
||||
|
@ -108,12 +69,7 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags,
|
|||
if ((h->freeme = malloc(h->size))) {
|
||||
data = ZIP_LFILE_CONTENT(zipos->map + lf);
|
||||
size = GetZipLfileCompressedSize(zipos->map + lf);
|
||||
if (IsTiny()) {
|
||||
rc = __zipos_inflate_tiny(h, data, size);
|
||||
} else {
|
||||
rc = __zipos_inflate_fast(h, data, size);
|
||||
}
|
||||
if (rc != -1) {
|
||||
if ((rc = __zipos_inflate(h, data, size)) != -1) {
|
||||
h->mem = h->freeme;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue