cosmopolitan/libc/calls/mkntpath.c

197 lines
6.4 KiB
C
Raw Permalink Normal View History

2020-06-15 14:18:57 +00:00
/*-*- 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
2020-12-28 01:18:44 +00:00
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.
2020-06-15 14:18:57 +00:00
2020-12-28 01:18:44 +00:00
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.
2020-06-15 14:18:57 +00:00
*/
#include "libc/calls/ntmagicpaths.internal.h"
#include "libc/intrin/strace.internal.h"
2022-05-23 22:06:11 +00:00
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/macros.internal.h"
Add SSL to redbean Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
2021-06-24 19:31:26 +00:00
#include "libc/nt/systeminfo.h"
#include "libc/str/oldutf16.internal.h"
2020-06-15 14:18:57 +00:00
#include "libc/str/str.h"
#include "libc/str/tpdecode.internal.h"
2020-10-27 10:39:46 +00:00
#include "libc/sysv/consts/o.h"
2020-06-15 14:18:57 +00:00
#include "libc/sysv/errfuns.h"
static inline bool IsSlash(char c) {
return c == '/' || c == '\\';
}
static inline int IsAlpha(int c) {
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}
2020-10-27 10:39:46 +00:00
textwindows static const char *FixNtMagicPath(const char *path,
unsigned flags) {
const struct NtMagicPaths *mp = &kNtMagicPaths;
asm("" : "+r"(mp));
if (!IsSlash(path[0])) return path;
2020-12-01 11:43:40 +00:00
if (strcmp(path, mp->devtty) == 0) {
2020-10-27 10:39:46 +00:00
if ((flags & O_ACCMODE) == O_RDONLY) {
return mp->conin;
} else if ((flags & O_ACCMODE) == O_WRONLY) {
return mp->conout;
}
}
2020-12-01 11:43:40 +00:00
if (strcmp(path, mp->devnull) == 0) return mp->nul;
if (strcmp(path, mp->devstdin) == 0) return mp->conin;
if (strcmp(path, mp->devstdout) == 0) return mp->conout;
2020-10-27 10:39:46 +00:00
return path;
}
2020-12-01 11:43:40 +00:00
textwindows int __mkntpath(const char *path,
char16_t path16[hasatleast PATH_MAX]) {
2020-12-01 11:43:40 +00:00
return __mkntpath2(path, path16, -1);
}
2020-06-15 14:18:57 +00:00
/**
* Copies path for Windows NT.
*
* This entails (1) UTF-8 to UTF-16 conversion; (2) replacing
* forward-slashes with backslashes; and (3) remapping several
* well-known paths (e.g. /dev/null NUL) for convenience.
*
2020-10-27 10:39:46 +00:00
* @param flags is used by open()
2020-06-15 14:18:57 +00:00
* @param path16 is shortened so caller can prefix, e.g. \\.\pipe\, and
* due to a plethora of special-cases throughout the Win32 API
* @return short count excluding NUL on success, or -1 w/ errno
* @error ENAMETOOLONG
*/
2020-12-01 11:43:40 +00:00
textwindows int __mkntpath2(const char *path,
char16_t path16[hasatleast PATH_MAX], int flags) {
2020-06-15 14:18:57 +00:00
/*
* 1. Need +1 for NUL-terminator
* 2. Need +1 for UTF-16 overflow
* 3. Need 2 for SetCurrentDirectory trailing slash requirement
* 5. Need 13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
* which is an "8.3 filename" from the DOS days
2020-06-15 14:18:57 +00:00
*/
const char *q;
bool isdospath;
char16_t c, *p;
size_t i, j, n, m, x, z;
2021-02-07 14:11:44 +00:00
if (!path) return efault();
2020-10-27 10:39:46 +00:00
path = FixNtMagicPath(path, flags);
Add SSL to redbean Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
2021-06-24 19:31:26 +00:00
p = path16;
q = path;
if (IsSlash(q[0]) && IsAlpha(q[1]) && IsSlash(q[2])) {
z = MIN(32767, PATH_MAX);
// turn "\c\foo" into "\\?\c:\foo"
p[0] = '\\';
p[1] = '\\';
p[2] = '?';
p[3] = '\\';
p[4] = q[1];
p[5] = ':';
p[6] = '\\';
p += 7;
q += 3;
z -= 7;
x = 7;
} else if (IsSlash(q[0]) && IsAlpha(q[1]) && !q[2]) {
z = MIN(32767, PATH_MAX);
// turn "\c" into "\\?\c:\"
p[0] = '\\';
p[1] = '\\';
p[2] = '?';
p[3] = '\\';
p[4] = q[1];
p[5] = ':';
p[6] = '\\';
p += 7;
q += 2;
z -= 7;
x = 7;
} else if (IsSlash(q[0]) && IsAlpha(q[1]) && IsSlash(q[2])) {
z = MIN(32767, PATH_MAX);
// turn "c:\foo" into "\\?\c:\foo"
p[0] = '\\';
p[1] = '\\';
p[2] = '?';
p[3] = '\\';
p[4] = q[0];
p[5] = ':';
p[6] = '\\';
p += 7;
q += 3;
z -= 7;
x = 7;
} else if (IsSlash(q[0]) && IsSlash(q[1]) && q[2] == '?' && IsSlash(q[3])) {
z = MIN(32767, PATH_MAX);
x = 0;
} else {
z = MIN(260, PATH_MAX);
x = 0;
}
// turn /tmp into GetTempPath()
if (!x && IsSlash(q[0]) && q[1] == 't' && q[2] == 'm' && q[3] == 'p' &&
(IsSlash(q[4]) || !q[4])) {
Add SSL to redbean Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
2021-06-24 19:31:26 +00:00
m = GetTempPath(z, p);
if (!q[4]) return m;
q += 5;
p += m;
z -= m;
} else {
m = 0;
}
// turn utf-8 into utf-16
Add SSL to redbean Your redbean can now interoperate with clients that require TLS crypto. This is accomplished using a protocol polyglot that lets us distinguish between HTTP and HTTPS regardless of the port number. Certificates will be generated automatically, if none are supplied by the user. Footprint increases by only a few hundred kb so redbean in MODY=tiny is now 1.0mb - Add lseek() polyfills for ZIP executable - Automatically polyfill /tmp/FOO paths on NT - Fix readdir() / ftw() / nftw() bugs on Windows - Introduce -B flag for slower SSL that's stronger - Remove mbedtls features Cosmopolitan doesn't need - Have base64 decoder support the uri-safe alternative - Remove Truncated HMAC because it's forbidden by the IETF - Add all the mbedtls test suites and make them go 3x faster - Support opendir() / readdir() / closedir() on ZIP executable - Use Everest for ECDHE-ECDSA because it's so good it's so good - Add tinier implementation of sha1 since it's not worth the rom - Add chi-square monte-carlo mean correlation tests for getrandom() - Source entropy on Windows from the proper interface everyone uses We're continuing to outperform NGINX and other servers on raw message throughput. Using SSL means that instead of 1,000,000 qps you can get around 300,000 qps. However redbean isn't as fast as NGINX yet at SSL handshakes, since redbean can do 2,627 per second and NGINX does 4.3k Right now, the SSL UX story works best if you give your redbean a key signing key since that can be easily generated by openssl using a one liner then redbean will do all the things that are impossibly hard to do like signing ecdsa and rsa certificates that'll work in chrome. We should integrate the let's encrypt acme protocol in the future. Live Demo: https://redbean.justine.lol/ Root Cert: https://redbean.justine.lol/redbean1.crt
2021-06-24 19:31:26 +00:00
n = tprecode8to16(p, z, q).ax;
if (n >= z - 1) {
STRACE("path too long for windows: %#s", path);
return enametoolong();
}
// 1. turn `/` into `\`
// 2. turn `\\` into `\` if not at beginning
for (j = i = 0; i < n; ++i) {
c = p[i];
if (c == '/') {
c = '\\';
2020-06-15 14:18:57 +00:00
}
if (j > 1 && c == '\\' && p[j - 1] == '\\') {
continue;
}
p[j++] = c;
2020-06-15 14:18:57 +00:00
}
p[j] = 0;
n = j;
vista: backport execve escaping and using cocmd as shell for system, etc. (#660) * Introduce testlib_extract() helper * Have execve() escape double quotes in cmd.exe's preferred style This makes it possible for us to use system() and popen() with paths that redirect to filenames that contain spaces, e.g. system("echo.com hello >\"hello there.txt\"") It's difficult to solve this problem, because WIN32 only allows passing one single argument when launching programs and each program is allowed to tokenize that however it wants. Most software follows the convention of cmd.exe which is poorly documented and positively byzantine. In the future we're going to solve this by not using cmd.exe at all and instead embedding the cocmd.com interpreter into the system() function. In the meantime, our documentation has been updated to help recalibrate any expectation the user might hold regarding the security of using the Windows command interpreter. Fixes #644 * Introduce double quote support in cocmd.com shell * Add some tests for execve() * Embed cocmd.com interpreter for system() / open() This change lets you use system() in an easier and portable way. The problem with the call in the past has always been that bourne and cmd.com on Windows have less than nothing in common, so pretty much the only command system() could be used for across platforms was maybe echo. cmd.exe is also a security liability due to its escaping rules. Since cocmd.com implements 85% of what we need from bourne, in a really tiny way, it makes perfect sense to be embedded in these functionss. We get a huge performance boost too. Fixes #644 * Support whitespace after cocmd output redirection Co-authored-by: Justine Tunney <jtunney@gmail.com>
2022-10-12 04:17:50 +00:00
// our path is now stored at `path16` with length `n`
n = x + m + n;
// To avoid toil like this:
//
// CMD.EXE was started with the above path as the current directory.
// UNC paths are not supported. Defaulting to Windows directory.
// Access is denied.
//
// Remove \\?\ prefix if we're within 260 character limit.
if (n > 4 && n < 260 && //
path16[0] == '\\' && //
path16[1] == '\\' && //
path16[2] == '?' && //
path16[3] == '\\') {
memmove(path16, path16 + 4, (n - 4 + 1) * sizeof(char16_t));
n -= 4;
}
return n;
2020-06-15 14:18:57 +00:00
}