1 | // |
---|---|
2 | // File.cpp |
3 | // |
4 | // Library: Foundation |
5 | // Package: Filesystem |
6 | // Module: File |
7 | // |
8 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/File.h" |
16 | #include "Poco/Path.h" |
17 | #include "Poco/DirectoryIterator.h" |
18 | |
19 | |
20 | #if defined(POCO_OS_FAMILY_WINDOWS) |
21 | #if defined(_WIN32_WCE) |
22 | #include "File_WINCE.cpp" |
23 | #else |
24 | #include "File_WIN32.cpp" |
25 | #endif |
26 | #elif defined(POCO_VXWORKS) |
27 | #include "File_VX.cpp" |
28 | #elif defined(POCO_OS_FAMILY_UNIX) |
29 | #include "File_UNIX.cpp" |
30 | #else |
31 | #include "File_VMS.cpp" |
32 | #endif |
33 | #include "Poco/Thread.h" |
34 | |
35 | |
36 | namespace Poco { |
37 | |
38 | |
39 | File::File() |
40 | { |
41 | } |
42 | |
43 | |
44 | File::File(const std::string& rPath): FileImpl(rPath) |
45 | { |
46 | poco_assert(std::char_traits<char>::length(rPath.data()) == rPath.size()); |
47 | } |
48 | |
49 | |
50 | File::File(const char* pPath): FileImpl(std::string(pPath)) |
51 | { |
52 | } |
53 | |
54 | |
55 | File::File(const Path& rPath): FileImpl(rPath.toString()) |
56 | { |
57 | } |
58 | |
59 | |
60 | File::File(const File& file): FileImpl(file.getPathImpl()) |
61 | { |
62 | } |
63 | |
64 | |
65 | File::~File() |
66 | { |
67 | } |
68 | |
69 | |
70 | File& File::operator = (const File& file) |
71 | { |
72 | setPathImpl(file.getPathImpl()); |
73 | return *this; |
74 | } |
75 | |
76 | |
77 | File& File::operator = (const std::string& rPath) |
78 | { |
79 | poco_assert(std::char_traits<char>::length(rPath.data()) == rPath.size()); |
80 | setPathImpl(rPath); |
81 | return *this; |
82 | } |
83 | |
84 | |
85 | File& File::operator = (const char* pPath) |
86 | { |
87 | poco_check_ptr (pPath); |
88 | setPathImpl(pPath); |
89 | return *this; |
90 | } |
91 | |
92 | |
93 | File& File::operator = (const Path& rPath) |
94 | { |
95 | setPathImpl(rPath.toString()); |
96 | return *this; |
97 | } |
98 | |
99 | |
100 | void File::swap(File& file) |
101 | { |
102 | swapImpl(file); |
103 | } |
104 | |
105 | |
106 | bool File::exists() const |
107 | { |
108 | return existsImpl(); |
109 | } |
110 | |
111 | |
112 | bool File::canRead() const |
113 | { |
114 | return canReadImpl(); |
115 | } |
116 | |
117 | |
118 | bool File::canWrite() const |
119 | { |
120 | return canWriteImpl(); |
121 | } |
122 | |
123 | |
124 | bool File::canExecute() const |
125 | { |
126 | return canExecuteImpl(); |
127 | } |
128 | |
129 | |
130 | bool File::isFile() const |
131 | { |
132 | return isFileImpl(); |
133 | } |
134 | |
135 | |
136 | bool File::isDirectory() const |
137 | { |
138 | return isDirectoryImpl(); |
139 | } |
140 | |
141 | |
142 | bool File::isLink() const |
143 | { |
144 | return isLinkImpl(); |
145 | } |
146 | |
147 | |
148 | bool File::isDevice() const |
149 | { |
150 | return isDeviceImpl(); |
151 | } |
152 | |
153 | |
154 | bool File::isHidden() const |
155 | { |
156 | return isHiddenImpl(); |
157 | } |
158 | |
159 | |
160 | Timestamp File::created() const |
161 | { |
162 | return createdImpl(); |
163 | } |
164 | |
165 | |
166 | Timestamp File::getLastModified() const |
167 | { |
168 | return getLastModifiedImpl(); |
169 | } |
170 | |
171 | |
172 | File& File::setLastModified(const Timestamp& ts) |
173 | { |
174 | setLastModifiedImpl(ts); |
175 | return *this; |
176 | } |
177 | |
178 | |
179 | File::FileSize File::getSize() const |
180 | { |
181 | return getSizeImpl(); |
182 | } |
183 | |
184 | |
185 | File& File::setSize(FileSizeImpl size) |
186 | { |
187 | setSizeImpl(size); |
188 | return *this; |
189 | } |
190 | |
191 | |
192 | File& File::setWriteable(bool flag) |
193 | { |
194 | setWriteableImpl(flag); |
195 | return *this; |
196 | } |
197 | |
198 | |
199 | File& File::setReadOnly(bool flag) |
200 | { |
201 | setWriteableImpl(!flag); |
202 | return *this; |
203 | } |
204 | |
205 | |
206 | File& File::setExecutable(bool flag) |
207 | { |
208 | setExecutableImpl(flag); |
209 | return *this; |
210 | } |
211 | |
212 | |
213 | void File::copyTo(const std::string& rPath) const |
214 | { |
215 | poco_assert(std::char_traits<char>::length(rPath.data()) == rPath.size()); |
216 | Path src(getPathImpl()); |
217 | Path dest(rPath); |
218 | File destFile(rPath); |
219 | if ((destFile.exists() && destFile.isDirectory()) || dest.isDirectory()) |
220 | { |
221 | dest.makeDirectory(); |
222 | dest.setFileName(src.getFileName()); |
223 | } |
224 | if (isDirectory()) |
225 | copyDirectory(dest.toString()); |
226 | else |
227 | copyToImpl(dest.toString()); |
228 | } |
229 | |
230 | |
231 | void File::copyDirectory(const std::string& rPath) const |
232 | { |
233 | poco_assert(std::char_traits<char>::length(rPath.data()) == rPath.size()); |
234 | File target(rPath); |
235 | target.createDirectories(); |
236 | |
237 | Path src(getPathImpl()); |
238 | src.makeFile(); |
239 | DirectoryIterator it(src); |
240 | DirectoryIterator end; |
241 | for (; it != end; ++it) |
242 | { |
243 | it->copyTo(rPath); |
244 | } |
245 | } |
246 | |
247 | |
248 | void File::moveTo(const std::string& rPath) |
249 | { |
250 | poco_assert(std::char_traits<char>::length(rPath.data()) == rPath.size()); |
251 | copyTo(rPath); |
252 | remove(true); |
253 | setPathImpl(rPath); |
254 | } |
255 | |
256 | |
257 | void File::renameTo(const std::string& rPath) |
258 | { |
259 | poco_assert(std::char_traits<char>::length(rPath.data()) == rPath.size()); |
260 | renameToImpl(rPath); |
261 | setPathImpl(rPath); |
262 | } |
263 | |
264 | |
265 | void File::remove(bool recursive) |
266 | { |
267 | if (recursive && !isLink() && isDirectory()) |
268 | { |
269 | std::vector<File> files; |
270 | list(files); |
271 | for (std::vector<File>::iterator it = files.begin(); it != files.end(); ++it) |
272 | { |
273 | it->remove(true); |
274 | } |
275 | |
276 | // Note: On Windows, removing a directory may not succeed at first |
277 | // try because deleting files is not a synchronous operation. Files |
278 | // are merely marked as deleted, and actually removed at a later time. |
279 | // |
280 | // An alternate strategy would be moving files to a different directory |
281 | // first (on the same drive, but outside the deleted tree), and marking |
282 | // them as hidden, before deleting them, but this could lead to other issues. |
283 | // So we simply retry after some time until we succeed, or give up. |
284 | |
285 | int retry = 8; |
286 | long sleep = 10; |
287 | while (retry > 0) |
288 | { |
289 | try |
290 | { |
291 | removeImpl(); |
292 | retry = 0; |
293 | } |
294 | catch (DirectoryNotEmptyException&) |
295 | { |
296 | if (--retry == 0) throw; |
297 | Poco::Thread::sleep(sleep); |
298 | sleep *= 2; |
299 | } |
300 | } |
301 | } |
302 | else |
303 | { |
304 | removeImpl(); |
305 | } |
306 | } |
307 | |
308 | |
309 | bool File::createFile() |
310 | { |
311 | return createFileImpl(); |
312 | } |
313 | |
314 | |
315 | bool File::createDirectory() |
316 | { |
317 | return createDirectoryImpl(); |
318 | } |
319 | |
320 | |
321 | void File::createDirectories() |
322 | { |
323 | if (!exists()) |
324 | { |
325 | Path p(getPathImpl()); |
326 | p.makeDirectory(); |
327 | if (p.depth() > 1) |
328 | { |
329 | p.makeParent(); |
330 | File f(p); |
331 | f.createDirectories(); |
332 | } |
333 | try |
334 | { |
335 | createDirectoryImpl(); |
336 | } |
337 | catch (FileExistsException&) |
338 | { |
339 | } |
340 | } |
341 | } |
342 | |
343 | |
344 | void File::list(std::vector<std::string>& files) const |
345 | { |
346 | files.clear(); |
347 | DirectoryIterator it(*this); |
348 | DirectoryIterator end; |
349 | while (it != end) |
350 | { |
351 | files.push_back(it.name()); |
352 | ++it; |
353 | } |
354 | } |
355 | |
356 | |
357 | File::FileSize File::totalSpace() const |
358 | { |
359 | return totalSpaceImpl(); |
360 | } |
361 | |
362 | |
363 | File::FileSize File::usableSpace() const |
364 | { |
365 | return usableSpaceImpl(); |
366 | } |
367 | |
368 | |
369 | File::FileSize File::freeSpace() const |
370 | { |
371 | return freeSpaceImpl(); |
372 | } |
373 | |
374 | |
375 | void File::list(std::vector<File>& files) const |
376 | { |
377 | files.clear(); |
378 | DirectoryIterator it(*this); |
379 | DirectoryIterator end; |
380 | while (it != end) |
381 | { |
382 | files.push_back(*it); |
383 | ++it; |
384 | } |
385 | } |
386 | |
387 | |
388 | void File::handleLastError(const std::string& path) |
389 | { |
390 | handleLastErrorImpl(path); |
391 | } |
392 | |
393 | |
394 | } // namespace Poco |
395 |