mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-07 02:28:56 -10:00
Fix GetProgramExecutableName() on NetBSD (#1529)
The sysctl parameters for querying KERN_PROC_PATHNAME are different from FreeBSD. The tests now check the GPEN path using stat instead of strcmp.
This commit is contained in:
1 parent
34fa4edae8
commit
b0cebefd8e
4 files changed
+122
-9
No files matched your search
@@ -43,6 +43,7 @@ __static_yoink("_init_program_executable_name");
|
||||
|
||||
#define CTL_KERN 1
|
||||
#define KERN_PROC 14
|
||||
#define KERN_PROC_ARGS 48
|
||||
#define KERN_PROC_PATHNAME_FREEBSD 12
|
||||
#define KERN_PROC_PATHNAME_NETBSD 5
|
||||
|
||||
@@ -173,13 +174,15 @@ static inline void InitProgramExecutableNameImpl(void) {
|
||||
if (IsFreebsd() || IsNetbsd()) {
|
||||
int cmd[4];
|
||||
cmd[0] = CTL_KERN;
|
||||
cmd[1] = KERN_PROC;
|
||||
if (IsFreebsd()) {
|
||||
cmd[1] = KERN_PROC;
|
||||
cmd[2] = KERN_PROC_PATHNAME_FREEBSD;
|
||||
cmd[3] = -1; // current process
|
||||
} else {
|
||||
cmd[2] = KERN_PROC_PATHNAME_NETBSD;
|
||||
cmd[1] = KERN_PROC_ARGS;
|
||||
cmd[2] = -1; // current process
|
||||
cmd[3] = KERN_PROC_PATHNAME_NETBSD;
|
||||
}
|
||||
cmd[3] = -1; // current process
|
||||
if (sysctl(cmd, ARRAYLEN(cmd), b, &n, 0, 0) != -1) {
|
||||
if (!OldApeLoader(b)) {
|
||||
goto UseBuf;
|
||||
|
||||
@@ -73,6 +73,7 @@ o/$(MODE)/test/libc/calls/getprogramexecutablename_test.dbg: \
|
||||
$(TEST_LIBC_CALLS_DEPS) \
|
||||
o/$(MODE)/test/libc/calls/getprogramexecutablename_test.o \
|
||||
o/$(MODE)/test/libc/calls/ape.elf.zip.o \
|
||||
o/$(MODE)/test/libc/calls/gpenchild.elf.zip.o \
|
||||
o/$(MODE)/test/libc/calls/calls.pkg \
|
||||
$(LIBC_TESTMAIN) \
|
||||
$(CRT) \
|
||||
@@ -125,14 +126,25 @@ o/$(MODE)/test/libc/calls/life-nomod.dbg: \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/test/libc/calls/zipread.dbg: \
|
||||
$(LIBC_RUNTIME) \
|
||||
o/$(MODE)/test/libc/calls/zipread.o \
|
||||
o/$(MODE)/test/libc/mem/prog/life.elf.zip.o \
|
||||
$(CRT) \
|
||||
o/$(MODE)/test/libc/calls/gpenchild.dbg: \
|
||||
$(LIBC_RUNTIME) \
|
||||
o/$(MODE)/test/libc/calls/gpenchild.o \
|
||||
$(CRT) \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/test/libc/calls/gpenchild.elf: \
|
||||
o/$(MODE)/tool/build/assimilate \
|
||||
o/$(MODE)/test/libc/calls/gpenchild \
|
||||
o/$(MODE)/tool/build/cp
|
||||
@$(COMPILE) -wACP -T$@ \
|
||||
o/$(MODE)/tool/build/cp \
|
||||
o/$(MODE)/test/libc/calls/gpenchild \
|
||||
o/$(MODE)/test/libc/calls/gpenchild.elf
|
||||
@$(COMPILE) -wAASSIMILATE -T$@ \
|
||||
o/$(MODE)/tool/build/assimilate -bcef \
|
||||
o/$(MODE)/test/libc/calls/gpenchild.elf
|
||||
|
||||
o/$(MODE)/test/libc/calls/ape.elf: \
|
||||
o/$(MODE)/tool/build/cp \
|
||||
o/$(MODE)/ape/ape.elf
|
||||
@@ -142,6 +154,7 @@ o/$(MODE)/test/libc/calls/ape.elf: \
|
||||
o/$(MODE)/test/libc/calls/ape.elf
|
||||
|
||||
o/$(MODE)/test/libc/calls/ape.elf.zip.o \
|
||||
o/$(MODE)/test/libc/calls/gpenchild.elf.zip.o \
|
||||
o/$(MODE)/test/libc/calls/tiny64.elf.zip.o \
|
||||
o/$(MODE)/test/libc/calls/life-nomod.zip.o \
|
||||
o/$(MODE)/test/libc/calls/life-classic.zip.o: private \
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/metalfile.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
@@ -70,6 +71,18 @@ void SetUpOnce(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool isAbsPath(const char *path) {
|
||||
return strlen(path) >= 2 && path[0] == '/' && path[1] != '/';
|
||||
}
|
||||
|
||||
static bool isSameFile(const char *a, const char *b) {
|
||||
struct stat st_a, st_b;
|
||||
if (stat(a, &st_a) || stat(b, &st_b)) {
|
||||
return false;
|
||||
}
|
||||
return (st_a.st_dev == st_b.st_dev) && (st_a.st_ino == st_b.st_ino);
|
||||
}
|
||||
|
||||
__attribute__((__constructor__)) static void Child(int argc, char *argv[]) {
|
||||
loaded = !!__program_executable_name;
|
||||
if (argc >= 2 && !strcmp(argv[1], "Child")) {
|
||||
@@ -82,7 +95,8 @@ __attribute__((__constructor__)) static void Child(int argc, char *argv[]) {
|
||||
if (rc) {
|
||||
exit(122);
|
||||
}
|
||||
if (strcmp(argv[2], GetProgramExecutableName())) {
|
||||
const char *path = GetProgramExecutableName();
|
||||
if (!path || !isAbsPath(path) || !isSameFile(argv[2], path)) {
|
||||
exit(123);
|
||||
}
|
||||
if (argc >= 4) {
|
||||
@@ -192,3 +206,23 @@ TEST(GetProgramExecutableName, nullArgvAPELoader) {
|
||||
abort();
|
||||
EXITS(0);
|
||||
}
|
||||
|
||||
TEST(GetProgramExecutableName, elf) {
|
||||
if (skiptests || IsOpenbsd() || IsXnu() || IsWindows() || IsMetal())
|
||||
return;
|
||||
char buf[BUFSIZ];
|
||||
testlib_extract("/zip/gpenchild.elf", "test.elf", 0555);
|
||||
ASSERT_NE(NULL, getcwd(buf, BUFSIZ - 5));
|
||||
stpcpy(buf + strlen(buf), "/test.elf");
|
||||
SPAWN(fork);
|
||||
execve(buf, (char *[]){"hello", "Child", buf, skiparg0 ? 0 : "hello", 0},
|
||||
(char *[]){0});
|
||||
abort();
|
||||
EXITS(0);
|
||||
SPAWN(fork);
|
||||
execve("./test.elf",
|
||||
(char *[]){"hello", "Child", buf, skiparg0 ? 0 : "hello", 0},
|
||||
(char *[]){0});
|
||||
abort();
|
||||
EXITS(0);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2026 Gavin Arthur Hayes │
|
||||
│ │
|
||||
│ 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/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static bool isAbsPath(const char *path) {
|
||||
return strlen(path) >= 2 && path[0] == '/' && path[1] != '/';
|
||||
}
|
||||
|
||||
static bool isSameFile(const char *a, const char *b) {
|
||||
struct stat st_a, st_b;
|
||||
if (stat(a, &st_a) || stat(b, &st_b)) {
|
||||
return false;
|
||||
}
|
||||
return (st_a.st_dev == st_b.st_dev) && (st_a.st_ino == st_b.st_ino);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc >= 2 && !strcmp(argv[1], "Child")) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
rc = sys_chdir("/");
|
||||
} else {
|
||||
rc = sys_chdir_nt("/");
|
||||
}
|
||||
if (rc) {
|
||||
exit(122);
|
||||
}
|
||||
const char *path = GetProgramExecutableName();
|
||||
if (!path || !isAbsPath(path) || !isSameFile(argv[2], path)) {
|
||||
exit(123);
|
||||
}
|
||||
if (argc >= 4) {
|
||||
if (strcmp(argv[3], argv[0])) {
|
||||
exit(124);
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
exit(128);
|
||||
}
|
||||
Reference in new issue
Block a user