Implement getcwd() for XNU

This commit is contained in:
Justine Tunney
2021-01-30 08:54:12 -08:00
parent 417797d218
commit 95173645a1
17 changed files with 239 additions and 77 deletions

View File

@@ -232,10 +232,6 @@ int prctl();
int sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
int fchdir(int);
#define getcwd(BUF, SIZE) \
(__builtin_constant_p(BUF) && (&(BUF)[0] == NULL) ? get_current_dir_name() \
: getcwd(BUF, SIZE))
/*───────────────────────────────────────────────────────────────────────────│─╗
│ cosmopolitan § system calls » formatting ─╬─│┼
╚────────────────────────────────────────────────────────────────────────────│*/
@@ -248,6 +244,10 @@ int vdprintf(int, const char *, va_list) paramsnonnull();
╚────────────────────────────────────────────────────────────────────────────│*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define getcwd(BUF, SIZE) \
(__builtin_constant_p(BUF) && !(BUF) ? get_current_dir_name() \
: getcwd(BUF, SIZE))
void _init_onntconsoleevent(void);
void _init_wincrash(void);

View File

@@ -23,12 +23,12 @@
#include "libc/sysv/errfuns.h"
textwindows char *getcwd$nt(char *buf, size_t size) {
uint16_t name16[PATH_MAX + 1];
uint16_t name16[PATH_MAX];
if (GetCurrentDirectory(ARRAYLEN(name16), name16)) {
tprecode16to8(buf, size, name16);
return buf;
} else {
__winerr();
return NULL;
}
return NULL;
}

57
libc/calls/getcwd-xnu.c Normal file
View File

@@ -0,0 +1,57 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2021 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/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
#define XNU_F_GETPATH 50
#define XNU_MAXPATHLEN 1024
char *getcwd$xnu(char *res, size_t size) {
int fd;
struct stat st[2];
char buf[XNU_MAXPATHLEN], *ret = NULL;
if ((fd = openat$sysv(AT_FDCWD, ".", O_RDONLY | O_DIRECTORY)) != -1) {
if (fstat$sysv(fd, &st[0]) != -1) {
if (st[0].st_dev && st[0].st_ino) {
if (fcntl$sysv(fd, XNU_F_GETPATH, buf) != -1) {
if (fstatat$sysv(AT_FDCWD, buf, &st[1], 0) != -1) {
if (st[0].st_dev == st[1].st_dev && st[0].st_ino == st[1].st_ino) {
if (memccpy(res, buf, '\0', size)) {
ret = res;
} else {
erange();
}
} else {
einval();
}
}
}
} else {
einval();
}
}
close(fd);
}
return ret;
}

View File

@@ -19,8 +19,6 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/sysv/errfuns.h"
/**
* Returns current working directory.
@@ -34,28 +32,16 @@
* @error ERANGE, EINVAL
*/
char *(getcwd)(char *buf, size_t size) {
if (buf) {
buf[0] = '\0';
if (!IsWindows()) {
int olderr = errno;
if (getcwd$sysv(buf, size) != NULL) {
return buf;
} else if (IsXnu() && errno == ENOSYS) {
if (size >= 2) {
buf[0] = '.'; /* XXX: could put forth more effort */
buf[1] = '\0';
errno = olderr;
return buf;
} else {
erange();
}
}
return NULL;
if (buf && size) buf[0] = '\0';
if (!IsWindows()) {
if (IsXnu()) {
return getcwd$xnu(buf, size);
} else if (getcwd$sysv(buf, size) != (void *)-1) {
return buf;
} else {
return getcwd$nt(buf, size);
return NULL;
}
} else {
efault();
return NULL;
return getcwd$nt(buf, size);
}
}

View File

@@ -32,7 +32,6 @@
*/
nodiscard char *get_current_dir_name(void) {
char *buf, *res;
if ((res = getenv("PWD"))) return strdup(res);
if (!(buf = malloc(PATH_MAX))) return NULL;
if (!(res = (getcwd)(buf, PATH_MAX))) free(buf);
return res;

View File

@@ -99,6 +99,7 @@ forceinline size_t clampio(size_t size) {
╚────────────────────────────────────────────────────────────────────────────│*/
char *getcwd$sysv(char *, u64) hidden;
char *getcwd$xnu(char *, u64) hidden;
i32 __dup3$sysv(i32, i32, i32) hidden;
i32 __execve$sysv(const char *, char *const[], char *const[]) hidden;
i32 __fstat$sysv(i32, struct stat *) hidden;
@@ -120,7 +121,7 @@ i32 fchmod$sysv(i32, u32) hidden;
i32 fchmodat$sysv(i32, const char *, u32, u32) hidden;
i32 fchown$sysv(i64, u32, u32) hidden;
i32 fchownat$sysv(i32, const char *, u32, u32, u32) hidden;
i32 fcntl$sysv(i32, i32, i32) hidden;
i32 fcntl$sysv(i32, i32, ...) hidden;
i32 fdatasync$sysv(i32) hidden;
i32 flock$sysv(i32, i32) hidden;
i32 fork$sysv(void) hidden;
@@ -151,7 +152,7 @@ i32 mprotect$sysv(void *, u64, i32) hidden;
i32 msync$sysv(void *, u64, i32) hidden;
i32 munmap$sysv(void *, u64) hidden;
i32 nanosleep$sysv(const struct timespec *, struct timespec *) hidden;
i32 openat$sysv(i32, const char *, i32, i32) hidden;
i32 openat$sysv(i32, const char *, i32, ...) hidden;
i32 pause$sysv(void) hidden;
i32 pipe$sysv(i32[hasatleast 2]) hidden;
i32 pipe2$sysv(i32[hasatleast 2], u32) hidden;