mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 07:18:30 +00:00
Make more improvements
This change includes many bug fixes, for the NT polyfills, strings, memory, boot, and math libraries which were discovered by adding more tools for recreational programming, such as PC emulation. Lemon has also been vendored because it works so well at parsing languages.
This commit is contained in:
parent
416fd86676
commit
23d333c090
201 changed files with 14558 additions and 3082 deletions
|
@ -45,9 +45,9 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
|
|||
#define ROL(w, k) ((w) << (k) | CheckUnsigned(w) >> (sizeof(w) * 8 - (k)))
|
||||
#define SAR(w, k) (((w) & ~(~0u >> (k))) | ((w) >> ((k) & (sizeof(w) * 8 - 1))))
|
||||
|
||||
#define bitreverse8(X) (kReverseBits[(X)&0xff])
|
||||
#define bitreverse16(X) \
|
||||
((uint16_t)kReverseBits[(X)&0xff] << 010 | \
|
||||
#define bitreverse8(X) (kReverseBits[(uint8_t)(X)])
|
||||
#define bitreverse16(X) \
|
||||
((uint16_t)kReverseBits[(uint8_t)(X)] << 010 | \
|
||||
kReverseBits[((uint16_t)(X) >> 010) & 0xff])
|
||||
|
||||
#define READ16LE(S) \
|
||||
|
|
|
@ -19,4 +19,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
long(roundup)(long w, long k) { return ROUNDUP(w, k); }
|
||||
long(roundup)(long w, long k) {
|
||||
return ROUNDUP(w, k);
|
||||
}
|
||||
|
|
|
@ -84,7 +84,6 @@ char *get_current_dir_name(void) nodiscard;
|
|||
char *getcwd(char *, size_t);
|
||||
char *realpath(const char *, char *);
|
||||
char *replaceuser(const char *) nodiscard;
|
||||
char *slurp(const char *, size_t *) nodiscard;
|
||||
char *ttyname(int);
|
||||
char *commandv(const char *, char[hasatleast PATH_MAX]);
|
||||
int access(const char *, int) nothrow;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
textwindows int close$nt(int fd) {
|
||||
bool32 ok;
|
||||
if (isfdindex(fd)) {
|
||||
if (isfdopen(fd)) {
|
||||
if (g_fds.p[fd].kind == kFdFile) {
|
||||
/*
|
||||
* Like Linux, closing a file on Windows doesn't guarantee it's
|
||||
|
|
|
@ -34,13 +34,13 @@ textwindows int dup$nt(int oldfd, int newfd, int flags) {
|
|||
if (newfd == -1) {
|
||||
if ((newfd = createfd()) == -1) return -1;
|
||||
} else if (isfdindex(newfd)) {
|
||||
close(newfd);
|
||||
} else if (isfdlegal(newfd)) {
|
||||
if (g_fds.p[newfd].kind != kFdEmpty) {
|
||||
close(newfd);
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
if (growfds() == -1) return -1;
|
||||
} while (newfd >= g_fds.n);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
|
||||
GetCurrentProcess(), &g_fds.p[newfd].handle, 0,
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int fcntl$nt(int fd, int cmd, unsigned arg) {
|
||||
if (!isfdindex(fd)) return ebadf();
|
||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
||||
switch (cmd) {
|
||||
case F_GETFD:
|
||||
return GetHandleInformation(g_fds.p[fd].handle, &arg) ? (arg ^ FD_CLOEXEC)
|
||||
|
|
|
@ -33,7 +33,10 @@ uint32_t fprot2nt(int prot, int flags) {
|
|||
return (HAS(prot, PROT_READ) ? kNtFileMapRead : 0) |
|
||||
(HAS(prot, PROT_WRITE) ? kNtFileMapWrite : 0) |
|
||||
(HAS(prot, PROT_EXEC) ? kNtFileMapExecute : 0) |
|
||||
(HAS(flags, MAP_PRIVATE) ? kNtFileMapCopy : 0) |
|
||||
(HAS(flags, kNtSecLargePages) ? kNtFileMapLargePages : 0) |
|
||||
(HAS(flags, kNtSecReserve) ? kNtFileMapReserve : 0);
|
||||
(HAS(flags, kNtSecReserve) ? kNtFileMapReserve : 0) |
|
||||
((HAS(flags, MAP_PRIVATE) && HAS(prot, PROT_READ) &&
|
||||
HAS(prot, PROT_WRITE))
|
||||
? kNtFileMapCopy
|
||||
: 0);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
* @see libc/sysv/consts.sh
|
||||
*/
|
||||
int getrlimit(int resource, struct rlimit *rlim) {
|
||||
/* TODO(jart): Windows */
|
||||
if (resource == -1) return einval();
|
||||
return getrlimit$sysv(resource, rlim);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ int growfds(void) {
|
|||
struct Fd *p;
|
||||
if (weaken(realloc)) {
|
||||
if ((p = weaken(realloc)(g_fds.p != g_fds.__init_p ? g_fds.p : NULL,
|
||||
(n = ((i = g_fds.n) * 2)) * sizeof(*p)))) {
|
||||
(n = (i = g_fds.n) << 1) * sizeof(*p)))) {
|
||||
do {
|
||||
p[i++].kind = kFdEmpty;
|
||||
} while (i < n);
|
||||
|
|
|
@ -46,8 +46,7 @@ LIBC_CALLS_HEFTY_A_DIRECTDEPS = \
|
|||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_TIME
|
||||
LIBC_SYSV_CALLS
|
||||
|
||||
LIBC_CALLS_HEFTY_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_CALLS_HEFTY_A_DIRECTDEPS),$($(x))))
|
||||
|
|
|
@ -1,22 +1,3 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_INTERNAL_H_
|
||||
#ifndef __STRICT_ANSI__
|
||||
|
@ -54,15 +35,8 @@ struct IoctlPtmGet {
|
|||
char workername[16];
|
||||
};
|
||||
|
||||
/**
|
||||
* List of open handles on Windows NT.
|
||||
*
|
||||
* The array is indexed by the sysv-style file descriptor numbers that
|
||||
* we assign. It's needed to make file descriptors only require 32bits
|
||||
* and helps us abstract peculiarities like close() vs. closesocket().
|
||||
*/
|
||||
struct Fds {
|
||||
size_t f; // length
|
||||
size_t f; // arbitrary free slot start search index
|
||||
size_t n; // capacity
|
||||
struct Fd {
|
||||
int64_t handle;
|
||||
|
@ -82,34 +56,27 @@ struct Fds {
|
|||
|
||||
extern const struct Fd kEmptyFd;
|
||||
|
||||
hidden extern int g_sighandrvas[NSIG];
|
||||
hidden extern struct Fds g_fds;
|
||||
hidden extern struct NtSystemInfo g_ntsysteminfo;
|
||||
hidden extern struct NtStartupInfo g_ntstartupinfo;
|
||||
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
|
||||
|
||||
forceinline bool isfdlegal(int fd) {
|
||||
if (!IsTrustworthy()) {
|
||||
return (0 <= fd && fd <= INT_MAX);
|
||||
} else {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
forceinline bool isfdindex(int fd) {
|
||||
if (!IsTrustworthy()) {
|
||||
return (0 <= fd && fd < g_fds.n);
|
||||
} else {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
extern int g_sighandrvas[NSIG] hidden;
|
||||
extern struct Fds g_fds hidden;
|
||||
extern struct NtSystemInfo g_ntsysteminfo hidden;
|
||||
extern struct NtStartupInfo g_ntstartupinfo hidden;
|
||||
extern const struct NtSecurityAttributes kNtIsInheritable hidden;
|
||||
|
||||
ssize_t createfd(void) hidden;
|
||||
int growfds(void) hidden;
|
||||
void removefd(int) hidden;
|
||||
enum FdKind fdkind(int) hidden nosideeffect;
|
||||
bool isfdopen(int) hidden nosideeffect;
|
||||
bool isfdkind(int, enum FdKind) hidden nosideeffect;
|
||||
|
||||
forceinline bool isfdindex(int fd) {
|
||||
if (!IsTrustworthy()) {
|
||||
return (0 <= fd && fd < g_fds.n);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
forceinline size_t clampio(size_t size) {
|
||||
if (!IsTrustworthy()) {
|
||||
return MIN(size, 0x7ffff000);
|
||||
|
|
|
@ -29,8 +29,8 @@ int ioctl$default(int fd, uint64_t request, void *memory) {
|
|||
int64_t handle;
|
||||
if (!IsWindows()) {
|
||||
return ioctl$sysv(fd, request, memory);
|
||||
} else if (isfdindex(fd)) {
|
||||
if (isfdkind(fd, kFdSocket)) {
|
||||
} else if (isfdopen(fd)) {
|
||||
if (g_fds.p[fd].kind == kFdSocket) {
|
||||
handle = g_fds.p[fd].handle;
|
||||
if ((rc = weaken(__ioctlsocket$nt)(handle, request, memory)) != -1) {
|
||||
return rc;
|
||||
|
|
|
@ -20,9 +20,5 @@
|
|||
#include "libc/calls/internal.h"
|
||||
|
||||
bool isfdkind(int fd, enum FdKind kind) {
|
||||
if (isfdindex(fd)) {
|
||||
return g_fds.p[fd].kind == kind;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return isfdindex(fd) && g_fds.p[fd].kind == kind;
|
||||
}
|
||||
|
|
24
libc/calls/isfdopen.c
Normal file
24
libc/calls/isfdopen.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
|
||||
bool isfdopen(int fd) {
|
||||
return isfdindex(fd) && g_fds.p[fd].kind != kFdEmpty;
|
||||
}
|
|
@ -39,5 +39,4 @@ kTmpPath:
|
|||
ezlea GetTempPathA$flunk,ax
|
||||
call __getntsyspath
|
||||
.init.end 300,_init_kTmpPath
|
||||
|
||||
.source __FILE__
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/ntmagicpaths.h"
|
||||
#include "libc/nexgen32e/tinystrcmp.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/enum/fsctl.h"
|
||||
#include "libc/nt/errors.h"
|
||||
|
@ -38,7 +39,10 @@ static textwindows int64_t open$nt$impl(const char *file, uint32_t flags,
|
|||
char16_t file16[PATH_MAX];
|
||||
if (mkntpath2(file, flags, file16) == -1) return -1;
|
||||
if ((handle = CreateFile(
|
||||
file16, (flags & 0xf000000f),
|
||||
file16,
|
||||
(flags & 0xf000000f) | (/* this is needed if we mmap(rwx+cow)
|
||||
nt is choosy about open() access */
|
||||
kNtGenericExecute | kNtFileGenericWrite),
|
||||
(flags & O_EXCL)
|
||||
? kNtFileShareExclusive
|
||||
: kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
|
||||
|
|
|
@ -37,7 +37,7 @@ privileged uint32_t prot2nt(int prot, int flags) {
|
|||
: HAS(prot, PROT_READ | PROT_WRITE)
|
||||
? (HAS(flags, MAP_SHARED) || HAS(flags, MAP_ANONYMOUS))
|
||||
? kNtPageReadwrite
|
||||
: kNtPageWritecopy
|
||||
: kNtPageReadwrite /* kNtPageWritecopy */
|
||||
: HAS(prot, PROT_READ | PROT_EXEC)
|
||||
? kNtPageExecuteRead
|
||||
: HAS(prot, PROT_EXEC)
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
void removefd(int fd) {
|
||||
if (isfdindex(fd)) {
|
||||
if (isfdopen(fd)) {
|
||||
g_fds.p[fd].kind = kFdEmpty;
|
||||
g_fds.f = min(g_fds.f, fd);
|
||||
g_fds.f = MIN(g_fds.f, fd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,9 +50,6 @@ textwindows int utimensat$nt(int dirfd, const char *path,
|
|||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else if (isfdindex(dirfd)) {
|
||||
fh = g_fds.p[dirfd].handle;
|
||||
closeme = false;
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
|
@ -61,6 +61,11 @@ o/$(MODE)/libc/conv/filetimetotimeval.o: \
|
|||
OVERRIDE_CFLAGS += \
|
||||
-O3
|
||||
|
||||
o/$(MODE)/libc/conv/itoa64radix10.greg.o \
|
||||
o/$(MODE)/libc/conv/itoa128radix10.greg.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fwrapv
|
||||
|
||||
$(LIBC_CONV_A_OBJS): \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(NO_MAGIC)
|
||||
|
|
|
@ -16,17 +16,10 @@ COSMOPOLITAN_C_START_
|
|||
- uint128toarray_radix10(0x31337, a) l: 93 (27ns) m: 141 (41ns)
|
||||
- int128toarray_radix10(0x31337, a) l: 96 (28ns) m: 173 (51ns)
|
||||
|
||||
SLOWEST + GENERAL
|
||||
|
||||
- int64toarray(0x31337, a, 10) l: 218 (64ns) m: 262 (77ns)
|
||||
- uint64toarray(0x31337, a, 10) l: 565 (166ns) m: 260 (76ns)
|
||||
|
||||
*/
|
||||
|
||||
size_t int64toarray_radix10(int64_t, char *);
|
||||
size_t uint64toarray_radix10(uint64_t, char *);
|
||||
size_t int64toarray(int64_t, char *, int);
|
||||
size_t uint64toarray(uint64_t, char *, int);
|
||||
size_t int64toarray_radix10(int64_t, char[hasatleast 21]);
|
||||
size_t uint64toarray_radix10(uint64_t, char[hasatleast 21]);
|
||||
size_t uint64toarray_radix16(uint64_t, char[hasatleast 17]);
|
||||
size_t uint64toarray_fixed16(uint64_t, char[hasatleast 17], uint8_t);
|
||||
|
||||
|
|
|
@ -48,15 +48,7 @@ noinline size_t uint128toarray_radix10(uint128_t i, char *a) {
|
|||
* @return bytes written w/o nul
|
||||
*/
|
||||
size_t int128toarray_radix10(int128_t i, char *a) {
|
||||
if (i < 0) {
|
||||
if (i != INT128_MIN) {
|
||||
*a++ = '-';
|
||||
return 1 + uint128toarray_radix10(-i, a);
|
||||
} else {
|
||||
memcpy(a, "-170141183460469231731687303715884105728", 41);
|
||||
return 40;
|
||||
}
|
||||
} else {
|
||||
return uint128toarray_radix10(i, a);
|
||||
}
|
||||
if (i >= 0) return uint128toarray_radix10(i, a);
|
||||
*a++ = '-';
|
||||
return 1 + uint128toarray_radix10(-i, a);
|
||||
}
|
||||
|
|
|
@ -45,15 +45,7 @@ noinline size_t uint64toarray_radix10(uint64_t i, char *a) {
|
|||
* @return bytes written w/o nul
|
||||
*/
|
||||
size_t int64toarray_radix10(int64_t i, char *a) {
|
||||
if (i < 0) {
|
||||
if (i != INT64_MIN) {
|
||||
*a++ = '-';
|
||||
return 1 + uint64toarray_radix10(-i, a);
|
||||
} else {
|
||||
memcpy(a, "-9223372036854775808", 21);
|
||||
return 20;
|
||||
}
|
||||
} else {
|
||||
return uint64toarray_radix10(i, a);
|
||||
}
|
||||
if (i >= 0) return uint64toarray_radix10(i, a);
|
||||
*a++ = '-';
|
||||
return 1 + uint64toarray_radix10(-i, a);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
#endif
|
||||
|
||||
#define BIGPAGESIZE 0x200000
|
||||
#define STACKSIZE 0x20000
|
||||
#define STACKSIZE 0x80000 /* todo: zlib's fault? */
|
||||
#define FRAMESIZE 0x10000 /* 8086 */
|
||||
#define PAGESIZE 0x1000 /* i386+ */
|
||||
#define BUFSIZ 0x1000 /* best stdio default */
|
||||
|
|
|
@ -31,6 +31,16 @@
|
|||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Prints stack frames with symbols.
|
||||
*
|
||||
* PrintBacktraceUsingSymbols(stdout, NULL, getsymboltable());
|
||||
*
|
||||
* @param f is output stream
|
||||
* @param bp is rbp which can be NULL to detect automatically
|
||||
* @param st is open symbol table for current executable
|
||||
* @return -1 w/ errno if error happened
|
||||
*/
|
||||
int PrintBacktraceUsingSymbols(FILE *f, const struct StackFrame *bp,
|
||||
struct SymbolTable *st) {
|
||||
size_t gi;
|
||||
|
@ -41,6 +51,7 @@ int PrintBacktraceUsingSymbols(FILE *f, const struct StackFrame *bp,
|
|||
const struct Symbol *symbol;
|
||||
const struct StackFrame *frame;
|
||||
if (!st) return -1;
|
||||
if (!bp) bp = __builtin_frame_address(0);
|
||||
garbage = weaken(g_garbage);
|
||||
gi = garbage ? garbage->i : 0;
|
||||
for (frame = bp; frame; frame = frame->next) {
|
||||
|
|
|
@ -33,27 +33,6 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
static struct CanColor {
|
||||
bool once;
|
||||
bool result;
|
||||
struct OldNtConsole {
|
||||
unsigned codepage;
|
||||
unsigned mode;
|
||||
int64_t handle;
|
||||
} oldin, oldout;
|
||||
} g_cancolor;
|
||||
|
||||
static textwindows void restorecmdexe(void) {
|
||||
if (g_cancolor.oldin.handle) {
|
||||
SetConsoleCP(g_cancolor.oldin.codepage);
|
||||
SetConsoleMode(g_cancolor.oldin.handle, g_cancolor.oldin.mode);
|
||||
}
|
||||
if (g_cancolor.oldout.handle) {
|
||||
SetConsoleOutputCP(g_cancolor.oldout.codepage);
|
||||
SetConsoleMode(g_cancolor.oldout.handle, g_cancolor.oldout.mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if ANSI terminal colors are appropriate.
|
||||
*
|
||||
|
@ -75,47 +54,20 @@ static textwindows void restorecmdexe(void) {
|
|||
* It's that easy fam.
|
||||
*/
|
||||
bool cancolor(void) {
|
||||
int64_t handle;
|
||||
static bool once;
|
||||
static bool result;
|
||||
const char *term;
|
||||
if (g_cancolor.once) return g_cancolor.result;
|
||||
g_cancolor.once = true;
|
||||
if (IsWindows()) {
|
||||
if ((int)weakaddr("v_ntsubsystem") == kNtImageSubsystemWindowsCui &&
|
||||
NtGetVersion() >= kNtVersionWindows10) {
|
||||
atexit(restorecmdexe);
|
||||
if (GetFileType((handle = g_fds.p[STDIN_FILENO].handle)) ==
|
||||
kNtFileTypeChar) {
|
||||
g_cancolor.result = true;
|
||||
g_cancolor.oldin.handle = handle;
|
||||
g_cancolor.oldin.codepage = GetConsoleCP();
|
||||
SetConsoleCP(kNtCpUtf8);
|
||||
GetConsoleMode(handle, &g_cancolor.oldin.mode);
|
||||
SetConsoleMode(handle, g_cancolor.oldin.mode | kNtEnableProcessedInput |
|
||||
kNtEnableVirtualTerminalInput);
|
||||
}
|
||||
if (GetFileType((handle = g_fds.p[STDOUT_FILENO].handle)) ==
|
||||
kNtFileTypeChar ||
|
||||
GetFileType((handle = g_fds.p[STDERR_FILENO].handle)) ==
|
||||
kNtFileTypeChar) {
|
||||
g_cancolor.result = true;
|
||||
g_cancolor.oldout.handle = handle;
|
||||
g_cancolor.oldout.codepage = GetConsoleOutputCP();
|
||||
SetConsoleOutputCP(kNtCpUtf8);
|
||||
GetConsoleMode(handle, &g_cancolor.oldout.mode);
|
||||
SetConsoleMode(handle, g_cancolor.oldout.mode |
|
||||
kNtEnableProcessedOutput |
|
||||
kNtEnableVirtualTerminalProcessing);
|
||||
if (!once) {
|
||||
if (!result) {
|
||||
if ((term = getenv("TERM"))) {
|
||||
/* anything but emacs basically */
|
||||
result = strcmp(term, "dumb") != 0;
|
||||
} else {
|
||||
/* TODO(jart): Why does Mac bash login shell exec nuke TERM? */
|
||||
result = IsXnu();
|
||||
}
|
||||
}
|
||||
once = true;
|
||||
}
|
||||
if (!g_cancolor.result) {
|
||||
if ((term = getenv("TERM"))) {
|
||||
/* anything but emacs basically */
|
||||
g_cancolor.result = strcmp(term, "dumb") != 0;
|
||||
} else {
|
||||
/* TODO(jart): Why does Mac bash login shell exec nuke TERM? */
|
||||
g_cancolor.result = IsXnu();
|
||||
}
|
||||
}
|
||||
return g_cancolor.result;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ cescapec:
|
|||
ret
|
||||
.LHT: mov $'t,%ah
|
||||
ret
|
||||
.LLF: or $'n<<010|'\\<<020|'\n<<030,%eax
|
||||
.LLF: mov $'n,%ah
|
||||
ret
|
||||
.LVT: mov $'v,%ah
|
||||
ret
|
||||
|
|
|
@ -100,10 +100,15 @@ MemCpy: .leafprologue
|
|||
mov %ecx,(%rdi)
|
||||
mov %ebx,-4(%rdi,%rdx)
|
||||
jmp 1b
|
||||
.L3: mov 2(%rsi),%cl
|
||||
mov %cl,2(%rdi)
|
||||
.L2: mov 1(%rsi),%cl
|
||||
mov %cl,1(%rdi)
|
||||
.L3: push %rbx
|
||||
mov (%rsi),%cx
|
||||
mov -2(%rsi,%rdx),%bx
|
||||
mov %cx,(%rdi)
|
||||
mov %bx,-2(%rdi,%rdx)
|
||||
jmp 1b
|
||||
.L2: mov (%rsi),%cx
|
||||
mov %cx,(%rdi)
|
||||
jmp .L0
|
||||
.L1: mov (%rsi),%cl
|
||||
mov %cl,(%rdi)
|
||||
jmp .L0
|
||||
|
|
|
@ -48,20 +48,20 @@
|
|||
* @mode long,legacy,real
|
||||
*/
|
||||
|
||||
#define VIDYA_ROWS 25
|
||||
#define VIDYA_COLUMNS 80
|
||||
#define VIDYA_SIZE (VIDYA_ROWS * VIDYA_COLUMNS * 2)
|
||||
#define VIDYA_MODE_MDA 7
|
||||
#define VIDYA_MODE_CGA 3
|
||||
#define VIDYA_ADDR_MDA 0xb0000
|
||||
#define VIDYA_ADDR_CGA 0xb8000
|
||||
#define VIDYA_ATTR_NORMAL 0x07 /* cozy default for both mda and cga */
|
||||
#define VIDYA_REWIND ~0x7fff /* derived from mode addr min. lzcnt */
|
||||
#define VIDYA_SERVICE 0x10
|
||||
#define VIDYA_SET_MODE 0
|
||||
#define VIDYA_SET_CURSOR 0x0100
|
||||
#define VIDYA_SET_CURSOR_NONE 0x2000
|
||||
#define VIDYA_SET_BLINKING 0x1003
|
||||
#define VIDYA_ROWS 25
|
||||
#define VIDYA_COLUMNS 80
|
||||
#define VIDYA_SIZE (VIDYA_ROWS * VIDYA_COLUMNS * 2)
|
||||
#define VIDYA_MODE_MDA 7
|
||||
#define VIDYA_MODE_CGA 3
|
||||
#define VIDYA_ADDR_MDA 0xb0000
|
||||
#define VIDYA_ADDR_CGA 0xb8000
|
||||
#define VIDYA_ATTR_NORMAL 0x07 /* cozy default for both mda and cga */
|
||||
#define VIDYA_REWIND ~0x7fff /* derived from mode addr min. lzcnt */
|
||||
#define VIDYA_SERVICE 0x10
|
||||
#define VIDYA_SET_MODE 0x0003
|
||||
#define VIDYA_SET_CURSOR 0x0100
|
||||
#define VIDYA_SET_CURSOR_NONE 0x2000
|
||||
#define VIDYA_SET_BLINKING 0x1003
|
||||
#define VIDYA_SET_BLINKING_NONE 0x0000
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
|
|
@ -5478,7 +5478,7 @@ imp 'RtlSetDaclSecurityDescriptor' RtlSetDaclSecurityDescriptor ntdll 138
|
|||
imp 'RtlSetDynamicTimeZoneInformation' RtlSetDynamicTimeZoneInformation ntdll 1386
|
||||
imp 'RtlSetEnvironmentStrings' RtlSetEnvironmentStrings ntdll 1387
|
||||
imp 'RtlSetEnvironmentVar' RtlSetEnvironmentVar ntdll 1388
|
||||
imp 'RtlSetEnvironmentVariable' RtlSetEnvironmentVariable ntdll 1389
|
||||
imp 'RtlSetEnvironmentVariable' RtlSetEnvironmentVariable ntdll 1389
|
||||
imp 'RtlSetExtendedFeaturesMask' RtlSetExtendedFeaturesMask ntdll 1390
|
||||
imp 'RtlSetGroupSecurityDescriptor' RtlSetGroupSecurityDescriptor ntdll 1391
|
||||
imp 'RtlSetHeapInformation' RtlSetHeapInformation ntdll 1392
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
#define GetConsoleMode(...) __imp_GetConsoleMode(__VA_ARGS__)
|
||||
#define SetConsoleCP(...) __imp_SetConsoleCP(__VA_ARGS__)
|
||||
#define SetConsoleCtrlHandler(...) __imp_SetConsoleCtrlHandler(__VA_ARGS__)
|
||||
#define SetConsoleMode(...) __imp_SetConsoleMode(__VA_ARGS__)
|
||||
#define SetConsoleOutputCP(...) __imp_SetConsoleOutputCP(__VA_ARGS__)
|
||||
|
||||
extern typeof(GetConsoleMode) *const __imp_GetConsoleMode __msabi;
|
||||
|
||||
#define SetConsoleCP(...) __imp_SetConsoleCP(__VA_ARGS__)
|
||||
extern typeof(SetConsoleCP) *const __imp_SetConsoleCP __msabi;
|
||||
|
||||
#define GetConsoleCP(...) __imp_GetConsoleCP(__VA_ARGS__)
|
||||
extern typeof(GetConsoleCP) *const __imp_GetConsoleCP __msabi;
|
||||
|
||||
#define SetConsoleCtrlHandler(...) __imp_SetConsoleCtrlHandler(__VA_ARGS__)
|
||||
extern typeof(SetConsoleCtrlHandler) *const __imp_SetConsoleCtrlHandler __msabi;
|
||||
|
||||
#define SetConsoleMode(...) __imp_SetConsoleMode(__VA_ARGS__)
|
||||
extern typeof(SetConsoleMode) *const __imp_SetConsoleMode __msabi;
|
||||
|
||||
#define SetConsoleOutputCP(...) __imp_SetConsoleOutputCP(__VA_ARGS__)
|
||||
extern typeof(SetConsoleOutputCP) *const __imp_SetConsoleOutputCP __msabi;
|
||||
|
||||
#define GetConsoleOutputCP(...) __imp_GetConsoleOutputCP(__VA_ARGS__)
|
||||
extern typeof(GetConsoleOutputCP) *const __imp_GetConsoleOutputCP __msabi;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#define CopyFile(...) __imp_CopyFileW(__VA_ARGS__)
|
||||
#define FlushFileBuffers(...) __imp_FlushFileBuffers(__VA_ARGS__)
|
||||
|
||||
#define CopyFile(...) __imp_CopyFileW(__VA_ARGS__)
|
||||
extern typeof(CopyFile) *const __imp_CopyFileW __msabi;
|
||||
|
||||
#define FlushFileBuffers(...) __imp_FlushFileBuffers(__VA_ARGS__)
|
||||
extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers __msabi;
|
||||
|
||||
#define GetFileType(...) __imp_GetFileType(__VA_ARGS__)
|
||||
extern typeof(GetFileType) *const __imp_GetFileType __msabi;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/directmap.h"
|
||||
|
@ -25,14 +26,21 @@
|
|||
static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
|
||||
unsigned prot, unsigned flags,
|
||||
int fd, int64_t off) {
|
||||
int64_t handle;
|
||||
struct DirectMap res;
|
||||
if ((res.maphandle = CreateFileMappingNuma(
|
||||
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
|
||||
&kNtIsInheritable, prot2nt(prot, flags), size >> 32, size, NULL,
|
||||
kNtNumaNoPreferredNode))) {
|
||||
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, fprot2nt(prot, flags),
|
||||
off >> 32, off, size, addr,
|
||||
kNtNumaNoPreferredNode))) {
|
||||
uint32_t protect, access;
|
||||
if (fd != -1) {
|
||||
handle = g_fds.p[fd].handle;
|
||||
} else {
|
||||
handle = kNtInvalidHandleValue;
|
||||
}
|
||||
protect = prot2nt(prot, flags);
|
||||
access = fprot2nt(prot, flags);
|
||||
if ((res.maphandle =
|
||||
CreateFileMappingNuma(handle, &kNtIsInheritable, protect, size >> 32,
|
||||
size, NULL, kNtNumaNoPreferredNode))) {
|
||||
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, access, off >> 32, off,
|
||||
size, addr, kNtNumaNoPreferredNode))) {
|
||||
CloseHandle(res.maphandle);
|
||||
res.maphandle = kNtInvalidHandleValue;
|
||||
res.addr = (void *)(intptr_t)winerr();
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/notice.inc"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/dce.h"
|
||||
.text.startup
|
||||
.source __FILE__
|
||||
|
@ -40,12 +42,15 @@ _executive:
|
|||
mov %rdx,%r14
|
||||
mov %rcx,%r15
|
||||
call _spawn
|
||||
mov %r12,%rdi
|
||||
mov %r13,%rsi
|
||||
mov %r14,%rdx
|
||||
mov %r15,%rcx
|
||||
call _getstack
|
||||
mov %rax,%rdi
|
||||
.weak main
|
||||
call main
|
||||
mov $main,%esi
|
||||
mov %r12,%rdx
|
||||
mov %r13,%rcx
|
||||
mov %r14,%r8
|
||||
mov %r15,%r9
|
||||
call _setstack
|
||||
mov %eax,%edi
|
||||
call exit
|
||||
9: .endfn _executive,weak,hidden
|
||||
|
|
|
@ -34,9 +34,9 @@ int mapfileread(const char *filename, struct MappedFile *mf) {
|
|||
mf->addr = MAP_FAILED;
|
||||
if ((mf->fd = open(filename, O_RDONLY)) != -1 &&
|
||||
(mf->size = getfiledescriptorsize(mf->fd)) < INT_MAX &&
|
||||
(mf->addr = mf->size
|
||||
? mmap(NULL, mf->size, PROT_READ, MAP_SHARED, mf->fd, 0)
|
||||
: NULL) != MAP_FAILED) {
|
||||
(mf->addr = mf->size ? mmap(NULL, mf->size, PROT_READ,
|
||||
MAP_PRIVATE | MAP_POPULATE, mf->fd, 0)
|
||||
: NULL) != MAP_FAILED) {
|
||||
return 0;
|
||||
} else {
|
||||
unmapfile(mf);
|
||||
|
@ -50,7 +50,7 @@ int mapfileread(const char *filename, struct MappedFile *mf) {
|
|||
int unmapfile(struct MappedFile *mf) {
|
||||
int rc;
|
||||
rc = 0;
|
||||
if (mf->addr != MAP_FAILED) {
|
||||
if (mf->addr && mf->addr != MAP_FAILED) {
|
||||
rc |= munmap(mf->addr, mf->size);
|
||||
mf->addr = MAP_FAILED;
|
||||
}
|
||||
|
|
36
libc/runtime/getstack.c
Normal file
36
libc/runtime/getstack.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
/**
|
||||
* Allocates deterministic stack for process.
|
||||
* @see _executive()
|
||||
*/
|
||||
void *_getstack(void) {
|
||||
char *p;
|
||||
p = mmap((char *)0x700000000000 - STACKSIZE, STACKSIZE,
|
||||
PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1,
|
||||
0);
|
||||
if (p == MAP_FAILED) abort();
|
||||
return p + STACKSIZE;
|
||||
}
|
|
@ -12,8 +12,8 @@ struct MemoryIntervals {
|
|||
struct MemoryInterval {
|
||||
int x;
|
||||
int y;
|
||||
} p[32];
|
||||
long h[32];
|
||||
} p[64];
|
||||
long h[64];
|
||||
};
|
||||
|
||||
extern struct MemoryIntervals _mmi;
|
||||
|
|
|
@ -44,6 +44,10 @@ struct MemoryIntervals _mmi;
|
|||
/**
|
||||
* Beseeches system for page-table entries.
|
||||
*
|
||||
* char *p = mmap(NULL, 65536, PROT_READ | PROT_WRITE,
|
||||
* MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
* munmap(p, 65536);
|
||||
*
|
||||
* @param addr optionally requests a particular virtual base address,
|
||||
* which needs to be 64kb aligned if passed (for NT compatibility)
|
||||
* @param size must be >0 and needn't be a multiple of FRAMESIZE
|
||||
|
@ -82,8 +86,6 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
|
|||
}
|
||||
addr = (void *)(intptr_t)((int64_t)x << 16);
|
||||
}
|
||||
assert((flags & MAP_FIXED) ||
|
||||
(!isheap(addr) && !isheap((char *)addr + size - 1)));
|
||||
dm = DirectMap(addr, size, prot, flags | MAP_FIXED, fd, off);
|
||||
if (dm.addr == MAP_FAILED || dm.addr != addr) {
|
||||
return MAP_FAILED;
|
||||
|
|
|
@ -25,16 +25,14 @@
|
|||
|
||||
textwindows int msync$nt(void *addr, size_t size, int flags) {
|
||||
int x, y, l, r, i;
|
||||
if (!FlushViewOfFile(addr, size)) return winerr();
|
||||
x = (intptr_t)addr >> 16;
|
||||
y = x + (ROUNDUP(size, 65536) >> 16) - 1;
|
||||
l = FindMemoryInterval(&_mmi, x);
|
||||
r = FindMemoryInterval(&_mmi, y);
|
||||
if (l && x <= _mmi.p[l - 1].y) --l;
|
||||
if (r && y <= _mmi.p[r - 1].y) --r;
|
||||
if (l < _mmi.i) {
|
||||
for (i = l; i <= r; --i) {
|
||||
FlushFileBuffers(_mmi.h[i - 1]);
|
||||
x = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
|
||||
y = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
|
||||
for (i = FindMemoryInterval(&_mmi, x); i < _mmi.i; ++i) {
|
||||
if ((x >= _mmi.p[i].x && x <= _mmi.p[i].y) ||
|
||||
(y >= _mmi.p[i].x && y <= _mmi.p[i].y)) {
|
||||
FlushFileBuffers(_mmi.h[i]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -44,6 +44,7 @@ void exit(int) noreturn;
|
|||
void quick_exit(int) noreturn;
|
||||
void _exit(int) libcesque noreturn;
|
||||
void _Exit(int) libcesque noreturn;
|
||||
long _setstack(void *, void *, ...);
|
||||
void abort(void) noreturn noinstrument;
|
||||
void panic(void) noreturn noinstrument privileged;
|
||||
void triplf(void) noreturn noinstrument privileged;
|
||||
|
|
|
@ -69,6 +69,8 @@ o/$(MODE)/libc/runtime/winmain.greg.o: \
|
|||
DEFAULT_CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
||||
o/$(MODE)/libc/runtime/main-gcc.asm: OVERRIDE_CFLAGS += -ffixed-r12 -ffixed-r13 -ffixed-r14 -ffixed-r15
|
||||
|
||||
LIBC_RUNTIME_LIBS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)))
|
||||
LIBC_RUNTIME_SRCS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_RUNTIME_HDRS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_HDRS))
|
||||
|
|
|
@ -17,30 +17,30 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/macros.h"
|
||||
.text.startup
|
||||
.source __FILE__
|
||||
|
||||
/ Merges page table entries for pages with identical content.
|
||||
/ Switches stack.
|
||||
/
|
||||
/ This is a hint. It can help trim physical memory for things
|
||||
/ like extremely sparse data.
|
||||
/
|
||||
/ @param rdi is base address
|
||||
/ @param rsi is byte length
|
||||
mergepages:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov $-PAGESIZE,%rax
|
||||
and %rax,%rdi
|
||||
and %rax,%rsi
|
||||
mov __NR_madvise,%eax
|
||||
mov MADV_MERGEABLE,%edx
|
||||
test %edx,%edx
|
||||
jz 1f
|
||||
syscall
|
||||
1: .leafepilogue
|
||||
.endfn mergepages,globl
|
||||
/ @param rdi is new rsp, passed as malloc(size) + size
|
||||
/ @param rsi is function to call in new stack space
|
||||
/ @param rdx,rcx,r8,r9 get passed as args to rsi
|
||||
/ @return happens on original stack
|
||||
_setstack:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
push %rbx
|
||||
mov %rsp,%rbx
|
||||
mov %rdi,%rsp
|
||||
push 16(%rbx)
|
||||
push 8(%rbx)
|
||||
mov %rsi,%rax
|
||||
mov %rdx,%rdi
|
||||
mov %rcx,%rsi
|
||||
mov %r8,%rdx
|
||||
mov %r9,%rcx
|
||||
call *%rax
|
||||
mov %rbx,%rsp
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn _setstack,globl
|
|
@ -19,15 +19,32 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/enum/loadlibrarysearch.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/pedef.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/runtime/getdosenviron.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
static void LoadFasterAndPreventHijacking(void) {
|
||||
static struct CmdExe {
|
||||
bool result;
|
||||
struct OldNtConsole {
|
||||
unsigned codepage;
|
||||
unsigned mode;
|
||||
int64_t handle;
|
||||
} oldin, oldout;
|
||||
} g_cmdexe;
|
||||
|
||||
static textwindows void MitigateDriveByDownloads(void) {
|
||||
unsigned wrote;
|
||||
if (!SetDefaultDllDirectories(kNtLoadLibrarySearchSearchSystem32)) {
|
||||
WriteFile(GetStdHandle(kNtStdErrorHandle), "nodll\n", 6, &wrote, NULL);
|
||||
|
@ -35,6 +52,78 @@ static void LoadFasterAndPreventHijacking(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static textwindows void RestoreCmdExe(void) {
|
||||
if (g_cmdexe.oldin.handle) {
|
||||
SetConsoleCP(g_cmdexe.oldin.codepage);
|
||||
SetConsoleMode(g_cmdexe.oldin.handle, g_cmdexe.oldin.mode);
|
||||
}
|
||||
if (g_cmdexe.oldout.handle) {
|
||||
SetConsoleOutputCP(g_cmdexe.oldout.codepage);
|
||||
SetConsoleMode(g_cmdexe.oldout.handle, g_cmdexe.oldout.mode);
|
||||
}
|
||||
}
|
||||
|
||||
static textwindows void SetTrueColor(void) {
|
||||
SetEnvironmentVariable(u"TERM", u"xterm-truecolor");
|
||||
}
|
||||
|
||||
static textwindows void NormalizeCmdExe(void) {
|
||||
int64_t handle, hstdin, hstdout, hstderr;
|
||||
if ((int)weakaddr("v_ntsubsystem") == kNtImageSubsystemWindowsCui &&
|
||||
NtGetVersion() >= kNtVersionWindows10) {
|
||||
atexit(RestoreCmdExe);
|
||||
hstdin = GetStdHandle(pushpop(kNtStdInputHandle));
|
||||
hstdout = GetStdHandle(pushpop(kNtStdOutputHandle));
|
||||
hstderr = GetStdHandle(pushpop(kNtStdErrorHandle));
|
||||
if (GetFileType((handle = hstdin)) == kNtFileTypeChar) {
|
||||
SetTrueColor();
|
||||
g_cmdexe.oldin.handle = handle;
|
||||
g_cmdexe.oldin.codepage = GetConsoleCP();
|
||||
SetConsoleCP(kNtCpUtf8);
|
||||
GetConsoleMode(handle, &g_cmdexe.oldin.mode);
|
||||
SetConsoleMode(handle, g_cmdexe.oldin.mode | kNtEnableProcessedInput |
|
||||
kNtEnableVirtualTerminalInput);
|
||||
}
|
||||
if (GetFileType((handle = hstdout)) == kNtFileTypeChar ||
|
||||
GetFileType((handle = hstderr)) == kNtFileTypeChar) {
|
||||
SetTrueColor();
|
||||
g_cmdexe.oldout.handle = handle;
|
||||
g_cmdexe.oldout.codepage = GetConsoleOutputCP();
|
||||
SetConsoleOutputCP(kNtCpUtf8);
|
||||
GetConsoleMode(handle, &g_cmdexe.oldout.mode);
|
||||
SetConsoleMode(handle, g_cmdexe.oldout.mode | kNtEnableProcessedOutput |
|
||||
kNtEnableVirtualTerminalProcessing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function on Windows NT.
|
||||
*
|
||||
* The Cosmopolitan Runtime provides the following services, which aim
|
||||
* to bring Windows NT behavior closer in harmony with System Five:
|
||||
*
|
||||
* 1. We configure CMD.EXE for UTF-8 and enable ANSI colors on Win10.
|
||||
*
|
||||
* 2. Command line arguments are passed as a blob of UTF-16 text. We
|
||||
* chop them up into an char *argv[] UTF-8 data structure, in
|
||||
* accordance with the DOS conventions for argument quoting.
|
||||
*
|
||||
* 3. Environment variables are passed to us as a sorted UTF-16 double
|
||||
* NUL terminated list. We translate this to char ** using UTF-8.
|
||||
*
|
||||
* 4. NT likes to choose a stack address that's beneath the program
|
||||
* image. We want to be able to assume that stack addresses are
|
||||
* located at higher addresses than heap and program memory. So the
|
||||
* _executive() function will switch stacks appropriately.
|
||||
*
|
||||
* 5. Windows users are afraid of "drive-by downloads" where someone
|
||||
* might accidentally an evil DLL to their Downloads folder which
|
||||
* then overrides the behavior of a legitimate EXE being run from
|
||||
* the downloads folder. Since we don't even use dynamic linking,
|
||||
* we've cargo culted some API calls, that may harden against it.
|
||||
*
|
||||
*/
|
||||
textwindows int WinMain(void *hInstance, void *hPrevInstance,
|
||||
const char *lpCmdLine, int nCmdShow) {
|
||||
int i, count;
|
||||
|
@ -42,7 +131,8 @@ textwindows int WinMain(void *hInstance, void *hPrevInstance,
|
|||
char *argarray[512], *envarray[512];
|
||||
char argblock[ARG_MAX], envblock[ENV_MAX];
|
||||
long auxarray[][2] = {{pushpop(0L), pushpop(0L)}};
|
||||
LoadFasterAndPreventHijacking();
|
||||
MitigateDriveByDownloads();
|
||||
NormalizeCmdExe();
|
||||
*(/*unconst*/ int *)&hostos = WINDOWS;
|
||||
cmd16 = GetCommandLine();
|
||||
env16 = GetEnvironmentStrings();
|
||||
|
|
|
@ -23,7 +23,5 @@
|
|||
* Returns number of bytes available in stream buffer.
|
||||
*/
|
||||
unsigned favail(FILE *f) {
|
||||
if (f->beg == f->end) return f->size;
|
||||
if (f->end > f->beg) return f->end - f->beg;
|
||||
return (f->size - f->beg) + f->end;
|
||||
return ((f->end - f->beg - 1) & (f->size - 1)) + 1;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,11 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Writes string to stream.
|
||||
|
@ -32,15 +35,14 @@
|
|||
* @return strlen(s) or -1 w/ errno on error
|
||||
*/
|
||||
int fputs(const char *s, FILE *f) {
|
||||
unsigned char *p = (unsigned char *)s;
|
||||
int res = 0;
|
||||
while (*p) {
|
||||
if (fputc(*p++, f) == -1) {
|
||||
int i, n, m;
|
||||
n = strlen(s);
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (fputc(s[i], f) == -1) {
|
||||
if (ferror(f) == EINTR) continue;
|
||||
if (feof(f)) errno = f->state = EPIPE;
|
||||
return -1;
|
||||
}
|
||||
++res;
|
||||
}
|
||||
return ++res;
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ LIBC_STDIO_A_DIRECTDEPS = \
|
|||
LIBC_ALG \
|
||||
LIBC_BITS \
|
||||
LIBC_CALLS \
|
||||
LIBC_CALLS_HEFTY \
|
||||
LIBC_CONV \
|
||||
LIBC_ESCAPE \
|
||||
LIBC_FMT \
|
||||
|
|
|
@ -26,6 +26,13 @@
|
|||
* @see getline
|
||||
*/
|
||||
char *(chomp)(char *line) {
|
||||
if (line) line[strcspn(line, "\r\n")] = '\0';
|
||||
size_t i;
|
||||
for (i = strlen(line); i--;) {
|
||||
if (line[i] == '\r' || line[i] == '\n') {
|
||||
line[i] = '\0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,6 @@
|
|||
* @see getline
|
||||
*/
|
||||
char16_t *chomp16(char16_t *line) {
|
||||
if (line) line[strcspn(line, u"\r\n")] = '\0';
|
||||
if (line) line[strcspn16(line, u"\r\n")] = '\0';
|
||||
return line;
|
||||
}
|
||||
|
|
|
@ -283,24 +283,6 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
|
||||
#if __STDC_VERSION__ + 0 >= 201112
|
||||
|
||||
#define strstr(haystack, needle) \
|
||||
_Generic(*(haystack), wchar_t \
|
||||
: wcsstr, char16_t \
|
||||
: strstr16, default \
|
||||
: strstr)(haystack, needle)
|
||||
|
||||
#define strrchr(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsrchr, char16_t \
|
||||
: strrchr16, default \
|
||||
: strrchr)(s, c)
|
||||
|
||||
#define strchrnul(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcschrnul, char16_t \
|
||||
: strchrnul16, default \
|
||||
: strchrnul)(s, c)
|
||||
|
||||
#define strnlen(s, n) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsnlen, char16_t \
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
/**
|
||||
* Returns prefix length, consisting of chars not in reject.
|
||||
* a.k.a. Return index of first byte that's in charset.
|
||||
*
|
||||
* @param reject is nul-terminated character set
|
||||
* @see strspn(), strtok_r()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t(strcspn)(const char *s, const char *reject) {
|
||||
|
|
|
@ -35,13 +35,13 @@
|
|||
char *(strstr)(const char *haystack, const char *needle) {
|
||||
if (needle[0]) {
|
||||
if (needle[1]) {
|
||||
if (!((intptr_t)needle & 0xf) && X86_HAVE(SSE4_2) && !IsTiny()) {
|
||||
if (!((intptr_t)needle & 0xf) && X86_HAVE(SSE4_2)) {
|
||||
return strstr$sse42(haystack, needle);
|
||||
} else {
|
||||
size_t needlelen;
|
||||
alignas(16) char needle2[64];
|
||||
needlelen = strlen(needle);
|
||||
if (needlelen < 64 && X86_HAVE(SSE4_2) && !IsTiny()) {
|
||||
if (needlelen < 64 && X86_HAVE(SSE4_2)) {
|
||||
memcpy(needle2, needle, (needlelen + 1) * sizeof(char));
|
||||
return strstr$sse42(haystack, needle2);
|
||||
} else {
|
||||
|
|
|
@ -26,6 +26,6 @@
|
|||
* @see getline
|
||||
*/
|
||||
wchar_t *wchomp(wchar_t *line) {
|
||||
if (line) line[strcspn(line, L"\r\n")] = '\0';
|
||||
if (line) line[wcscspn(line, L"\r\n")] = '\0';
|
||||
return line;
|
||||
}
|
||||
|
|
|
@ -247,7 +247,7 @@ syscon mmap MAP_HUGE_MASK 63 0 0 0 0
|
|||
syscon mmap MAP_HUGE_SHIFT 26 0 0 0 0
|
||||
syscon mmap MAP_LOCKED 0x2000 0 0 0 0
|
||||
syscon mmap MAP_NONBLOCK 0x010000 0 0 0 0
|
||||
syscon mmap MAP_POPULATE 0x8000 0 0 0 0
|
||||
syscon mmap MAP_POPULATE 0x8000 0 0 0 0 # can avoid madvise(MADV_WILLNEED) on private file mapping
|
||||
syscon mmap MAP_TYPE 15 0 0 0 0 # what is it
|
||||
syscon compat MAP_EXECUTABLE 0x1000 0 0 0 0 # ignored
|
||||
syscon compat MAP_DENYWRITE 0x0800 0 0 0 0
|
||||
|
@ -301,8 +301,8 @@ syscon mprot PROT_NONE 0 0 0 0 0 # unix consensus (nt needs special
|
|||
syscon mprot PROT_READ 1 1 1 1 1 # unix consensus
|
||||
syscon mprot PROT_WRITE 2 2 2 2 2 # unix consensus
|
||||
syscon mprot PROT_EXEC 4 4 4 4 4 # unix consensus
|
||||
syscon mprot PROT_GROWSDOWN 0x01000000 0 0 0 0x01000000 # bsd consensus
|
||||
syscon mprot PROT_GROWSUP 0x02000000 0 0 0 0
|
||||
syscon mprot PROT_GROWSDOWN 0x01000000 0 0 0 0 # intended for mprotect; see MAP_GROWSDOWN for mmap() (todo: what was 0x01000000 on nt)
|
||||
syscon mprot PROT_GROWSUP 0x02000000 0 0 0 0 # intended for mprotect; see MAP_GROWSDOWN for mmap()
|
||||
|
||||
syscon mremap MREMAP_MAYMOVE 1 1 1 1 1 # faked non-linux (b/c linux only)
|
||||
syscon mremap MREMAP_FIXED 2 2 2 2 2 # faked non-linux (b/c linux only)
|
||||
|
@ -320,6 +320,28 @@ syscon access X_OK 1 1 1 1 0xa0000000 # unix consensus and kNtGener
|
|||
syscon access W_OK 2 2 2 2 0x40000000 # unix consensus and kNtGenericWrite
|
||||
syscon access R_OK 4 4 4 4 0x80000000 # unix consensus and kNtGenericRead
|
||||
|
||||
# flock() flags
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD XENIX Commentary
|
||||
syscon lock LOCK_SH 1 1 1 1 0 # shared [unix consensus]
|
||||
syscon lock LOCK_EX 2 2 2 2 2 # exclusive [consensus!]
|
||||
syscon lock LOCK_NB 4 4 4 4 1 # non-blocking [unix consensus]
|
||||
syscon lock LOCK_UN 8 8 8 8 8 # unlock [unix consensus & faked NT]
|
||||
|
||||
# waitpid() / wait4() options
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD XENIX Commentary
|
||||
syscon waitpid WNOHANG 1 1 1 1 0 # unix consensus
|
||||
syscon waitpid WUNTRACED 2 2 2 2 0 # unix consensus
|
||||
syscon waitpid WCONTINUED 8 0x10 4 8 0
|
||||
|
||||
# waitid() options
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD XENIX Commentary
|
||||
syscon waitid WEXITED 4 4 0x10 0 0
|
||||
syscon waitid WSTOPPED 2 8 2 0 0
|
||||
syscon waitid WNOWAIT 0x01000000 0x20 8 0 0
|
||||
|
||||
# stat::st_mode constants
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD XENIX Commentary
|
||||
|
@ -1049,7 +1071,6 @@ syscon af AF_VSOCK 40 0 0 0 0
|
|||
syscon af AF_KCM 41 0 0 0 0
|
||||
syscon af AF_MAX 42 40 42 36 35
|
||||
|
||||
|
||||
syscon pf PF_UNIX 1 1 1 1 1 # consensus
|
||||
syscon pf PF_UNSPEC 0 0 0 0 0 # consensus
|
||||
syscon pf PF_APPLETALK 5 0x10 0x10 0x10 0x10 # bsd consensus
|
||||
|
@ -1862,6 +1883,7 @@ syscon misc LC_MONETARY_MASK 0x10 0 4 8 0
|
|||
syscon misc LC_MESSAGES_MASK 0x20 0 0x20 0x40 0
|
||||
syscon misc LC_ALL_MASK 0x1fbf 0 63 126 0
|
||||
|
||||
syscon lock LOCK_UNLOCK_CACHE 54 0 0 0 0 # wut
|
||||
|
||||
syscon ptrace PTRACE_GETREGSET 0x4204 0 0 0 0
|
||||
syscon ptrace PTRACE_GETSIGMASK 0x420a 0 0 0 0
|
||||
|
@ -1894,12 +1916,6 @@ syscon misc IP6F_MORE_FRAG 0x0100 0x0100 0x0100 0x0100 0x0100 # con
|
|||
syscon misc IP6F_OFF_MASK 0xf8ff 0xf8ff 0xf8ff 0xf8ff 0xf8ff # consensus
|
||||
syscon misc IP6F_RESERVED_MASK 0x0600 0x0600 0x0600 0x0600 0x0600 # consensus
|
||||
|
||||
syscon lock LOCK_SH 1 1 1 1 0 # unix consensus
|
||||
syscon lock LOCK_EX 2 2 2 2 2 # consensus!
|
||||
syscon lock LOCK_NB 4 4 4 4 1 # unix consensus
|
||||
syscon lock LOCK_UN 8 8 8 8 8 # unix consensus & faked NT
|
||||
syscon lock LOCK_UNLOCK_CACHE 54 0 0 0 0
|
||||
|
||||
syscon misc NO_SENSE 0 0 0 0 0 # consensus
|
||||
syscon misc NO_ADDRESS 4 4 4 4 0x2afc # unix consensus
|
||||
syscon misc NO_DATA 4 4 4 4 0x2afc # unix consensus
|
||||
|
@ -2025,9 +2041,9 @@ syscon misc RTLD_NOLOAD 4 0x10 0x2000 0 0
|
|||
syscon misc RTLD_DI_LINKMAP 0 0 2 0 0
|
||||
syscon misc RTLD_LOCAL 0 4 0 0 0
|
||||
|
||||
syscon misc RUSAGE_SELF 0 0 0 0 0 # unix consensus & faked nt
|
||||
syscon misc RUSAGE_CHILDREN -1 -1 -1 -1 99 # unix consensus & unavailable on nt
|
||||
syscon misc RUSAGE_THREAD 1 99 1 1 1 # faked nt & unavailable on xnu
|
||||
syscon rusage RUSAGE_SELF 0 0 0 0 0 # unix consensus & faked nt
|
||||
syscon rusage RUSAGE_CHILDREN -1 -1 -1 -1 99 # unix consensus & unavailable on nt
|
||||
syscon rusage RUSAGE_THREAD 1 99 1 1 1 # faked nt & unavailable on xnu
|
||||
|
||||
syscon misc FSETLOCKING_QUERY 0 0 0 0 0 # consensus
|
||||
syscon misc FSETLOCKING_BYCALLER 2 0 0 0 0
|
||||
|
@ -2315,10 +2331,8 @@ syscon misc TUEXEC 0x40 0x40 0x40 0x40 0 # unix consensus
|
|||
syscon misc TUREAD 0x0100 0x0100 0x0100 0x0100 0 # unix consensus
|
||||
syscon misc TUWRITE 0x80 0x80 0x80 0x80 0 # unix consensus
|
||||
syscon misc TVERSLEN 2 2 2 2 0 # unix consensus
|
||||
syscon misc WNOHANG 1 1 1 1 0 # unix consensus
|
||||
syscon misc WORD_BIT 0x20 0x20 0x20 0x20 0 # unix consensus
|
||||
syscon misc WRQ 2 2 2 2 0 # unix consensus
|
||||
syscon misc WUNTRACED 2 2 2 2 0 # unix consensus
|
||||
syscon misc SIGEV_THREAD 2 3 2 0 0
|
||||
syscon misc SIGEV_SIGNAL 0 1 1 0 0
|
||||
syscon misc SIGEV_NONE 1 0 0 0 0
|
||||
|
@ -2757,10 +2771,6 @@ syscon misc TSS_DTOR_ITERATIONS 0 0 4 0 0
|
|||
syscon misc TTY_NAME_MAX 0x20 0 0 260 0
|
||||
syscon misc UIO_MAXIOV 0x0400 0 0 0x0400 0
|
||||
syscon misc USER_PROCESS 7 7 4 0 0
|
||||
syscon misc WCONTINUED 8 0x10 4 8 0
|
||||
syscon misc WEXITED 4 4 0x10 0 0
|
||||
syscon misc WNOWAIT 0x01000000 0x20 8 0 0
|
||||
syscon misc WSTOPPED 2 8 2 0 0
|
||||
syscon misc YESEXPR 0x050000 52 52 47 0
|
||||
syscon misc YESSTR 0x050002 54 54 46 0
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon mprot PROT_GROWSDOWN 0x01000000 0 0 0 0x01000000
|
||||
.syscon mprot PROT_GROWSDOWN 0x01000000 0 0 0 0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon misc RUSAGE_CHILDREN -1 -1 -1 -1 99
|
||||
.syscon rusage RUSAGE_CHILDREN -1 -1 -1 -1 99
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon misc RUSAGE_SELF 0 0 0 0 0
|
||||
.syscon rusage RUSAGE_SELF 0 0 0 0 0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon misc RUSAGE_THREAD 1 99 1 1 1
|
||||
.syscon rusage RUSAGE_THREAD 1 99 1 1 1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon misc WCONTINUED 8 0x10 4 8 0
|
||||
.syscon waitpid WCONTINUED 8 0x10 4 8 0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon misc WEXITED 4 4 0x10 0 0
|
||||
.syscon waitid WEXITED 4 4 0x10 0 0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon misc WNOHANG 1 1 1 1 0
|
||||
.syscon waitpid WNOHANG 1 1 1 1 0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon misc WNOWAIT 0x01000000 0x20 8 0 0
|
||||
.syscon waitid WNOWAIT 0x01000000 0x20 8 0 0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon misc WSTOPPED 2 8 2 0 0
|
||||
.syscon waitid WSTOPPED 2 8 2 0 0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon misc WUNTRACED 2 2 2 2 0
|
||||
.syscon waitpid WUNTRACED 2 2 2 2 0
|
||||
|
|
|
@ -27,10 +27,10 @@ hidden extern const long MAP_TYPE;
|
|||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
||||
#define MAP_FILE LITERALLY(0)
|
||||
#define MAP_SHARED LITERALLY(1)
|
||||
#define MAP_PRIVATE LITERALLY(2)
|
||||
#define MAP_FIXED LITERALLY(16)
|
||||
#define MAP_FILE 0
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_FIXED 16
|
||||
|
||||
#define MAP_32BIT SYMBOLIC(MAP_32BIT)
|
||||
#define MAP_ANONYMOUS SYMBOLIC(MAP_ANONYMOUS)
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_W_H_
|
||||
#include "libc/runtime/symbolic.h"
|
||||
|
||||
#define WNOHANG SYMBOLIC(WNOHANG)
|
||||
#define WUNTRACED SYMBOLIC(WUNTRACED)
|
||||
#define WNOHANG SYMBOLIC(WNOHANG)
|
||||
#define WUNTRACED SYMBOLIC(WUNTRACED)
|
||||
#define WCONTINUED SYMBOLIC(WCONTINUED)
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
hidden extern const long WNOHANG;
|
||||
hidden extern const long WUNTRACED;
|
||||
hidden extern const long WCONTINUED;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -35,6 +35,7 @@ STATIC_YOINK("ntoa");
|
|||
*/
|
||||
|
||||
static char *xiso8601$impl(struct timespec *opt_ts, int sswidth) {
|
||||
char *p;
|
||||
struct tm tm;
|
||||
struct timespec ts;
|
||||
int64_t sec, subsec;
|
||||
|
@ -60,7 +61,8 @@ static char *xiso8601$impl(struct timespec *opt_ts, int sswidth) {
|
|||
localtime_r(&sec, &tm);
|
||||
strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S", &tm);
|
||||
strftime(zonebuf, sizeof(zonebuf), "%z", &tm);
|
||||
return (xasprintf)("%s.%0*ld%s", timebuf, sswidth, subsec, zonebuf);
|
||||
(asprintf)(&p, "%s.%0*ld%s", timebuf, sswidth, subsec, zonebuf);
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
|
@ -28,6 +28,6 @@
|
|||
/ @note the greatest of all libm functions
|
||||
tinymath_atan2:
|
||||
ezlea tinymath_atan2l,ax
|
||||
jmp _f2ld2
|
||||
jmp _d2ld2
|
||||
.endfn tinymath_atan2,globl
|
||||
.alias tinymath_atan2,atan2
|
||||
|
|
|
@ -43,31 +43,6 @@ kCombiningChars:
|
|||
add $1208,%rsi
|
||||
.init.end 400,_init_kCombiningChars
|
||||
|
||||
/ The data below is sparse, as evidenced by:
|
||||
/ o/tool/viz/bing.com <o/libc/str/CombiningChars.bin |
|
||||
/ o/tool/viz/fold.com
|
||||
/ Thus ask the kernel to shrink its physical memory requirements
|
||||
/ which might sadly need mmap intermediate step on linux to work
|
||||
/ how one would have hoped.
|
||||
.text.startup
|
||||
kCombiningCharsInit:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
ezlea kCombiningChars,di
|
||||
mov $114752,%esi
|
||||
call mergepages
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn kCombiningCharsInit
|
||||
.previous
|
||||
.init_array
|
||||
.align 8
|
||||
kCombiningCharsCtor:
|
||||
.quad kCombiningCharsInit
|
||||
.endobj kCombiningCharsCtor
|
||||
.previous
|
||||
|
||||
/ o/tool/build/lz4toasm.com \
|
||||
/ -o o/libc/str/CombiningChars.s \
|
||||
/ -s kCombiningChars \
|
||||
|
|
|
@ -44,7 +44,7 @@ void *unbingbuf(void *buf, size_t size, const char16_t *glyphs, int fill) {
|
|||
char *p, *pe;
|
||||
for (p = buf, pe = p + size; p < pe && *glyphs; ++p, ++glyphs) {
|
||||
*p = (b = unbing(*glyphs)) & 0xff;
|
||||
DCHECK_NE(-1, b, "%`'hc ∉ IBMCP437\n", *glyphs);
|
||||
/* DCHECK_NE(-1, b, "%`'hc ∉ IBMCP437\n", *glyphs); */
|
||||
}
|
||||
if (fill != -1) memset(p, fill, pe - p);
|
||||
return buf;
|
||||
|
|
|
@ -49,6 +49,7 @@ int xwrite(int, const void *, uint64_t);
|
|||
│ cosmopolitan § eXtended apis » memory ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
void xdie(void) noreturn;
|
||||
char *xdtoa(double) _XMAL;
|
||||
char *xasprintf(const char *, ...) printfesque(1) paramsnonnull((1)) _XMAL;
|
||||
char *xvasprintf(const char *, va_list) _XPNN _XMAL;
|
||||
|
@ -63,6 +64,7 @@ char *xstrdup(const char *) _XPNN _XMAL;
|
|||
char *xstrndup(const char *, size_t) _XPNN _XMAL;
|
||||
char *xstrcat(const char *, ...) paramsnonnull((1)) nullterminated() _XMAL;
|
||||
char *xstrmul(const char *, size_t) paramsnonnull((1)) _XMAL;
|
||||
char *xjoinpaths(const char *, const char *) paramsnonnull() _XMAL;
|
||||
char *xinet_ntop(int, const void *) _XPNN _XMAL;
|
||||
char *xaescapec(const char *) _XPNN _XMAL;
|
||||
char *xaescapesh(const char *) _XPNN _XMAL;
|
||||
|
@ -82,7 +84,8 @@ char *xiso8601ts(struct timespec *) mallocesque;
|
|||
│ cosmopolitan § eXtended apis » input / output ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
char *xslurp(const char *) _XPNN _XMALPG nodiscard;
|
||||
char *xslurp(const char *, size_t *) paramsnonnull((1)) _XMALPG nodiscard;
|
||||
int xbarf(const char *, const void *, size_t);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § eXtended apis » safety ─╬─│┼
|
||||
|
|
|
@ -37,7 +37,6 @@ LIBC_X_A_DIRECTDEPS = \
|
|||
LIBC_CALLS \
|
||||
LIBC_ESCAPE \
|
||||
LIBC_FMT \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
|
@ -45,7 +44,6 @@ LIBC_X_A_DIRECTDEPS = \
|
|||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TIME \
|
||||
THIRD_PARTY_DTOA
|
||||
|
||||
LIBC_X_A_DEPS := \
|
||||
|
|
|
@ -32,7 +32,7 @@ char *xaescape(const char *unescaped,
|
|||
unsigned length)) {
|
||||
char *escaped = NULL;
|
||||
if (aescape(&escaped, 32, unescaped, strlen(unescaped), impl) == -1) {
|
||||
die();
|
||||
xdie();
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
|
|
65
libc/x/xbarf.c
Normal file
65
libc/x/xbarf.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
/**
|
||||
* Writes data to file.
|
||||
*
|
||||
* @param size can be -1 to strlen(data)
|
||||
* @return if failed, -1 w/ errno
|
||||
* @note this is uninterruptible
|
||||
*/
|
||||
int xbarf(const char *path, const void *data, size_t size) {
|
||||
char *p;
|
||||
ssize_t rc;
|
||||
int fd, res;
|
||||
size_t i, wrote;
|
||||
res = 0;
|
||||
p = data;
|
||||
if (size == -1) size = strlen(p);
|
||||
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) != -1) {
|
||||
if (ftruncate(fd, size) != -1) {
|
||||
if (size > 2 * 1024 * 1024) {
|
||||
fadvise(fd, 0, size, MADV_SEQUENTIAL);
|
||||
}
|
||||
for (i = 0; i < size; i += wrote) {
|
||||
TryAgain:
|
||||
if ((rc = pwrite(fd, p + i, size - i, i)) != -1) {
|
||||
wrote = rc;
|
||||
} else if (errno == EINTR) {
|
||||
goto TryAgain;
|
||||
} else {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = -1;
|
||||
}
|
||||
close(fd);
|
||||
} else {
|
||||
res = -1;
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -26,6 +26,6 @@
|
|||
*/
|
||||
void *xcalloc(size_t count, size_t size) {
|
||||
void *res = calloc(count, size);
|
||||
if (!res) die();
|
||||
if (!res) xdie();
|
||||
return res;
|
||||
}
|
||||
|
|
28
libc/x/xdie.c
Normal file
28
libc/x/xdie.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
void xdie(void) {
|
||||
if (weaken(die)) die();
|
||||
abort();
|
||||
}
|
37
libc/x/xjoinpaths.c
Normal file
37
libc/x/xjoinpaths.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Joins paths.
|
||||
*/
|
||||
char *xjoinpaths(const char *path, const char *other) {
|
||||
if (!*other) {
|
||||
return xstrdup(path);
|
||||
} else if (startswith(other, "/") || strcmp(path, ".") == 0) {
|
||||
return xstrdup(other);
|
||||
} else if (endswith(other, "/")) {
|
||||
return xstrcat(path, other);
|
||||
} else {
|
||||
return xstrcat(path, '/', other);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,6 @@
|
|||
*/
|
||||
void *xmalloc(size_t bytes) {
|
||||
void *res = malloc(bytes);
|
||||
if (!res) die();
|
||||
if (!res) xdie();
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,6 @@
|
|||
*/
|
||||
void *xmemalign(size_t alignment, size_t bytes) {
|
||||
void *res = memalign(alignment, bytes);
|
||||
if (!res) die();
|
||||
if (!res) xdie();
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,6 @@
|
|||
*/
|
||||
void *xrealloc(void *p1, size_t newsize) {
|
||||
void *p2 = realloc(p1, newsize);
|
||||
if (!p2) die();
|
||||
if (!p2) xdie();
|
||||
return p2;
|
||||
}
|
||||
|
|
|
@ -17,73 +17,56 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
static size_t getfilesize(int fd) {
|
||||
struct stat st;
|
||||
st.st_size = 0;
|
||||
fstat(fd, &st);
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
static size_t smudgefilesize(size_t size) {
|
||||
return roundup(size, PAGESIZE) + PAGESIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads entire file into memory.
|
||||
*
|
||||
* This function is fantastic for being lazy. It may waste space if the
|
||||
* file is large, but it's implemented in a conscientious way that won't
|
||||
* bomb the systemwide page cache. It means performance too, naturally.
|
||||
*
|
||||
* @return contents which must be free()'d or NULL w/ errno
|
||||
* @return NUL-terminated malloc'd contents, or NULL w/ errno
|
||||
* @note this is uninterruptible
|
||||
*/
|
||||
char *slurp(const char *path, size_t *opt_out_readlength) {
|
||||
char *xslurp(const char *path, size_t *opt_out_size) {
|
||||
int fd;
|
||||
ssize_t rc;
|
||||
size_t i, got;
|
||||
char *res, *p;
|
||||
size_t i, n, got, want;
|
||||
struct stat st;
|
||||
res = NULL;
|
||||
if ((fd = open(path, O_RDONLY)) == -1) goto Failure;
|
||||
n = getfilesize(fd);
|
||||
/* TODO(jart): Fix this, it's totally broken */
|
||||
if (!(res = valloc(smudgefilesize(n)))) goto Failure;
|
||||
if (n > FRAMESIZE) fadvise(fd, 0, n, MADV_SEQUENTIAL);
|
||||
i = 0;
|
||||
for (;;) {
|
||||
want = smudgefilesize(n - i);
|
||||
TryAgain:
|
||||
if ((rc = read(fd, &res[i], want)) == -1) {
|
||||
if (errno == EINTR) goto TryAgain;
|
||||
goto Failure;
|
||||
}
|
||||
got = (size_t)rc;
|
||||
if (i + 1 >= n) {
|
||||
if ((p = realloc(res, smudgefilesize((n += n >> 1))))) {
|
||||
res = p;
|
||||
} else {
|
||||
goto Failure;
|
||||
if ((fd = open(path, O_RDONLY)) != -1) {
|
||||
if (fstat(fd, &st) != -1 && (res = valloc(st.st_size))) {
|
||||
if (st.st_size > 2 * 1024 * 1024) {
|
||||
fadvise(fd, 0, st.st_size, MADV_SEQUENTIAL);
|
||||
}
|
||||
for (i = 0; i < st.st_size; i += got) {
|
||||
TryAgain:
|
||||
if ((rc = pread(fd, res + i, st.st_size - i, i)) != -1) {
|
||||
if (!(got = rc)) {
|
||||
if (fstat(fd, &st) == -1) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
} else if (errno == EINTR) {
|
||||
goto TryAgain;
|
||||
} else {
|
||||
free(res);
|
||||
res = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (res) {
|
||||
if (opt_out_size) {
|
||||
*opt_out_size = st.st_size;
|
||||
}
|
||||
res[i] = '\0';
|
||||
}
|
||||
}
|
||||
i += got;
|
||||
if (got == 0) break;
|
||||
if (got > want) abort();
|
||||
close(fd);
|
||||
}
|
||||
if (opt_out_readlength) *opt_out_readlength = i;
|
||||
res[i] = '\0';
|
||||
close(fd);
|
||||
return res;
|
||||
Failure:
|
||||
free(res);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
|
@ -27,6 +27,6 @@
|
|||
*/
|
||||
char *xstrdup(const char *s) {
|
||||
void *res = strdup(s);
|
||||
if (!res) die();
|
||||
if (!res) xdie();
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Multiplies string.
|
||||
*/
|
||||
char *xstrmul(const char *s, size_t n) {
|
||||
char *p;
|
||||
size_t i, m, size;
|
||||
|
|
|
@ -31,6 +31,6 @@
|
|||
*/
|
||||
char *xstrndup(const char *s, size_t n) {
|
||||
void *res = strndup(s, n);
|
||||
if (!res) die();
|
||||
if (!res) xdie();
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,6 @@
|
|||
*/
|
||||
void *xvalloc(size_t size) {
|
||||
void *res = valloc(size);
|
||||
if (!res) die();
|
||||
if (!res) xdie();
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,6 @@
|
|||
*/
|
||||
char *(xvasprintf)(const char *fmt, va_list va) {
|
||||
char *buf;
|
||||
if ((vasprintf)(&buf, fmt, va) == -1) die();
|
||||
if ((vasprintf)(&buf, fmt, va) == -1) xdie();
|
||||
return buf;
|
||||
}
|
||||
|
|
68
libc/zip.h
68
libc/zip.h
|
@ -81,41 +81,41 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/* end of central directory record */
|
||||
#define ZIP_CDIR_MAGIC(P) read32le(P)
|
||||
#define ZIP_CDIR_DISK(P) read16le((P) + 4)
|
||||
#define ZIP_CDIR_STARTINGDISK(P) read16le((P) + 6)
|
||||
#define ZIP_CDIR_RECORDSONDISK(P) read16le((P) + 8)
|
||||
#define ZIP_CDIR_RECORDS(P) read16le((P) + 10)
|
||||
#define ZIP_CDIR_SIZE(P) read32le((P) + 12)
|
||||
#define ZIP_CDIR_OFFSET(P) read32le((P) + 16)
|
||||
#define ZIP_CDIR_COMMENTSIZE(P) read16le((P) + 20)
|
||||
#define ZIP_CDIR_MAGIC(P) READ32LE(P)
|
||||
#define ZIP_CDIR_DISK(P) READ16LE((P) + 4)
|
||||
#define ZIP_CDIR_STARTINGDISK(P) READ16LE((P) + 6)
|
||||
#define ZIP_CDIR_RECORDSONDISK(P) READ16LE((P) + 8)
|
||||
#define ZIP_CDIR_RECORDS(P) READ16LE((P) + 10)
|
||||
#define ZIP_CDIR_SIZE(P) READ32LE((P) + 12)
|
||||
#define ZIP_CDIR_OFFSET(P) READ32LE((P) + 16)
|
||||
#define ZIP_CDIR_COMMENTSIZE(P) READ16LE((P) + 20)
|
||||
#define ZIP_CDIR_COMMENT(P) (&(P)[22])
|
||||
#define ZIP_CDIR_HDRSIZE(P) (ZIP_CDIR_COMMENTSIZE(P) + kZipCdirHdrMinSize)
|
||||
|
||||
/* central directory file header */
|
||||
#define ZIP_CFILE_MAGIC(P) read32le(P)
|
||||
#define ZIP_CFILE_MAGIC(P) READ32LE(P)
|
||||
#define ZIP_CFILE_VERSIONMADE(P) ((P)[4])
|
||||
#define ZIP_CFILE_FILEATTRCOMPAT(P) ((P)[5])
|
||||
#define ZIP_CFILE_VERSIONNEED(P) ((P)[6])
|
||||
#define ZIP_CFILE_OSNEED(P) ((P)[7])
|
||||
#define ZIP_CFILE_GENERALFLAG(P) read16le((P) + kZipCfileOffsetGeneralflag)
|
||||
#define ZIP_CFILE_GENERALFLAG(P) READ16LE((P) + kZipCfileOffsetGeneralflag)
|
||||
#define ZIP_CFILE_COMPRESSIONMETHOD(P) \
|
||||
read16le((P) + kZipCfileOffsetCompressionmethod)
|
||||
READ16LE((P) + kZipCfileOffsetCompressionmethod)
|
||||
#define ZIP_CFILE_LASTMODIFIEDTIME(P) \
|
||||
read16le((P) + kZipCfileOffsetLastmodifiedtime) /* @see DOS_TIME() */
|
||||
READ16LE((P) + kZipCfileOffsetLastmodifiedtime) /* @see DOS_TIME() */
|
||||
#define ZIP_CFILE_LASTMODIFIEDDATE(P) \
|
||||
read16le((P) + kZipCfileOffsetLastmodifieddate) /* @see DOS_DATE() */
|
||||
#define ZIP_CFILE_CRC32(P) read32le((P) + kZipCfileOffsetCrc32)
|
||||
READ16LE((P) + kZipCfileOffsetLastmodifieddate) /* @see DOS_DATE() */
|
||||
#define ZIP_CFILE_CRC32(P) READ32LE((P) + kZipCfileOffsetCrc32)
|
||||
#define ZIP_CFILE_COMPRESSEDSIZE(P) READ32LE(P + kZipCfileOffsetCompressedsize)
|
||||
#define ZIP_CFILE_UNCOMPRESSEDSIZE(P) read32le((P) + 24)
|
||||
#define ZIP_CFILE_NAMESIZE(P) read16le((P) + 28)
|
||||
#define ZIP_CFILE_EXTRASIZE(P) read16le((P) + 30)
|
||||
#define ZIP_CFILE_COMMENTSIZE(P) read16le((P) + 32)
|
||||
#define ZIP_CFILE_DISK(P) read16le((P) + 34)
|
||||
#define ZIP_CFILE_INTERNALATTRIBUTES(P) read16le((P) + 36)
|
||||
#define ZIP_CFILE_UNCOMPRESSEDSIZE(P) READ32LE((P) + 24)
|
||||
#define ZIP_CFILE_NAMESIZE(P) READ16LE((P) + 28)
|
||||
#define ZIP_CFILE_EXTRASIZE(P) READ16LE((P) + 30)
|
||||
#define ZIP_CFILE_COMMENTSIZE(P) READ16LE((P) + 32)
|
||||
#define ZIP_CFILE_DISK(P) READ16LE((P) + 34)
|
||||
#define ZIP_CFILE_INTERNALATTRIBUTES(P) READ16LE((P) + 36)
|
||||
#define ZIP_CFILE_EXTERNALATTRIBUTES(P) \
|
||||
read32le((P) + kZipCfileOffsetExternalattributes)
|
||||
#define ZIP_CFILE_OFFSET(P) read32le((P) + kZipCfileOffsetOffset)
|
||||
READ32LE((P) + kZipCfileOffsetExternalattributes)
|
||||
#define ZIP_CFILE_OFFSET(P) READ32LE((P) + kZipCfileOffsetOffset)
|
||||
#define ZIP_CFILE_NAME(P) ((const char *)(&(P)[46])) /* not nul-terminated */
|
||||
#define ZIP_CFILE_EXTRA(P) (&(P)[46 + ZIP_CFILE_NAMESIZE(P)])
|
||||
#define ZIP_CFILE_COMMENT(P) \
|
||||
|
@ -125,22 +125,22 @@
|
|||
kZipCfileHdrMinSize)
|
||||
|
||||
/* central directory file header */
|
||||
#define ZIP_LFILE_MAGIC(P) read32le(P)
|
||||
#define ZIP_LFILE_MAGIC(P) READ32LE(P)
|
||||
#define ZIP_LFILE_VERSIONNEED(P) ((P)[4])
|
||||
#define ZIP_LFILE_OSNEED(P) ((P)[5])
|
||||
#define ZIP_LFILE_GENERALFLAG(P) read16le((P) + kZipLfileOffsetGeneralflag)
|
||||
#define ZIP_LFILE_GENERALFLAG(P) READ16LE((P) + kZipLfileOffsetGeneralflag)
|
||||
#define ZIP_LFILE_COMPRESSIONMETHOD(P) \
|
||||
read16le((P) + kZipLfileOffsetCompressionmethod)
|
||||
READ16LE((P) + kZipLfileOffsetCompressionmethod)
|
||||
#define ZIP_LFILE_LASTMODIFIEDTIME(P) \
|
||||
read16le((P) + kZipLfileOffsetLastmodifiedtime) /* @see DOS_TIME() */
|
||||
READ16LE((P) + kZipLfileOffsetLastmodifiedtime) /* @see DOS_TIME() */
|
||||
#define ZIP_LFILE_LASTMODIFIEDDATE(P) \
|
||||
read16le((P) + kZipLfileOffsetLastmodifieddate) /* @see DOS_DATE() */
|
||||
#define ZIP_LFILE_CRC32(P) read32le((P) + kZipLfileOffsetCrc32)
|
||||
READ16LE((P) + kZipLfileOffsetLastmodifieddate) /* @see DOS_DATE() */
|
||||
#define ZIP_LFILE_CRC32(P) READ32LE((P) + kZipLfileOffsetCrc32)
|
||||
#define ZIP_LFILE_COMPRESSEDSIZE(P) \
|
||||
read32le((P) + kZipLfileOffsetCompressedsize)
|
||||
#define ZIP_LFILE_UNCOMPRESSEDSIZE(P) read32le((P) + 22)
|
||||
#define ZIP_LFILE_NAMESIZE(P) read16le((P) + 26)
|
||||
#define ZIP_LFILE_EXTRASIZE(P) read16le((P) + 28)
|
||||
READ32LE((P) + kZipLfileOffsetCompressedsize)
|
||||
#define ZIP_LFILE_UNCOMPRESSEDSIZE(P) READ32LE((P) + 22)
|
||||
#define ZIP_LFILE_NAMESIZE(P) READ16LE((P) + 26)
|
||||
#define ZIP_LFILE_EXTRASIZE(P) READ16LE((P) + 28)
|
||||
#define ZIP_LFILE_NAME(P) ((const char *)(&(P)[30]))
|
||||
#define ZIP_LFILE_EXTRA(P) (&(P)[30 + ZIP_LFILE_NAMESIZE(P)])
|
||||
#define ZIP_LFILE_HDRSIZE(P) \
|
||||
|
@ -148,8 +148,8 @@
|
|||
#define ZIP_LFILE_CONTENT(P) ((P) + ZIP_LFILE_HDRSIZE(P))
|
||||
#define ZIP_LFILE_SIZE(P) (ZIP_LFILE_HDRSIZE(P) + ZIP_LFILE_COMPRESSEDSIZE(P))
|
||||
|
||||
#define ZIP_EXTRA_HEADERID(P) read16le(P)
|
||||
#define ZIP_EXTRA_CONTENTSIZE(P) read16le((P) + 2)
|
||||
#define ZIP_EXTRA_HEADERID(P) READ16LE(P)
|
||||
#define ZIP_EXTRA_CONTENTSIZE(P) READ16LE((P) + 2)
|
||||
#define ZIP_EXTRA_CONTENT(P) (&(P)[4])
|
||||
#define ZIP_EXTRA_SIZE(P) (ZIP_EXTRA_CONTENTSIZE(P) + kZipExtraHdrSize)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue