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 (*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 */

View file

@ -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
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
@$(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 \

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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"

View file

@ -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;
}

View file

@ -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;

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_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

View file

@ -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
View file

@ -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;
}

View file

@ -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");