diff --git a/libc/calls/fixenotdir.c b/libc/calls/fixenotdir.c index 5b9146b38..31c9711f6 100644 --- a/libc/calls/fixenotdir.c +++ b/libc/calls/fixenotdir.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/errno.h" +#include "libc/intrin/kprintf.h" #include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/errors.h" #include "libc/nt/files.h" @@ -44,10 +45,14 @@ static textwindows bool SubpathExistsThatsNotDirectory(char16_t *path) { textwindows dontinline int64_t __fix_enotdir3(int64_t rc, char16_t *path1, char16_t *path2) { - if (rc == -1 && errno == kNtErrorPathNotFound) { - if ((!path1 || !SubpathExistsThatsNotDirectory(path1)) && - (!path2 || !SubpathExistsThatsNotDirectory(path2))) { - errno = kNtErrorFileNotFound; + if (rc == -1 && (errno == kNtErrorPathNotFound || // Windows returns ENOTDIR + errno == kNtErrorInvalidName)) { // e.g. has trailing slash + bool isdir = false; + if ((!path1 || !(isdir |= SubpathExistsThatsNotDirectory(path1))) && + (!path2 || !(isdir |= SubpathExistsThatsNotDirectory(path2)))) { + errno = kNtErrorFileNotFound; // ENOENT + } else if (isdir) { + errno = kNtErrorPathNotFound; // ENOTDIR } } return rc; diff --git a/libc/calls/getdomainname.c b/libc/calls/getdomainname.c index 885499ccb..bbda62d70 100644 --- a/libc/calls/getdomainname.c +++ b/libc/calls/getdomainname.c @@ -19,7 +19,6 @@ #include "libc/calls/calls.h" #include "libc/calls/syscall_support-sysv.internal.h" #include "libc/dce.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/macros.internal.h" #include "libc/nt/enum/computernameformat.h" diff --git a/libc/calls/gethostname.c b/libc/calls/gethostname.c index 0439a735f..a01b84e7d 100644 --- a/libc/calls/gethostname.c +++ b/libc/calls/gethostname.c @@ -19,7 +19,6 @@ #include "libc/calls/calls.h" #include "libc/calls/syscall_support-sysv.internal.h" #include "libc/dce.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/nt/enum/computernameformat.h" #include "libc/sysv/errfuns.h" diff --git a/libc/calls/mkntpath.c b/libc/calls/mkntpath.c index df68f4d9b..17d5dbe17 100644 --- a/libc/calls/mkntpath.c +++ b/libc/calls/mkntpath.c @@ -194,5 +194,10 @@ textwindows int __mkntpath2(const char *path, n -= 4; } + // turn "foo\\." into "foo\\" + if (n > 2 && path16[n - 1] == u'.' && path16[n - 2] == u'\\') { + path16[--n] = 0; + } + return n; } diff --git a/libc/calls/open-nt.c b/libc/calls/open-nt.c index b7d0fb26c..66da47629 100644 --- a/libc/calls/open-nt.c +++ b/libc/calls/open-nt.c @@ -22,6 +22,7 @@ #include "libc/calls/state.internal.h" #include "libc/calls/syscall-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h" +#include "libc/intrin/kprintf.h" #include "libc/nt/createfile.h" #include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/enum/filetype.h" diff --git a/libc/calls/openpty.c b/libc/calls/openpty.c index 8382ff2e3..c4801ff45 100644 --- a/libc/calls/openpty.c +++ b/libc/calls/openpty.c @@ -28,7 +28,6 @@ #include "libc/calls/termios.internal.h" #include "libc/dce.h" #include "libc/intrin/asan.internal.h" -#include "libc/intrin/kprintf.h" #include "libc/log/rop.internal.h" #include "libc/str/str.h" #include "libc/sysv/consts/at.h" diff --git a/libc/calls/preadv.c b/libc/calls/preadv.c index 81e2a8055..b98c598c9 100644 --- a/libc/calls/preadv.c +++ b/libc/calls/preadv.c @@ -25,7 +25,6 @@ #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/likely.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" diff --git a/libc/calls/pwritev.c b/libc/calls/pwritev.c index f624aab5c..c2cade35d 100644 --- a/libc/calls/pwritev.c +++ b/libc/calls/pwritev.c @@ -25,7 +25,6 @@ #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/asan.internal.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/likely.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" diff --git a/libc/calls/readv.c b/libc/calls/readv.c index 479ec157d..9c2d84d7a 100644 --- a/libc/calls/readv.c +++ b/libc/calls/readv.c @@ -25,13 +25,12 @@ #include "libc/errno.h" #include "libc/intrin/asan.internal.h" #include "libc/intrin/describeflags.internal.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/likely.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" +#include "libc/runtime/zipos.internal.h" #include "libc/sock/internal.h" #include "libc/sysv/errfuns.h" -#include "libc/runtime/zipos.internal.h" /** * Reads data to multiple buffers. diff --git a/libc/calls/unveil.c b/libc/calls/unveil.c index 0891cc0f4..89d99dcd0 100644 --- a/libc/calls/unveil.c +++ b/libc/calls/unveil.c @@ -31,7 +31,6 @@ #include "libc/errno.h" #include "libc/fmt/conv.h" #include "libc/fmt/libgen.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/macros.internal.h" #include "libc/nexgen32e/vendor.internal.h" diff --git a/libc/calls/wait4-nt.c b/libc/calls/wait4-nt.c index 6e66cfef2..8c1897110 100644 --- a/libc/calls/wait4-nt.c +++ b/libc/calls/wait4-nt.c @@ -24,7 +24,6 @@ #include "libc/calls/struct/rusage.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/fmt/conv.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/macros.internal.h" #include "libc/nt/accounting.h" diff --git a/libc/calls/writev.c b/libc/calls/writev.c index 006b55e1c..0c4cf128b 100644 --- a/libc/calls/writev.c +++ b/libc/calls/writev.c @@ -24,7 +24,6 @@ #include "libc/errno.h" #include "libc/intrin/asan.internal.h" #include "libc/intrin/describeflags.internal.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/likely.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" diff --git a/libc/intrin/memtrack.greg.c b/libc/intrin/memtrack.greg.c index 7e2c8deb0..ce6f17e4e 100644 --- a/libc/intrin/memtrack.greg.c +++ b/libc/intrin/memtrack.greg.c @@ -23,7 +23,6 @@ #include "libc/intrin/asan.internal.h" #include "libc/intrin/bits.h" #include "libc/intrin/directmap.internal.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/log/libfatal.internal.h" #include "libc/log/log.h" diff --git a/libc/intrin/nocolor.c b/libc/intrin/nocolor.c index d2ac956ab..60ad3efa9 100644 --- a/libc/intrin/nocolor.c +++ b/libc/intrin/nocolor.c @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" -#include "libc/intrin/kprintf.h" #include "libc/log/internal.h" #include "libc/nt/version.h" #include "libc/runtime/runtime.h" diff --git a/libc/intrin/strcpy.c b/libc/intrin/strcpy.c index 8683c3c72..237b84822 100644 --- a/libc/intrin/strcpy.c +++ b/libc/intrin/strcpy.c @@ -18,7 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" #include "libc/intrin/asan.internal.h" -#include "libc/intrin/kprintf.h" #include "libc/str/str.h" #ifndef __aarch64__ diff --git a/libc/runtime/cocmd.c b/libc/runtime/cocmd.c index 04abacac4..e4e1f3ded 100644 --- a/libc/runtime/cocmd.c +++ b/libc/runtime/cocmd.c @@ -27,7 +27,6 @@ #include "libc/fmt/magnumstrs.internal.h" #include "libc/intrin/_getenv.internal.h" #include "libc/intrin/bits.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/weaken.h" #include "libc/macros.internal.h" #include "libc/runtime/runtime.h" diff --git a/libc/runtime/cosmo2.c b/libc/runtime/cosmo2.c index c5f2f182b..3cae9c5d0 100644 --- a/libc/runtime/cosmo2.c +++ b/libc/runtime/cosmo2.c @@ -21,7 +21,6 @@ #include "libc/calls/syscall-sysv.internal.h" #include "libc/dce.h" #include "libc/errno.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/limits.h" #include "libc/macros.internal.h" diff --git a/libc/runtime/getlogin_r.c b/libc/runtime/getlogin_r.c index 373e87f79..5bc9d1398 100644 --- a/libc/runtime/getlogin_r.c +++ b/libc/runtime/getlogin_r.c @@ -18,7 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/syscall_support-nt.internal.h" #include "libc/dce.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/macros.internal.h" #include "libc/nt/accounting.h" diff --git a/libc/runtime/hook.greg.c b/libc/runtime/hook.greg.c index 5a7f931ca..c781336e5 100644 --- a/libc/runtime/hook.greg.c +++ b/libc/runtime/hook.greg.c @@ -18,7 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "ape/sections.internal.h" #include "libc/calls/struct/sigset.h" -#include "libc/intrin/kprintf.h" #include "libc/limits.h" #include "libc/macros.internal.h" #include "libc/runtime/runtime.h" diff --git a/libc/runtime/zipos-access.c b/libc/runtime/zipos-access.c index 535dead40..ebc49caa3 100644 --- a/libc/runtime/zipos-access.c +++ b/libc/runtime/zipos-access.c @@ -40,7 +40,7 @@ int __zipos_access(struct ZiposUri *name, int amode) { ssize_t cf; if ((cf = __zipos_find(z, name)) == -1) { - return enoent(); + return -1; } int mode = GetZipCfileMode(z->map + cf); diff --git a/libc/runtime/zipos-find.c b/libc/runtime/zipos-find.c index 647f14f6f..71eb1417c 100644 --- a/libc/runtime/zipos-find.c +++ b/libc/runtime/zipos-find.c @@ -1,7 +1,7 @@ /*-*- 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 2020 Justine Alexandra Roberts Tunney │ +│ Copyright 2023 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 │ @@ -17,10 +17,17 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/runtime/zipos.internal.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/s.h" +#include "libc/sysv/errfuns.h" #include "libc/zip.internal.h" -ssize_t __zipos_find(struct Zipos *zipos, struct ZiposUri *name) { - if (!name->len) { +static ssize_t __zipos_scan(struct Zipos *zipos, struct ZiposUri *name) { + size_t len = name->len; + if (len && name->path[len - 1] == '/') { + --len; + } + if (!len) { return ZIPOS_SYNTHETIC_DIRECTORY; } bool found_subfile = false; @@ -29,12 +36,11 @@ ssize_t __zipos_find(struct Zipos *zipos, struct ZiposUri *name) { for (size_t i = 0; i < n; ++i, c += ZIP_CFILE_HDRSIZE(zipos->map + c)) { const char *zname = ZIP_CFILE_NAME(zipos->map + c); size_t zsize = ZIP_CFILE_NAMESIZE(zipos->map + c); - if ((name->len == zsize || - (name->len + 1 == zsize && zname[name->len] == '/')) && - !memcmp(name->path, zname, name->len)) { + if ((len == zsize || (len + 1 == zsize && zname[len] == '/')) && + !memcmp(name->path, zname, len)) { return c; - } else if (name->len + 1 < zsize && zname[name->len] == '/' && - !memcmp(name->path, zname, name->len)) { + } else if (len + 1 < zsize && zname[len] == '/' && + !memcmp(name->path, zname, len)) { found_subfile = true; } } @@ -43,3 +49,28 @@ ssize_t __zipos_find(struct Zipos *zipos, struct ZiposUri *name) { } return -1; } + +// support code for open(), stat(), and access() +ssize_t __zipos_find(struct Zipos *zipos, struct ZiposUri *name) { + ssize_t cf; + if ((cf = __zipos_scan(zipos, name)) == -1) { + // test if parent component exists that isn't a directory + char *p; + while ((p = memrchr(name->path, '/', name->len))) { + name->path[name->len = p - name->path] = 0; + if ((cf = __zipos_scan(zipos, name)) != -1 && + cf != ZIPOS_SYNTHETIC_DIRECTORY && + !S_ISDIR(GetZipCfileMode(zipos->map + cf))) { + return enotdir(); + } + } + return enoent(); + } + // test if we're opening "foo/" and "foo" isn't a directory + if (cf != ZIPOS_SYNTHETIC_DIRECTORY && // + name->len && name->path[name->len - 1] == '/' && + !S_ISDIR(GetZipCfileMode(zipos->map + cf))) { + return enotdir(); + } + return cf; +} diff --git a/libc/runtime/zipos-get.c b/libc/runtime/zipos-get.c index 4fdf35a20..964b5bd67 100644 --- a/libc/runtime/zipos-get.c +++ b/libc/runtime/zipos-get.c @@ -21,7 +21,6 @@ #include "libc/calls/struct/stat.h" #include "libc/fmt/conv.h" #include "libc/intrin/cmpxchg.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/promises.internal.h" #include "libc/intrin/strace.internal.h" #include "libc/macros.internal.h" diff --git a/libc/runtime/zipos-normpath.c b/libc/runtime/zipos-normpath.c index f426131f6..9a6bdedce 100644 --- a/libc/runtime/zipos-normpath.c +++ b/libc/runtime/zipos-normpath.c @@ -21,8 +21,7 @@ // normalizes zip filesystem path w/ overlapping strlcpy() style api // zip paths look like relative paths, but they're actually absolute // with respect to the archive; so similar to how /../etc would mean -// /etc, we'd translate that here to "etc". when storing assets in a -// zip archive, callers should append trailing slash for directories +// /etc, we'd translate that here to "etc", and "etc/" slash is kept // returns strlen of 𝑑; returns 𝑛 when insufficient buffer available // nul terminator is guaranteed if n>0. it's fine if 𝑑 and 𝑠 overlap // test vectors for this algorithm in: test/libc/stdio/zipdir_test.c @@ -49,8 +48,6 @@ size_t __zipos_normpath(char *d, const char *s, size_t n) { } // if we didn't overflow if (p < e) { - // trim trailing slashes and add nul terminator - while (p > d && p[-1] == '/') --p; *p = '\0'; } else { // force nul-terminator to exist if possible diff --git a/libc/runtime/zipos-open.c b/libc/runtime/zipos-open.c index fa33adeb9..0f89a1c28 100644 --- a/libc/runtime/zipos-open.c +++ b/libc/runtime/zipos-open.c @@ -209,7 +209,7 @@ static int __zipos_open_impl(struct ZiposUri *name, int flags) { } ssize_t cf; if ((cf = __zipos_find(zipos, name)) == -1) { - return enoent(); + return -1; } if (flags & O_EXCL) { return eexist(); diff --git a/libc/runtime/zipos-stat.c b/libc/runtime/zipos-stat.c index a7b929071..813cbe2a8 100644 --- a/libc/runtime/zipos-stat.c +++ b/libc/runtime/zipos-stat.c @@ -23,14 +23,14 @@ /** * Reads file metadata from αcτµαlly pδrταblε εxεcµταblε object store. * - * @param uri is obtained via __zipos_parseuri() + * @param name is obtained via __zipos_parseuri() * @asyncsignalsafe */ int __zipos_stat(struct ZiposUri *name, struct stat *st) { ssize_t cf; struct Zipos *zipos; if (!(zipos = __zipos_get())) return enoexec(); - if ((cf = __zipos_find(zipos, name)) == -1) return enoent(); + if ((cf = __zipos_find(zipos, name)) == -1) return -1; if (__zipos_stat_impl(zipos, cf, st)) return -1; st->st_ino = __zipos_inode(zipos, cf, name->path, name->len); return 0; diff --git a/libc/runtime/zipos.internal.h b/libc/runtime/zipos.internal.h index bc0013b37..c8e21f602 100644 --- a/libc/runtime/zipos.internal.h +++ b/libc/runtime/zipos.internal.h @@ -44,8 +44,8 @@ void __zipos_unlock(void); void __zipos_free(struct ZiposHandle *); struct Zipos *__zipos_get(void) pureconst; size_t __zipos_normpath(char *, const char *, size_t); -ssize_t __zipos_parseuri(const char *, struct ZiposUri *); ssize_t __zipos_find(struct Zipos *, struct ZiposUri *); +ssize_t __zipos_parseuri(const char *, struct ZiposUri *); uint64_t __zipos_inode(struct Zipos *, int64_t, const void *, size_t); int __zipos_open(struct ZiposUri *, int); int __zipos_access(struct ZiposUri *, int); diff --git a/libc/sock/socket-nt.c b/libc/sock/socket-nt.c index 6eaed651b..fbb4e4969 100644 --- a/libc/sock/socket-nt.c +++ b/libc/sock/socket-nt.c @@ -20,7 +20,6 @@ #include "libc/calls/internal.h" #include "libc/calls/state.internal.h" #include "libc/errno.h" -#include "libc/intrin/kprintf.h" #include "libc/mem/mem.h" #include "libc/nt/enum/fileflagandattributes.h" #include "libc/nt/iphlpapi.h" diff --git a/libc/sock/wsablock.c b/libc/sock/wsablock.c index 7639f2c4d..9169ced24 100644 --- a/libc/sock/wsablock.c +++ b/libc/sock/wsablock.c @@ -20,7 +20,6 @@ #include "libc/calls/internal.h" #include "libc/calls/sig.internal.h" #include "libc/errno.h" -#include "libc/intrin/kprintf.h" #include "libc/nt/enum/wait.h" #include "libc/nt/enum/wsa.h" #include "libc/nt/errors.h" diff --git a/libc/stdio/dirstream.c b/libc/stdio/dirstream.c index 02de208e8..9f3b7a274 100644 --- a/libc/stdio/dirstream.c +++ b/libc/stdio/dirstream.c @@ -24,7 +24,6 @@ #include "libc/calls/syscall_support-nt.internal.h" #include "libc/dce.h" #include "libc/errno.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" #include "libc/limits.h" diff --git a/libc/thread/pthread_cancel.c b/libc/thread/pthread_cancel.c index 9757834cc..ec38015e6 100644 --- a/libc/thread/pthread_cancel.c +++ b/libc/thread/pthread_cancel.c @@ -26,7 +26,6 @@ #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/atomic.h" -#include "libc/intrin/kprintf.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "libc/sysv/consts/sa.h" diff --git a/libc/thread/pthread_create.c b/libc/thread/pthread_create.c index 0e807fb9d..f4736e8d5 100644 --- a/libc/thread/pthread_create.c +++ b/libc/thread/pthread_create.c @@ -28,7 +28,6 @@ #include "libc/intrin/bits.h" #include "libc/intrin/bsr.h" #include "libc/intrin/dll.h" -#include "libc/intrin/kprintf.h" #include "libc/log/internal.h" #include "libc/macros.internal.h" #include "libc/mem/mem.h" diff --git a/libc/thread/pthread_exit.c b/libc/thread/pthread_exit.c index af44019a4..d7da9949e 100644 --- a/libc/thread/pthread_exit.c +++ b/libc/thread/pthread_exit.c @@ -20,7 +20,6 @@ #include "libc/atomic.h" #include "libc/dce.h" #include "libc/intrin/atomic.h" -#include "libc/intrin/kprintf.h" #include "libc/intrin/strace.internal.h" #include "libc/intrin/weaken.h" #include "libc/limits.h" diff --git a/test/libc/calls/open_test.c b/test/libc/calls/open_test.c index 30e49a227..fb3273a3a 100644 --- a/test/libc/calls/open_test.c +++ b/test/libc/calls/open_test.c @@ -47,6 +47,9 @@ TEST(open, enoent) { TEST(open, enotdir) { ASSERT_SYS(0, 0, touch("o", 0644)); + ASSERT_SYS(ENOTDIR, -1, open("o/", O_RDONLY)); + ASSERT_SYS(ENOTDIR, -1, open("o/.", O_RDONLY)); + ASSERT_SYS(ENOTDIR, -1, open("o/./", O_RDONLY)); ASSERT_SYS(ENOTDIR, -1, open("o/doesnotexist", O_RDONLY)); } diff --git a/test/libc/runtime/zipos_test.c b/test/libc/runtime/zipos_test.c index 46a6109b9..52f0e3e35 100644 --- a/test/libc/runtime/zipos_test.c +++ b/test/libc/runtime/zipos_test.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/calls/struct/stat.h" #include "libc/errno.h" #include "libc/limits.h" #include "libc/mem/gc.h" @@ -82,3 +83,12 @@ TEST(zipos_O_DIRECTORY, blocksOpeningOfNormalFiles) { ASSERT_SYS(ENOTDIR, -1, open("/zip/libc/testlib/hyperion.txt", O_RDONLY | O_DIRECTORY)); } + +TEST(zipos, trailingComponents_willEnodirFile) { + struct stat st; + ASSERT_SYS(ENOTDIR, -1, open("/zip/libc/testlib/hyperion.txt/", O_RDONLY)); + ASSERT_SYS(ENOTDIR, -1, open("/zip/libc/testlib/hyperion.txt/.", O_RDONLY)); + ASSERT_SYS(ENOTDIR, -1, open("/zip/libc/testlib/hyperion.txt/./", O_RDONLY)); + ASSERT_SYS(ENOTDIR, -1, open("/zip/libc/testlib/hyperion.txt/a/b", O_RDONLY)); + ASSERT_SYS(ENOTDIR, -1, stat("/zip/libc/testlib/hyperion.txt/", &st)); +} diff --git a/test/libc/stdio/zipdir_test.c b/test/libc/stdio/zipdir_test.c index f281a2ddd..4dcdc4d9f 100644 --- a/test/libc/stdio/zipdir_test.c +++ b/test/libc/stdio/zipdir_test.c @@ -93,9 +93,10 @@ TEST(__zipos_normpath, vectors) { {"./", ""}, {"..", ""}, {"../", ""}, + {"foo/", "foo/"}, {"../abc/def", "abc/def"}, - {"../abc/def/..", "abc"}, - {"../abc/././././def/..", "abc"}, + {"../abc/def/..", "abc/"}, + {"../abc/././././def/..", "abc/"}, {"////../abc/def", "abc/def"}, {"/../def", "def"}, {"../def", "def"}, @@ -121,11 +122,11 @@ TEST(__zipos_normpath, vectors) { {"../../../a", "a"}, {"../a../../a", "a"}, {"cccc/abc////..////.//../", ""}, - {"aaaa/cccc/abc////..////.//../", "aaaa"}, - {"..//////.///..////..////.//////abc////.////..////def//abc/..", "def"}, + {"aaaa/cccc/abc////..////.//../", "aaaa/"}, + {"..//////.///..////..////.//////abc////.////..////def//abc/..", "def/"}, {"////////////..//////.///..////..////.//////abc////.////..////def//abc/" "..", - "def"}, + "def/"}, }; int fails = 0;