diff --git a/include/ircd/fs/fd.h b/include/ircd/fs/fd.h new file mode 100644 index 000000000..043276bc3 --- /dev/null +++ b/include/ircd/fs/fd.h @@ -0,0 +1,51 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +#pragma once +#define HAVE_IRCD_FS_FD_H + +namespace ircd::fs +{ + struct fd; +} + +/// Object for maintaining state to an open file or directory. Instances can +/// be used with various functions around ircd::fs. +struct ircd::fs::fd +{ + struct opts; + + int fdno{-1}; + + public: + operator const int &() const + { + return fdno; + } + + fd(const string_view &path, const opts &); + fd(const string_view &path); + fd() = default; + fd(fd &&) noexcept; + fd(const fd &) = delete; + fd &operator=(fd &&) noexcept; + fd &operator=(const fd &) = delete; + ~fd() noexcept(false); +}; + +struct ircd::fs::fd::opts +{ + ulong flags {0}; + ulong mask {0}; + bool ate {false}; + + opts(const std::ios::open_mode &); + opts() = default; +}; diff --git a/include/ircd/fs/fs.h b/include/ircd/fs/fs.h index 8c7797527..c7c6e0a17 100644 --- a/include/ircd/fs/fs.h +++ b/include/ircd/fs/fs.h @@ -91,6 +91,7 @@ namespace ircd::fs extern aio *aioctx; } +#include "fd.h" #include "read.h" #include "write.h" #include "stdin.h" diff --git a/ircd/fs.cc b/ircd/fs.cc index d2c406e66..fde33e608 100644 --- a/ircd/fs.cc +++ b/ircd/fs.cc @@ -260,6 +260,121 @@ ircd::fs::write__std(const string_view &path, return buf; } +/////////////////////////////////////////////////////////////////////////////// +// +// fs/fd.h +// +// TODO: x-platform +// + +namespace ircd::fs +{ + thread_local char path_buf[2048]; + static const char *path_str(const string_view &); + static uint posix_flags(const std::ios::open_mode &mode); +} + +uint +ircd::fs::posix_flags(const std::ios::open_mode &mode) +{ + static const auto rdwr + { + std::ios::in | std::ios::out + }; + + uint ret{0}; + if((mode & rdwr) == rdwr) + ret |= O_RDWR; + else if(mode & std::ios::out) + ret |= O_WRONLY; + else + ret |= O_RDONLY; + + ret |= mode & std::ios::trunc? O_TRUNC : 0; + ret |= mode & std::ios::app? O_APPEND : 0; + ret |= ret & O_WRONLY? O_CREAT : 0; + ret |= ret & O_RDWR && ret & (O_TRUNC | O_APPEND)? O_CREAT : 0; + return ret; +} + +const char * +ircd::fs::path_str(const string_view &s) +{ + return data(strlcpy(path_buf, s)); +} + +// +// fd::opts +// + +ircd::fs::fd::opts::opts(const std::ios::open_mode &mode) +:flags +{ + posix_flags(mode) + | O_CLOEXEC +} +,mask +{ + flags & O_CREAT? + S_IRUSR | S_IWUSR: + 0U +} +,ate +{ + bool(mode & std::ios::ate) +} +{ +} + +// +// fd::fd +// + +ircd::fs::fd::fd(const string_view &path) +:fd{path, opts{}} +{ +} + +ircd::fs::fd::fd(const string_view &path, + const opts &opts) +:fdno +{ + int(syscall(::open, path_str(path), int(opts.flags), mode_t(opts.mask))) +} +{ + if(opts.ate) + syscall(::lseek, fdno, 0, SEEK_END); +} + +ircd::fs::fd::fd(fd &&o) +noexcept +:fdno +{ + std::move(o.fdno) +} +{ + o.fdno = -1; +} + +ircd::fs::fd & +ircd::fs::fd::operator=(fd &&o) +noexcept +{ + this->~fd(); + fdno = std::move(o.fdno); + o.fdno = -1; + return *this; +} + +ircd::fs::fd::~fd() +noexcept(false) +{ + if(fdno < 0) + return; + + syscall(::close, fdno); +} + /////////////////////////////////////////////////////////////////////////////// // // fs.h / misc