diff --git a/Makefile.am b/Makefile.am index a8742402..8cf194c0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -297,6 +297,8 @@ POSIX_FILES = \ posix/dir.cpp \ posix/dir.hpp \ posix/dir.ipp \ + posix/fd.cpp \ + posix/fd.hpp \ time_posix.cpp diff --git a/io.cpp b/io.cpp index 5b7a6d0e..2d7097c5 100644 --- a/io.cpp +++ b/io.cpp @@ -36,8 +36,9 @@ using namespace util; //---------------------------------------------------------------------------- std::vector -util::slurp (const boost::filesystem::path& path) { - fd out (path, O_RDONLY | O_BINARY); +util::slurp (const char *path) +{ + posix::fd out (path, O_RDONLY | O_BINARY); // Calculate the total file size off_t size = lseek (out, 0, SEEK_END); @@ -117,7 +118,7 @@ util::slurp (FILE *stream) //----------------------------------------------------------------------------- void -util::write (const fd &out, +util::write (const posix::fd &out, const void *restrict data, size_t bytes) { @@ -135,37 +136,6 @@ util::write (const fd &out, } -////////////////////////////////////////////////////////////////////////////// -fd::fd (int _fd): - m_fd (_fd) -{ - if (_fd < 0) - throw std::invalid_argument ("invalid descriptor"); -} - - -//----------------------------------------------------------------------------- -fd::fd (const char *path, int flags, mode_t mode): - m_fd (open (path, flags, mode)) -{ - if (m_fd < 0) - errno_error::throw_code (); -} - - -//----------------------------------------------------------------------------- -fd::fd (const boost::filesystem::path &path, int flags): - fd (path.string ().c_str (), flags) -{ ; } - - -//----------------------------------------------------------------------------- -fd::~fd () { - CHECK (m_fd >= 0); - close (m_fd); -} - - ////////////////////////////////////////////////////////////////////////////// int indenter::overflow (int ch) { diff --git a/io.hpp b/io.hpp index 4a352757..38d9973d 100644 --- a/io.hpp +++ b/io.hpp @@ -20,6 +20,7 @@ #include "types.hpp" #include "platform.hpp" #include "nocopy.hpp" +#include "posix/fd.hpp" #include @@ -35,37 +36,20 @@ #endif namespace util { - ///------------------------------------------------------------------------ - /// A simple RAII wrapper for file descriptors - struct fd { - public: - explicit fd (int); - fd (const char *path, int flags, mode_t mode = 0660); - fd (const boost::filesystem::path&, int flags); - - ~fd (); - - operator int (void) const { return m_fd; } - - private: - int m_fd; - }; - - //------------------------------------------------------------------------- /// Reads an entire file into memory. - std::vector slurp (const boost::filesystem::path&); + std::vector slurp (const char *path); std::vector slurp (FILE *); //------------------------------------------------------------------------- - void write (const fd&, const void *restrict data, size_t bytes); + void write (const posix::fd&, const void *restrict data, size_t bytes); template - void write (const fd&, const T &data); + void write (const posix::fd&, const T &data); template - void write (const fd&, const T *restrict first, const T *restrict last); + void write (const posix::fd&, const T *restrict first, const T *restrict last); //------------------------------------------------------------------------- class indenter : public std::streambuf { diff --git a/io.ipp b/io.ipp index 44a918e7..ab598bc0 100644 --- a/io.ipp +++ b/io.ipp @@ -26,7 +26,7 @@ namespace util { //------------------------------------------------------------------------- template void - write (const fd &_fd, const T &data) + write (const posix::fd &_fd, const T &data) { write (_fd, &data, sizeof (T)); } @@ -35,7 +35,7 @@ namespace util { //------------------------------------------------------------------------- template void - write (const fd &_fd, const T *restrict first, const T *restrict last) + write (const posix::fd &_fd, const T *restrict first, const T *restrict last) { write (_fd, first, (last - first) * sizeof (T)); } diff --git a/io_posix.cpp b/io_posix.cpp index a3846da3..7ccda3c6 100644 --- a/io_posix.cpp +++ b/io_posix.cpp @@ -18,6 +18,7 @@ #include "debug.hpp" #include "except.hpp" +#include "posix/fd.hpp" #include #include @@ -26,11 +27,19 @@ using util::detail::posix::mapped_file; ////////////////////////////////////////////////////////////////////////////// -mapped_file::mapped_file (const char *_path, int fflags, int mflags): - m_fd (_path, fflags) +mapped_file::mapped_file (const char *_path, int fflags, int mflags) { try { - load_fd (mflags); + ::util::posix::fd src (_path, fflags); + + struct stat meta; + if (fstat (src, &meta) < 0) + throw errno_error (); + + m_size = (size_t)meta.st_size; + m_data = (uint8_t *)mmap (NULL, m_size, mflags, MAP_SHARED, src, 0); + if (m_data == MAP_FAILED) + throw errno_error (); } catch (const errno_error &e) { // ignore zero length mapping error if (e.code () == EINVAL && m_size == 0) @@ -47,20 +56,6 @@ mapped_file::~mapped_file () } -//---------------------------------------------------------------------------- -void -mapped_file::load_fd (int mflags) { - struct stat meta; - if (fstat (m_fd, &meta) < 0) - throw errno_error (); - - m_size = (size_t)meta.st_size; - m_data = (uint8_t *)mmap (NULL, m_size, mflags, MAP_SHARED, m_fd, 0); - if (m_data == MAP_FAILED) - throw errno_error (); -} - - //---------------------------------------------------------------------------- size_t mapped_file::size (void) const diff --git a/io_posix.hpp b/io_posix.hpp index c443b3f4..ced8c190 100644 --- a/io_posix.hpp +++ b/io_posix.hpp @@ -61,11 +61,8 @@ namespace util { as_view () &; private: - fd m_fd; uint8_t *m_data; size_t m_size; - - void load_fd (int mflags); }; } } diff --git a/posix/fd.cpp b/posix/fd.cpp new file mode 100644 index 00000000..94f9eae8 --- /dev/null +++ b/posix/fd.cpp @@ -0,0 +1,99 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2016 Danny Robson + */ + +#include "./fd.hpp" + +#include "../except.hpp" + +#include +#include +#include + +using util::posix::fd; + + +/////////////////////////////////////////////////////////////////////////////// +fd::fd (const char *path, int flags): + m_fd (open (path, flags)) +{ + if (m_fd < 0) + errno_error::throw_code (); +} + + +//----------------------------------------------------------------------------- +fd::fd (const char *path, int flags, mode_t mode): + m_fd (open (path, flags, mode)) +{ + if (m_fd < 0) + errno_error::throw_code (); +} + + +//----------------------------------------------------------------------------- +fd::fd (fd &&rhs): + m_fd (-1) +{ + std::swap (m_fd, rhs.m_fd); +} + + +//----------------------------------------------------------------------------- +fd::fd (const fd &rhs): + m_fd (dup (rhs.m_fd)) +{ + if (m_fd < 0) + errno_error::throw_code (); +} + + +//----------------------------------------------------------------------------- +fd::fd (int _fd): + m_fd (_fd) +{ ; } + + +//----------------------------------------------------------------------------- +fd::~fd () +{ + if (m_fd < 0) + return; + + if (close (m_fd)) + errno_error::throw_code (); +} + + +/////////////////////////////////////////////////////////////////////////////// +struct ::stat +fd::stat (void) const +{ + struct stat buf; + if (fstat (m_fd, &buf)) + errno_error::throw_code (); + return buf; +} + + +/////////////////////////////////////////////////////////////////////////////// +fd::operator int (void) const +{ + return m_fd; +} + + +/////////////////////////////////////////////////////////////////////////////// +const fd fd::INVALID (-1); diff --git a/posix/fd.hpp b/posix/fd.hpp new file mode 100644 index 00000000..a69780a9 --- /dev/null +++ b/posix/fd.hpp @@ -0,0 +1,49 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2016 Danny Robson + */ + +#ifndef __CRUFT_UTIL_POSIX_FD_HPP +#define __CRUFT_UTIL_POSIX_FD_HPP + +#include +#include + +namespace util::posix { + ///------------------------------------------------------------------------ + /// A simple RAII wrapper for file descriptors + class fd { + public: + fd (const char *path, int flags); + fd (const char *path, int flags, mode_t); + + fd (fd &&); + explicit fd (const fd&); + explicit fd (int); + + ~fd (); + + struct ::stat stat (void) const; + + operator int (void) const; + + static const fd INVALID; + + private: + int m_fd; + }; +} + + +#endif