mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 15:28:30 +00:00
Fix handling of paths with dirfd on Windows
This change fixes an issue with all system calls ending with *at(), when the caller passes `dirfd != AT_FDCWD` and an absolute path. It's because the old code was turning paths like C:\bin\ls into \\C:\bin\ls\C:\bin\ls after being converted from paths like /C/bin/ls. I noticed this when the Emacs dired mode stopped working. It's unclear if it's a regression with Cosmopolitan Libc or if this was introduced by the Emacs v29 upgrade. It also impacted posix_spawn() for which a newly minted example now exists.
This commit is contained in:
parent
a089c07ddc
commit
39e7f24947
10 changed files with 373 additions and 46 deletions
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
|
@ -27,6 +28,18 @@
|
|||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static int IsAlpha(int c) {
|
||||
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
|
||||
}
|
||||
|
||||
static bool IsAbsolutePathWin32(char16_t *path) {
|
||||
if (path[0] == '\\')
|
||||
return true;
|
||||
if (IsAlpha(path[0]) && path[1] == ':')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static textwindows int __mkntpathath_impl(int64_t dirhand, const char *path,
|
||||
int flags,
|
||||
char16_t file[hasatleast PATH_MAX]) {
|
||||
|
@ -39,7 +52,7 @@ static textwindows int __mkntpathath_impl(int64_t dirhand, const char *path,
|
|||
return -1;
|
||||
if (!filelen)
|
||||
return enoent();
|
||||
if (file[0] != u'\\' && dirhand != AT_FDCWD) { // ProTip: \\?\C:\foo
|
||||
if (dirhand != AT_FDCWD && !IsAbsolutePathWin32(file)) {
|
||||
dirlen = GetFinalPathNameByHandle(dirhand, dir, ARRAYLEN(dir),
|
||||
kNtFileNameNormalized | kNtVolumeNameDos);
|
||||
if (!dirlen)
|
||||
|
@ -49,7 +62,8 @@ static textwindows int __mkntpathath_impl(int64_t dirhand, const char *path,
|
|||
dir[dirlen] = u'\\';
|
||||
memcpy(dir + dirlen + 1, file, (filelen + 1) * sizeof(char16_t));
|
||||
memcpy(file, dir, ((n = dirlen + 1 + filelen) + 1) * sizeof(char16_t));
|
||||
return __normntpath(file, n);
|
||||
int res = __normntpath(file, n);
|
||||
return res;
|
||||
} else {
|
||||
return filelen;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue