1 // Filesystem operation utilities -*- C++ -*-
2 
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.
10 
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.
15 
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.
19 
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/>.
24 
25 #ifndef _GLIBCXX_OPS_COMMON_H
26 #define _GLIBCXX_OPS_COMMON_H 1
27 
28 #include <chrono>
29 
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 
_GLIBCXX_VISIBILITY(default)38 namespace std _GLIBCXX_VISIBILITY(default)
39 {
40 _GLIBCXX_BEGIN_NAMESPACE_VERSION
41 namespace filesystem
42 {
43   template<typename Bitmask>
44     inline bool is_set(Bitmask obj, Bitmask bits)
45     {
46       return (obj & bits) != Bitmask::none;
47     }
48 
49   inline bool
50   is_not_found_errno(int err) noexcept
51   {
52     return err == ENOENT || err == ENOTDIR;
53   }
54 
55 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
56   typedef struct ::stat stat_type;
57 
58   inline std::chrono::system_clock::time_point
59   file_time(const stat_type& st, std::error_code& ec) noexcept
60   {
61     using namespace std::chrono;
62 #ifdef _GLIBCXX_USE_ST_MTIM
63     time_t s = st.st_mtim.tv_sec;
64     nanoseconds ns{st.st_mtim.tv_nsec};
65 #else
66     time_t s = st.st_mtime;
67     nanoseconds ns{};
68 #endif
69 
70     if (s >= (nanoseconds::max().count() / 1e9))
71       {
72 	ec = std::make_error_code(std::errc::value_too_large); // EOVERFLOW
73 	return system_clock::time_point::min();
74       }
75     ec.clear();
76     return system_clock::time_point{seconds{s} + ns};
77   }
78 
79   struct copy_options_existing_file
80   {
81     bool skip, update, overwrite;
82   };
83 
84   bool
85   do_copy_file(const char* from, const char* to,
86 	       copy_options_existing_file options,
87 	       stat_type* from_st, stat_type* to_st,
88 	       std::error_code& ec) noexcept;
89 
90 #endif // _GLIBCXX_HAVE_SYS_STAT_H
91 
92 } // namespace filesystem
93 
94 // BEGIN/END macros must be defined before including this file.
95 _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM
96 
97 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
98   typedef struct ::stat stat_type;
99 
100   inline file_type
101   make_file_type(const stat_type& st) noexcept
102   {
103 #ifdef _GLIBCXX_HAVE_S_ISREG
104     if (S_ISREG(st.st_mode))
105       return file_type::regular;
106     else if (S_ISDIR(st.st_mode))
107       return file_type::directory;
108     else if (S_ISCHR(st.st_mode))
109       return file_type::character;
110     else if (S_ISBLK(st.st_mode))
111       return file_type::block;
112     else if (S_ISFIFO(st.st_mode))
113       return file_type::fifo;
114     else if (S_ISLNK(st.st_mode))
115       return file_type::symlink;
116 #ifdef S_ISSOCK // not present until POSIX:2001
117     else if (S_ISSOCK(st.st_mode))
118       return file_type::socket;
119 #endif
120 #endif
121     return file_type::unknown;
122   }
123 
124   inline file_status
125   make_file_status(const stat_type& st) noexcept
126   {
127     return file_status{
128 	make_file_type(st),
129 	static_cast<perms>(st.st_mode) & perms::mask
130     };
131   }
132 
133   inline std::filesystem::copy_options_existing_file
134   copy_file_options(copy_options opt)
135   {
136     using std::filesystem::is_set;
137     return {
138 	is_set(opt, copy_options::skip_existing),
139 	is_set(opt, copy_options::update_existing),
140 	is_set(opt, copy_options::overwrite_existing)
141     };
142   }
143 #endif // _GLIBCXX_HAVE_SYS_STAT_H
144 
145 _GLIBCXX_END_NAMESPACE_FILESYSTEM
146 
147 _GLIBCXX_END_NAMESPACE_VERSION
148 } // namespace std
149 
150 #endif // _GLIBCXX_OPS_COMMON_H
151