mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-15 05:16:30 +00:00
Prepend getcwd to exename early in init (#1048)
This commit is contained in:
parent
2f89c2482a
commit
68dbe5312f
5 changed files with 70 additions and 22 deletions
|
@ -34,6 +34,10 @@
|
|||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
__static_yoink("_init_program_executable_name");
|
||||
#endif
|
||||
|
||||
#define CTL_KERN 1
|
||||
#define KERN_PROC 14
|
||||
#define KERN_PROC_PATHNAME_FREEBSD 12
|
||||
|
@ -88,31 +92,37 @@ static int OldApeLoader(char *s) {
|
|||
(!strncmp((b = basename(s)), ".ape-", 5) && AllNumDot(b + 5));
|
||||
}
|
||||
|
||||
// if q exists then turn it into an absolute path. we also try adding
|
||||
// a .com suffix since the ape auto-appends it when resolving
|
||||
static int TryPath(const char *q, int com) {
|
||||
char c, *p, *e;
|
||||
if (!q) return 0;
|
||||
p = g_prog.u.buf;
|
||||
e = p + sizeof(g_prog.u.buf);
|
||||
static char *CopyWithCwd(const char *q, char *p, char *e) {
|
||||
char c;
|
||||
if (*q != '/') {
|
||||
if (q[0] == '.' && q[1] == '/') {
|
||||
q += 2;
|
||||
}
|
||||
int got = __getcwd(p, e - p - 1 /* '/' */ - com * 4);
|
||||
int got = __getcwd(p, e - p - 1 /* '/' */);
|
||||
if (got != -1) {
|
||||
p += got - 1;
|
||||
*p++ = '/';
|
||||
}
|
||||
}
|
||||
while ((c = *q++)) {
|
||||
if (p + com * 4 + 1 /* nul */ < e) {
|
||||
if (p + 1 /* nul */ < e) {
|
||||
*p++ = c;
|
||||
} else {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
// if q exists then turn it into an absolute path. we also try adding
|
||||
// a .com suffix since the ape auto-appends it when resolving
|
||||
static int TryPath(const char *q, int com) {
|
||||
char *p;
|
||||
if (!(p = CopyWithCwd(q, g_prog.u.buf,
|
||||
g_prog.u.buf + sizeof(g_prog.u.buf) - com * 4))) {
|
||||
return 0;
|
||||
}
|
||||
if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) return 1;
|
||||
if (!com) return 0;
|
||||
p = WRITE32LE(p, READ32LE(".com"));
|
||||
|
@ -121,6 +131,16 @@ static int TryPath(const char *q, int com) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// if the loader passed a relative path, prepend cwd to it.
|
||||
// called early in init.
|
||||
void __init_program_executable_name(void) {
|
||||
if (__program_executable_name && *__program_executable_name != '/' &&
|
||||
CopyWithCwd(__program_executable_name, g_prog.u.buf,
|
||||
g_prog.u.buf + sizeof(g_prog.u.buf))) {
|
||||
__program_executable_name = g_prog.u.buf;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void InitProgramExecutableNameImpl(void) {
|
||||
size_t n;
|
||||
ssize_t got;
|
||||
|
@ -167,18 +187,6 @@ static inline void InitProgramExecutableNameImpl(void) {
|
|||
goto UseEmpty;
|
||||
}
|
||||
}
|
||||
if (*__program_executable_name == '/') {
|
||||
return;
|
||||
}
|
||||
// loader passed us a relative path; prepend cwd.
|
||||
if (TryPath(__program_executable_name, 0)) {
|
||||
goto UseBuf;
|
||||
}
|
||||
/* if TryPath fails, it probably failed because getcwd() was too long.
|
||||
we are out of options now; KERN_PROC_PATHNAME et al will return the
|
||||
name of the loader not the binary, and argv et al will at best have
|
||||
the same problem. just use the relative path we got from the loader
|
||||
as-is, and accept that if we chdir then things will break. */
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
27
libc/calls/program_executable_name_init.S
Normal file
27
libc/calls/program_executable_name_init.S
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
.init.start 305,_init_program_executable_name
|
||||
push %rdi
|
||||
push %rsi
|
||||
call __init_program_executable_name
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
.init.end 305,_init_program_executable_name
|
|
@ -172,6 +172,9 @@ wontreturn textstartup void cosmo(long *sp, struct Syslib *m1, char *exename,
|
|||
// initialize file system
|
||||
__init_fds(argc, argv, envp);
|
||||
|
||||
// prepend cwd to executable path
|
||||
__init_program_executable_name();
|
||||
|
||||
__enable_tls();
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -47,6 +47,7 @@ void *__mmap_unlocked(void *, size_t, int, int, int, int64_t);
|
|||
int __munmap_unlocked(char *, size_t);
|
||||
void __on_arithmetic_overflow(void);
|
||||
void __init_fds(int, char **, char **);
|
||||
void __init_program_executable_name(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* ANSI */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/metalfile.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -57,6 +58,9 @@ void SetUpOnce(void) {
|
|||
|
||||
__attribute__((__constructor__)) static void Child(int argc, char *argv[]) {
|
||||
if (argc >= 2 && !strcmp(argv[1], "Child")) {
|
||||
if (sys_chdir("/")) {
|
||||
exit(122);
|
||||
}
|
||||
if (strcmp(argv[2], GetProgramExecutableName())) {
|
||||
exit(123);
|
||||
}
|
||||
|
@ -138,4 +142,9 @@ TEST(GetProgramExecutableName, movedSelf) {
|
|||
execve(buf, (char *[]){"hello", "Child", buf, "hello", 0}, (char *[]){0});
|
||||
abort();
|
||||
EXITS(0);
|
||||
SPAWN(fork);
|
||||
execve("./test", (char *[]){"hello", "Child", buf, "hello", 0},
|
||||
(char *[]){0});
|
||||
abort();
|
||||
EXITS(0);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue