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