mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-27 11:43:37 +08:00
Keep an fd for the cwd in the parser
To support distinct parsers having different working directories, we need to keep the working directory alive, and also retain a non-path reference to it.
This commit is contained in:
parent
6ce85aebc6
commit
6637ccd3a2
|
@ -2,6 +2,7 @@
|
||||||
#include "config.h" // IWYU pragma: keep
|
#include "config.h" // IWYU pragma: keep
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
|
@ -68,14 +69,17 @@ int builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
||||||
|
|
||||||
wcstring norm_dir = normalize_path(dir);
|
wcstring norm_dir = normalize_path(dir);
|
||||||
|
|
||||||
if (wchdir(norm_dir) != 0) {
|
// We need to keep around the fd for this directory, in the parser.
|
||||||
|
autoclose_fd_t dir_fd(wopen_cloexec(norm_dir, O_RDONLY));
|
||||||
|
bool success = dir_fd.valid() && fchdir(dir_fd.fd()) == 0;
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
status = wstat(dir, &buffer);
|
status = wstat(dir, &buffer);
|
||||||
if (!status && S_ISDIR(buffer.st_mode)) {
|
if (!status && S_ISDIR(buffer.st_mode)) {
|
||||||
streams.err.append_format(_(L"%ls: Permission denied: '%ls'\n"), cmd, dir_in.c_str());
|
streams.err.append_format(_(L"%ls: Permission denied: '%ls'\n"), cmd, dir_in.c_str());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
streams.err.append_format(_(L"%ls: '%ls' is not a directory\n"), cmd, dir_in.c_str());
|
streams.err.append_format(_(L"%ls: '%ls' is not a directory\n"), cmd, dir_in.c_str());
|
||||||
}
|
}
|
||||||
|
@ -87,6 +91,7 @@ int builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
||||||
return STATUS_CMD_ERROR;
|
return STATUS_CMD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parser.libdata().cwd_fd = std::make_shared<const autoclose_fd_t>(std::move(dir_fd));
|
||||||
std::vector<event_t> evts;
|
std::vector<event_t> evts;
|
||||||
parser.vars().set_one(L"PWD", ENV_EXPORT | ENV_GLOBAL, std::move(norm_dir), &evts);
|
parser.vars().set_one(L"PWD", ENV_EXPORT | ENV_GLOBAL, std::move(norm_dir), &evts);
|
||||||
for (const auto &evt : evts) {
|
for (const auto &evt : evts) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// The fish parser. Contains functions for parsing and evaluating code.
|
// The fish parser. Contains functions for parsing and evaluating code.
|
||||||
#include "config.h" // IWYU pragma: keep
|
#include "config.h" // IWYU pragma: keep
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
|
|
||||||
|
@ -102,6 +103,12 @@ wcstring parser_t::user_presentable_path(const wcstring &path) const {
|
||||||
|
|
||||||
parser_t::parser_t(std::shared_ptr<env_stack_t> vars) : variables(std::move(vars)) {
|
parser_t::parser_t(std::shared_ptr<env_stack_t> vars) : variables(std::move(vars)) {
|
||||||
assert(variables.get() && "Null variables in parser initializer");
|
assert(variables.get() && "Null variables in parser initializer");
|
||||||
|
int cwd = open_cloexec(".", O_RDONLY);
|
||||||
|
if (cwd < 0) {
|
||||||
|
perror("Unable to open the current working directory");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
libdata().cwd_fd = std::make_shared<const autoclose_fd_t>(cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
parser_t::parser_t() : parser_t(env_stack_t::principal_ref()) {}
|
parser_t::parser_t() : parser_t(env_stack_t::principal_ref()) {}
|
||||||
|
|
|
@ -169,6 +169,10 @@ struct library_data_t {
|
||||||
/// machinery when wrapping: e.g. if `tig` wraps `git` then git completions need to see git on
|
/// machinery when wrapping: e.g. if `tig` wraps `git` then git completions need to see git on
|
||||||
/// the command line.
|
/// the command line.
|
||||||
wcstring_list_t transient_commandlines{};
|
wcstring_list_t transient_commandlines{};
|
||||||
|
|
||||||
|
/// A file descriptor holding the current working directory, for use in openat().
|
||||||
|
/// This is never null and never invalid.
|
||||||
|
std::shared_ptr<const autoclose_fd_t> cwd_fd{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class parser_t : public std::enable_shared_from_this<parser_t> {
|
class parser_t : public std::enable_shared_from_this<parser_t> {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user