mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 13:53:10 +00:00
Migrate more fd-concerned functions from wutil into fds
Functions like wopen_cloexec have a new home in fds.cpp. This is in preparation for reworking how internal fds avoid conflict with user fds.
This commit is contained in:
parent
6588cf35f4
commit
4b4bf541d1
7 changed files with 114 additions and 104 deletions
85
src/fds.cpp
85
src/fds.cpp
|
@ -5,11 +5,17 @@
|
|||
#include "fds.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "flog.h"
|
||||
#include "wutil.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
|
||||
void autoclose_fd_t::close() {
|
||||
if (fd_ < 0) return;
|
||||
exec_close(fd_);
|
||||
|
@ -63,6 +69,85 @@ maybe_t<autoclose_pipes_t> make_autoclose_pipes(const fd_set_t &fdset) {
|
|||
return autoclose_pipes_t(std::move(read_end), std::move(write_end));
|
||||
}
|
||||
|
||||
int set_cloexec(int fd, bool should_set) {
|
||||
// Note we don't want to overwrite existing flags like O_NONBLOCK which may be set. So fetch the
|
||||
// existing flags and modify them.
|
||||
int flags = fcntl(fd, F_GETFD, 0);
|
||||
if (flags < 0) {
|
||||
return -1;
|
||||
}
|
||||
int new_flags = flags;
|
||||
if (should_set) {
|
||||
new_flags |= FD_CLOEXEC;
|
||||
} else {
|
||||
new_flags &= ~FD_CLOEXEC;
|
||||
}
|
||||
if (flags == new_flags) {
|
||||
return 0;
|
||||
} else {
|
||||
return fcntl(fd, F_SETFD, new_flags);
|
||||
}
|
||||
}
|
||||
|
||||
int open_cloexec(const std::string &path, int flags, mode_t mode) {
|
||||
return open_cloexec(path.c_str(), flags, mode);
|
||||
}
|
||||
|
||||
int open_cloexec(const char *path, int flags, mode_t mode) {
|
||||
int fd;
|
||||
|
||||
// Prefer to use O_CLOEXEC.
|
||||
#ifdef O_CLOEXEC
|
||||
fd = open(path, flags | O_CLOEXEC, mode);
|
||||
#else
|
||||
fd = open(path, flags, mode);
|
||||
if (fd >= 0 && !set_cloexec(fd)) {
|
||||
exec_close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
int wopen_cloexec(const wcstring &pathname, int flags, mode_t mode) {
|
||||
return open_cloexec(wcs2string(pathname), flags, mode);
|
||||
}
|
||||
|
||||
int fd_check_is_remote(int fd) {
|
||||
UNUSED(fd);
|
||||
#if defined(__linux__)
|
||||
struct statfs buf {};
|
||||
if (fstatfs(fd, &buf) < 0) {
|
||||
return -1;
|
||||
}
|
||||
// Linux has constants for these like NFS_SUPER_MAGIC, SMB_SUPER_MAGIC, CIFS_MAGIC_NUMBER but
|
||||
// these are in varying headers. Simply hard code them.
|
||||
// NOTE: The cast is necessary for 32-bit systems because of the 4-byte CIFS_MAGIC_NUMBER
|
||||
switch (static_cast<unsigned int>(buf.f_type)) {
|
||||
case 0x6969: // NFS_SUPER_MAGIC
|
||||
case 0x517B: // SMB_SUPER_MAGIC
|
||||
case 0xFE534D42U: // SMB2_MAGIC_NUMBER - not in the manpage
|
||||
case 0xFF534D42U: // CIFS_MAGIC_NUMBER
|
||||
return 1;
|
||||
default:
|
||||
// Other FSes are assumed local.
|
||||
return 0;
|
||||
}
|
||||
#elif defined(ST_LOCAL)
|
||||
// ST_LOCAL is a flag to statvfs, which is itself standardized.
|
||||
// In practice the only system to use this path is NetBSD.
|
||||
struct statvfs buf {};
|
||||
if (fstatvfs(fd, &buf) < 0) return -1;
|
||||
return (buf.f_flag & ST_LOCAL) ? 0 : 1;
|
||||
#elif defined(MNT_LOCAL)
|
||||
struct statfs buf {};
|
||||
if (fstatfs(fd, &buf) < 0) return -1;
|
||||
return (buf.f_flags & MNT_LOCAL) ? 0 : 1;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void exec_close(int fd) {
|
||||
assert(fd >= 0 && "Invalid fd");
|
||||
while (close(fd) == -1) {
|
||||
|
|
24
src/fds.h
24
src/fds.h
|
@ -4,10 +4,13 @@
|
|||
#define FISH_FDS_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "maybe.h"
|
||||
|
||||
using wcstring = std::wstring;
|
||||
|
||||
/// Pipe redirection error message.
|
||||
#define PIPE_ERROR _(L"An error occurred while setting up pipe")
|
||||
|
||||
|
@ -95,6 +98,27 @@ maybe_t<autoclose_pipes_t> make_autoclose_pipes(const fd_set_t &fdset);
|
|||
/// cloexec. \returns invalid fd on failure (in which case the given fd is still closed).
|
||||
autoclose_fd_t move_fd_to_unused(autoclose_fd_t fd, const fd_set_t &fdset);
|
||||
|
||||
/// Sets CLO_EXEC on a given fd according to the value of \p should_set.
|
||||
int set_cloexec(int fd, bool should_set = true);
|
||||
|
||||
/// Wide character version of open() that also sets the close-on-exec flag (atomically when
|
||||
/// possible).
|
||||
int wopen_cloexec(const wcstring &pathname, int flags, mode_t mode = 0);
|
||||
|
||||
/// Narrow versions of wopen_cloexec.
|
||||
int open_cloexec(const std::string &path, int flags, mode_t mode = 0);
|
||||
int open_cloexec(const char *path, int flags, mode_t mode = 0);
|
||||
|
||||
/// Mark an fd as nonblocking; returns errno or 0 on success.
|
||||
int make_fd_nonblocking(int fd);
|
||||
|
||||
/// Mark an fd as blocking; returns errno or 0 on success.
|
||||
int make_fd_blocking(int fd);
|
||||
|
||||
/// Check if an fd is on a remote filesystem (NFS, SMB, CFS)
|
||||
/// Return 1 if remote, 0 if local, -1 on error or if not implemented on this platform.
|
||||
int fd_check_is_remote(int fd);
|
||||
|
||||
/// Close a file descriptor \p fd, retrying on EINTR.
|
||||
void exec_close(int fd);
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|||
#include "env.h"
|
||||
#include "expand.h"
|
||||
#include "fish_version.h"
|
||||
#include "fds.h"
|
||||
#include "flog.h"
|
||||
#include "highlight.h"
|
||||
#include "operation_context.h"
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
#include "history_file.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "fds.h"
|
||||
#include "history.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
// Some forward declarations.
|
||||
static history_item_t decode_item_fish_2_0(const char *base, size_t len);
|
||||
static history_item_t decode_item_fish_1_x(const char *begin, size_t length);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <thread>
|
||||
|
||||
#include "common.h"
|
||||
#include "fds.h"
|
||||
#include "flog.h"
|
||||
#include "global_safety.h"
|
||||
#include "wutil.h"
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
#include <cstring>
|
||||
#if defined(__linux__)
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
#include <sys/mount.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -142,50 +139,6 @@ wcstring wgetcwd() {
|
|||
return wcstring();
|
||||
}
|
||||
|
||||
int set_cloexec(int fd, bool should_set) {
|
||||
// Note we don't want to overwrite existing flags like O_NONBLOCK which may be set. So fetch the
|
||||
// existing flags and modify them.
|
||||
int flags = fcntl(fd, F_GETFD, 0);
|
||||
if (flags < 0) {
|
||||
return -1;
|
||||
}
|
||||
int new_flags = flags;
|
||||
if (should_set) {
|
||||
new_flags |= FD_CLOEXEC;
|
||||
} else {
|
||||
new_flags &= ~FD_CLOEXEC;
|
||||
}
|
||||
if (flags == new_flags) {
|
||||
return 0;
|
||||
} else {
|
||||
return fcntl(fd, F_SETFD, new_flags);
|
||||
}
|
||||
}
|
||||
|
||||
int open_cloexec(const std::string &path, int flags, mode_t mode) {
|
||||
return open_cloexec(path.c_str(), flags, mode);
|
||||
}
|
||||
|
||||
int open_cloexec(const char *path, int flags, mode_t mode) {
|
||||
int fd;
|
||||
|
||||
// Prefer to use O_CLOEXEC.
|
||||
#ifdef O_CLOEXEC
|
||||
fd = open(path, flags | O_CLOEXEC, mode);
|
||||
#else
|
||||
fd = open(path, flags, mode);
|
||||
if (fd >= 0 && !set_cloexec(fd)) {
|
||||
exec_close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
int wopen_cloexec(const wcstring &pathname, int flags, mode_t mode) {
|
||||
cstring tmp = wcs2string(pathname);
|
||||
return open_cloexec(tmp, flags, mode);
|
||||
}
|
||||
|
||||
DIR *wopendir(const wcstring &name) {
|
||||
const cstring tmp = wcs2string(name);
|
||||
|
@ -256,40 +209,6 @@ int make_fd_blocking(int fd) {
|
|||
return err == -1 ? errno : 0;
|
||||
}
|
||||
|
||||
int fd_check_is_remote(int fd) {
|
||||
#if defined(__linux__)
|
||||
struct statfs buf {};
|
||||
if (fstatfs(fd, &buf) < 0) {
|
||||
return -1;
|
||||
}
|
||||
// Linux has constants for these like NFS_SUPER_MAGIC, SMB_SUPER_MAGIC, CIFS_MAGIC_NUMBER but
|
||||
// these are in varying headers. Simply hard code them.
|
||||
// NOTE: The cast is necessary for 32-bit systems because of the 4-byte CIFS_MAGIC_NUMBER
|
||||
switch (static_cast<unsigned int>(buf.f_type)) {
|
||||
case 0x6969: // NFS_SUPER_MAGIC
|
||||
case 0x517B: // SMB_SUPER_MAGIC
|
||||
case 0xFE534D42U: // SMB2_MAGIC_NUMBER - not in the manpage
|
||||
case 0xFF534D42U: // CIFS_MAGIC_NUMBER
|
||||
return 1;
|
||||
default:
|
||||
// Other FSes are assumed local.
|
||||
return 0;
|
||||
}
|
||||
#elif defined(ST_LOCAL)
|
||||
// ST_LOCAL is a flag to statvfs, which is itself standardized.
|
||||
// In practice the only system to use this path is NetBSD.
|
||||
struct statvfs buf {};
|
||||
if (fstatvfs(fd, &buf) < 0) return -1;
|
||||
return (buf.f_flag & ST_LOCAL) ? 0 : 1;
|
||||
#elif defined(MNT_LOCAL)
|
||||
struct statfs buf {};
|
||||
if (fstatfs(fd, &buf) < 0) return -1;
|
||||
return (buf.f_flags & MNT_LOCAL) ? 0 : 1;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void safe_append(char *buffer, const char *s, size_t buffsize) {
|
||||
std::strncat(buffer, s, buffsize - std::strlen(buffer) - 1);
|
||||
}
|
||||
|
|
21
src/wutil.h
21
src/wutil.h
|
@ -19,27 +19,6 @@
|
|||
#include "common.h"
|
||||
#include "maybe.h"
|
||||
|
||||
/// Sets CLO_EXEC on a given fd according to the value of \p should_set.
|
||||
int set_cloexec(int fd, bool should_set = true);
|
||||
|
||||
/// Wide character version of open() that also sets the close-on-exec flag (atomically when
|
||||
/// possible).
|
||||
int wopen_cloexec(const wcstring &pathname, int flags, mode_t mode = 0);
|
||||
|
||||
/// Narrow versions of wopen_cloexec.
|
||||
int open_cloexec(const std::string &path, int flags, mode_t mode = 0);
|
||||
int open_cloexec(const char *path, int flags, mode_t mode = 0);
|
||||
|
||||
/// Mark an fd as nonblocking; returns errno or 0 on success.
|
||||
int make_fd_nonblocking(int fd);
|
||||
|
||||
/// Mark an fd as blocking; returns errno or 0 on success.
|
||||
int make_fd_blocking(int fd);
|
||||
|
||||
/// Check if an fd is on a remote filesystem (NFS, SMB, CFS)
|
||||
/// Return 1 if remote, 0 if local, -1 on error or if not implemented on this platform.
|
||||
int fd_check_is_remote(int fd);
|
||||
|
||||
/// Wide character version of opendir(). Note that opendir() is guaranteed to set close-on-exec by
|
||||
/// POSIX (hooray).
|
||||
DIR *wopendir(const wcstring &name);
|
||||
|
|
Loading…
Reference in a new issue