drop unused functions and configure checks

Remove the following C++ functions/methods, which have no callers:

common.cpp:
- read_loop
- narrow_string_safe
- escape_string_for_double_quotes
- read_unquoted_escape
- format_size
- format_size_safe
- valid_func_name
- get_executable_path

env.cpp:
- env_stack_t::set_empty
- env_stack_t::set_argv

fallback.cpp:
- fish_mkstemp_cloexec
- flock

proc_util.cpp:
- parse_util_slice_length
- parse_util_argument_is_help

path.cpp:
- path_get_path
- path_as_implicit_cd
- path_apply_working_directory
- path_emit_config_directory_messages
- path_get_data_remoteness
- path_get_config_remoteness
- path_is_valid
- paths_are_same_file

wcstringutil.cpp:
- split_string_tok

wutil.cpp:
- wgetcwd
- wunlink
- wrealpath
- wrename
- file_id_for_path
- fish_wcstoull

Also drop unused configure checks/defines:
- HAVE_FLOCK
This commit is contained in:
David Adam 2023-11-20 15:21:58 +08:00
parent f773697bc1
commit f2f41c6eec
18 changed files with 0 additions and 917 deletions

View File

@ -118,7 +118,6 @@ check_cxx_symbol_exists(ctermid_r stdio.h HAVE_CTERMID_R)
check_struct_has_member("struct dirent" d_type dirent.h HAVE_STRUCT_DIRENT_D_TYPE LANGUAGE CXX)
check_cxx_symbol_exists(dirfd "sys/types.h;dirent.h" HAVE_DIRFD)
check_include_file_cxx(execinfo.h HAVE_EXECINFO_H)
check_cxx_symbol_exists(flock sys/file.h HAVE_FLOCK)
check_cxx_symbol_exists(getpwent pwd.h HAVE_GETPWENT)
check_cxx_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE)
check_cxx_symbol_exists(gettext libintl.h HAVE_GETTEXT)

View File

@ -16,9 +16,6 @@
/* Define to 1 if you have the <execinfo.h> header file. */
#cmakedefine HAVE_EXECINFO_H 1
/* Define to 1 if you have the `flock' function. */
#cmakedefine HAVE_FLOCK 1
/* Define to 1 if you have the `getpwent' function. */
#cmakedefine HAVE_GETPWENT 1

View File

@ -231,36 +231,6 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE
----
**License for flock**
``fish`` also contains small amounts of code from NetBSD, namely the ``flock`` fallback function. This code is copyright 2001 The NetBSD Foundation, Inc., and derived from software contributed to The NetBSD Foundation by Todd Vierling.
The NetBSD license follows.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
----
**MIT License**
``fish`` includes a copy of Alpine.js, which is copyright 2019-2021 Caleb Porzio and contributors, and licensed under the MIT License. It also includes the Dracula theme, which is copyright 2018 Dracula Team, and is licensed under the same license.

View File

