92 lines
3.2 KiB
C++
92 lines
3.2 KiB
C++
/**
|
|
* @file lltempredirect.h
|
|
* @author Nat Goodspeed
|
|
* @date 2019-10-31
|
|
* @brief RAII low-level file-descriptor redirection
|
|
*
|
|
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
|
|
* Copyright (c) 2019, Linden Research, Inc.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#if ! defined(LL_LLTEMPREDIRECT_H)
|
|
#define LL_LLTEMPREDIRECT_H
|
|
|
|
// Functions in this namespace are intended to insulate the caller from the
|
|
// aggravating distinction between ::close() and Microsoft _close().
|
|
namespace llfd
|
|
{
|
|
|
|
int close(int fd);
|
|
int dup(int target);
|
|
int dup2(int target, int reference);
|
|
FILE* open(int fd, const char* mode);
|
|
int fileno(FILE* stream);
|
|
|
|
} // namespace llfd
|
|
|
|
/**
|
|
* LLTempRedirect is an RAII class that performs file redirection on low-level
|
|
* file descriptors, expressed as ints. (Use llfd::fileno() to obtain the file
|
|
* descriptor from a classic-C FILE*. There is no portable way to obtain the
|
|
* file descriptor from a std::fstream.)
|
|
*
|
|
* Instantiate LLTempRedirect with a target file descriptor (e.g. for some
|
|
* open file) and a reference file descriptor (e.g. for stderr). From that
|
|
* point until the LLTempRedirect instance is destroyed, all OS-level writes
|
|
* to the reference file descriptor will be redirected to the target file.
|
|
*
|
|
* Because dup2() is used for redirection, the original passed target file
|
|
* descriptor remains open. If you want LLTempRedirect's destructor to close
|
|
* the target file, close() the target file descriptor after passing it to
|
|
* LLTempRedirect's constructor.
|
|
*
|
|
* LLTempRedirect's constructor saves the original target of the reference
|
|
* file descriptor. Its destructor restores the reference file descriptor to
|
|
* point once again to its original target.
|
|
*/
|
|
class LLTempRedirect
|
|
{
|
|
public:
|
|
LLTempRedirect();
|
|
/**
|
|
* For the lifespan of this LLTempRedirect instance, all writes to
|
|
* 'reference' will be redirected to 'target'. When this LLTempRedirect is
|
|
* destroyed, the original target for 'reference' will be restored.
|
|
*
|
|
* Pass 'target' as NULL if you simply want to save and restore
|
|
* 'reference' against possible redirection in the meantime.
|
|
*/
|
|
LLTempRedirect(FILE* target, FILE* reference);
|
|
/**
|
|
* For the lifespan of this LLTempRedirect instance, all writes to
|
|
* 'reference' will be redirected to 'target'. When this LLTempRedirect is
|
|
* destroyed, the original target for 'reference' will be restored.
|
|
*
|
|
* Pass 'target' as -1 if you simply want to save and restore
|
|
* 'reference' against possible redirection in the meantime.
|
|
*/
|
|
LLTempRedirect(int target, int reference);
|
|
LLTempRedirect(const LLTempRedirect&) = delete;
|
|
LLTempRedirect(LLTempRedirect&& other);
|
|
|
|
~LLTempRedirect();
|
|
|
|
LLTempRedirect& operator=(const LLTempRedirect&) = delete;
|
|
LLTempRedirect& operator=(LLTempRedirect&& other);
|
|
|
|
/// returns (duplicate file descriptor for) the original target of the
|
|
/// 'reference' file descriptor passed to our constructor
|
|
int getOriginalTarget() const { return mOrigTarget; }
|
|
/// returns the original 'reference' file descriptor passed to our
|
|
/// constructor
|
|
int getReference() const { return mReference; }
|
|
|
|
private:
|
|
void reset();
|
|
|
|
int mOrigTarget, mReference;
|
|
};
|
|
|
|
#endif /* ! defined(LL_LLTEMPREDIRECT_H) */
|