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
				
			
		
							
								
								
									
										135
									
								
								ape/ape-m1.c
									
										
									
									
									
								
							
							
						
						
									
										135
									
								
								ape/ape-m1.c
									
										
									
									
									
								
							|  | @ -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 */ | ||||||
|  |  | ||||||
|  | @ -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
									
								
							
							
						
						
									
										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 | 		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		\
 | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								ape/loader.c
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								ape/loader.c
									
										
									
									
									
								
							|  | @ -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; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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" | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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
									
									
								
							
							
						
						
									
										119
									
								
								third_party/musl/pwd.c
									
										
									
									
										vendored
									
									
								
							|  | @ -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; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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"); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue