Line data Source code
1 : /*!
2 : * \file esys/repo/filesystem.cpp
3 : * \brief
4 : *
5 : * \cond
6 : * __legal_b__
7 : *
8 : * Copyright (c) 2020 Michel Gillet
9 : * Distributed under the MIT License.
10 : * (See accompanying file LICENSE.txt or
11 : * copy at https://opensource.org/licenses/MIT)
12 : *
13 : * __legal_e__
14 : * \endcond
15 : *
16 : */
17 :
18 : #include "esys/repo/esysrepo_prec.h"
19 : #include "esys/repo/filesystem.h"
20 :
21 : #if ESYSREPO_HAS_STD_FILESYSTEM
22 : #include <filesystem>
23 : #endif
24 :
25 : #include <boost/filesystem.hpp>
26 : #include <boost/version.hpp>
27 :
28 : #if BOOST_VERSION <= 107100
29 : #define ESYSREPO_BOOST_FILESYSTEM_HAS_RECUR 0
30 : #else
31 : #define ESYSREPO_BOOST_FILESYSTEM_HAS_RECUR 1
32 : #endif
33 :
34 : namespace esys::repo
35 : {
36 :
37 : namespace stdcpp
38 : {
39 :
40 0 : ESYSREPO_API int copy(const std::string &src, const std::string &dst, bool recursive)
41 : {
42 : #if ESYSREPO_HAS_STD_FILESYSTEM
43 : try
44 : {
45 : if (recursive)
46 : std::filesystem::copy(src, dst, std::filesystem::copy_options::recursive);
47 : else
48 : std::filesystem::copy(src, dst);
49 : }
50 : catch (std::exception &)
51 : {
52 : return -1;
53 : }
54 : return 0;
55 : #else
56 0 : return -1;
57 : #endif
58 : }
59 :
60 0 : ESYSREPO_API int remove_all(const std::string &path)
61 : {
62 : #if ESYSREPO_HAS_STD_FILESYSTEM
63 : try
64 : {
65 : std::filesystem::remove_all(path);
66 : }
67 : catch (std::exception &)
68 : {
69 : return -1;
70 : }
71 : return 0;
72 : #else
73 0 : return -1;
74 : #endif
75 : }
76 :
77 : } // namespace stdcpp
78 :
79 : namespace boost_no_recur
80 : {
81 :
82 579 : ESYSREPO_API int copy(const std::string &src, const std::string &dst, bool recursive)
83 : {
84 579 : if (!recursive)
85 : {
86 0 : try
87 : {
88 0 : boost::filesystem::copy(src, dst);
89 : }
90 0 : catch (std::exception &)
91 : {
92 0 : return -1;
93 0 : }
94 0 : return 0;
95 : }
96 :
97 579 : boost::filesystem::directory_iterator it(src);
98 :
99 579 : try
100 : {
101 1823 : while (it != boost::filesystem::directory_iterator{})
102 : {
103 1244 : boost::filesystem::path copy_to = dst;
104 2488 : copy_to /= it->path().filename();
105 :
106 1244 : if (boost::filesystem::is_directory(*it))
107 : {
108 546 : if (!boost::filesystem::create_directory(copy_to.string())) return -1;
109 546 : int result = copy(it->path().string(), copy_to.string(), recursive);
110 546 : if (result < 0) return result;
111 : }
112 : else
113 : {
114 698 : boost::system::error_code ec;
115 :
116 698 : boost::filesystem::copy(*it, copy_to, ec);
117 698 : if (ec) return -1;
118 : }
119 :
120 1244 : *it++;
121 1244 : }
122 : }
123 0 : catch (std::exception &)
124 : {
125 0 : return -1;
126 0 : }
127 : return 0;
128 579 : }
129 :
130 : } // namespace boost_no_recur
131 :
132 : namespace boost_recur
133 : {
134 :
135 0 : ESYSREPO_API int copy(const std::string &src, const std::string &dst, bool recursive)
136 : {
137 : #if ESYSREPO_BOOST_FILESYSTEM_HAS_RECUR
138 0 : try
139 : {
140 0 : if (recursive)
141 0 : boost::filesystem::copy(src, dst, boost::filesystem::copy_options::recursive);
142 : else
143 0 : boost::filesystem::copy(src, dst);
144 : }
145 0 : catch (std::exception &)
146 : {
147 0 : return -1;
148 0 : }
149 : return 0;
150 : #else
151 : return -1;
152 : #endif
153 : }
154 :
155 : } // namespace boost_recur
156 :
157 : namespace boost_all
158 : {
159 :
160 0 : ESYSREPO_API int remove_all(const std::string &path)
161 : {
162 0 : try
163 : {
164 0 : boost::filesystem::remove_all(path);
165 : }
166 0 : catch (std::exception &)
167 : {
168 0 : return -1;
169 0 : }
170 0 : return 0;
171 : }
172 :
173 : } // namespace boost_all
174 :
175 : namespace boost_no_all
176 : {
177 :
178 582 : ESYSREPO_API int remove_all(const std::string &path)
179 : {
180 582 : boost::filesystem::directory_iterator it(path);
181 582 : boost::filesystem::file_status stat;
182 582 : boost::system::error_code ec;
183 :
184 582 : try
185 : {
186 1828 : while (it != boost::filesystem::directory_iterator{})
187 : {
188 1246 : if (boost::filesystem::is_directory(*it))
189 : {
190 548 : int result = boost_no_all::remove_all(it->path().string());
191 548 : if (result < 0) return result;
192 : }
193 : else
194 : {
195 698 : stat = boost::filesystem::status(it->path(), ec);
196 :
197 698 : if (ec == boost::system::error_code())
198 : {
199 698 : if ((stat.permissions() & boost::filesystem::perms::others_write)
200 : != boost::filesystem::perms::others_write)
201 : {
202 694 : boost::filesystem::permissions(*it,
203 : stat.permissions() | boost::filesystem::perms::others_write);
204 : }
205 : }
206 :
207 698 : try
208 : {
209 698 : boost::filesystem::remove(*it);
210 : }
211 0 : catch (std::exception &)
212 : {
213 0 : return -1;
214 0 : }
215 : }
216 1246 : *it++;
217 : }
218 582 : boost::filesystem::remove_all(path);
219 : }
220 0 : catch (std::exception &)
221 : {
222 0 : return -1;
223 0 : }
224 582 : return 0;
225 582 : }
226 :
227 33 : ESYSREPO_API int move(const std::string &src, const std::string &dst, bool recursive)
228 : {
229 33 : int result = copy(src, dst, recursive);
230 33 : if (result < 0) return -1;
231 :
232 33 : result = remove_all(src);
233 33 : if (result < 0) return -2;
234 : return 0;
235 : }
236 :
237 : } // namespace boost_no_all
238 :
239 0 : ESYSREPO_API int move(const std::string &src, const std::string &dst, bool recursive)
240 : {
241 0 : int result = copy(src, dst, recursive);
242 0 : if (result < 0) return -1;
243 :
244 0 : result = remove_all(src);
245 0 : if (result < 0) return -2;
246 : return 0;
247 : }
248 :
249 : } // namespace esys::repo
|