PR libstdc++/78870 support std::filesystem on Windows
[official-gcc.git] / libstdc++-v3 / src / filesystem / ops-common.h
blobc1b817189a9591457091ae135b99b017a9ad26bb
1 // Filesystem operation utilities -*- C++ -*-
3 // Copyright (C) 2014-2018 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 #ifndef _GLIBCXX_OPS_COMMON_H
26 #define _GLIBCXX_OPS_COMMON_H 1
28 #include <chrono>
30 #ifdef _GLIBCXX_HAVE_UNISTD_H
31 # include <unistd.h>
32 # if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H)
33 # include <sys/types.h>
34 # include <sys/stat.h>
35 # endif
36 #endif
37 #if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
38 # include <utime.h> // utime
39 #endif
41 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
42 # include <wchar.h>
43 #endif
45 namespace std _GLIBCXX_VISIBILITY(default)
47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
48 namespace filesystem
50 namespace __gnu_posix
52 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
53 // Adapt the Windows _wxxx functions to look like POSIX xxx, but for wchar_t*.
54 inline int open(const wchar_t* path, int flags)
55 { return ::_wopen(path, flags); }
57 inline int open(const wchar_t* path, int flags, int mode)
58 { return ::_wopen(path, flags, mode); }
60 inline int close(int fd)
61 { return ::_close(fd); }
63 typedef struct ::_stat stat_type;
65 inline int stat(const wchar_t* path, stat_type* buffer)
66 { return ::_wstat(path, buffer); }
68 inline lstat(const wchar_t* path, stat_type* buffer)
70 // TODO symlinks not currently supported
71 return stat(path, buffer);
74 using ::mode_t;
76 inline int chmod(const wchar_t* path, mode_t mode)
77 { return ::_wchmod(path, mode); }
79 inline int mkdir(const wchar_t* path, mode_t)
80 { return ::_wmkdir(path); }
82 inline wchar_t* getcwd(wchar_t* buf, size_t size)
83 { return ::_wgetcwd(buf, size > (size_t)INT_MAX ? INT_MAX : (int)size); }
85 inline int chdir(const wchar_t* path)
86 { return ::_wchdir(path); }
88 #if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
89 using utimbuf = _utimbuf;
91 inline int utime(const wchar_t* path, utimbuf* times)
92 { return ::_wutime(path, times); }
93 #endif
95 inline int rename(const wchar_t* oldname, const wchar_t* newname)
96 { return _wrename(oldname, newname); }
98 inline int truncate(const wchar_t* path, _off64_t length)
100 const int fd = ::_wopen(path, _O_BINARY|_O_RDWR);
101 if (fd == -1)
102 return fd;
103 const int ret = ::ftruncate64(fd, length);
104 int err;
105 ::_get_errno(&err);
106 ::_close(fd);
107 ::_set_errno(err);
108 return ret;
110 using char_type = wchar_t;
111 #else // _GLIBCXX_FILESYSTEM_IS_WINDOWS
112 using ::open;
113 using ::close;
114 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
115 typedef struct ::stat stat_type;
116 using ::stat;
117 using ::lstat;
118 #endif
119 using ::mode_t;
120 using ::chmod;
121 using ::mkdir;
122 using ::getcwd;
123 using ::chdir;
124 #if !_GLIBCXX_USE_UTIMENSAT && _GLIBCXX_HAVE_UTIME_H
125 using ::utimbuf;
126 using ::utime;
127 #endif
128 using ::rename;
129 using ::truncate;
130 using char_type = char;
131 #endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
132 } // namespace __gnu_posix
134 template<typename Bitmask>
135 inline bool is_set(Bitmask obj, Bitmask bits)
137 return (obj & bits) != Bitmask::none;
140 inline bool
141 is_not_found_errno(int err) noexcept
143 return err == ENOENT || err == ENOTDIR;
146 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
147 using __gnu_posix::stat_type;
149 inline std::chrono::system_clock::time_point
150 file_time(const stat_type& st, std::error_code& ec) noexcept
152 using namespace std::chrono;
153 #ifdef _GLIBCXX_USE_ST_MTIM
154 time_t s = st.st_mtim.tv_sec;
155 nanoseconds ns{st.st_mtim.tv_nsec};
156 #else
157 time_t s = st.st_mtime;
158 nanoseconds ns{};
159 #endif
161 if (s >= (nanoseconds::max().count() / 1e9))
163 ec = std::make_error_code(std::errc::value_too_large); // EOVERFLOW
164 return system_clock::time_point::min();
166 ec.clear();
167 return system_clock::time_point{seconds{s} + ns};
170 struct copy_options_existing_file
172 bool skip, update, overwrite;
175 bool
176 do_copy_file(const __gnu_posix::char_type* from,
177 const __gnu_posix::char_type* to,
178 copy_options_existing_file options,
179 stat_type* from_st, stat_type* to_st,
180 std::error_code& ec) noexcept;
182 void
183 do_space(const __gnu_posix::char_type* pathname,
184 uintmax_t& capacity, uintmax_t& free, uintmax_t& available,
185 std::error_code&);
187 #endif // _GLIBCXX_HAVE_SYS_STAT_H
189 } // namespace filesystem
191 // BEGIN/END macros must be defined before including this file.
192 _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
194 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
195 using std::filesystem::__gnu_posix::stat_type;
197 inline file_type
198 make_file_type(const stat_type& st) noexcept
200 #ifdef _GLIBCXX_HAVE_S_ISREG
201 if (S_ISREG(st.st_mode))
202 return file_type::regular;
203 else if (S_ISDIR(st.st_mode))
204 return file_type::directory;
205 else if (S_ISCHR(st.st_mode))
206 return file_type::character;
207 else if (S_ISBLK(st.st_mode))
208 return file_type::block;
209 else if (S_ISFIFO(st.st_mode))
210 return file_type::fifo;
211 #ifdef S_ISLNK // not present in mingw
212 else if (S_ISLNK(st.st_mode))
213 return file_type::symlink;
214 #endif
215 #ifdef S_ISSOCK // not present until POSIX:2001
216 else if (S_ISSOCK(st.st_mode))
217 return file_type::socket;
218 #endif
219 #endif
220 return file_type::unknown;
223 inline file_status
224 make_file_status(const stat_type& st) noexcept
226 return file_status{
227 make_file_type(st),
228 static_cast<perms>(st.st_mode) & perms::mask
232 inline std::filesystem::copy_options_existing_file
233 copy_file_options(copy_options opt)
235 using std::filesystem::is_set;
236 return {
237 is_set(opt, copy_options::skip_existing),
238 is_set(opt, copy_options::update_existing),
239 is_set(opt, copy_options::overwrite_existing)
242 #endif // _GLIBCXX_HAVE_SYS_STAT_H
244 _GLIBCXX_END_NAMESPACE_FILESYSTEM
246 _GLIBCXX_END_NAMESPACE_VERSION
247 } // namespace std
249 #endif // _GLIBCXX_OPS_COMMON_H