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
36namespace Poco {
37
38
39File::File()
40{
41}
42
43
44File::File(const std::string& rPath): FileImpl(rPath)
45{
46 poco_assert(std::char_traits<char>::length(rPath.data()) == rPath.size());
47}
48
49
50File::File(const char* pPath): FileImpl(std::string(pPath))
51{
52}
53
54
55File::File(const Path& rPath): FileImpl(rPath.toString())
56{
57}
58
59
60File::File(const File& file): FileImpl(file.getPathImpl())
61{
62}
63
64
65File::~File()
66{
67}
68
69
70File& File::operator = (const File& file)
71{
72 setPathImpl(file.getPathImpl());
73 return *this;
74}
75
76
77File& 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
85File& File::operator = (const char* pPath)
86{
87 poco_check_ptr (pPath);
88 setPathImpl(pPath);
89 return *this;
90}
91
92
93File& File::operator = (const Path& rPath)
94{
95 setPathImpl(rPath.toString());
96 return *this;
97}
98
99
100void File::swap(File& file)
101{
102 swapImpl(file);
103}
104
105
106bool File::exists() const
107{
108 return existsImpl();
109}
110
111
112bool File::canRead() const
113{
114 return canReadImpl();
115}
116
117
118bool File::canWrite() const
119{
120 return canWriteImpl();
121}
122
123
124bool File::canExecute() const
125{
126 return canExecuteImpl();
127}
128
129
130bool File::isFile() const
131{
132 return isFileImpl();
133}
134
135
136bool File::isDirectory() const
137{
138 return isDirectoryImpl();
139}
140
141
142bool File::isLink() const
143{
144 return isLinkImpl();
145}
146
147
148bool File::isDevice() const
149{
150 return isDeviceImpl();
151}
152
153
154bool File::isHidden() const
155{
156 return isHiddenImpl();
157}
158
159
160Timestamp File::created() const
161{
162 return createdImpl();
163}
164
165
166Timestamp File::getLastModified() const
167{
168 return getLastModifiedImpl();
169}
170
171
172File& File::setLastModified(const Timestamp& ts)
173{
174 setLastModifiedImpl(ts);
175 return *this;
176}
177
178
179File::FileSize File::getSize() const
180{
181 return getSizeImpl();
182}
183
184
185File& File::setSize(FileSizeImpl size)
186{
187 setSizeImpl(size);
188 return *this;
189}
190
191
192File& File::setWriteable(bool flag)
193{
194 setWriteableImpl(flag);
195 return *this;
196}
197
198
199File& File::setReadOnly(bool flag)
200{
201 setWriteableImpl(!flag);
202 return *this;
203}
204
205
206File& File::setExecutable(bool flag)
207{
208 setExecutableImpl(flag);
209 return *this;
210}
211
212
213void 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
231void 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
248void 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
257void 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
265void 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
309bool File::createFile()
310{
311 return createFileImpl();
312}
313
314
315bool File::createDirectory()
316{
317 return createDirectoryImpl();
318}
319
320
321void 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
344void 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
357File::FileSize File::totalSpace() const
358{
359 return totalSpaceImpl();
360}
361
362
363File::FileSize File::usableSpace() const
364{
365 return usableSpaceImpl();
366}
367
368
369File::FileSize File::freeSpace() const
370{
371 return freeSpaceImpl();
372}
373
374
375void 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
388void File::handleLastError(const std::string& path)
389{
390 handleLastErrorImpl(path);
391}
392
393
394} // namespace Poco
395