2023-10-25 00:43:36 -04:00
|
|
|
#pragma once
|
|
|
|
///@file
|
|
|
|
|
|
|
|
#include "types.hh"
|
|
|
|
#include "error.hh"
|
|
|
|
|
2023-09-02 17:35:16 -04:00
|
|
|
#ifdef _WIN32
|
|
|
|
# define WIN32_LEAN_AND_MEAN
|
|
|
|
# include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2023-10-25 00:43:36 -04:00
|
|
|
namespace nix {
|
|
|
|
|
|
|
|
struct Sink;
|
|
|
|
struct Source;
|
|
|
|
|
2024-03-29 15:59:14 -04:00
|
|
|
/**
|
|
|
|
* Operating System capability
|
|
|
|
*/
|
2023-09-02 17:35:16 -04:00
|
|
|
typedef
|
|
|
|
#if _WIN32
|
|
|
|
HANDLE
|
|
|
|
#else
|
|
|
|
int
|
|
|
|
#endif
|
|
|
|
Descriptor;
|
|
|
|
|
|
|
|
const Descriptor INVALID_DESCRIPTOR =
|
|
|
|
#if _WIN32
|
|
|
|
INVALID_HANDLE_VALUE
|
|
|
|
#else
|
|
|
|
-1
|
|
|
|
#endif
|
|
|
|
;
|
2024-03-29 15:59:14 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert a native `Descriptor` to a POSIX file descriptor
|
|
|
|
*
|
|
|
|
* This is a no-op except on Windows.
|
|
|
|
*/
|
|
|
|
static inline Descriptor toDescriptor(int fd)
|
|
|
|
{
|
2023-09-02 17:35:16 -04:00
|
|
|
#ifdef _WIN32
|
|
|
|
return (HANDLE) _get_osfhandle(fd);
|
|
|
|
#else
|
2024-03-29 15:59:14 -04:00
|
|
|
return fd;
|
2023-09-02 17:35:16 -04:00
|
|
|
#endif
|
2024-03-29 15:59:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-09-02 17:35:16 -04:00
|
|
|
* Convert a POSIX file descriptor to a native `Descriptor` in read-only
|
|
|
|
* mode.
|
2024-03-29 15:59:14 -04:00
|
|
|
*
|
|
|
|
* This is a no-op except on Windows.
|
|
|
|
*/
|
2023-09-02 17:35:16 -04:00
|
|
|
static inline int fromDescriptorReadOnly(Descriptor fd)
|
2024-03-29 15:59:14 -04:00
|
|
|
{
|
2023-09-02 17:35:16 -04:00
|
|
|
#ifdef _WIN32
|
|
|
|
return _open_osfhandle((intptr_t) fd, _O_RDONLY);
|
|
|
|
#else
|
2024-03-29 15:59:14 -04:00
|
|
|
return fd;
|
2023-09-02 17:35:16 -04:00
|
|
|
#endif
|
2024-03-29 15:59:14 -04:00
|
|
|
}
|
|
|
|
|
2023-10-25 00:43:36 -04:00
|
|
|
/**
|
|
|
|
* Read the contents of a resource into a string.
|
|
|
|
*/
|
2024-03-29 15:59:14 -04:00
|
|
|
std::string readFile(Descriptor fd);
|
2023-10-25 00:43:36 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Wrappers arount read()/write() that read/write exactly the
|
|
|
|
* requested number of bytes.
|
|
|
|
*/
|
2024-03-29 15:59:14 -04:00
|
|
|
void readFull(Descriptor fd, char * buf, size_t count);
|
2023-10-25 00:43:36 -04:00
|
|
|
|
2024-03-29 15:59:14 -04:00
|
|
|
void writeFull(Descriptor fd, std::string_view s, bool allowInterrupts = true);
|
2023-10-25 00:43:36 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Read a line from a file descriptor.
|
|
|
|
*/
|
2024-03-29 15:59:14 -04:00
|
|
|
std::string readLine(Descriptor fd);
|
2023-10-25 00:43:36 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Write a line to a file descriptor.
|
|
|
|
*/
|
2024-03-29 15:59:14 -04:00
|
|
|
void writeLine(Descriptor fd, std::string s);
|
2023-10-25 00:43:36 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Read a file descriptor until EOF occurs.
|
|
|
|
*/
|
2024-03-29 15:59:14 -04:00
|
|
|
std::string drainFD(Descriptor fd, bool block = true, const size_t reserveSize=0);
|
2023-10-25 00:43:36 -04:00
|
|
|
|
2023-09-02 17:35:16 -04:00
|
|
|
/**
|
|
|
|
* The Windows version is always blocking.
|
|
|
|
*/
|
|
|
|
void drainFD(
|
|
|
|
Descriptor fd
|
|
|
|
, Sink & sink
|
|
|
|
#ifndef _WIN32
|
|
|
|
, bool block = true
|
|
|
|
#endif
|
|
|
|
);
|
2024-03-29 15:59:14 -04:00
|
|
|
|
|
|
|
[[gnu::always_inline]]
|
|
|
|
inline Descriptor getStandardOut() {
|
2023-09-02 17:35:16 -04:00
|
|
|
#ifndef _WIN32
|
2024-03-29 15:59:14 -04:00
|
|
|
return STDOUT_FILENO;
|
2023-09-02 17:35:16 -04:00
|
|
|
#else
|
|
|
|
return GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
#endif
|
2024-03-29 15:59:14 -04:00
|
|
|
}
|
2023-10-25 00:43:36 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Automatic cleanup of resources.
|
|
|
|
*/
|
|
|
|
class AutoCloseFD
|
|
|
|
{
|
2024-03-29 15:59:14 -04:00
|
|
|
Descriptor fd;
|
2023-10-25 00:43:36 -04:00
|
|
|
public:
|
|
|
|
AutoCloseFD();
|
2024-03-29 15:59:14 -04:00
|
|
|
AutoCloseFD(Descriptor fd);
|
2023-10-25 00:43:36 -04:00
|
|
|
AutoCloseFD(const AutoCloseFD & fd) = delete;
|
|
|
|
AutoCloseFD(AutoCloseFD&& fd);
|
|
|
|
~AutoCloseFD();
|
|
|
|
AutoCloseFD& operator =(const AutoCloseFD & fd) = delete;
|
|
|
|
AutoCloseFD& operator =(AutoCloseFD&& fd);
|
2024-03-29 15:59:14 -04:00
|
|
|
Descriptor get() const;
|
2023-10-25 00:43:36 -04:00
|
|
|
explicit operator bool() const;
|
2024-03-29 15:59:14 -04:00
|
|
|
Descriptor release();
|
2023-10-25 00:43:36 -04:00
|
|
|
void close();
|
|
|
|
void fsync();
|
|
|
|
};
|
|
|
|
|
|
|
|
class Pipe
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AutoCloseFD readSide, writeSide;
|
|
|
|
void create();
|
|
|
|
void close();
|
|
|
|
};
|
|
|
|
|
2023-09-02 17:35:16 -04:00
|
|
|
#ifndef _WIN32 // Not needed on Windows, where we don't fork
|
|
|
|
|
2023-10-25 00:43:36 -04:00
|
|
|
/**
|
|
|
|
* Close all file descriptors except those listed in the given set.
|
|
|
|
* Good practice in child processes.
|
|
|
|
*/
|
2024-03-29 15:59:14 -04:00
|
|
|
void closeMostFDs(const std::set<Descriptor> & exceptions);
|
2023-10-25 00:43:36 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the close-on-exec flag for the given file descriptor.
|
|
|
|
*/
|
2024-03-29 15:59:14 -04:00
|
|
|
void closeOnExec(Descriptor fd);
|
2023-10-25 00:43:36 -04:00
|
|
|
|
2023-09-02 17:35:16 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
# if _WIN32_WINNT >= 0x0600
|
|
|
|
Path handleToPath(Descriptor handle);
|
|
|
|
std::wstring handleToFileName(Descriptor handle);
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2023-10-25 00:43:36 -04:00
|
|
|
MakeError(EndOfFile, Error);
|
|
|
|
|
|
|
|
}
|