mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Get Fat Emacs working on Apple Silicon
This commit is contained in:
parent
3f9b39883f
commit
bf835de612
14 changed files with 294 additions and 144 deletions
135
ape/ape-m1.c
135
ape/ape-m1.c
|
@ -50,7 +50,7 @@ struct Syslib {
|
|||
void *);
|
||||
void (*pthread_exit)(void *);
|
||||
int (*pthread_kill)(pthread_t, int);
|
||||
int (*pthread_sigmask)(int, const sigset_t *restrict, sigset_t *restrict);
|
||||
int (*pthread_sigmask)(int, const sigset_t *, sigset_t *);
|
||||
int (*pthread_setname_np)(const char *);
|
||||
dispatch_semaphore_t (*dispatch_semaphore_create)(long);
|
||||
long (*dispatch_semaphore_signal)(dispatch_semaphore_t);
|
||||
|
@ -399,26 +399,24 @@ static char *Commandv(struct PathSearcher *ps, const char *name,
|
|||
static void pthread_jit_write_protect_np_workaround(int enabled) {
|
||||
int count_start = 8192;
|
||||
volatile int count = count_start;
|
||||
unsigned long *addr, *other, val, val2, reread = -1;
|
||||
unsigned long *addr, val, val2, reread = -1;
|
||||
addr = (unsigned long *)(!enabled ? _COMM_PAGE_APRR_WRITE_ENABLE
|
||||
: _COMM_PAGE_APRR_WRITE_DISABLE);
|
||||
other = (unsigned long *)(enabled ? _COMM_PAGE_APRR_WRITE_ENABLE
|
||||
: _COMM_PAGE_APRR_WRITE_DISABLE);
|
||||
switch (*(volatile unsigned char *)_COMM_PAGE_APRR_SUPPORT) {
|
||||
case 1:
|
||||
do {
|
||||
val = *addr;
|
||||
reread = -1;
|
||||
asm volatile("msr\tS3_4_c15_c2_7,%0\n"
|
||||
"isb\tsy\n"
|
||||
: /* no outputs */
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
__asm__ volatile("msr\tS3_4_c15_c2_7,%0\n"
|
||||
"isb\tsy\n"
|
||||
: /* no outputs */
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
val2 = *addr;
|
||||
asm volatile("mrs\t%0,S3_4_c15_c2_7\n"
|
||||
: "=r"(reread)
|
||||
: /* no inputs */
|
||||
: "memory");
|
||||
__asm__ volatile("mrs\t%0,S3_4_c15_c2_7\n"
|
||||
: "=r"(reread)
|
||||
: /* no inputs */
|
||||
: "memory");
|
||||
if (val2 == reread) {
|
||||
return;
|
||||
}
|
||||
|
@ -429,16 +427,16 @@ static void pthread_jit_write_protect_np_workaround(int enabled) {
|
|||
do {
|
||||
val = *addr;
|
||||
reread = -1;
|
||||
asm volatile("msr\tS3_6_c15_c1_5,%0\n"
|
||||
"isb\tsy\n"
|
||||
: /* no outputs */
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
__asm__ volatile("msr\tS3_6_c15_c1_5,%0\n"
|
||||
"isb\tsy\n"
|
||||
: /* no outputs */
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
val2 = *addr;
|
||||
asm volatile("mrs\t%0,S3_6_c15_c1_5\n"
|
||||
: "=r"(reread)
|
||||
: /* no inputs */
|
||||
: "memory");
|
||||
__asm__ volatile("mrs\t%0,S3_6_c15_c1_5\n"
|
||||
: "=r"(reread)
|
||||
: /* no inputs */
|
||||
: "memory");
|
||||
if (val2 == reread) {
|
||||
return;
|
||||
}
|
||||
|
@ -595,42 +593,42 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
|||
/* finish up */
|
||||
close(fd);
|
||||
|
||||
register long *x0 asm("x0") = sp;
|
||||
register struct Syslib *x15 asm("x15") = lib;
|
||||
register long x16 asm("x16") = e->e_entry;
|
||||
asm volatile("mov\tx1,#0\n\t"
|
||||
"mov\tx2,#0\n\t"
|
||||
"mov\tx3,#0\n\t"
|
||||
"mov\tx4,#0\n\t"
|
||||
"mov\tx5,#0\n\t"
|
||||
"mov\tx6,#0\n\t"
|
||||
"mov\tx7,#0\n\t"
|
||||
"mov\tx8,#0\n\t"
|
||||
"mov\tx9,#0\n\t"
|
||||
"mov\tx10,#0\n\t"
|
||||
"mov\tx11,#0\n\t"
|
||||
"mov\tx12,#0\n\t"
|
||||
"mov\tx13,#0\n\t"
|
||||
"mov\tx14,#0\n\t"
|
||||
"mov\tx17,#0\n\t"
|
||||
"mov\tx19,#0\n\t"
|
||||
"mov\tx20,#0\n\t"
|
||||
"mov\tx21,#0\n\t"
|
||||
"mov\tx22,#0\n\t"
|
||||
"mov\tx23,#0\n\t"
|
||||
"mov\tx24,#0\n\t"
|
||||
"mov\tx25,#0\n\t"
|
||||
"mov\tx26,#0\n\t"
|
||||
"mov\tx27,#0\n\t"
|
||||
"mov\tx28,#0\n\t"
|
||||
"mov\tx29,#0\n\t"
|
||||
"mov\tx30,#0\n\t"
|
||||
"mov\tsp,x0\n\t"
|
||||
"mov\tx0,#0\n\t"
|
||||
"br\tx16"
|
||||
: /* no outputs */
|
||||
: "r"(x0), "r"(x15), "r"(x16)
|
||||
: "memory");
|
||||
register long *x0 __asm__("x0") = sp;
|
||||
register struct Syslib *x15 __asm__("x15") = lib;
|
||||
register long x16 __asm__("x16") = e->e_entry;
|
||||
__asm__ volatile("mov\tx1,#0\n\t"
|
||||
"mov\tx2,#0\n\t"
|
||||
"mov\tx3,#0\n\t"
|
||||
"mov\tx4,#0\n\t"
|
||||
"mov\tx5,#0\n\t"
|
||||
"mov\tx6,#0\n\t"
|
||||
"mov\tx7,#0\n\t"
|
||||
"mov\tx8,#0\n\t"
|
||||
"mov\tx9,#0\n\t"
|
||||
"mov\tx10,#0\n\t"
|
||||
"mov\tx11,#0\n\t"
|
||||
"mov\tx12,#0\n\t"
|
||||
"mov\tx13,#0\n\t"
|
||||
"mov\tx14,#0\n\t"
|
||||
"mov\tx17,#0\n\t"
|
||||
"mov\tx19,#0\n\t"
|
||||
"mov\tx20,#0\n\t"
|
||||
"mov\tx21,#0\n\t"
|
||||
"mov\tx22,#0\n\t"
|
||||
"mov\tx23,#0\n\t"
|
||||
"mov\tx24,#0\n\t"
|
||||
"mov\tx25,#0\n\t"
|
||||
"mov\tx26,#0\n\t"
|
||||
"mov\tx27,#0\n\t"
|
||||
"mov\tx28,#0\n\t"
|
||||
"mov\tx29,#0\n\t"
|
||||
"mov\tx30,#0\n\t"
|
||||
"mov\tsp,x0\n\t"
|
||||
"mov\tx0,#0\n\t"
|
||||
"br\tx16"
|
||||
: /* no outputs */
|
||||
: "r"(x0), "r"(x15), "r"(x16)
|
||||
: "memory");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
|
@ -769,7 +767,7 @@ static long sys_pipe(int pfds[2]) {
|
|||
}
|
||||
|
||||
static long sys_clock_gettime(int clock, struct timespec *ts) {
|
||||
return sysret(clock_gettime(clock, ts));
|
||||
return sysret(clock_gettime((clockid_t)clock, ts));
|
||||
}
|
||||
|
||||
static long sys_nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
|
@ -782,17 +780,16 @@ static long sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
|
|||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
long z;
|
||||
void *map;
|
||||
int c, i, n, fd, rc;
|
||||
unsigned i;
|
||||
int c, n, fd, rc;
|
||||
struct ApeLoader *M;
|
||||
long *sp, *sp2, *auxv;
|
||||
union ElfEhdrBuf *ebuf;
|
||||
char *p, *pe, *tp, *exe, *prog, *execfn;
|
||||
char *p, *pe, *exe, *prog, *execfn;
|
||||
|
||||
/* allocate loader memory in program's arg block */
|
||||
n = sizeof(struct ApeLoader);
|
||||
M = __builtin_alloca(n);
|
||||
M = (struct ApeLoader *)__builtin_alloca(n);
|
||||
|
||||
/* expose apple libs */
|
||||
M->lib.magic = SYSLIB_MAGIC;
|
||||
|
@ -839,7 +836,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
} else if (argc < 2) {
|
||||
Emit("usage: ape PROG [ARGV1,ARGV2,...]\n"
|
||||
" ape - PROG [ARGV0,ARGV1,...]\n"
|
||||
"actually portable executable loader silicon 1.6\n"
|
||||
"actually portable executable loader silicon 1.7\n"
|
||||
"copyright 2023 justine alexandra roberts tunney\n"
|
||||
"https://justine.lol/ape.html\n");
|
||||
_exit(1);
|
||||
|
@ -853,7 +850,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
system v abi aligns this on a 16-byte boundary
|
||||
grows down the alloc by poking the guard pages */
|
||||
n = (auxv - sp + AUXV_WORDS + 1) * sizeof(long);
|
||||
sp2 = __builtin_alloca(n);
|
||||
sp2 = (long *)__builtin_alloca(n);
|
||||
if ((long)sp2 & 15) ++sp2;
|
||||
for (; n > 0; n -= pagesz) {
|
||||
((char *)sp2)[n - 1] = 0;
|
||||
|
@ -866,7 +863,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
|
||||
/* allocate ephemeral memory for reading file */
|
||||
n = sizeof(union ElfEhdrBuf);
|
||||
ebuf = __builtin_alloca(n);
|
||||
ebuf = (union ElfEhdrBuf *)__builtin_alloca(n);
|
||||
for (; n > 0; n -= pagesz) {
|
||||
((char *)ebuf)[n - 1] = 0;
|
||||
}
|
||||
|
@ -886,9 +883,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
/* resolve argv[0] to reflect path search */
|
||||
if ((argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
|
||||
!StrCmp(BaseName(prog), argv[0])) {
|
||||
tp -= (n = StrLen(exe) + 1);
|
||||
MemMove(tp, exe, n);
|
||||
argv[0] = tp;
|
||||
argv[0] = exe;
|
||||
}
|
||||
|
||||
/* generate some hard random data */
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "libc/runtime/pc.internal.h"
|
||||
#include "ape/ape.internal.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "ape/ape.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
#define USE_SYMBOL_HACK 1
|
||||
|
@ -610,7 +611,9 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
|||
// extract the loader into a temp folder, and use it to
|
||||
// load the APE without modifying it.
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.7\"\n"
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-"
|
||||
.ascii APE_VERSION_STR
|
||||
.ascii "\"\n"
|
||||
.ascii "[ -x \"$t\" ] || {\n"
|
||||
.ascii "mkdir -p \"${t%/*}\" &&\n"
|
||||
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
|
||||
|
@ -818,7 +821,7 @@ ape.ident:
|
|||
.long 1
|
||||
1: .asciz "APE"
|
||||
2: .balign 4
|
||||
3: .long 107000000
|
||||
3: .long APE_VERSION_NOTE
|
||||
4: .size ape.ident,.-ape.ident
|
||||
.type ape.ident,@object
|
||||
.previous
|
||||
|
|
13
ape/ape.h
Normal file
13
ape/ape.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef COSMOPOLITAN_APE_APE_H_
|
||||
#define COSMOPOLITAN_APE_APE_H_
|
||||
|
||||
#define APE_VERSION_MAJOR 1
|
||||
#define APE_VERSION_MINOR 7
|
||||
#define APE_VERSION_STR APE_VERSION_STR_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
|
||||
#define APE_VERSION_NOTE APE_VERSION_NOTE_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
|
||||
|
||||
#define APE_VERSION_STR__(x, y) #x "." #y
|
||||
#define APE_VERSION_STR_(x, y) APE_VERSION_STR__(x, y)
|
||||
#define APE_VERSION_NOTE_(x, y) (100000000 * (x) + 1000000 * (y))
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_APE_H_ */
|
|
@ -88,7 +88,7 @@ o/$(MODE)/ape/ape.elf.dbg: \
|
|||
o/$(MODE)/ape/systemcall.o
|
||||
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
||||
|
||||
o/$(MODE)/ape/loader.o: ape/loader.c
|
||||
o/$(MODE)/ape/loader.o: ape/loader.c ape/ape.h
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/start.o: ape/start.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
@ -130,6 +130,8 @@ APE_LOADER_FLAGS = \
|
|||
-iquote. \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Werror \
|
||||
-pedantic-errors \
|
||||
-fpie \
|
||||
-Os \
|
||||
-ffreestanding \
|
||||
|
@ -153,6 +155,7 @@ o/ape/idata.inc: \
|
|||
|
||||
o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
ape/ape.S \
|
||||
ape/ape.h \
|
||||
ape/macros.internal.h \
|
||||
ape/notice.inc \
|
||||
ape/relocations.h \
|
||||
|
@ -183,6 +186,7 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
|
|||
|
||||
o/$(MODE)/ape/ape-copy-self.o: \
|
||||
ape/ape.S \
|
||||
ape/ape.h \
|
||||
ape/macros.internal.h \
|
||||
ape/notice.inc \
|
||||
ape/relocations.h \
|
||||
|
|
29
ape/loader.c
29
ape/loader.c
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/ape.h"
|
||||
|
||||
/**
|
||||
* @fileoverview APE Loader for GNU/Systemd/XNU/FreeBSD/NetBSD/OpenBSD
|
||||
|
@ -104,6 +105,12 @@
|
|||
#define IsAarch64() 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C extern "C"
|
||||
#else
|
||||
#define EXTERN_C
|
||||
#endif
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
|
@ -213,8 +220,8 @@ struct ApeLoader {
|
|||
char path[1024];
|
||||
};
|
||||
|
||||
long SystemCall(long, long, long, long, long, long, long, int);
|
||||
void Launch(void *, long, void *, int) __attribute__((__noreturn__));
|
||||
EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
|
||||
EXTERN_C void Launch(void *, long, void *, int) __attribute__((__noreturn__));
|
||||
|
||||
extern char __executable_start[];
|
||||
extern char _end[];
|
||||
|
@ -882,11 +889,11 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
|||
Spawn(os, exe, fd, sp, pagesz, e, p);
|
||||
}
|
||||
|
||||
static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) {
|
||||
__attribute__((__noreturn__)) static void ShowUsage(int os, int fd, int rc) {
|
||||
Print(os, fd,
|
||||
"NAME\n"
|
||||
"\n"
|
||||
" actually portable executable loader version 1.7\n"
|
||||
" actually portable executable loader version " APE_VERSION_STR "\n"
|
||||
" copyright 2023 justine alexandra roberts tunney\n"
|
||||
" https://justine.lol/ape.html\n"
|
||||
"\n"
|
||||
|
@ -904,15 +911,17 @@ static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) {
|
|||
Exit(rc, os);
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
||||
EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||
char dl) {
|
||||
int rc, n;
|
||||
unsigned i;
|
||||
const char *ape;
|
||||
int c, fd, os, argc;
|
||||
struct ApeLoader *M;
|
||||
unsigned long pagesz;
|
||||
union ElfEhdrBuf *ebuf;
|
||||
long *auxv, *ap, *endp, *sp2;
|
||||
char *p, *pe, *exe, *ape, *prog, **argv, **envp;
|
||||
char *p, *pe, *exe, *prog, **argv, **envp;
|
||||
|
||||
(void)Utox;
|
||||
|
||||
|
@ -999,13 +1008,13 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
|
||||
/* allocate loader memory in program's arg block */
|
||||
n = sizeof(struct ApeLoader);
|
||||
M = __builtin_alloca(n);
|
||||
M = (struct ApeLoader *)__builtin_alloca(n);
|
||||
|
||||
/* create new bottom of stack for spawned program
|
||||
system v abi aligns this on a 16-byte boundary
|
||||
grows down the alloc by poking the guard pages */
|
||||
n = (endp - sp + 1) * sizeof(long);
|
||||
sp2 = __builtin_alloca(n);
|
||||
sp2 = (long *)__builtin_alloca(n);
|
||||
if ((long)sp2 & 15) ++sp2;
|
||||
for (; n > 0; n -= pagesz) {
|
||||
((char *)sp2)[n - 1] = 0;
|
||||
|
@ -1013,12 +1022,12 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
MemMove(sp2, sp, (endp - sp) * sizeof(long));
|
||||
argv = (char **)(sp2 + 1);
|
||||
envp = (char **)(sp2 + 1 + argc + 1);
|
||||
auxv = (char **)(sp2 + (auxv - sp));
|
||||
auxv = sp2 + (auxv - sp);
|
||||
sp = sp2;
|
||||
|
||||
/* allocate ephemeral memory for reading file */
|
||||
n = sizeof(union ElfEhdrBuf);
|
||||
ebuf = __builtin_alloca(n);
|
||||
ebuf = (union ElfEhdrBuf *)__builtin_alloca(n);
|
||||
for (; n > 0; n -= pagesz) {
|
||||
((char *)ebuf)[n - 1] = 0;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "ape/ape.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
#ifdef __aarch64__
|
||||
|
@ -64,7 +65,7 @@ ape.ident:
|
|||
.long 1
|
||||
1: .asciz "APE"
|
||||
2: .balign 4
|
||||
3: .long 107000000
|
||||
3: .long APE_VERSION_NOTE
|
||||
4: .size ape.ident,.-ape.ident
|
||||
.type ape.ident,@object
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/ape.h"
|
||||
#include "libc/calls/blockcancel.internal.h"
|
||||
#include "libc/calls/blocksigs.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
@ -85,9 +86,9 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
|
|||
(CanExecute((ape = "/usr/bin/ape")) ||
|
||||
CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"),
|
||||
firstnonnull(getenv("HOME"), ".")),
|
||||
".ape-1.7", buf))) ||
|
||||
CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."), ".ape-1.7",
|
||||
buf))))) {
|
||||
".ape-" APE_VERSION_STR, buf))) ||
|
||||
CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."),
|
||||
".ape-" APE_VERSION_STR, buf))))) {
|
||||
shargs[0] = ape;
|
||||
shargs[1] = "-";
|
||||
shargs[2] = prog;
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zip.internal.h"
|
||||
|
||||
|
@ -43,7 +44,12 @@ int __zipos_access(struct ZiposUri *name, int amode) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int mode = GetZipCfileMode(z->map + cf);
|
||||
int mode;
|
||||
if (cf != ZIPOS_SYNTHETIC_DIRECTORY) {
|
||||
mode = GetZipCfileMode(z->map + cf);
|
||||
} else {
|
||||
mode = S_IFDIR | 0555;
|
||||
}
|
||||
if (amode == F_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -33,16 +33,28 @@ static int64_t __zipos_lseek_impl(struct ZiposHandle *h, int64_t offset,
|
|||
}
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
return offset;
|
||||
if (offset >= 0) {
|
||||
return offset;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
case SEEK_CUR:
|
||||
if (!ckd_add(&pos, h->pos, offset)) {
|
||||
return pos;
|
||||
if (pos >= 0) {
|
||||
return pos;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else {
|
||||
return eoverflow();
|
||||
}
|
||||
case SEEK_END:
|
||||
if (!ckd_sub(&pos, h->size, offset)) {
|
||||
return pos;
|
||||
if (pos >= 0) {
|
||||
return pos;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else {
|
||||
return eoverflow();
|
||||
}
|
||||
|
@ -61,7 +73,6 @@ static int64_t __zipos_lseek_impl(struct ZiposHandle *h, int64_t offset,
|
|||
*/
|
||||
int64_t __zipos_lseek(struct ZiposHandle *h, int64_t offset, unsigned whence) {
|
||||
int64_t pos;
|
||||
if (offset < 0) return einval();
|
||||
pthread_mutex_lock(&h->lock);
|
||||
if ((pos = __zipos_lseek_impl(h, offset, whence)) != -1) {
|
||||
h->pos = pos;
|
||||
|
|
|
@ -12,62 +12,62 @@ LIBC_TIME_A_HDRS := $(filter %.h,$(LIBC_TIME_A_FILES))
|
|||
LIBC_TIME_A_SRCS_S = $(filter %.S,$(LIBC_TIME_A_FILES))
|
||||
LIBC_TIME_A_SRCS_C = $(filter %.c,$(LIBC_TIME_A_FILES))
|
||||
|
||||
LIBC_TIME_A_SRCS = \
|
||||
$(LIBC_TIME_A_SRCS_S) \
|
||||
LIBC_TIME_A_SRCS = \
|
||||
$(LIBC_TIME_A_SRCS_S) \
|
||||
$(LIBC_TIME_A_SRCS_C)
|
||||
|
||||
LIBC_TIME_A_OBJS = \
|
||||
o/$(MODE)/usr/share/zoneinfo/.zip.o \
|
||||
$(LIBC_TIME_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(LIBC_TIME_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(LIBC_TIME_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(LIBC_TIME_ZONEINFOS:%=o/$(MODE)/%.zip.o)
|
||||
LIBC_TIME_A_OBJS = \
|
||||
$(LIBC_TIME_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(LIBC_TIME_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(LIBC_TIME_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(LIBC_TIME_ZONEINFOS:%=o/$(MODE)/%.zip.o) \
|
||||
o/$(MODE)/usr/share/zoneinfo/.zip.o
|
||||
|
||||
LIBC_TIME_A_CHECKS = \
|
||||
$(LIBC_TIME_A).pkg \
|
||||
LIBC_TIME_A_CHECKS = \
|
||||
$(LIBC_TIME_A).pkg \
|
||||
$(LIBC_TIME_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_TIME_A_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_TIME_A_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
THIRD_PARTY_COMPILER_RT
|
||||
|
||||
LIBC_TIME_A_DEPS := \
|
||||
LIBC_TIME_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_TIME_A): libc/time/ \
|
||||
$(LIBC_TIME_A).pkg \
|
||||
$(LIBC_TIME_A): libc/time/ \
|
||||
$(LIBC_TIME_A).pkg \
|
||||
$(LIBC_TIME_A_OBJS)
|
||||
|
||||
$(LIBC_TIME_A).pkg: \
|
||||
$(LIBC_TIME_A_OBJS) \
|
||||
$(LIBC_TIME_A).pkg: \
|
||||
$(LIBC_TIME_A_OBJS) \
|
||||
$(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/time/strftime.o: private \
|
||||
CFLAGS += \
|
||||
o/$(MODE)/libc/time/strftime.o: private \
|
||||
CFLAGS += \
|
||||
-fno-jump-tables
|
||||
|
||||
o/$(MODE)/libc/time/localtime.o: private \
|
||||
CFLAGS += \
|
||||
-fdata-sections \
|
||||
o/$(MODE)/libc/time/localtime.o: private \
|
||||
CFLAGS += \
|
||||
-fdata-sections \
|
||||
-ffunction-sections
|
||||
|
||||
# we need -O3 because:
|
||||
# we're dividing by constants
|
||||
o/$(MODE)/libc/time/iso8601.o \
|
||||
o/$(MODE)/libc/time/iso8601us.o: private \
|
||||
CFLAGS += \
|
||||
o/$(MODE)/libc/time/iso8601.o \
|
||||
o/$(MODE)/libc/time/iso8601us.o: private \
|
||||
CFLAGS += \
|
||||
-O3
|
||||
|
||||
o/$(MODE)/usr/share/zoneinfo/.zip.o: \
|
||||
o/$(MODE)/usr/share/zoneinfo/.zip.o: \
|
||||
usr/share/zoneinfo
|
||||
|
||||
o/$(MODE)/libc/time/kmonthname.o: libc/time/kmonthname.S
|
||||
|
|
|
@ -69,10 +69,12 @@ TEST(zipos, enoent) {
|
|||
TEST(zipos, readPastEof) {
|
||||
char buf[512];
|
||||
ASSERT_SYS(0, 3, open("/zip/libc/testlib/hyperion.txt", O_RDONLY));
|
||||
EXPECT_SYS(EINVAL, -1, lseek(3, -1, SEEK_CUR));
|
||||
EXPECT_SYS(EINVAL, -1, lseek(3, -1, SEEK_SET));
|
||||
EXPECT_SYS(EINVAL, -1, pread(3, buf, 512, UINT64_MAX));
|
||||
EXPECT_SYS(0, 0, pread(3, buf, 512, INT64_MAX));
|
||||
EXPECT_SYS(EINVAL, -1, lseek(3, UINT64_MAX, SEEK_SET));
|
||||
EXPECT_SYS(0, INT64_MAX, lseek(3, INT64_MAX, SEEK_SET));
|
||||
EXPECT_SYS(EOVERFLOW, -1, lseek(3, 2, SEEK_CUR));
|
||||
EXPECT_SYS(EBADF, -1, write(3, buf, 512));
|
||||
EXPECT_SYS(EBADF, -1, pwrite(3, buf, 512, 0));
|
||||
EXPECT_SYS(0, 0, read(3, buf, 512));
|
||||
|
@ -92,3 +94,15 @@ TEST(zipos, trailingComponents_willEnodirFile) {
|
|||
ASSERT_SYS(ENOTDIR, -1, open("/zip/libc/testlib/hyperion.txt/a/b", O_RDONLY));
|
||||
ASSERT_SYS(ENOTDIR, -1, stat("/zip/libc/testlib/hyperion.txt/", &st));
|
||||
}
|
||||
|
||||
TEST(zipos, lseek) {
|
||||
char b1[512], b2[512];
|
||||
ASSERT_SYS(0, 3, open("/zip/libc/testlib/hyperion.txt", O_RDONLY));
|
||||
EXPECT_SYS(0, 512, pread(3, b2, 512, 512 - 200));
|
||||
EXPECT_SYS(0, 512, read(3, b1, 512));
|
||||
EXPECT_SYS(0, 512, lseek(3, 0, SEEK_CUR));
|
||||
EXPECT_SYS(0, 512 - 200, lseek(3, -200, SEEK_CUR));
|
||||
EXPECT_SYS(0, 512, read(3, b1, 512));
|
||||
EXPECT_EQ(0, memcmp(b1, b2, 512));
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
|
119
third_party/musl/pwd.c
vendored
119
third_party/musl/pwd.c
vendored
|
@ -25,9 +25,14 @@
|
|||
│ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
│ │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/append.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
@ -39,6 +44,57 @@ Copyright 2005-2014 Rich Felker, et. al.\"");
|
|||
asm(".include \"libc/disclaimer.inc\"");
|
||||
/* clang-format off */
|
||||
|
||||
static char *
|
||||
__create_synthetic_passwd_file(void)
|
||||
{
|
||||
int uid, gid;
|
||||
char login[256], cwd[PATH_MAX];
|
||||
char *user, *home, *shell, *res = 0;
|
||||
uid = getuid();
|
||||
gid = getgid();
|
||||
user = getenv("USER");
|
||||
home = getenv("HOME");
|
||||
shell = getenv("SHELL");
|
||||
if (user && strchr(user, ':'))
|
||||
user = 0;
|
||||
if (home && strchr(home, ':'))
|
||||
user = 0;
|
||||
if (shell && strchr(shell, ':'))
|
||||
user = 0;
|
||||
if (!shell)
|
||||
shell = _PATH_BSHELL;
|
||||
if (!user && getlogin_r(login, sizeof(login)) != -1)
|
||||
user = login;
|
||||
if (!home && getcwd(cwd, sizeof(cwd))) {
|
||||
if (!strchr(cwd, ':'))
|
||||
home = cwd;
|
||||
else
|
||||
home = "/";
|
||||
}
|
||||
if (uid)
|
||||
appendf(&res, "root:x:0:0:root:/root:%s\n", shell);
|
||||
if (user && home) {
|
||||
appendf(&res, "%s:x:%d:%d:%s:%s:%s\n",
|
||||
user, uid, gid, user, home, shell);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static FILE *
|
||||
__fopen_passwd(void)
|
||||
{
|
||||
FILE *f;
|
||||
char *s;
|
||||
// MacOS has a fake /etc/passwd file without any user details.
|
||||
if (!IsXnu() && (f = fopen("/etc/passwd", "rbe")))
|
||||
return f;
|
||||
if (!(s = __create_synthetic_passwd_file()))
|
||||
return 0;
|
||||
if (!(f = fmemopen(s, strlen(s), "rb")))
|
||||
free(s);
|
||||
return f;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
atou(char **s)
|
||||
{
|
||||
|
@ -104,7 +160,7 @@ __getpw_a(const char *name, uid_t uid, struct passwd *pw, char **buf,
|
|||
int rv = 0;
|
||||
*res = 0;
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
|
||||
if ((f = fopen("/etc/passwd", "rbe"))) {
|
||||
if ((f = __fopen_passwd())) {
|
||||
while (!(rv = __getpwent_a(f, pw, buf, size, res)) && *res) {
|
||||
if ((name && !strcmp(name, (*res)->pw_name)) ||
|
||||
(!name && (*res)->pw_uid == uid)) {
|
||||
|
@ -167,46 +223,83 @@ static struct GetpwentState {
|
|||
char *line;
|
||||
struct passwd pw;
|
||||
size_t size;
|
||||
} g_getpwent[1];
|
||||
} g_getpwent;
|
||||
|
||||
/**
|
||||
* Closes global handle to password database.
|
||||
*
|
||||
* @see getpwent()
|
||||
*/
|
||||
void
|
||||
endpwent()
|
||||
endpwent(void)
|
||||
{
|
||||
setpwent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewinds global handle to password database.
|
||||
*
|
||||
* @see getpwent()
|
||||
*/
|
||||
void
|
||||
setpwent()
|
||||
setpwent(void)
|
||||
{
|
||||
if (g_getpwent->f) fclose(g_getpwent->f);
|
||||
g_getpwent->f = 0;
|
||||
if (g_getpwent.f)
|
||||
fclose(g_getpwent.f);
|
||||
g_getpwent.f = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next entry in password database.
|
||||
*
|
||||
* @return pointer to entry static memory, or NULL on EOF
|
||||
* @see getpwent()
|
||||
*/
|
||||
struct passwd *
|
||||
getpwent()
|
||||
{
|
||||
struct passwd *res;
|
||||
if (!g_getpwent->f) g_getpwent->f = fopen("/etc/passwd", "rbe");
|
||||
if (!g_getpwent->f) return 0;
|
||||
__getpwent_a(g_getpwent->f, &g_getpwent->pw, &g_getpwent->line,
|
||||
&g_getpwent->size, &res);
|
||||
if (!g_getpwent.f)
|
||||
g_getpwent.f = __fopen_passwd();
|
||||
if (!g_getpwent.f)
|
||||
return 0;
|
||||
__getpwent_a(g_getpwent.f, &g_getpwent.pw, &g_getpwent.line,
|
||||
&g_getpwent.size, &res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns password database entry for user id.
|
||||
*
|
||||
* This is essentially guaranteed to succeed if `uid == getuid()`, since
|
||||
* this implementation will generate an entry based on the environment
|
||||
* if `/etc/passwd` doesn't exist, or is fake (e.g. MacOS).
|
||||
*
|
||||
* @return pointer to passwd entry static memory, or NULL if not found
|
||||
*/
|
||||
struct passwd *
|
||||
getpwuid(uid_t uid)
|
||||
{
|
||||
struct passwd *res;
|
||||
__getpw_a(0, uid, &g_getpwent->pw, &g_getpwent->line, &g_getpwent->size,
|
||||
__getpw_a(0, uid, &g_getpwent.pw, &g_getpwent.line, &g_getpwent.size,
|
||||
&res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns password database entry for user name.
|
||||
*
|
||||
* This is essentially guaranteed to succeed if `uid == getenv("USER")`,
|
||||
* since this implementation will generate an entry based on `environ`
|
||||
* if `/etc/passwd` doesn't exist, or is fake (e.g. MacOS).
|
||||
*
|
||||
* @return pointer to passwd entry static memory, or NULL if not found
|
||||
*/
|
||||
struct passwd *
|
||||
getpwnam(const char *name)
|
||||
{
|
||||
struct passwd *res;
|
||||
__getpw_a(name, 0, &g_getpwent->pw, &g_getpwent->line,
|
||||
&g_getpwent->size, &res);
|
||||
__getpw_a(name, 0, &g_getpwent.pw, &g_getpwent.line,
|
||||
&g_getpwent.size, &res);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/ape.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -1390,7 +1391,7 @@ static char *GenerateElfNotes(char *p) {
|
|||
char *save;
|
||||
save = p = ALIGN(p, 4);
|
||||
noteoff = p - prologue;
|
||||
p = GenerateElfNote(p, "APE", 1, 107000000);
|
||||
p = GenerateElfNote(p, "APE", 1, APE_VERSION_NOTE);
|
||||
if (support_vector & _HOSTOPENBSD) {
|
||||
p = GenerateElfNote(p, "OpenBSD", 1, 0);
|
||||
}
|
||||
|
@ -1941,7 +1942,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
// otherwise try to use the ad-hoc self-extracted loader, securely
|
||||
if (loaders.n) {
|
||||
p = stpcpy(p, "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.7\"\n"
|
||||
p = stpcpy(p, "t=\"${TMPDIR:-${HOME:-.}}/.ape-" APE_VERSION_STR "\"\n"
|
||||
"[ x\"$1\" != x--assimilate ] && "
|
||||
"[ -x \"$t\" ] && "
|
||||
"exec \"$t\" \"$o\" \"$@\"\n");
|
||||
|
|
Loading…
Reference in a new issue