Fix bug with realpath() on Windows

This commit is contained in:
Justine Tunney 2024-05-29 18:47:01 -07:00
parent 2816df59b2
commit f31a98d50a
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
4 changed files with 57 additions and 3 deletions

View file

@ -27,6 +27,7 @@
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/limits.h"
@ -41,6 +42,11 @@ __static_yoink("musl_libc_notice");
// clang-format off
static inline int IsAlpha(int c)
{
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}
static size_t GetSlashLen(const char *s)
{
const char *s0 = s;
@ -93,6 +99,33 @@ char *realpath(const char *filename, char *resolved)
einval();
return 0;
}
/* Normalize windows paths before proceeding. */
if (IsWindows()) {
int c, i = 0;
/* Turn backslash into slash. */
while ((c = *filename++)) {
if (i == PATH_MAX - 1)
goto toolong;
if (c == '\\')
c = '/';
output[i++] = c;
}
output[i] = 0;
/* Turn paths like "C:" into "/C"
* Turn paths like "C:/..." into "/C/..." */
if (IsAlpha(output[0]) && output[1] == ':' &&
(!output[2] || output[2] == '/')) {
output[1] = output[0];
output[0] = '/';
}
filename = output;
}
/* Copy the path and handle ZipOS. */
l = strnlen(filename, sizeof stack);
if (!l) {
enoent();
@ -124,8 +157,7 @@ restart:
continue;
}
z = (char *)min((intptr_t)strchrnul(stack+p, '/'),
(intptr_t)strchrnul(stack+p, '\\'));
z = strchrnul(stack+p, '/');
l0 = l = z-(stack+p);
if (!l && !check_dir) break;