mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-05 02:38:31 +00:00
Fix basename() and dirname()
This commit is contained in:
parent
9b11206ae3
commit
04d39d47f1
41 changed files with 489 additions and 207 deletions
|
@ -24,7 +24,7 @@
|
|||
* @param line is NULL-propagating
|
||||
* @see getline
|
||||
*/
|
||||
char *chomp(char *line) {
|
||||
char *_chomp(char *line) {
|
||||
size_t i;
|
||||
if (line) {
|
||||
for (i = strlen(line); i--;) {
|
||||
|
|
|
@ -24,7 +24,16 @@
|
|||
* @param line is NULL-propagating
|
||||
* @see getline
|
||||
*/
|
||||
char16_t *chomp16(char16_t *line) {
|
||||
if (line) line[strcspn16(line, u"\r\n")] = '\0';
|
||||
char16_t *_chomp16(char16_t *line) {
|
||||
size_t i;
|
||||
if (line) {
|
||||
for (i = strlen16(line); i--;) {
|
||||
if (line[i] == '\r' || line[i] == '\n') {
|
||||
line[i] = '\0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
|
154
libc/str/classifypath.c
Normal file
154
libc/str/classifypath.c
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*-*- 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 2022 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/dce.h"
|
||||
#include "libc/str/path.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Classifies file path name.
|
||||
*
|
||||
* For the purposes of this function, we always consider backslash
|
||||
* interchangeable with forward slash, even though the underlying
|
||||
* operating system might not. Therefore, for the sake of clarity,
|
||||
* remaining documentation will only use the forward slash.
|
||||
*
|
||||
* This function behaves the same on all platforms. For instance, this
|
||||
* function will categorize `C:/FOO.BAR` as a DOS path, even if you're
|
||||
* running on UNIX rather than DOS.
|
||||
*
|
||||
* If you wish to check if a pathname is absolute, in a manner that's
|
||||
* inclusive of DOS drive paths, DOS rooted paths, in addition to the
|
||||
* New Technology UNC paths, then you may do the following:
|
||||
*
|
||||
* if (_classifypath(str) & _PATH_ABS) { ... }
|
||||
*
|
||||
* To check if path is a relative path:
|
||||
*
|
||||
* if (~_classifypath(str) & _PATH_ABS) { ... }
|
||||
*
|
||||
* Please note the above check includes rooted paths such as `\foo`
|
||||
* which is considered absolute by MSDN and we consider it absolute
|
||||
* although, it's technically relative to the current drive letter.
|
||||
*
|
||||
* Please note that `/foo/bar` is an absolute path on Windows, even
|
||||
* though it's actually a rooted path that's considered relative to
|
||||
* current drive by WIN32.
|
||||
*
|
||||
* @return integer value that's one of following:
|
||||
* - `0` if non-weird relative path e.g. `c`
|
||||
* - `_PATH_ABS` if absolute (or rooted dos) path e.g. `/⋯`
|
||||
* - `_PATH_DOS` if `c:`, `d:foo` i.e. drive-relative path
|
||||
* - `_PATH_ABS|_PATH_DOS` if proper dos path e.g. `c:/foo`
|
||||
* - `_PATH_DOS|_PATH_DEV` if dos device path e.g. `nul`, `conin$`
|
||||
* - `_PATH_ABS|_PATH_WIN` if `//c`, `//?c`, etc.
|
||||
* - `_PATH_ABS|_PATH_WIN|_PATH_DEV` if `//./⋯`, `//?/⋯`
|
||||
* - `_PATH_ABS|_PATH_WIN|_PATH_DEV|_PATH_ROOT` if `//.` or `//?`
|
||||
* - `_PATH_ABS|_PATH_NT` e.g. `\??\\⋯` (undoc. strict backslash)
|
||||
* @see "The Definitive Guide on Win32 to NT Path Conversion", James
|
||||
* Forshaw, Google Project Zero Blog, 2016-02-29
|
||||
* @see "Naming Files, Paths, and Namespaces", MSDN 01/04/2021
|
||||
*/
|
||||
int _classifypath(const char *s) {
|
||||
if (s) {
|
||||
switch (s[0]) {
|
||||
case 0: // ""
|
||||
return 0;
|
||||
default:
|
||||
if (!SupportsWindows()) {
|
||||
return 0;
|
||||
}
|
||||
if (((((s[0] == 'a' || s[0] == 'A') && // aux
|
||||
(s[1] == 'u' || s[1] == 'U') && //
|
||||
(s[2] == 'x' || s[2] == 'X')) || //
|
||||
((s[0] == 'p' || s[0] == 'P') && // prn
|
||||
(s[1] == 'r' || s[1] == 'R') && //
|
||||
(s[2] == 'n' || s[2] == 'N')) || //
|
||||
((s[0] == 'n' || s[0] == 'N') && // nul
|
||||
(s[1] == 'u' || s[1] == 'U') && //
|
||||
(s[2] == 'l' || s[2] == 'L')) || //
|
||||
((s[0] == 'c' || s[0] == 'C') && // con
|
||||
(s[1] == 'o' || s[1] == 'O') && //
|
||||
(s[2] == 'n' || s[2] == 'N'))) && //
|
||||
!s[3]) ||
|
||||
((((s[0] == 'l' || s[0] == 'L') && // lpt
|
||||
(s[1] == 'p' || s[1] == 'P') && //
|
||||
(s[2] == 't' || s[2] == 'T')) || //
|
||||
((s[0] == 'c' || s[0] == 'C') && // com
|
||||
(s[1] == 'o' || s[1] == 'O') && //
|
||||
(s[2] == 'm' || s[2] == 'M'))) && //
|
||||
('1' <= s[3] && s[3] <= '9') && //
|
||||
!s[4])) {
|
||||
return _PATH_DOS | _PATH_DEV;
|
||||
}
|
||||
switch (s[1]) {
|
||||
case ':':
|
||||
switch (s[2]) {
|
||||
case 0: // c:
|
||||
default: // c:wut⋯
|
||||
return _PATH_DOS;
|
||||
case '/': // c:/⋯
|
||||
case '\\': // c:\⋯
|
||||
return _PATH_ABS | _PATH_DOS;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case '\\':
|
||||
if (SupportsWindows()) {
|
||||
if (s[1] == '?' && s[2] == '?') {
|
||||
if (!s[3]) {
|
||||
return _PATH_ABS | _PATH_NT | _PATH_ROOT; // \??\⋯
|
||||
} else if (s[3] == '\\') {
|
||||
return _PATH_ABS | _PATH_NT; // \??\⋯
|
||||
}
|
||||
}
|
||||
}
|
||||
// fallthrough
|
||||
case '/':
|
||||
if (!SupportsWindows()) {
|
||||
return _PATH_ABS;
|
||||
}
|
||||
switch (s[1]) {
|
||||
case 0: // /
|
||||
default: // /⋯
|
||||
return _PATH_ABS;
|
||||
case '/':
|
||||
case '\\':
|
||||
switch (s[2]) {
|
||||
case 0: // //
|
||||
default: // //⋯
|
||||
return _PATH_ABS | _PATH_WIN;
|
||||
case '.':
|
||||
case '?':
|
||||
switch (s[3]) {
|
||||
case 0: // //? or //.
|
||||
return _PATH_ABS | _PATH_WIN | _PATH_DEV | _PATH_ROOT;
|
||||
default: // //?⋯ or //.⋯
|
||||
return _PATH_ABS | _PATH_WIN;
|
||||
case '/':
|
||||
case '\\': // //?/⋯ or //./⋯
|
||||
return _PATH_ABS | _PATH_WIN | _PATH_DEV;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -43,8 +43,8 @@ static textwindows bool shouldquotedos(const char16_t c) {
|
|||
* Escapes command so DOS can run it.
|
||||
* @see Iain Patterson's NSSM for original code in public domain
|
||||
*/
|
||||
textwindows bool escapedos(char16_t *buffer, unsigned buflen,
|
||||
const char16_t *unquoted, unsigned len) {
|
||||
textwindows bool _escapedos(char16_t *buffer, unsigned buflen,
|
||||
const char16_t *unquoted, unsigned len) {
|
||||
unsigned i, j, n;
|
||||
if (len > buflen - 1) return false;
|
||||
bool escape = false;
|
||||
|
|
|
@ -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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2020 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 │
|
||||
|
@ -16,33 +16,21 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/str/path.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns true if pathname is absolute, e.g.
|
||||
* Returns true if pathname is considered absolute.
|
||||
*
|
||||
* - `/home/jart/foo.txt` is absolute
|
||||
* - `C:/Users/jart/foo.txt` is absolute on NT
|
||||
* - `C:\Users\jart\foo.txt` is absolute on NT
|
||||
* - `\??\C:\Users\jart\foo.txt` is absolute on NT
|
||||
* - `\\.\C:\Users\jart\foo.txt` is absolute on NT
|
||||
* - `/Users/jart/foo.txt` we consider it absolute enough on NT
|
||||
* - `\Users\jart\foo.txt` we consider it absolute enough on NT
|
||||
* - `C:/Users/jart/foo.txt` is absolute on Windows
|
||||
* - `C:\Users\jart\foo.txt` is absolute on Windows
|
||||
* - `\??\C:\Users\jart\foo.txt` is absolute on Windows
|
||||
* - `\\.\C:\Users\jart\foo.txt` is absolute on Windows
|
||||
* - `/Users/jart/foo.txt` is effectively absolute on Windows
|
||||
* - `\Users\jart\foo.txt` is effectively absolute on Windows
|
||||
*
|
||||
* Please note that the recommended approach to using Cosmopolitan is to
|
||||
* not use absolute paths at all. If you do use absolute paths then it's
|
||||
* a good idea on Windows to stay within the C: drive. This is because
|
||||
* Cosmopolitan Libc doesn't create a virtual filesystem layer and
|
||||
* instead just replaces `\` characters with `/`.
|
||||
*/
|
||||
bool _isabspath(const char *p) {
|
||||
if (*p == '/') {
|
||||
return true;
|
||||
}
|
||||
if (IsWindows() &&
|
||||
(*p == '/' || *p == '\\' || (isalpha(p[0]) && p[1] == ':'))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool _isabspath(const char *path) {
|
||||
return _classifypath(path) & _PATH_ABS;
|
||||
}
|
||||
|
|
27
libc/str/isdirsep.c
Normal file
27
libc/str/isdirsep.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- 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 2022 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/dce.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns true if character is directory separator slash.
|
||||
*/
|
||||
bool _isdirsep(int c) {
|
||||
return c == '/' || c == '\\';
|
||||
}
|
20
libc/str/path.h
Normal file
20
libc/str/path.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_PATH_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_PATH_H_
|
||||
|
||||
#define _PATH_ABS 1
|
||||
#define _PATH_DEV 2
|
||||
#define _PATH_ROOT 4
|
||||
#define _PATH_DOS 8
|
||||
#define _PATH_WIN 16
|
||||
#define _PATH_NT 32
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int _classifypath(const char *) libcesque nosideeffect;
|
||||
bool _isabspath(const char *) libcesque strlenesque;
|
||||
bool _isdirsep(int) libcesque pureconst;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_PATH_H_ */
|
|
@ -196,17 +196,16 @@ char *strerror(int) returnsnonnull dontthrow nocallback;
|
|||
long a64l(const char *);
|
||||
char *l64a(long);
|
||||
|
||||
char *strntolower(char *, size_t);
|
||||
char *strtolower(char *) paramsnonnull();
|
||||
char *strntoupper(char *, size_t);
|
||||
char *strtoupper(char *) paramsnonnull();
|
||||
char *chomp(char *);
|
||||
char16_t *chomp16(char16_t *);
|
||||
wchar_t *wchomp(wchar_t *);
|
||||
bool _istext(const void *, size_t);
|
||||
bool _isutf8(const void *, size_t);
|
||||
bool _isabspath(const char *) strlenesque;
|
||||
bool escapedos(char16_t *, unsigned, const char16_t *, unsigned);
|
||||
char *strntolower(char *, size_t) libcesque;
|
||||
char *strtolower(char *) libcesque paramsnonnull();
|
||||
char *strntoupper(char *, size_t) libcesque;
|
||||
char *strtoupper(char *) libcesque paramsnonnull();
|
||||
char *_chomp(char *) libcesque;
|
||||
char16_t *_chomp16(char16_t *) libcesque;
|
||||
wchar_t *_wchomp(wchar_t *) libcesque;
|
||||
bool _istext(const void *, size_t) libcesque;
|
||||
bool _isutf8(const void *, size_t) libcesque;
|
||||
bool _escapedos(char16_t *, unsigned, const char16_t *, unsigned) libcesque;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » multibyte ─╬─│┼
|
||||
|
|
|
@ -24,7 +24,16 @@
|
|||
* @param line is NULL-propagating
|
||||
* @see getline
|
||||
*/
|
||||
wchar_t *wchomp(wchar_t *line) {
|
||||
if (line) line[wcscspn(line, L"\r\n")] = '\0';
|
||||
wchar_t *_wchomp(wchar_t *line) {
|
||||
size_t i;
|
||||
if (line) {
|
||||
for (i = wcslen(line); i--;) {
|
||||
if (line[i] == '\r' || line[i] == '\n') {
|
||||
line[i] = '\0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue