mirror of
				https://github.com/jart/cosmopolitan.git
				synced 2025-10-25 02:30:57 +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
				
			
		
							
								
								
									
										43
									
								
								ape/ape-m1.c
									
										
									
									
									
								
							
							
						
						
									
										43
									
								
								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,23 +399,21 @@ 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" | ||||
|         __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" | ||||
|         __asm__ volatile("mrs\t%0,S3_4_c15_c2_7\n" | ||||
|                          : "=r"(reread) | ||||
|                          : /* no inputs */ | ||||
|                          : "memory"); | ||||
|  | @ -429,13 +427,13 @@ 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" | ||||
|         __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" | ||||
|         __asm__ volatile("mrs\t%0,S3_6_c15_c1_5\n" | ||||
|                          : "=r"(reread) | ||||
|                          : /* no inputs */ | ||||
|                          : "memory"); | ||||
|  | @ -595,10 +593,10 @@ __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" | ||||
|   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" | ||||
|  | @ -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: | ||||
|       if (offset >= 0) { | ||||
|         return offset; | ||||
|       } else { | ||||
|         return einval(); | ||||
|       } | ||||
|     case SEEK_CUR: | ||||
|       if (!ckd_add(&pos, h->pos, offset)) { | ||||
|         if (pos >= 0) { | ||||
|           return pos; | ||||
|         } else { | ||||
|           return einval(); | ||||
|         } | ||||
|       } else { | ||||
|         return eoverflow(); | ||||
|       } | ||||
|     case SEEK_END: | ||||
|       if (!ckd_sub(&pos, h->size, offset)) { | ||||
|         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; | ||||
|  |  | |||
|  | @ -17,11 +17,11 @@ LIBC_TIME_A_SRCS =				\ | |||
| 	$(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_ZONEINFOS:%=o/$(MODE)/%.zip.o)	\
 | ||||
| 	o/$(MODE)/usr/share/zoneinfo/.zip.o | ||||
| 
 | ||||
| LIBC_TIME_A_CHECKS =					\
 | ||||
| 	$(LIBC_TIME_A).pkg				\
 | ||||
|  |  | |||
|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue