sys.h
#ifndef WREPORT_SYS_H
#define WREPORT_SYS_H
#include <string>
#include <memory>
#include <iterator>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
namespace wreport {
namespace sys {
std::unique_ptr<struct stat> stat(const std::string& pathname);
void stat(const std::string& pathname, struct stat& st);
bool isdir(const std::string& pathname);
bool isblk(const std::string& pathname);
bool ischr(const std::string& pathname);
bool isfifo(const std::string& pathname);
bool islnk(const std::string& pathname);
bool isreg(const std::string& pathname);
bool issock(const std::string& pathname);
time_t timestamp(const std::string& file);
time_t timestamp(const std::string& file, time_t def);
size_t size(const std::string& file);
size_t size(const std::string& file, size_t def);
ino_t inode(const std::string& file);
ino_t inode(const std::string& file, ino_t def);
bool access(const std::string& s, int m);
bool exists(const std::string& s);
std::string getcwd();
void chdir(const std::string& dir);
void chroot(const std::string& dir);
mode_t umask(mode_t mask);
std::string abspath(const std::string& pathname);
class MMap
{
void* addr;
size_t length;
public:
MMap(const MMap&) = delete;
MMap(MMap&&);
MMap(void* addr, size_t length);
~MMap();
MMap& operator=(const MMap&) = delete;
MMap& operator=(MMap&&);
size_t size() const { return length; }
void munmap();
template<typename T>
operator const T*() const { return reinterpret_cast<const T*>(addr); }
template<typename T>
operator T*() const { return reinterpret_cast<T*>(addr); }
};
class FileDescriptor
{
protected:
int fd = -1;
public:
FileDescriptor();
FileDescriptor(FileDescriptor&& o);
FileDescriptor(int fd);
virtual ~FileDescriptor();
// We can copy at the FileDescriptor level because the destructor does not
// close fd
FileDescriptor(const FileDescriptor& o) = default;
FileDescriptor& operator=(const FileDescriptor& o) = default;
[[noreturn]] virtual void throw_error(const char* desc);
[[noreturn]] virtual void throw_runtime_error(const char* desc);
bool is_open() const;
void close();
void fstat(struct stat& st);
void fchmod(mode_t mode);
void futimens(const struct ::timespec ts[2]);
void fsync();
void fdatasync();
int dup();
size_t read(void* buf, size_t count);
bool read_all_or_retry(void* buf, size_t count);
void read_all_or_throw(void* buf, size_t count);
size_t write(const void* buf, size_t count);
template<typename Container>
size_t write(const Container& c)
{
return write(c.data(), c.size() * sizeof(Container::value_type));
}
void write_all_or_retry(const void* buf, size_t count);
template<typename Container>
void write_all_or_retry(const Container& c)
{
write_all_or_retry(c.data(), c.size() * sizeof(typename Container::value_type));
}
void write_all_or_throw(const void* buf, size_t count);
template<typename Container>
void write_all_or_throw(const Container& c)
{
write_all_or_throw(c.data(), c.size() * sizeof(typename Container::value_type));
}
off_t lseek(off_t offset, int whence=SEEK_SET);
size_t pread(void* buf, size_t count, off_t offset);
size_t pwrite(const void* buf, size_t count, off_t offset);
template<typename Container>
size_t pwrite(const Container& c, off_t offset)
{
return pwrite(c.data(), c.size() * sizeof(typename Container::value_type), offset);
}
void ftruncate(off_t length);
MMap mmap(size_t length, int prot, int flags, off_t offset=0);
bool ofd_setlk(struct ::flock&);
bool ofd_setlkw(struct ::flock&, bool retry_on_signal=true);
bool ofd_getlk(struct ::flock&);
int getfl();
void setfl(int flags);
operator int() const { return fd; }
};
class PreserveFileTimes
{
protected:
FileDescriptor fd;
struct ::timespec ts[2];
public:
PreserveFileTimes(FileDescriptor fd);
~PreserveFileTimes();
};
class NamedFileDescriptor : public FileDescriptor
{
protected:
std::string pathname;
public:
NamedFileDescriptor(int fd, const std::string& pathname);
NamedFileDescriptor(NamedFileDescriptor&&);
NamedFileDescriptor& operator=(NamedFileDescriptor&&);
// We can copy at the NamedFileDescriptor level because the destructor does not
// close fd
NamedFileDescriptor(const NamedFileDescriptor& o) = default;
NamedFileDescriptor& operator=(const NamedFileDescriptor& o) = default;
[[noreturn]] virtual void throw_error(const char* desc);
[[noreturn]] virtual void throw_runtime_error(const char* desc);
const std::string& name() const { return pathname; }
};
struct ManagedNamedFileDescriptor : public NamedFileDescriptor
{
using NamedFileDescriptor::NamedFileDescriptor;
ManagedNamedFileDescriptor(ManagedNamedFileDescriptor&&) = default;
ManagedNamedFileDescriptor(const ManagedNamedFileDescriptor&) = delete;
~ManagedNamedFileDescriptor();
ManagedNamedFileDescriptor& operator=(const ManagedNamedFileDescriptor&) = delete;
ManagedNamedFileDescriptor& operator=(ManagedNamedFileDescriptor&&);
};
struct Path : public ManagedNamedFileDescriptor
{
struct iterator
{
using iterator_category = std::input_iterator_tag;
using value_type = struct dirent;
using difference_type = int;
using pointer = struct dirent*;
using reference = struct dirent&;
Path* path = nullptr;
DIR* dir = nullptr;
struct dirent* cur_entry = nullptr;
// End iterator
iterator();
// Start iteration on dir
iterator(Path& dir);
iterator(iterator&) = delete;
iterator(iterator&& o)
: dir(o.dir), cur_entry(o.cur_entry)
{
o.dir = nullptr;
o.cur_entry = nullptr;
}
~iterator();
iterator& operator=(iterator&) = delete;
iterator& operator=(iterator&&) = delete;
bool operator==(const iterator& i) const;
bool operator!=(const iterator& i) const;
struct dirent& operator*() const { return *cur_entry; }
struct dirent* operator->() const { return cur_entry; }
void operator++();
bool isdir() const;
bool isblk() const;
bool ischr() const;
bool isfifo() const;
bool islnk() const;
bool isreg() const;
bool issock() const;
Path open_path(int flags=0) const;
};
using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor;
Path(const char* pathname, int flags=0, mode_t mode=0777);
Path(const std::string& pathname, int flags=0, mode_t mode=0777);
Path(Path& parent, const char* pathname, int flags=0, mode_t mode=0777);
Path(const Path&) = delete;
Path(Path&&) = default;
Path& operator=(const Path&) = delete;
Path& operator=(Path&&) = default;
void open(int flags, mode_t mode=0777);
DIR* fdopendir();
iterator begin();
iterator end();
int openat(const char* pathname, int flags, mode_t mode=0777);
int openat_ifexists(const char* pathname, int flags, mode_t mode=0777);
bool faccessat(const char* pathname, int mode, int flags=0);
void fstatat(const char* pathname, struct stat& st);
bool fstatat_ifexists(const char* pathname, struct stat& st);
void lstatat(const char* pathname, struct stat& st);
bool lstatat_ifexists(const char* pathname, struct stat& st);
void unlinkat(const char* pathname);
void mkdirat(const char* pathname, mode_t mode=0777);
void rmdirat(const char* pathname);
void symlinkat(const char* target, const char* linkpath);
std::string readlinkat(const char* pathname);
void rmtree();
static std::string mkdtemp(const std::string& prefix);
static std::string mkdtemp(const char* prefix);
static std::string mkdtemp(char* pathname_template);
};
class File : public ManagedNamedFileDescriptor
{
public:
using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor;
File(File&&) = default;
File(const File&) = delete;
File(const std::string& pathname);
File(const std::string& pathname, int flags, mode_t mode=0777);
File& operator=(const File&) = delete;
File& operator=(File&&) = default;
void open(int flags, mode_t mode=0777);
bool open_ifexists(int flags, mode_t mode=0777);
static File mkstemp(const std::string& prefix);
static File mkstemp(const char* prefix);
static File mkstemp(char* pathname_template);
};
class Tempfile : public File
{
protected:
bool m_unlink_on_exit = true;
public:
Tempfile();
Tempfile(const std::string& prefix);
Tempfile(const char* prefix);
~Tempfile();
void unlink_on_exit(bool val);
void unlink();
};
class Tempdir : public Path
{
protected:
bool m_rmtree_on_exit = true;
public:
Tempdir();
Tempdir(const std::string& prefix);
Tempdir(const char* prefix);
~Tempdir();
void rmtree_on_exit(bool val);
};
std::string read_file(const std::string &file);
void write_file(const std::string& file, const std::string& data, mode_t mode=0777);
void write_file(const std::string& file, const void* data, size_t size, mode_t mode=0777);
void write_file_atomically(const std::string& file, const std::string& data, mode_t mode=0777);
void write_file_atomically(const std::string& file, const void* data, size_t size, mode_t mode=0777);
#if 0
// Create a temporary directory based on a template.
std::string mkdtemp(std::string templ);
void mkFilePath(const std::string& file);
#endif
bool unlink_ifexists(const std::string& file);
bool rename_ifexists(const std::string& src, const std::string& dst);
bool mkdir_ifmissing(const char* pathname, mode_t mode=0777);
bool mkdir_ifmissing(const std::string& pathname, mode_t mode=0777);
bool makedirs(const std::string& pathname, mode_t=0777);
std::string which(const std::string& name);
void unlink(const std::string& pathname);
void rmdir(const std::string& pathname);
void rmtree(const std::string& pathname);
bool rmtree_ifexists(const std::string& pathname);
void rename(const std::string& src_pathname, const std::string& dst_pathname);
void touch(const std::string& pathname, time_t ts);
void clock_gettime(::clockid_t clk_id, struct ::timespec& ts);
unsigned long long timesec_elapsed(const struct ::timespec& begin, const struct ::timespec& until);
struct Clock
{
::clockid_t clk_id;
struct ::timespec ts;
Clock(::clockid_t clk_id);
unsigned long long elapsed();
};
void getrlimit(int resource, struct ::rlimit& rlim);
void setrlimit(int resource, const struct ::rlimit& rlim);
struct OverrideRlimit
{
int resource;
struct ::rlimit orig;
OverrideRlimit(int resource, rlim_t rlim);
~OverrideRlimit();
void set(rlim_t rlim);
};
}
}
#endif
wreport::sys::FileDescriptor
Common operations on file descriptors.
Definition sys.h:144
wreport::sys::FileDescriptor::write_all_or_retry
void write_all_or_retry(const void *buf, size_t count)
Write all the data in buf, retrying partial writes.
wreport::sys::FileDescriptor::setfl
void setfl(int flags)
Set open flags for the file.
wreport::sys::FileDescriptor::ofd_setlk
bool ofd_setlk(struct ::flock &)
Open file description locks F_OFD_SETLK operation.
wreport::sys::FileDescriptor::read_all_or_retry
bool read_all_or_retry(void *buf, size_t count)
Read count bytes into bufr, retrying partial reads, stopping at EOF.
wreport::sys::FileDescriptor::ofd_setlkw
bool ofd_setlkw(struct ::flock &, bool retry_on_signal=true)
Open file description locks F_OFD_SETLKW operation.
wreport::sys::FileDescriptor::ofd_getlk
bool ofd_getlk(struct ::flock &)
Open file description locks F_OFD_GETLK operation.
wreport::sys::FileDescriptor::write_all_or_throw
void write_all_or_throw(const void *buf, size_t count)
Write all the data in buf, throwing runtime_error in case of a partial write.
wreport::sys::FileDescriptor::close
void close()
Close the file descriptor, setting its value to -1.
wreport::sys::FileDescriptor::read_all_or_throw
void read_all_or_throw(void *buf, size_t count)
Read all the data into buf, throwing runtime_error in case of a partial read.
wreport::sys::FileDescriptor::getfl
int getfl()
Get open flags for the file.
wreport::sys::FileDescriptor::is_open
bool is_open() const
Check if the file descriptor is open (that is, if it is not -1).
wreport::sys::FileDescriptor::throw_runtime_error
virtual void throw_runtime_error(const char *desc)
Throw a runtime_error unrelated from errno.
wreport::sys::FileDescriptor::throw_error
virtual void throw_error(const char *desc)
Throw an exception based on errno and the given message.
wreport::sys::File::open
void open(int flags, mode_t mode=0777)
Wrapper around open(2).
wreport::sys::File::File
File(const std::string &pathname, int flags, mode_t mode=0777)
Wrapper around open(2).
wreport::sys::File::File
File(const std::string &pathname)
Create an unopened File object for the given pathname.
wreport::sys::File::open_ifexists
bool open_ifexists(int flags, mode_t mode=0777)
Wrap open(2) and return false instead of throwing an exception if open fails with ENOENT.
wreport::sys::NamedFileDescriptor::name
const std::string & name() const
Return the file pathname.
Definition sys.h:332
wreport::sys::NamedFileDescriptor::throw_runtime_error
virtual void throw_runtime_error(const char *desc)
Throw a runtime_error unrelated from errno.
wreport::sys::NamedFileDescriptor::throw_error
virtual void throw_error(const char *desc)
Throw an exception based on errno and the given message.
wreport::sys::Tempdir::rmtree_on_exit
void rmtree_on_exit(bool val)
Change the rmtree-on-exit behaviour.
wreport::sys::Tempfile::unlink_on_exit
void unlink_on_exit(bool val)
Change the unlink-on-exit behaviour.
wreport::sys::Tempfile::unlink
void unlink()
Unlink the file right now.
wreport
String functions.
Definition benchmark.h:13
wreport::sys::Clock::Clock
Clock(::clockid_t clk_id)
Initialize ts with the value of the given clock.
wreport::sys::Clock::elapsed
unsigned long long elapsed()
Return the number of nanoseconds elapsed since the last time ts was updated.
wreport::sys::ManagedNamedFileDescriptor::~ManagedNamedFileDescriptor
~ManagedNamedFileDescriptor()
The destructor closes the file descriptor, but does not check errors on close().
wreport::sys::OverrideRlimit::set
void set(rlim_t rlim)
Change the limit value again.
wreport::sys::Path::iterator
Iterator for directory entries.
Definition sys.h:369
wreport::sys::Path::iterator::issock
bool issock() const
wreport::sys::Path::iterator::isdir
bool isdir() const
wreport::sys::Path::iterator::ischr
bool ischr() const
wreport::sys::Path::iterator::islnk
bool islnk() const
wreport::sys::Path::iterator::open_path
Path open_path(int flags=0) const
Return a Path object for this entry.
wreport::sys::Path::iterator::isreg
bool isreg() const
wreport::sys::Path::iterator::isblk
bool isblk() const
wreport::sys::Path::iterator::isfifo
bool isfifo() const
wreport::sys::Path::lstatat_ifexists
bool lstatat_ifexists(const char *pathname, struct stat &st)
lstatat, but in case of ENOENT returns false instead of throwing
wreport::sys::Path::Path
Path(const std::string &pathname, int flags=0, mode_t mode=0777)
Open the given pathname with flags | O_PATH.
wreport::sys::Path::lstatat
void lstatat(const char *pathname, struct stat &st)
fstatat with the AT_SYMLINK_NOFOLLOW flag set
wreport::sys::Path::openat_ifexists
int openat_ifexists(const char *pathname, int flags, mode_t mode=0777)
Same as openat, but returns -1 if the file does not exist.
wreport::sys::Path::open
void open(int flags, mode_t mode=0777)
Wrapper around open(2) with flags | O_PATH.
wreport::sys::Path::begin
iterator begin()
Begin iterator on all directory entries.
wreport::sys::Path::fstatat_ifexists
bool fstatat_ifexists(const char *pathname, struct stat &st)
fstatat, but in case of ENOENT returns false instead of throwing
wreport::sys::Path::rmdirat
void rmdirat(const char *pathname)
unlinkat with the AT_REMOVEDIR flag set
wreport::sys::Path::rmtree
void rmtree()
Delete the directory pointed to by this Path, with all its contents.
wreport::sys::Path::Path
Path(const char *pathname, int flags=0, mode_t mode=0777)
Open the given pathname with flags | O_PATH.
wreport::sys::Path::end
iterator end()
End iterator on all directory entries.
wreport::sys::Path::Path
Path(Path &parent, const char *pathname, int flags=0, mode_t mode=0777)
Open the given pathname calling parent.openat, with flags | O_PATH.