Get Fat Emacs working on Apple Silicon

This commit is contained in:
Justine Tunney 2023-08-17 22:01:42 -07:00
parent 3f9b39883f
commit bf835de612
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
14 changed files with 294 additions and 144 deletions

View file

@ -50,7 +50,7 @@ struct Syslib {
void *); void *);
void (*pthread_exit)(void *); void (*pthread_exit)(void *);
int (*pthread_kill)(pthread_t, int); 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 *); int (*pthread_setname_np)(const char *);
dispatch_semaphore_t (*dispatch_semaphore_create)(long); dispatch_semaphore_t (*dispatch_semaphore_create)(long);
long (*dispatch_semaphore_signal)(dispatch_semaphore_t); 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) { static void pthread_jit_write_protect_np_workaround(int enabled) {
int count_start = 8192; int count_start = 8192;
volatile int count = count_start; 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 addr = (unsigned long *)(!enabled ? _COMM_PAGE_APRR_WRITE_ENABLE
: _COMM_PAGE_APRR_WRITE_DISABLE); : _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) { switch (*(volatile unsigned char *)_COMM_PAGE_APRR_SUPPORT) {
case 1: case 1:
do { do {
val = *addr; val = *addr;
reread = -1; reread = -1;
asm volatile("msr\tS3_4_c15_c2_7,%0\n" __asm__ volatile("msr\tS3_4_c15_c2_7,%0\n"
"isb\tsy\n" "isb\tsy\n"
: /* no outputs */ : /* no outputs */
: "r"(val) : "r"(val)
: "memory"); : "memory");
val2 = *addr; val2 = *addr;
asm volatile("mrs\t%0,S3_4_c15_c2_7\n" __asm__ volatile("mrs\t%0,S3_4_c15_c2_7\n"
: "=r"(reread) : "=r"(reread)
: /* no inputs */ : /* no inputs */
: "memory"); : "memory");
if (val2 == reread) { if (val2 == reread) {
return; return;
} }
@ -429,16 +427,16 @@ static void pthread_jit_write_protect_np_workaround(int enabled) {
do { do {
val = *addr; val = *addr;
reread = -1; reread = -1;
asm volatile("msr\tS3_6_c15_c1_5,%0\n" __asm__ volatile("msr\tS3_6_c15_c1_5,%0\n"
"isb\tsy\n" "isb\tsy\n"
: /* no outputs */ : /* no outputs */
: "r"(val) : "r"(val)
: "memory"); : "memory");
val2 = *addr; val2 = *addr;
asm volatile("mrs\t%0,S3_6_c15_c1_5\n" __asm__ volatile("mrs\t%0,S3_6_c15_c1_5\n"
: "=r"(reread) : "=r"(reread)
: /* no inputs */ : /* no inputs */
: "memory"); : "memory");
if (val2 == reread) { if (val2 == reread) {
return; return;
} }
@ -595,42 +593,42 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
/* finish up */ /* finish up */
close(fd); close(fd);
register long *x0 asm("x0") = sp; register long *x0 __asm__("x0") = sp;
register struct Syslib *x15 asm("x15") = lib; register struct Syslib *x15 __asm__("x15") = lib;
register long x16 asm("x16") = e->e_entry; register long x16 __asm__("x16") = e->e_entry;
asm volatile("mov\tx1,#0\n\t" __asm__ volatile("mov\tx1,#0\n\t"
"mov\tx2,#0\n\t" "mov\tx2,#0\n\t"
"mov\tx3,#0\n\t" "mov\tx3,#0\n\t"
"mov\tx4,#0\n\t" "mov\tx4,#0\n\t"
"mov\tx5,#0\n\t" "mov\tx5,#0\n\t"
"mov\tx6,#0\n\t" "mov\tx6,#0\n\t"
"mov\tx7,#0\n\t" "mov\tx7,#0\n\t"
"mov\tx8,#0\n\t" "mov\tx8,#0\n\t"
"mov\tx9,#0\n\t" "mov\tx9,#0\n\t"
"mov\tx10,#0\n\t" "mov\tx10,#0\n\t"
"mov\tx11,#0\n\t" "mov\tx11,#0\n\t"
"mov\tx12,#0\n\t" "mov\tx12,#0\n\t"
"mov\tx13,#0\n\t" "mov\tx13,#0\n\t"
"mov\tx14,#0\n\t" "mov\tx14,#0\n\t"
"mov\tx17,#0\n\t" "mov\tx17,#0\n\t"
"mov\tx19,#0\n\t" "mov\tx19,#0\n\t"
"mov\tx20,#0\n\t" "mov\tx20,#0\n\t"
"mov\tx21,#0\n\t" "mov\tx21,#0\n\t"
"mov\tx22,#0\n\t" "mov\tx22,#0\n\t"
"mov\tx23,#0\n\t" "mov\tx23,#0\n\t"
"mov\tx24,#0\n\t" "mov\tx24,#0\n\t"
"mov\tx25,#0\n\t" "mov\tx25,#0\n\t"
"mov\tx26,#0\n\t" "mov\tx26,#0\n\t"
"mov\tx27,#0\n\t" "mov\tx27,#0\n\t"
"mov\tx28,#0\n\t" "mov\tx28,#0\n\t"
"mov\tx29,#0\n\t" "mov\tx29,#0\n\t"
"mov\tx30,#0\n\t" "mov\tx30,#0\n\t"
"mov\tsp,x0\n\t" "mov\tsp,x0\n\t"
"mov\tx0,#0\n\t" "mov\tx0,#0\n\t"
"br\tx16" "br\tx16"
: /* no outputs */ : /* no outputs */
: "r"(x0), "r"(x15), "r"(x16) : "r"(x0), "r"(x15), "r"(x16)
: "memory"); : "memory");
__builtin_unreachable(); __builtin_unreachable();
} }
@ -769,7 +767,7 @@ static long sys_pipe(int pfds[2]) {
} }
static long sys_clock_gettime(int clock, struct timespec *ts) { 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) { 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) { int main(int argc, char **argv, char **envp) {
long z; unsigned i;
void *map; int c, n, fd, rc;
int c, i, n, fd, rc;
struct ApeLoader *M; struct ApeLoader *M;
long *sp, *sp2, *auxv; long *sp, *sp2, *auxv;
union ElfEhdrBuf *ebuf; union ElfEhdrBuf *ebuf;
char *p, *pe, *tp, *exe, *prog, *execfn; char *p, *pe, *exe, *prog, *execfn;
/* allocate loader memory in program's arg block */ /* allocate loader memory in program's arg block */
n = sizeof(struct ApeLoader); n = sizeof(struct ApeLoader);
M = __builtin_alloca(n); M = (struct ApeLoader *)__builtin_alloca(n);
/* expose apple libs */ /* expose apple libs */
M->lib.magic = SYSLIB_MAGIC; M->lib.magic = SYSLIB_MAGIC;
@ -839,7 +836,7 @@ int main(int argc, char **argv, char **envp) {
} else if (argc < 2) { } else if (argc < 2) {
Emit("usage: ape PROG [ARGV1,ARGV2,...]\n" Emit("usage: ape PROG [ARGV1,ARGV2,...]\n"
" ape - PROG [ARGV0,ARGV1,...]\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" "copyright 2023 justine alexandra roberts tunney\n"
"https://justine.lol/ape.html\n"); "https://justine.lol/ape.html\n");
_exit(1); _exit(1);
@ -853,7 +850,7 @@ int main(int argc, char **argv, char **envp) {
system v abi aligns this on a 16-byte boundary system v abi aligns this on a 16-byte boundary
grows down the alloc by poking the guard pages */ grows down the alloc by poking the guard pages */
n = (auxv - sp + AUXV_WORDS + 1) * sizeof(long); n = (auxv - sp + AUXV_WORDS + 1) * sizeof(long);
sp2 = __builtin_alloca(n); sp2 = (long *)__builtin_alloca(n);
if ((long)sp2 & 15) ++sp2; if ((long)sp2 & 15) ++sp2;
for (; n > 0; n -= pagesz) { for (; n > 0; n -= pagesz) {
((char *)sp2)[n - 1] = 0; ((char *)sp2)[n - 1] = 0;
@ -866,7 +863,7 @@ int main(int argc, char **argv, char **envp) {
/* allocate ephemeral memory for reading file */ /* allocate ephemeral memory for reading file */
n = sizeof(union ElfEhdrBuf); n = sizeof(union ElfEhdrBuf);
ebuf = __builtin_alloca(n); ebuf = (union ElfEhdrBuf *)__builtin_alloca(n);
for (; n > 0; n -= pagesz) { for (; n > 0; n -= pagesz) {
((char *)ebuf)[n - 1] = 0; ((char *)ebuf)[n - 1] = 0;
} }
@ -886,9 +883,7 @@ int main(int argc, char **argv, char **envp) {
/* resolve argv[0] to reflect path search */ /* resolve argv[0] to reflect path search */
if ((argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) || if ((argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
!StrCmp(BaseName(prog), argv[0])) { !StrCmp(BaseName(prog), argv[0])) {
tp -= (n = StrLen(exe) + 1); argv[0] = exe;
MemMove(tp, exe, n);
argv[0] = tp;
} }
/* generate some hard random data */ /* generate some hard random data */

View file

@ -44,6 +44,7 @@
#include "libc/runtime/pc.internal.h" #include "libc/runtime/pc.internal.h"
#include "ape/ape.internal.h" #include "ape/ape.internal.h"
#include "libc/thread/tls.h" #include "libc/thread/tls.h"
#include "ape/ape.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"
#define USE_SYMBOL_HACK 1 #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 // extract the loader into a temp folder, and use it to
// load the APE without modifying it. // load the APE without modifying it.
.ascii "[ x\"$1\" != x--assimilate ] && {\n" .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 "[ -x \"$t\" ] || {\n"
.ascii "mkdir -p \"${t%/*}\" &&\n" .ascii "mkdir -p \"${t%/*}\" &&\n"
.ascii "dd if=\"$o\" of=\"$t.$$\" skip=" .ascii "dd if=\"$o\" of=\"$t.$$\" skip="
@ -818,7 +821,7 @@ ape.ident:
.long 1 .long 1
1: .asciz "APE" 1: .asciz "APE"
2: .balign 4 2: .balign 4
3: .long 107000000 3: .long APE_VERSION_NOTE
4: .size ape.ident,.-ape.ident 4: .size ape.ident,.-ape.ident
.type ape.ident,@object .type ape.ident,@object
.previous .previous

13
ape/ape.h Normal file
View 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_ */

View file

@ -88,7 +88,7 @@ o/$(MODE)/ape/ape.elf.dbg: \
o/$(MODE)/ape/systemcall.o o/$(MODE)/ape/systemcall.o
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^) @$(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) @$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS)
o/$(MODE)/ape/start.o: ape/start.S o/$(MODE)/ape/start.o: ape/start.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $< @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
@ -130,6 +130,8 @@ APE_LOADER_FLAGS = \
-iquote. \ -iquote. \
-Wall \ -Wall \
-Wextra \ -Wextra \
-Werror \
-pedantic-errors \
-fpie \ -fpie \
-Os \ -Os \
-ffreestanding \ -ffreestanding \
@ -153,6 +155,7 @@ o/ape/idata.inc: \
o/$(MODE)/ape/ape-no-modify-self.o: \ o/$(MODE)/ape/ape-no-modify-self.o: \
ape/ape.S \ ape/ape.S \
ape/ape.h \
ape/macros.internal.h \ ape/macros.internal.h \
ape/notice.inc \ ape/notice.inc \
ape/relocations.h \ ape/relocations.h \
@ -183,6 +186,7 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
o/$(MODE)/ape/ape-copy-self.o: \ o/$(MODE)/ape/ape-copy-self.o: \
ape/ape.S \ ape/ape.S \
ape/ape.h \
ape/macros.internal.h \ ape/macros.internal.h \
ape/notice.inc \ ape/notice.inc \
ape/relocations.h \ ape/relocations.h \

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "ape/ape.h"
/** /**
* @fileoverview APE Loader for GNU/Systemd/XNU/FreeBSD/NetBSD/OpenBSD * @fileoverview APE Loader for GNU/Systemd/XNU/FreeBSD/NetBSD/OpenBSD
@ -104,6 +105,12 @@
#define IsAarch64() 0 #define IsAarch64() 0
#endif #endif
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif
#define O_RDONLY 0 #define O_RDONLY 0
#define PROT_NONE 0 #define PROT_NONE 0
#define PROT_READ 1 #define PROT_READ 1
@ -213,8 +220,8 @@ struct ApeLoader {
char path[1024]; char path[1024];
}; };
long SystemCall(long, long, long, long, long, long, long, int); EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
void Launch(void *, long, void *, int) __attribute__((__noreturn__)); EXTERN_C void Launch(void *, long, void *, int) __attribute__((__noreturn__));
extern char __executable_start[]; extern char __executable_start[];
extern char _end[]; 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); 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, Print(os, fd,
"NAME\n" "NAME\n"
"\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" " copyright 2023 justine alexandra roberts tunney\n"
" https://justine.lol/ape.html\n" " https://justine.lol/ape.html\n"
"\n" "\n"
@ -904,15 +911,17 @@ static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) {
Exit(rc, os); 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; int rc, n;
unsigned i; unsigned i;
const char *ape;
int c, fd, os, argc; int c, fd, os, argc;
struct ApeLoader *M; struct ApeLoader *M;
unsigned long pagesz; unsigned long pagesz;
union ElfEhdrBuf *ebuf; union ElfEhdrBuf *ebuf;
long *auxv, *ap, *endp, *sp2; long *auxv, *ap, *endp, *sp2;
char *p, *pe, *exe, *ape, *prog, **argv, **envp; char *p, *pe, *exe, *prog, **argv, **envp;
(void)Utox; (void)Utox;
@ -999,13 +1008,13 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
/* allocate loader memory in program's arg block */ /* allocate loader memory in program's arg block */
n = sizeof(struct ApeLoader); n = sizeof(struct ApeLoader);
M = __builtin_alloca(n); M = (struct ApeLoader *)__builtin_alloca(n);
/* create new bottom of stack for spawned program /* create new bottom of stack for spawned program
system v abi aligns this on a 16-byte boundary system v abi aligns this on a 16-byte boundary
grows down the alloc by poking the guard pages */ grows down the alloc by poking the guard pages */
n = (endp - sp + 1) * sizeof(long); n = (endp - sp + 1) * sizeof(long);
sp2 = __builtin_alloca(n); sp2 = (long *)__builtin_alloca(n);
if ((long)sp2 & 15) ++sp2; if ((long)sp2 & 15) ++sp2;
for (; n > 0; n -= pagesz) { for (; n > 0; n -= pagesz) {
((char *)sp2)[n - 1] = 0; ((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)); MemMove(sp2, sp, (endp - sp) * sizeof(long));
argv = (char **)(sp2 + 1); argv = (char **)(sp2 + 1);
envp = (char **)(sp2 + 1 + argc + 1); envp = (char **)(sp2 + 1 + argc + 1);
auxv = (char **)(sp2 + (auxv - sp)); auxv = sp2 + (auxv - sp);
sp = sp2; sp = sp2;
/* allocate ephemeral memory for reading file */ /* allocate ephemeral memory for reading file */
n = sizeof(union ElfEhdrBuf); n = sizeof(union ElfEhdrBuf);
ebuf = __builtin_alloca(n); ebuf = (union ElfEhdrBuf *)__builtin_alloca(n);
for (; n > 0; n -= pagesz) { for (; n > 0; n -= pagesz) {
((char *)ebuf)[n - 1] = 0; ((char *)ebuf)[n - 1] = 0;
} }

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/dce.h" #include "libc/dce.h"
#include "ape/ape.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#ifdef __aarch64__ #ifdef __aarch64__
@ -64,7 +65,7 @@ ape.ident:
.long 1 .long 1
1: .asciz "APE" 1: .asciz "APE"
2: .balign 4 2: .balign 4
3: .long 107000000 3: .long APE_VERSION_NOTE
4: .size ape.ident,.-ape.ident 4: .size ape.ident,.-ape.ident
.type ape.ident,@object .type ape.ident,@object

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "ape/ape.h"
#include "libc/calls/blockcancel.internal.h" #include "libc/calls/blockcancel.internal.h"
#include "libc/calls/blocksigs.internal.h" #include "libc/calls/blocksigs.internal.h"
#include "libc/calls/calls.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 = "/usr/bin/ape")) ||
CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"), CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"),
firstnonnull(getenv("HOME"), ".")), firstnonnull(getenv("HOME"), ".")),
".ape-1.7", buf))) || ".ape-" APE_VERSION_STR, buf))) ||
CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."), ".ape-1.7", CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."),
buf))))) { ".ape-" APE_VERSION_STR, buf))))) {
shargs[0] = ape; shargs[0] = ape;
shargs[1] = "-"; shargs[1] = "-";
shargs[2] = prog; shargs[2] = prog;

View file

@ -18,7 +18,6 @@
*/ */
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/weaken.h" #include "libc/intrin/weaken.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h" #include "libc/runtime/symbols.internal.h"

View file

@ -20,6 +20,7 @@
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/runtime/zipos.internal.h" #include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/ok.h" #include "libc/sysv/consts/ok.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#include "libc/zip.internal.h" #include "libc/zip.internal.h"
@ -43,7 +44,12 @@ int __zipos_access(struct ZiposUri *name, int amode) {
return -1; 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) { if (amode == F_OK) {
return 0; return 0;
} }

View file

@ -33,16 +33,28 @@ static int64_t __zipos_lseek_impl(struct ZiposHandle *h, int64_t offset,
} }
switch (whence) { switch (whence) {
case SEEK_SET: case SEEK_SET:
return offset; if (offset >= 0) {
return offset;
} else {
return einval();
}
case SEEK_CUR: case SEEK_CUR:
if (!ckd_add(&pos, h->pos, offset)) { if (!ckd_add(&pos, h->pos, offset)) {
return pos; if (pos >= 0) {
return pos;
} else {
return einval();
}
} else { } else {
return eoverflow(); return eoverflow();
} }
case SEEK_END: case SEEK_END:
if (!ckd_sub(&pos, h->size, offset)) { if (!ckd_sub(&pos, h->size, offset)) {
return pos; if (pos >= 0) {
return pos;
} else {
return einval();
}
} else { } else {
return eoverflow(); 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 __zipos_lseek(struct ZiposHandle *h, int64_t offset, unsigned whence) {
int64_t pos; int64_t pos;
if (offset < 0) return einval();
pthread_mutex_lock(&h->lock); pthread_mutex_lock(&h->lock);
if ((pos = __zipos_lseek_impl(h, offset, whence)) != -1) { if ((pos = __zipos_lseek_impl(h, offset, whence)) != -1) {
h->pos = pos; h->pos = pos;

View file

@ -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_S = $(filter %.S,$(LIBC_TIME_A_FILES))
LIBC_TIME_A_SRCS_C = $(filter %.c,$(LIBC_TIME_A_FILES)) LIBC_TIME_A_SRCS_C = $(filter %.c,$(LIBC_TIME_A_FILES))
LIBC_TIME_A_SRCS = \ LIBC_TIME_A_SRCS = \
$(LIBC_TIME_A_SRCS_S) \ $(LIBC_TIME_A_SRCS_S) \
$(LIBC_TIME_A_SRCS_C) $(LIBC_TIME_A_SRCS_C)
LIBC_TIME_A_OBJS = \ LIBC_TIME_A_OBJS = \
o/$(MODE)/usr/share/zoneinfo/.zip.o \ $(LIBC_TIME_A_SRCS_S:%.S=o/$(MODE)/%.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_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_ZONEINFOS:%=o/$(MODE)/%.zip.o) o/$(MODE)/usr/share/zoneinfo/.zip.o
LIBC_TIME_A_CHECKS = \ LIBC_TIME_A_CHECKS = \
$(LIBC_TIME_A).pkg \ $(LIBC_TIME_A).pkg \
$(LIBC_TIME_A_HDRS:%=o/$(MODE)/%.ok) $(LIBC_TIME_A_HDRS:%=o/$(MODE)/%.ok)
LIBC_TIME_A_DIRECTDEPS = \ LIBC_TIME_A_DIRECTDEPS = \
LIBC_CALLS \ LIBC_CALLS \
LIBC_FMT \ LIBC_FMT \
LIBC_INTRIN \ LIBC_INTRIN \
LIBC_MEM \ LIBC_MEM \
LIBC_NEXGEN32E \ LIBC_NEXGEN32E \
LIBC_NT_KERNEL32 \ LIBC_NT_KERNEL32 \
LIBC_RUNTIME \ LIBC_RUNTIME \
LIBC_STDIO \ LIBC_STDIO \
LIBC_STR \ LIBC_STR \
LIBC_SYSV \ LIBC_SYSV \
THIRD_PARTY_COMPILER_RT THIRD_PARTY_COMPILER_RT
LIBC_TIME_A_DEPS := \ LIBC_TIME_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x)))) $(call uniq,$(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x))))
$(LIBC_TIME_A): libc/time/ \ $(LIBC_TIME_A): libc/time/ \
$(LIBC_TIME_A).pkg \ $(LIBC_TIME_A).pkg \
$(LIBC_TIME_A_OBJS) $(LIBC_TIME_A_OBJS)
$(LIBC_TIME_A).pkg: \ $(LIBC_TIME_A).pkg: \
$(LIBC_TIME_A_OBJS) \ $(LIBC_TIME_A_OBJS) \
$(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x)_A).pkg) $(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/time/strftime.o: private \ o/$(MODE)/libc/time/strftime.o: private \
CFLAGS += \ CFLAGS += \
-fno-jump-tables -fno-jump-tables
o/$(MODE)/libc/time/localtime.o: private \ o/$(MODE)/libc/time/localtime.o: private \
CFLAGS += \ CFLAGS += \
-fdata-sections \ -fdata-sections \
-ffunction-sections -ffunction-sections
# we need -O3 because: # we need -O3 because:
# we're dividing by constants # we're dividing by constants
o/$(MODE)/libc/time/iso8601.o \ o/$(MODE)/libc/time/iso8601.o \
o/$(MODE)/libc/time/iso8601us.o: private \ o/$(MODE)/libc/time/iso8601us.o: private \
CFLAGS += \ CFLAGS += \
-O3 -O3
o/$(MODE)/usr/share/zoneinfo/.zip.o: \ o/$(MODE)/usr/share/zoneinfo/.zip.o: \
usr/share/zoneinfo usr/share/zoneinfo
o/$(MODE)/libc/time/kmonthname.o: libc/time/kmonthname.S o/$(MODE)/libc/time/kmonthname.o: libc/time/kmonthname.S

View file

@ -69,10 +69,12 @@ TEST(zipos, enoent) {
TEST(zipos, readPastEof) { TEST(zipos, readPastEof) {
char buf[512]; char buf[512];
ASSERT_SYS(0, 3, open("/zip/libc/testlib/hyperion.txt", O_RDONLY)); 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(EINVAL, -1, pread(3, buf, 512, UINT64_MAX));
EXPECT_SYS(0, 0, pread(3, buf, 512, INT64_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(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, write(3, buf, 512));
EXPECT_SYS(EBADF, -1, pwrite(3, buf, 512, 0)); EXPECT_SYS(EBADF, -1, pwrite(3, buf, 512, 0));
EXPECT_SYS(0, 0, read(3, buf, 512)); 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, open("/zip/libc/testlib/hyperion.txt/a/b", O_RDONLY));
ASSERT_SYS(ENOTDIR, -1, stat("/zip/libc/testlib/hyperion.txt/", &st)); 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
View file

@ -25,9 +25,14 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include "libc/calls/calls.h"
#include "libc/calls/weirdtypes.h" #include "libc/calls/weirdtypes.h"
#include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/mem/mem.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/stdio/stdio.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/thread/thread.h" #include "libc/thread/thread.h"
@ -39,6 +44,57 @@ Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\""); asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */ /* 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 static unsigned
atou(char **s) atou(char **s)
{ {
@ -104,7 +160,7 @@ __getpw_a(const char *name, uid_t uid, struct passwd *pw, char **buf,
int rv = 0; int rv = 0;
*res = 0; *res = 0;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); 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) { while (!(rv = __getpwent_a(f, pw, buf, size, res)) && *res) {
if ((name && !strcmp(name, (*res)->pw_name)) || if ((name && !strcmp(name, (*res)->pw_name)) ||
(!name && (*res)->pw_uid == uid)) { (!name && (*res)->pw_uid == uid)) {
@ -167,46 +223,83 @@ static struct GetpwentState {
char *line; char *line;
struct passwd pw; struct passwd pw;
size_t size; size_t size;
} g_getpwent[1]; } g_getpwent;
/**
* Closes global handle to password database.
*
* @see getpwent()
*/
void void
endpwent() endpwent(void)
{ {
setpwent(); setpwent();
} }
/**
* Rewinds global handle to password database.
*
* @see getpwent()
*/
void void
setpwent() setpwent(void)
{ {
if (g_getpwent->f) fclose(g_getpwent->f); if (g_getpwent.f)
g_getpwent->f = 0; 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 * struct passwd *
getpwent() getpwent()
{ {
struct passwd *res; struct passwd *res;
if (!g_getpwent->f) g_getpwent->f = fopen("/etc/passwd", "rbe"); if (!g_getpwent.f)
if (!g_getpwent->f) return 0; g_getpwent.f = __fopen_passwd();
__getpwent_a(g_getpwent->f, &g_getpwent->pw, &g_getpwent->line, if (!g_getpwent.f)
&g_getpwent->size, &res); return 0;
__getpwent_a(g_getpwent.f, &g_getpwent.pw, &g_getpwent.line,
&g_getpwent.size, &res);
return 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 * struct passwd *
getpwuid(uid_t uid) getpwuid(uid_t uid)
{ {
struct passwd *res; 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); &res);
return 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 * struct passwd *
getpwnam(const char *name) getpwnam(const char *name)
{ {
struct passwd *res; struct passwd *res;
__getpw_a(name, 0, &g_getpwent->pw, &g_getpwent->line, __getpw_a(name, 0, &g_getpwent.pw, &g_getpwent.line,
&g_getpwent->size, &res); &g_getpwent.size, &res);
return res; return res;
} }

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "ape/ape.h"
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/dce.h" #include "libc/dce.h"
@ -1390,7 +1391,7 @@ static char *GenerateElfNotes(char *p) {
char *save; char *save;
save = p = ALIGN(p, 4); save = p = ALIGN(p, 4);
noteoff = p - prologue; noteoff = p - prologue;
p = GenerateElfNote(p, "APE", 1, 107000000); p = GenerateElfNote(p, "APE", 1, APE_VERSION_NOTE);
if (support_vector & _HOSTOPENBSD) { if (support_vector & _HOSTOPENBSD) {
p = GenerateElfNote(p, "OpenBSD", 1, 0); 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 // otherwise try to use the ad-hoc self-extracted loader, securely
if (loaders.n) { 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\"$1\" != x--assimilate ] && "
"[ -x \"$t\" ] && " "[ -x \"$t\" ] && "
"exec \"$t\" \"$o\" \"$@\"\n"); "exec \"$t\" \"$o\" \"$@\"\n");