mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-14 06:59:10 +00:00
Implement getcwd() for XNU
This commit is contained in:
parent
417797d218
commit
95173645a1
17 changed files with 239 additions and 77 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
57
libc/calls/getcwd-xnu.c
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue