blob: c1b817189a9591457091ae135b99b017a9ad26bb [file] [log] [blame]
// Filesystem operation utilities -*- C++ -*-
// Copyright (C) 2014-2018 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
#ifndef _GLIBCXX_OPS_COMMON_H
#define _GLIBCXX_OPS_COMMON_H 1
#include <chrono>
#ifdef _GLIBCXX_HAVE_UNISTD_H
# include <unistd.h>
# if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H)
# include <sys/types.h>
# include <sys/stat.h>
# endif
#endif
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
# include <utime.h> // utime
#endif
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
# include <wchar.h>
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace filesystem
{
namespace __gnu_posix
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
// Adapt the Windows _wxxx functions to look like POSIX xxx, but for wchar_t*.
inline int open(const wchar_t* path, int flags)
{ return ::_wopen(path, flags); }
inline int open(const wchar_t* path, int flags, int mode)
{ return ::_wopen(path, flags, mode); }
inline int close(int fd)
{ return ::_close(fd); }
typedef struct ::_stat stat_type;
inline int stat(const wchar_t* path, stat_type* buffer)
{ return ::_wstat(path, buffer); }
inline lstat(const wchar_t* path, stat_type* buffer)
{
// TODO symlinks not currently supported
return stat(path, buffer);
}
using ::mode_t;
inline int chmod(const wchar_t* path, mode_t mode)
{ return ::_wchmod(path, mode); }
inline int mkdir(const wchar_t* path, mode_t)
{ return ::_wmkdir(path); }
inline wchar_t* getcwd(wchar_t* buf, size_t size)
{ return ::_wgetcwd(buf, size > (size_t)INT_MAX ? INT_MAX : (int)size); }
inline int chdir(const wchar_t* path)
{ return ::_wchdir(path); }
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
using utimbuf = _utimbuf;
inline int utime(const wchar_t* path, utimbuf* times)
{ return ::_wutime(path, times); }
#endif
inline int rename(const wchar_t* oldname, const wchar_t* newname)
{ return _wrename(oldname, newname); }
inline int truncate(const wchar_t* path, _off64_t length)
{
const int fd = ::_wopen(path, _O_BINARY|_O_RDWR);
if (fd == -1)
return fd;
const int ret = ::ftruncate64(fd, length);
int err;
::_get_errno(&err);
::_close(fd);
::_set_errno(err);
return ret;
}
using char_type = wchar_t;
#else // _GLIBCXX_FILESYSTEM_IS_WINDOWS
using ::open;
using ::close;
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
typedef struct ::stat stat_type;
using ::stat;
using ::lstat;
#endif
using ::mode_t;
using ::chmod;
using ::mkdir;
using ::getcwd;
using ::chdir;
#if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
using ::utimbuf;
using ::utime;
#endif
using ::rename;
using ::truncate;
using char_type = char;
#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
} // namespace __gnu_posix
template<typename Bitmask>
inline bool is_set(Bitmask obj, Bitmask bits)
{
return (obj & bits) != Bitmask::none;
}
inline bool
is_not_found_errno(int err) noexcept
{
return err == ENOENT || err == ENOTDIR;
}
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
using __gnu_posix::stat_type;
inline std::chrono::system_clock::time_point
file_time(const stat_type& st, std::error_code& ec) noexcept
{
using namespace std::chrono;
#ifdef _GLIBCXX_USE_ST_MTIM
time_t s = st.st_mtim.tv_sec;
nanoseconds ns{st.st_mtim.tv_nsec};
#else
time_t s = st.st_mtime;
nanoseconds ns{};
#endif
if (s >= (nanoseconds::max().count() / 1e9))
{
ec = std::make_error_code(std::errc::value_too_large); // EOVERFLOW
return system_clock::time_point::min();
}
ec.clear();
return system_clock::time_point{seconds{s} + ns};
}
struct copy_options_existing_file
{
bool skip, update, overwrite;
};
bool
do_copy_file(const __gnu_posix::char_type* from,
const __gnu_posix::char_type* to,
copy_options_existing_file options,
stat_type* from_st, stat_type* to_st,
std::error_code& ec) noexcept;
void
do_space(const __gnu_posix::char_type* pathname,
uintmax_t& capacity, uintmax_t& free, uintmax_t& available,
std::error_code&);
#endif // _GLIBCXX_HAVE_SYS_STAT_H
} // namespace filesystem
// BEGIN/END macros must be defined before including this file.
_GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
#ifdef _GLIBCXX_HAVE_SYS_STAT_H
using std::filesystem::__gnu_posix::stat_type;
inline file_type
make_file_type(const stat_type& st) noexcept
{
#ifdef _GLIBCXX_HAVE_S_ISREG
if (S_ISREG(st.st_mode))
return file_type::regular;
else if (S_ISDIR(st.st_mode))
return file_type::directory;
else if (S_ISCHR(st.st_mode))
return file_type::character;
else if (S_ISBLK(st.st_mode))
return file_type::block;
else if (S_ISFIFO(st.st_mode))
return file_type::fifo;
#ifdef S_ISLNK // not present in mingw
else if (S_ISLNK(st.st_mode))
return file_type::symlink;
#endif
#ifdef S_ISSOCK // not present until POSIX:2001
else if (S_ISSOCK(st.st_mode))
return file_type::socket;
#endif
#endif
return file_type::unknown;
}
inline file_status
make_file_status(const stat_type& st) noexcept
{
return file_status{
make_file_type(st),
static_cast<perms>(st.st_mode) & perms::mask
};
}
inline std::filesystem::copy_options_existing_file
copy_file_options(copy_options opt)
{
using std::filesystem::is_set;
return {
is_set(opt, copy_options::skip_existing),
is_set(opt, copy_options::update_existing),
is_set(opt, copy_options::overwrite_existing)
};
}
#endif // _GLIBCXX_HAVE_SYS_STAT_H
_GLIBCXX_END_NAMESPACE_FILESYSTEM
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _GLIBCXX_OPS_COMMON_H