@ -572,14 +572,6 @@ ssize_t write_loop(int fd, const char *buff, size_t count) {
return static_cast<ssize_t>(out_cum);
}
ssize_t read_loop(int fd, void *buff, size_t count) {
ssize_t result;
do {
result = read(fd, buff, count);
} while (result < 0 && (errno == EAGAIN || errno == EINTR));
return result;
}
/// Hack to not print error messages in the tests. Do not call this from functions in this module
/// like `debug()`. It is only intended to suppress diagnostic noise from testing things like the
/// fish parser where we expect a lot of diagnostic messages due to testing error conditions.
@ -645,20 +637,6 @@ void format_ullong_safe(wchar_t buff[64], unsigned long long val) {
return format_safe_impl(buff, 64, val);
}
void narrow_string_safe(char buff[64], const wchar_t *s) {
size_t idx = 0;
for (size_t widx = 0; s[widx] != L'\0'; widx++) {
wchar_t c = s[widx];
if (c <= 127) {
buff[idx++] = char(c);
if (idx + 1 == 64) {
break;
}
}
}
buff[idx] = '\0';
}
/// Escape a string in a fashion suitable for using as a URL. Store the result in out_str.
static void escape_string_url(const wcstring &in, wcstring &out) {
auto result = escape_string_url(in.c_str(), in.size());
@ -675,22 +653,6 @@ static void escape_string_var(const wcstring &in, wcstring &out) {
}
}
wcstring escape_string_for_double_quotes(wcstring in) {
// We need to escape backslashes, double quotes, and dollars only.
wcstring result = std::move(in);
size_t idx = result.size();
while (idx--) {
switch (result[idx]) {
case L'\\':
case L'$':
case L'"':
result.insert(idx, 1, L'\\');
break;
}
}
return result;
}
/// Escape a string in a fashion suitable for using in fish script. Store the result in out_str.
static void escape_string_script(const wchar_t *orig_in, size_t in_len, wcstring &out,
escape_flags_t flags) {
@ -785,228 +747,6 @@ wcstring escape_string(const wcstring &in, escape_flags_t flags, escape_string_s
return result;
}
/// Given a null terminated string starting with a backslash, read the escape as if it is unquoted,
/// appending to result. Return the number of characters consumed, or none on error.
maybe_t<size_t> read_unquoted_escape(const wchar_t *input, wcstring *result, bool allow_incomplete,
bool unescape_special) {
assert(input[0] == L'\\' && "Not an escape");
// Here's the character we'll ultimately append, or none. Note that L'\0' is a
// valid thing to append.
maybe_t<wchar_t> result_char_or_none = none();
bool errored = false;
size_t in_pos = 1; // in_pos always tracks the next character to read (and therefore the number
// of characters read so far)
// For multibyte \X sequences.
std::string byte_buff;
while (true) {
const wchar_t c = input[in_pos++];
switch (c) {
// A null character after a backslash is an error.
case L'\0': {
// Adjust in_pos to only include the backslash.
assert(in_pos > 0);
in_pos--;
// It's an error, unless we're allowing incomplete escapes.
if (!allow_incomplete) errored = true;
break;
}
// Numeric escape sequences. No prefix means octal escape, otherwise hexadecimal.
case L'0':
case L'1':
case L'2':
case L'3':
case L'4':
case L'5':
case L'6':
case L'7':
case L'u':
case L'U':
case L'x':
case L'X': {
long long res = 0;
size_t chars = 2;
int base = 16;
bool byte_literal = false;
wchar_t max_val = ASCII_MAX;
switch (c) {
case L'u': {
chars = 4;
max_val = UCS2_MAX;
break;
}
case L'U': {
chars = 8;
max_val = WCHAR_MAX;
// Don't exceed the largest Unicode code point - see #1107.
if (0x10FFFF < max_val) max_val = static_cast<wchar_t>(0x10FFFF);
break;
}
case L'x':
case L'X': {
byte_literal = true;
max_val = BYTE_MAX;
break;
}
default: {
base = 8;
chars = 3;
// Note that in_pos currently is just after the first post-backslash
// character; we want to start our escape from there.
assert(in_pos > 0);
in_pos--;
break;
}
}
for (size_t i = 0; i < chars; i++) {
long d = convert_digit(input[in_pos], base);
if (d < 0) {
// If we have no digit, this is a tokenizer error.
if (i == 0) errored = true;
break;
}
res = (res * base) + d;
in_pos++;
}
if (!errored && res <= max_val) {
if (byte_literal) {
// Multibyte encodings necessitate that we keep adjacent byte escapes.
// - `\Xc3\Xb6` is "ö", but only together.
// (this assumes a valid codepoint can't consist of multiple bytes
// that are valid on their own, which is true for UTF-8)
byte_buff.push_back(static_cast<char>(res));
result_char_or_none = none();
if (input[in_pos] == L'\\' &&
(input[in_pos + 1] == L'X' || input[in_pos + 1] == L'x')) {
in_pos++;
continue;
}
} else {
result_char_or_none = static_cast<wchar_t>(res);
}
} else {
errored = true;
}
break;
}
// \a means bell (alert).
case L'a': {
result_char_or_none = L'\a';
break;
}
// \b means backspace.
case L'b': {
result_char_or_none = L'\b';
break;
}
// \cX means control sequence X.
case L'c': {
const wchar_t sequence_char = input[in_pos++];
if (sequence_char >= L'a' && sequence_char <= (L'a' + 32)) {
result_char_or_none = sequence_char - L'a' + 1;
} else if (sequence_char >= L'A' && sequence_char <= (L'A' + 32)) {
result_char_or_none = sequence_char - L'A' + 1;
} else {
errored = true;
}
break;
}
// \x1B means escape.
case L'e': {
result_char_or_none = L'\x1B';
break;
}
// \f means form feed.
case L'f': {
result_char_or_none = L'\f';
break;
}
// \n means newline.
case L'n': {
result_char_or_none = L'\n';
break;
}
// \r means carriage return.
case L'r': {
result_char_or_none = L'\r';
break;
}
// \t means tab.
case L't': {
result_char_or_none = L'\t';
break;
}
// \v means vertical tab.
case L'v': {
result_char_or_none = L'\v';
break;
}
// If a backslash is followed by an actual newline, swallow them both.
case L'\n': {
result_char_or_none = none();
break;
}
default: {
if (unescape_special) result->push_back(INTERNAL_SEPARATOR);
result_char_or_none = c;
break;
}
}
if (errored) return none();
if (!byte_buff.empty()) {
result->append(str2wcstring(byte_buff));
}
break;
}
if (result_char_or_none.has_value()) {
result->push_back(*result_char_or_none);
}
return in_pos;
}
wcstring format_size(long long sz) {
wcstring result;
const wchar_t *sz_name[] = {L"kB", L"MB", L"GB", L"TB", L"PB", L"EB", L"ZB", L"YB", nullptr};
if (sz < 0) {
result.append(L"unknown");
} else if (sz < 1) {
result.append(_(L"empty"));
} else if (sz < 1024) {
result.append(format_string(L"%lldB", sz));
} else {
int i;
for (i = 0; sz_name[i]; i++) {
if (sz < (1024 * 1024) || !sz_name[i + 1]) {
long isz = (static_cast<long>(sz)) / 1024;
if (isz > 9)
result.append(format_string(L"%ld%ls", isz, sz_name[i]));
else
result.append(
format_string(L"%.1f%ls", static_cast<double>(sz) / 1024, sz_name[i]));
break;
}
sz /= 1024;
}
}
return result;
}
/// Crappy function to extract the most significant digit of an unsigned long long value.
static char extract_most_significant_digit(unsigned long long *xp) {
unsigned long long place_value = 1;
@ -1019,53 +759,6 @@ static char extract_most_significant_digit(unsigned long long *xp) {
return x + '0';
}
static void append_ull(char *buff, unsigned long long val, size_t *inout_idx, size_t max_len) {
size_t idx = *inout_idx;
while (val > 0 && idx < max_len) buff[idx++] = extract_most_significant_digit(&val);
*inout_idx = idx;
}
static void append_str(char *buff, const char *str, size_t *inout_idx, size_t max_len) {
size_t idx = *inout_idx;
while (*str && idx < max_len) buff[idx++] = *str++;
*inout_idx = idx;
}
void format_size_safe(char buff[128], unsigned long long sz) {
const size_t buff_size = 128;
const size_t max_len = buff_size - 1; // need to leave room for a null terminator
std::memset(buff, 0, buff_size);
size_t idx = 0;
const char *const sz_name[] = {"kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", nullptr};
if (sz < 1) {
strcpy(buff, "empty");
} else if (sz < 1024) {
append_ull(buff, sz, &idx, max_len);
append_str(buff, "B", &idx, max_len);
} else {
for (size_t i = 0; sz_name[i]; i++) {
if (sz < (1024 * 1024) || !sz_name[i + 1]) {
unsigned long long isz = sz / 1024;
if (isz > 9) {
append_ull(buff, isz, &idx, max_len);
} else {
append_ull(buff, isz, &idx, max_len);
// Maybe append a single fraction digit.
unsigned long long remainder = sz % 1024;
if (remainder > 0) {
char tmp[3] = {'.', extract_most_significant_digit(&remainder), 0};
append_str(buff, tmp, &idx, max_len);
}
}
append_str(buff, sz_name[i], &idx, max_len);
break;
}
sz /= 1024;
}
}
}
double timef() {
struct timeval tv;
assert_with_errno(gettimeofday(&tv, nullptr) != -1);
@ -1148,75 +841,6 @@ bool valid_var_name(const wchar_t *str) {
return true;
}
/// Test if the string is a valid function name.
bool valid_func_name(const wcstring &str) {
if (str.empty()) return false;
if (str.at(0) == L'-') return false;
// A function name needs to be a valid path, so no / and no NULL.
if (str.find_first_of(L'/') != wcstring::npos) return false;
if (str.find_first_of(L'\0') != wcstring::npos) return false;
return true;
}
/// Return the path to the current executable. This needs to be realpath'd.
std::string get_executable_path(const char *argv0) {
char buff[PATH_MAX];
#ifdef __APPLE__
// On OS X use it's proprietary API to get the path to the executable.
// This is basically grabbing exec_path after argc, argv, envp, ...: for us
// https://opensource.apple.com/source/adv_cmds/adv_cmds-163/ps/print.c
uint32_t buffSize = sizeof buff;
if (_NSGetExecutablePath(buff, &buffSize) == 0) return std::string(buff);
#elif defined(__BSD__) && defined(KERN_PROC_PATHNAME)
// BSDs do not have /proc by default, (although it can be mounted as procfs via the Linux
// compatibility layer). We can use sysctl instead: per sysctl(3), passing in a process ID of -1
// returns the value for the current process.
size_t buff_size = sizeof buff;
#if defined(__NetBSD__)
int name[] = {CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_PATHNAME};
#else
int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
#endif
int result = sysctl(name, sizeof(name) / sizeof(int), buff, &buff_size, nullptr, 0);
if (result != 0) {
wperror(L"sysctl KERN_PROC_PATHNAME");
} else {
return std::string(buff);
}
#else
// On other unixes, fall back to the Linux-ish /proc/ directory
ssize_t len;
len = readlink("/proc/self/exe", buff, sizeof buff - 1); // Linux
if (len == -1) {
len = readlink("/proc/curproc/file", buff, sizeof buff - 1); // other BSDs
if (len == -1) {
len = readlink("/proc/self/path/a.out", buff, sizeof buff - 1); // Solaris
}
}
if (len > 0) {
buff[len] = '\0';
// When /proc/self/exe points to a file that was deleted (or overwritten on update!)
// then linux adds a " (deleted)" suffix.
// If that's not a valid path, let's remove that awkward suffix.
std::string buffstr{buff};
if (access(buff, F_OK)) {
auto dellen = const_strlen(" (deleted)");
if (buffstr.size() > dellen &&
buffstr.compare(buffstr.size() - dellen, dellen, " (deleted)") == 0) {
buffstr = buffstr.substr(0, buffstr.size() - dellen);
}
}
return buffstr;
}
#endif
// Just return argv0, which probably won't work (i.e. it's not an absolute path or a path
// relative to the working directory, but instead something the caller found via $PATH). We'll
// eventually fall back to the compile time paths.
return std::string(argv0 ? argv0 : "");
}
/// Return a path to a directory where we can store temporary files.
std::string get_path_to_tmp_dir() {
char *env_tmpdir = getenv("TMPDIR");

View File

@ -321,21 +321,12 @@ bool should_suppress_stderr_for_tests();
#define likely(x) __builtin_expect(bool(x), 1)
#define unlikely(x) __builtin_expect(bool(x), 0)
/// Format the specified size (in bytes, kilobytes, etc.) into the specified stringbuffer.
wcstring format_size(long long sz);
/// Version of format_size that does not allocate memory.
void format_size_safe(char buff[128], unsigned long long sz);
/// Writes out a long safely.
void format_long_safe(char buff[64], long val);
void format_long_safe(wchar_t buff[64], long val);
void format_llong_safe(wchar_t buff[64], long long val);
void format_ullong_safe(wchar_t buff[64], unsigned long long val);
/// "Narrows" a wide character string. This just grabs any ASCII characters and truncates.
void narrow_string_safe(char buff[64], const wchar_t *s);
/// Stored in blocks to reference the file which created the block.
using filename_ref_t = std::shared_ptr<wcstring>;
@ -475,10 +466,6 @@ long read_blocked(int fd, void *buf, size_t count);
/// error.
ssize_t write_loop(int fd, const char *buff, size_t count);
/// Loop a read request while failure is non-critical. Return -1 and set errno in case of critical
/// error.
ssize_t read_loop(int fd, void *buff, size_t count);
/// Replace special characters with backslash escape sequences. Newline is replaced with \n, etc.
///
/// \param in The string to be escaped
@ -489,19 +476,10 @@ wcstring escape_string(const wchar_t *in, escape_flags_t flags = 0,
wcstring escape_string(const wcstring &in, escape_flags_t flags = 0,
escape_string_style_t style = STRING_STYLE_SCRIPT);
/// Escape a string so that it may be inserted into a double-quoted string.
/// This permits ownership transfer.
wcstring escape_string_for_double_quotes(wcstring in);
/// Expand backslashed escapes and substitute them with their unescaped counterparts. Also
/// optionally change the wildcards, the tilde character and a few more into constants which are
/// defined in a private use area of Unicode. This assumes wchar_t is a unicode character set.
/// Given a null terminated string starting with a backslash, read the escape as if it is unquoted,
/// appending to result. Return the number of characters consumed, or none() on error.
maybe_t<size_t> read_unquoted_escape(const wchar_t *input, wcstring *result, bool allow_incomplete,
bool unescape_special);
/// Return the number of seconds from the UNIX epoch, with subsecond precision. This function uses
/// the gettimeofday function and will have the same precision as that function.
using timepoint_t = double;
@ -552,7 +530,6 @@ std::string get_path_to_tmp_dir();
bool valid_var_name_char(wchar_t chr);
bool valid_var_name(const wcstring &str);
bool valid_var_name(const wchar_t *str);
bool valid_func_name(const wcstring &str);
// Return values (`$status` values for fish scripts) for various situations.
enum {
@ -610,9 +587,6 @@ struct hash<const wcstring> {
} // namespace std
#endif
/// Get the absolute path to the fish executable itself
std::string get_executable_path(const char *argv0);
/// A RAII wrapper for resources that don't recur, so we don't have to create a separate RAII
/// wrapper for each function. Avoids needing to call "return cleanup()" or similar / everywhere.
struct cleanup_t {

View File

@ -177,10 +177,6 @@ int env_stack_t::set_one(const wcstring &key, env_mode_flags_t mode, wcstring va
return set(key, mode, std::move(vals));
}
int env_stack_t::set_empty(const wcstring &key, env_mode_flags_t mode) {
return set(key, mode, {});
}
int env_stack_t::remove(const wcstring &key, int mode) {
return static_cast<int>(impl_->remove(key, mode));
}
@ -203,8 +199,6 @@ std::shared_ptr<environment_t> env_stack_t::snapshot() const {
return std::static_pointer_cast<environment_t>(res);
}
void env_stack_t::set_argv(std::vector<wcstring> argv) { set(L"argv", ENV_LOCAL, std::move(argv)); }
wcstring env_stack_t::get_pwd_slash() const {
std::unique_ptr<wcstring> res = impl_->get_pwd_slash();
return std::move(*res);

View File

@ -221,8 +221,6 @@ class env_stack_t final : public environment_t {
int set_one(const wcstring &key, env_mode_flags_t mode, wcstring val);
/// Sets the variable with the specified name to no values.
int set_empty(const wcstring &key, env_mode_flags_t mode);
/// Update the PWD variable based on the result of getcwd.
void set_pwd_from_getcwd();
@ -248,9 +246,6 @@ class env_stack_t final : public environment_t {
/// you want to read from another thread.
std::shared_ptr<environment_t> snapshot() const;
/// Sets up argv as the given list of strings.
void set_argv(std::vector<wcstring> argv);
/// Slightly optimized implementation.
wcstring get_pwd_slash() const override;

View File

@ -5,8 +5,6 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
// We need the sys/file.h for the flock() declaration on Linux but not OS X.
#include <sys/file.h> // IWYU pragma: keep
// We need the ioctl.h header so we can check if SIOCGIFHWADDR is defined by it so we know if we're
// on a Linux system.
#include <netinet/in.h> // IWYU pragma: keep

View File

@ -43,20 +43,6 @@ char *tparm_solaris_kludge(char *str, long p1, long p2, long p3, long p4, long p
}
#endif
int fish_mkstemp_cloexec(char *name_template) {
#if HAVE_MKOSTEMP
// null check because mkostemp may be a weak symbol
if (&mkostemp != nullptr) {
return mkostemp(name_template, O_CLOEXEC);
}
#endif
int result_fd = mkstemp(name_template);
if (result_fd != -1) {
fcntl(result_fd, F_SETFD, FD_CLOEXEC);
}
return result_fd;
}
/// Fallback implementations of wcsncasecmp and wcscasecmp. On systems where these are not needed
/// (e.g. building on Linux) these should end up just being stripped, as they are static functions
/// that are not referenced in this file.
@ -193,72 +179,3 @@ int fish_wcswidth(const wchar_t *str, size_t n) {
}
return result;
}
#ifndef HAVE_FLOCK
/* $NetBSD: flock.c,v 1.6 2008/04/28 20:24:12 martin Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Todd Vierling.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Emulate flock() with fcntl().
*/
int flock(int fd, int op) {
int rc = 0;
struct flock fl = {0};
switch (op & (LOCK_EX | LOCK_SH | LOCK_UN)) {
case LOCK_EX:
fl.l_type = F_WRLCK;
break;
case LOCK_SH:
fl.l_type = F_RDLCK;
break;
case LOCK_UN:
fl.l_type = F_UNLCK;
break;
default:
errno = EINVAL;
return -1;
}
fl.l_whence = SEEK_SET;
rc = fcntl(fd, op & LOCK_NB ? F_SETLK : F_SETLKW, &fl);
if (rc && (errno == EAGAIN)) errno = EWOULDBLOCK;
return rc;
}
#endif // HAVE_FLOCK

View File

@ -23,11 +23,6 @@ extern int32_t FISH_EMOJI_WIDTH;
int fish_wcwidth(wchar_t wc);
int fish_wcswidth(const wchar_t *str, size_t n);
// Replacement for mkostemp(str, O_CLOEXEC)
// This uses mkostemp if available,
// otherwise it uses mkstemp followed by fcntl
int fish_mkstemp_cloexec(char *);
/// thread_local support.
#if HAVE_CX11_THREAD_LOCAL
#define FISH_THREAD_LOCAL thread_local
@ -115,16 +110,4 @@ char *fish_textdomain(const char *domainname);
int killpg(int pgr, int sig);
#endif
#ifndef HAVE_FLOCK
/// Fallback implementation of flock in terms of fcntl.
/// Danger! The semantics of flock and fcntl locking are very different.
/// Use with caution.
int flock(int fd, int op);
#define LOCK_SH 1 // Shared lock.
#define LOCK_EX 2 // Exclusive lock.
#define LOCK_UN 8 // Unlock.
#define LOCK_NB 4 // Don't block when locking.
#endif
#endif // FISH_FALLBACK_H

View File

@ -204,48 +204,6 @@ static int parse_util_locate_cmdsub(const wchar_t *in, const wchar_t **begin, co
return 1;
}
long parse_util_slice_length(const wchar_t *in) {
assert(in && "null parameter");
const wchar_t openc = L'[';
const wchar_t closec = L']';
bool escaped = false;
// Check for initial opening [
if (*in != openc) return 0;
int bracket_count = 1;
assert(in && "null parameter");
for (const wchar_t *pos = in + 1; *pos; pos++) {
if (!escaped) {
if (*pos == L'\'' || *pos == L'"') {
const wchar_t *q_end = quote_end(pos, *pos);
if (q_end && *q_end) {
pos = q_end;
} else {
break;
}
} else {
if (*pos == openc) {
bracket_count++;
} else if (*pos == closec) {
bracket_count--;
if (bracket_count == 0) {
// pos points at the closing ], so add 1.
return pos - in + 1;
}
}
}
}
if (*pos == '\\') {
escaped = !escaped;
} else {
escaped = false;
}
}
assert(bracket_count > 0 && "Should have unclosed brackets");
return -1;
}
int parse_util_locate_cmdsubst_range(const wcstring &str, size_t *inout_cursor_offset,
wcstring *out_contents, size_t *out_start, size_t *out_end,
bool accept_incomplete, bool *inout_is_quoted,
@ -612,8 +570,6 @@ static bool append_syntax_error(parse_error_list_t *errors, size_t source_locati
return true;
}
bool parse_util_argument_is_help(const wcstring &s) { return s == L"-h" || s == L"--help"; }
// \return a pointer to the first argument node of an argument_or_redirection_list_t, or nullptr if
// there are no arguments.
static const ast::argument_t *get_first_arg(const ast::argument_or_redirection_list_t &list) {

View File

@ -18,11 +18,6 @@
struct Tok;
using tok_t = Tok;
/// Handles slices: the square brackets in an expression like $foo[5..4]
/// \return the length of the slice starting at \p in, or 0 if there is no slice, or -1 on error.
/// This never accepts incomplete slices.
long parse_util_slice_length(const wchar_t *in);
/// Alternative API. Iterate over command substitutions.
///
/// \param str the string to search for subshells
@ -101,9 +96,6 @@ size_t parse_util_get_offset(const wcstring &str, int line, long line_offset);
/// transformation.
wcstring parse_util_unescape_wildcards(const wcstring &str);
/// Checks if the specified string is a help option.
bool parse_util_argument_is_help(const wcstring &s);
/// Calculates information on the parameter at the specified index.
///
/// \param cmd The command to be analyzed

View File

@ -83,15 +83,6 @@ static get_path_result_t path_get_path_core(const wcstring &cmd,
return best;
}
maybe_t<wcstring> path_get_path(const wcstring &cmd, const environment_t &vars) {
auto result = path_try_get_path(cmd, vars);
if (result.err != 0) {
return none();
}
wcstring path = std::move(result.path);
return path;
}
get_path_result_t path_try_get_path(const wcstring &cmd, const environment_t &vars) {
auto pathvar = vars.get(L"PATH");
return path_get_path_core(cmd, pathvar ? pathvar->as_list() : kDefaultPath);
@ -196,81 +187,6 @@ maybe_t<wcstring> path_get_cdpath(const wcstring &dir, const wcstring &wd,
return none();
}
maybe_t<wcstring> path_as_implicit_cd(const wcstring &path, const wcstring &wd,
// todo!("should be environment_t")
const env_stack_t &vars) {
wcstring exp_path = path;
expand_tilde(exp_path, vars);
if (string_prefixes_string(L"/", exp_path) || string_prefixes_string(L"./", exp_path) ||
string_prefixes_string(L"../", exp_path) || string_suffixes_string(L"/", exp_path) ||
exp_path == L"..") {
// These paths can be implicit cd, so see if you cd to the path. Note that a single period
// cannot (that's used for sourcing files anyways).
return path_get_cdpath(exp_path, wd, vars);
}
return none();
}
// If the given path looks like it's relative to the working directory, then prepend that working
// directory. This operates on unescaped paths only (so a ~ means a literal ~).
wcstring path_apply_working_directory(const wcstring &path, const wcstring &working_directory) {
if (path.empty() || working_directory.empty()) return path;
// We're going to make sure that if we want to prepend the wd, that the string has no leading
// "/".
bool prepend_wd = path.at(0) != L'/' && path.at(0) != HOME_DIRECTORY;
if (!prepend_wd) {
// No need to prepend the wd, so just return the path we were given.
return path;
}
// Remove up to one "./".
wcstring path_component = path;
if (string_prefixes_string(L"./", path_component)) {
path_component.erase(0, 2);
}
// Removing leading /s.
while (string_prefixes_string(L"/", path_component)) {
path_component.erase(0, 1);
}
// Construct and return a new path.
wcstring new_path = working_directory;
append_path_component(new_path, path_component);
return new_path;
}
/// We separate this from path_create() for two reasons. First it's only caused if there is a
/// problem, and thus is not central to the behavior of that function. Second, we only want to issue
/// the message once. If the current shell starts a new fish shell (e.g., by running `fish -c` from
/// a function) we don't want that subshell to issue the same warnings.
static void maybe_issue_path_warning(const wcstring &which_dir, const wcstring &custom_error_msg,
bool using_xdg, const wcstring &xdg_var, const wcstring &path,
int saved_errno, env_stack_t &vars) {
wcstring warning_var_name = L"_FISH_WARNED_" + which_dir;
if (vars.get(warning_var_name, ENV_GLOBAL | ENV_EXPORT)) {
return;
}
vars.set_one(warning_var_name, ENV_GLOBAL | ENV_EXPORT, L"1");
FLOG(error, custom_error_msg.c_str());
if (path.empty()) {
FLOGF(warning_path, _(L"Unable to locate the %ls directory."), which_dir.c_str());
FLOGF(warning_path,
_(L"Please set the %ls or HOME environment variable before starting fish."),
xdg_var.c_str());
} else {
const wchar_t *env_var = using_xdg ? xdg_var.c_str() : L"HOME";
FLOGF(warning_path, _(L"Unable to locate %ls directory derived from $%ls: '%ls'."),
which_dir.c_str(), env_var, path.c_str());
FLOGF(warning_path, _(L"The error was '%s'."), std::strerror(saved_errno));
FLOGF(warning_path, _(L"Please set $%ls to a directory where you have write access."),
env_var);
}
ignore_result(write(STDERR_FILENO, "\n", 1));
}
/// Make sure the specified directory exists. If needed, try to create it and any currently not
/// existing parent directories, like mkdir -p,.
///
@ -350,27 +266,6 @@ static const base_directory_t &get_config_directory() {
return s_dir;
}
void path_emit_config_directory_messages(env_stack_t &vars) {
const auto &data = get_data_directory();
if (!data.success()) {
maybe_issue_path_warning(L"data", _(L"can not save history"), data.used_xdg,
L"XDG_DATA_HOME", data.path, data.err, vars);
}
if (data.remoteness == dir_remoteness_t::remote) {
FLOG(path, "data path appears to be on a network volume");
}
const auto &config = get_config_directory();
if (!config.success()) {
maybe_issue_path_warning(L"config", _(L"can not save universal variables or functions"),
config.used_xdg, L"XDG_CONFIG_HOME", config.path, config.err,
vars);
}
if (config.remoteness == dir_remoteness_t::remote) {
FLOG(path, "config path appears to be on a network volume");
}
}
bool path_get_config(wcstring &path) {
const auto &dir = get_config_directory();
path = dir.success() ? dir.path : L"";
@ -383,10 +278,6 @@ bool path_get_data(wcstring &path) {
return dir.success();
}
dir_remoteness_t path_get_data_remoteness() { return get_data_directory().remoteness; }
dir_remoteness_t path_get_config_remoteness() { return get_config_directory().remoteness; }
bool paths_are_equivalent(const wcstring &p1, const wcstring &p2) {
if (p1 == p2) return true;
@ -417,38 +308,6 @@ bool paths_are_equivalent(const wcstring &p1, const wcstring &p2) {
return idx1 == len1 && idx2 == len2;
}
bool path_is_valid(const wcstring &path, const wcstring &working_directory) {
bool path_is_valid;
// Some special paths are always valid.
if (path.empty()) {
path_is_valid = false;
} else if (path == L"." || path == L"./") {
path_is_valid = true;
} else if (path == L".." || path == L"../") {
path_is_valid = (!working_directory.empty() && working_directory != L"/");
} else if (path.at(0) != '/') {
// Prepend the working directory. Note that we know path is not empty here.
wcstring tmp = working_directory;
tmp.append(path);
path_is_valid = (0 == waccess(tmp, F_OK));
} else {
// Simple check.
path_is_valid = (0 == waccess(path, F_OK));
}
return path_is_valid;
}
bool paths_are_same_file(const wcstring &path1, const wcstring &path2) {
if (paths_are_equivalent(path1, path2)) return true;
struct stat s1, s2;
if (wstat(path1, &s1) == 0 && wstat(path2, &s2) == 0) {
return s1.st_ino == s2.st_ino && s1.st_dev == s2.st_dev;
}
return false;
}
void append_path_component(wcstring &path, const wcstring &component) {
if (path.empty() || component.empty()) {
path.append(component);

View File

@ -35,21 +35,6 @@ enum class dir_remoteness_t {
remote, // directory is known remote
};
/// \return the remoteness of the fish data directory.
/// This will be remote for filesystems like NFS, SMB, etc.
dir_remoteness_t path_get_data_remoteness();
/// Like path_get_data_remoteness but for the config directory.
dir_remoteness_t path_get_config_remoteness();
/// Emit any errors if config directories are missing.
/// Use the given environment stack to ensure this only occurs once.
void path_emit_config_directory_messages(env_stack_t &vars);
/// Finds the path of an executable named \p cmd, by looking in $PATH taken from \p vars.
/// \returns the path if found, none if not.
maybe_t<wcstring> path_get_path(const wcstring &cmd, const environment_t &vars);
/// Finds the path of an executable named \p cmd, by looking in $PATH taken from \p vars.
/// On success, err will be 0 and the path is returned.
/// On failure, we return the "best path" with err set appropriately.
@ -81,24 +66,10 @@ maybe_t<wcstring> path_get_cdpath(const wcstring &dir, const wcstring &wd,
std::vector<wcstring> path_apply_cdpath(const wcstring &dir, const wcstring &wd,
const env_stack_t &env_vars);
/// Returns the path resolved as an implicit cd command, or none() if none. This requires it to
/// start with one of the allowed prefixes (., .., ~) and resolve to a directory.
maybe_t<wcstring> path_as_implicit_cd(const wcstring &path, const wcstring &wd,
const env_stack_t &vars);
/// Check if two paths are equivalent, which means to ignore runs of multiple slashes (or trailing
/// slashes).
bool paths_are_equivalent(const wcstring &p1, const wcstring &p2);
bool path_is_valid(const wcstring &path, const wcstring &working_directory);
/// Returns whether the two paths refer to the same file.
bool paths_are_same_file(const wcstring &path1, const wcstring &path2);
/// If the given path looks like it's relative to the working directory, then prepend that working
/// directory. This operates on unescaped paths only (so a ~ means a literal ~).
wcstring path_apply_working_directory(const wcstring &path, const wcstring &working_directory);
/// Appends a path component, with a / if necessary.
void append_path_component(wcstring &path, const wcstring &component);

View File

@ -259,34 +259,6 @@ std::vector<wcstring> split_string(const wcstring &val, wchar_t sep) {
return out;
}
std::vector<wcstring> split_string_tok(const wcstring &val, const wcstring &seps,
size_t max_results) {
std::vector<wcstring> out;
size_t end = val.size();
size_t pos = 0;
while (pos < end && out.size() + 1 < max_results) {
// Skip leading seps.
pos = val.find_first_not_of(seps, pos);
if (pos == wcstring::npos) break;
// Find next sep.
size_t next_sep = val.find_first_of(seps, pos);
if (next_sep == wcstring::npos) {
next_sep = end;
}
out.emplace_back(val, pos, next_sep - pos);
// Note we skip exactly one sep here. This is because on the last iteration we retain all
// but the first leading separators. This is historical.
pos = next_sep + 1;
}
if (pos < end && max_results > 0) {
assert(out.size() + 1 == max_results && "Should have split the max");
out.emplace_back(val, pos);
}
assert(out.size() <= max_results && "Got too many results");
return out;
}
static wcstring join_strings_impl(const std::vector<wcstring> &vals, const wchar_t *sep,
size_t seplen) {
if (vals.empty()) return wcstring{};

View File

@ -130,16 +130,6 @@ inline maybe_t<string_fuzzy_match_t> string_fuzzy_match_string(const wcstring &s
/// Split a string by a separator character.
std::vector<wcstring> split_string(const wcstring &val, wchar_t sep);
/// Split a string by runs of any of the separator characters provided in \p seps.
/// Note the delimiters are the characters in \p seps, not \p seps itself.
/// \p seps may contain the NUL character.
/// Do not output more than \p max_results results. If we are to output exactly that much,
/// the last output is the the remainder of the input, including leading delimiters,
/// except for the first. This is historical behavior.
/// Example: split_string_tok(" a b c ", " ", 3) -> {"a", "b", " c "}
std::vector<wcstring> split_string_tok(const wcstring &val, const wcstring &seps,
size_t max_results = std::numeric_limits<size_t>::max());
/// Join a list of strings by a separator character or string.
wcstring join_strings(const std::vector<wcstring> &vals, wchar_t sep);
wcstring join_strings(const std::vector<wcstring> &vals, const wchar_t *sep);

View File

@ -45,17 +45,6 @@ wcstring_list_ffi_t::~wcstring_list_ffi_t() = default;
/// Map used as cache by wgettext.
static owning_lock<std::unordered_map<wcstring, wcstring>> wgettext_map;
wcstring wgetcwd() {
char cwd[PATH_MAX];
char *res = getcwd(cwd, sizeof(cwd));
if (res) {
return str2wcstring(res);
}
FLOGF(error, _(L"getcwd() failed with errno %d/%s"), errno, std::strerror(errno));
return wcstring();
}
DIR *wopendir(const wcstring &name) {
const cstring tmp = wcs2zstring(name);
return opendir(tmp.c_str());
@ -261,11 +250,6 @@ int waccess(const wcstring &file_name, int mode) {
return access(tmp.c_str(), mode);
}
int wunlink(const wcstring &file_name) {
const cstring tmp = wcs2zstring(file_name);
return unlink(tmp.c_str());
}
void wperror(wcharz_t s) {
int e = errno;
if (s.str[0] != L'\0') {
@ -294,59 +278,6 @@ int make_fd_blocking(int fd) {
return err == -1 ? errno : 0;
}
/// Wide character realpath. The last path component does not need to be valid. If an error occurs,
/// wrealpath() returns none() and errno is likely set.
maybe_t<wcstring> wrealpath(const wcstring &pathname) {
if (pathname.empty()) return none();
cstring real_path;
cstring narrow_path = wcs2zstring(pathname);
// Strip trailing slashes. This is treats "/a//" as equivalent to "/a" if /a is a non-directory.
while (narrow_path.size() > 1 && narrow_path.at(narrow_path.size() - 1) == '/') {
narrow_path.erase(narrow_path.size() - 1, 1);
}
char tmpbuf[PATH_MAX];
char *narrow_res = realpath(narrow_path.c_str(), tmpbuf);
if (narrow_res) {
real_path.append(narrow_res);
} else {
// Check if everything up to the last path component is valid.
size_t pathsep_idx = narrow_path.rfind('/');
if (pathsep_idx == 0) {
// If the only pathsep is the first character then it's an absolute path with a
// single path component and thus doesn't need conversion.
real_path = narrow_path;
} else {
// Only call realpath() on the portion up to the last component.
errno = 0;
if (pathsep_idx == cstring::npos) {
// If there is no "/", this is a file in $PWD, so give the realpath to that.
narrow_res = realpath(".", tmpbuf);
} else {
errno = 0;
// Only call realpath() on the portion up to the last component.
narrow_res = realpath(narrow_path.substr(0, pathsep_idx).c_str(), tmpbuf);
}
if (!narrow_res) return none();
pathsep_idx++;
real_path.append(narrow_res);
// This test is to deal with cases such as /../../x => //x.
if (real_path.size() > 1) real_path.append("/");
real_path.append(narrow_path.substr(pathsep_idx, cstring::npos));
}
}
return str2wcstring(real_path);
}
wcstring normalize_path(const wcstring &path, bool allow_leading_double_slashes) {
// Count the leading slashes.
const wchar_t sep = L'/';
@ -514,12 +445,6 @@ int wmkdir(const wcstring &name, int mode) {
return mkdir(name_narrow.c_str(), mode);
}
int wrename(const wcstring &old, const wcstring &newv) {
cstring old_narrow = wcs2zstring(old);
cstring new_narrow = wcs2zstring(newv);
return rename(old_narrow.c_str(), new_narrow.c_str());
}
ssize_t wwrite_to_fd(const wchar_t *input, size_t input_len, int fd) {
// Accumulate data in a local buffer.
char accum[512];
@ -740,24 +665,6 @@ file_id_t file_id_for_fd(int fd) {
file_id_t file_id_for_fd(const autoclose_fd_t &fd) { return file_id_for_fd(fd.fd()); }
file_id_t file_id_for_path(const wcstring &path) {
file_id_t result = kInvalidFileID;
struct stat buf = {};
if (0 == wstat(path, &buf)) {
result = file_id_t::from_stat(buf);
}
return result;
}
file_id_t file_id_for_path(const std::string &path) {
file_id_t result = kInvalidFileID;
struct stat buf = {};
if (0 == stat(path.c_str(), &buf)) {
result = file_id_t::from_stat(buf);
}
return result;
}
bool file_id_t::operator==(const file_id_t &rhs) const { return this->compare_file_id(rhs) == 0; }
bool file_id_t::operator!=(const file_id_t &rhs) const { return !(*this == rhs); }

View File

@ -89,19 +89,9 @@ int lwstat(const wcstring &file_name, struct stat *buf);
/// Wide character version of access().
int waccess(const wcstring &file_name, int mode);
/// Wide character version of unlink().
int wunlink(const wcstring &file_name);
/// Wide character version of perror().
void wperror(wcharz_t s);
/// Wide character version of getcwd().
wcstring wgetcwd();
/// Wide character version of realpath function.
/// \returns the canonicalized path, or none if the path is invalid.
maybe_t<wcstring> wrealpath(const wcstring &pathname);
/// Given an input path, "normalize" it:
/// 1. Collapse multiple /s into a single /, except maybe at the beginning.
/// 2. .. goes up a level.
@ -130,9 +120,6 @@ const wchar_t *wgettext_ptr(const wchar_t *in);
/// Wide character version of mkdir.
int wmkdir(const wcstring &name, int mode);
/// Wide character version of rename.
int wrename(const wcstring &oldName, const wcstring &newv);
/// Write a wide string to a file descriptor. This avoids doing any additional allocation.
/// This does NOT retry on EINTR or EAGAIN, it simply returns.
/// \return -1 on error in which case errno will have been set. In this event, the number of bytes
@ -317,8 +304,6 @@ struct hash<file_id_t> {
file_id_t file_id_for_fd(int fd);
file_id_t file_id_for_fd(const autoclose_fd_t &fd);
file_id_t file_id_for_path(const wcstring &path);
file_id_t file_id_for_path(const std::string &path);
extern const file_id_t kInvalidFileID;