diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake index db7ba5757..d54e8f4f9 100644 --- a/cmake/ConfigureChecks.cmake +++ b/cmake/ConfigureChecks.cmake @@ -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) diff --git a/config_cmake.h.in b/config_cmake.h.in index a53d8a11e..6251ef032 100644 --- a/config_cmake.h.in +++ b/config_cmake.h.in @@ -16,9 +16,6 @@ /* Define to 1 if you have the 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 diff --git a/doc_src/license.rst b/doc_src/license.rst index 9752db9ed..82296b30b 100644 --- a/doc_src/license.rst +++ b/doc_src/license.rst @@ -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. diff --git a/src/common.cpp b/src/common.cpp index feab40d4a..71739f127 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -572,14 +572,6 @@ ssize_t write_loop(int fd, const char *buff, size_t count) { return static_cast(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 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 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(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(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(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(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(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"); diff --git a/src/common.h b/src/common.h index d13abf6cd..0200e520f 100644 --- a/src/common.h +++ b/src/common.h @@ -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; @@ -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 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 { } // 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 { diff --git a/src/env.cpp b/src/env.cpp index eda32253d..d1bf206f5 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -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(impl_->remove(key, mode)); } @@ -203,8 +199,6 @@ std::shared_ptr env_stack_t::snapshot() const { return std::static_pointer_cast(res); } -void env_stack_t::set_argv(std::vector argv) { set(L"argv", ENV_LOCAL, std::move(argv)); } - wcstring env_stack_t::get_pwd_slash() const { std::unique_ptr res = impl_->get_pwd_slash(); return std::move(*res); diff --git a/src/env.h b/src/env.h index 193f334de..533c10c71 100644 --- a/src/env.h +++ b/src/env.h @@ -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 snapshot() const; - /// Sets up argv as the given list of strings. - void set_argv(std::vector argv); - /// Slightly optimized implementation. wcstring get_pwd_slash() const override; diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp index 2df78f484..01d9ea31c 100644 --- a/src/env_universal_common.cpp +++ b/src/env_universal_common.cpp @@ -5,8 +5,6 @@ #include #include #include -// We need the sys/file.h for the flock() declaration on Linux but not OS X. -#include // 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 // IWYU pragma: keep diff --git a/src/fallback.cpp b/src/fallback.cpp index 3d093d703..d538a936b 100644 --- a/src/fallback.cpp +++ b/src/fallback.cpp @@ -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 diff --git a/src/fallback.h b/src/fallback.h index f56ceda08..2eee0cb1f 100644 --- a/src/fallback.h +++ b/src/fallback.h @@ -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 diff --git a/src/parse_util.cpp b/src/parse_util.cpp index 4c1b0db3a..fc4e03722 100644 --- a/src/parse_util.cpp +++ b/src/parse_util.cpp @@ -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) { diff --git a/src/parse_util.h b/src/parse_util.h index 459441a6d..f4a075035 100644 --- a/src/parse_util.h +++ b/src/parse_util.h @@ -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 diff --git a/src/path.cpp b/src/path.cpp index aea864b73..7e4be3fb0 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -83,15 +83,6 @@ static get_path_result_t path_get_path_core(const wcstring &cmd, return best; } -maybe_t 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 path_get_cdpath(const wcstring &dir, const wcstring &wd, return none(); } -maybe_t 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); diff --git a/src/path.h b/src/path.h index 80751eb9c..3b27fe1f6 100644 --- a/src/path.h +++ b/src/path.h @@ -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 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 path_get_cdpath(const wcstring &dir, const wcstring &wd, std::vector 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 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); diff --git a/src/wcstringutil.cpp b/src/wcstringutil.cpp index 9a8318f03..71c56b392 100644 --- a/src/wcstringutil.cpp +++ b/src/wcstringutil.cpp @@ -259,34 +259,6 @@ std::vector split_string(const wcstring &val, wchar_t sep) { return out; } -std::vector split_string_tok(const wcstring &val, const wcstring &seps, - size_t max_results) { - std::vector 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 &vals, const wchar_t *sep, size_t seplen) { if (vals.empty()) return wcstring{}; diff --git a/src/wcstringutil.h b/src/wcstringutil.h index 789d83660..46c03abf3 100644 --- a/src/wcstringutil.h +++ b/src/wcstringutil.h @@ -130,16 +130,6 @@ inline maybe_t string_fuzzy_match_string(const wcstring &s /// Split a string by a separator character. std::vector 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 split_string_tok(const wcstring &val, const wcstring &seps, - size_t max_results = std::numeric_limits::max()); - /// Join a list of strings by a separator character or string. wcstring join_strings(const std::vector &vals, wchar_t sep); wcstring join_strings(const std::vector &vals, const wchar_t *sep); diff --git a/src/wutil.cpp b/src/wutil.cpp index 5e690f02d..2bc77fe38 100644 --- a/src/wutil.cpp +++ b/src/wutil.cpp @@ -45,17 +45,6 @@ wcstring_list_ffi_t::~wcstring_list_ffi_t() = default; /// Map used as cache by wgettext. static owning_lock> 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 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); } diff --git a/src/wutil.h b/src/wutil.h index 5e11577c6..5b97dce53 100644 --- a/src/wutil.h +++ b/src/wutil.h @@ -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 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_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;