1 // operations.cpp --------------------------------------------------------------------//
3 // Copyright 2002-2009 Beman Dawes
4 // Copyright 2001 Dietmar Kuehl
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
9 // See library home page at http://www.boost.org/libs/filesystem
11 //--------------------------------------------------------------------------------------//
13 // define 64-bit offset macros BEFORE including boost/config.hpp (see ticket #5355)
14 #if !(defined(__HP_aCC) && defined(_ILP32) && !defined(_STATVFS_ACPP_PROBLEMS_FIXED))
15 #define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect,
18 #define __USE_FILE_OFFSET64 // but that is harmless on Windows and on POSIX
19 // 64-bit systems or on 32-bit systems which don't have files larger
20 // than can be represented by a traditional POSIX/UNIX off_t type.
21 // OTOH, defining them should kick in 64-bit off_t's (and thus
22 // st_size)on 32-bit systems that provide the Large File
23 // Support (LFS)interface, such as Linux, Solaris, and IRIX.
24 // The defines are given before any headers are included to
25 // ensure that they are available to all included headers.
26 // That is required at least on Solaris, and possibly on other
29 #define _FILE_OFFSET_BITS 64
32 #include <boost/config.hpp>
33 #if !defined( BOOST_NO_STD_WSTRING )
34 // Boost.Filesystem V3 and later requires std::wstring support.
35 // During the transition to V3, libraries are compiled with both V2 and V3 sources.
36 // On old compilers that don't support V3 anyhow, we just skip everything so the compile
37 // will succeed and the library can be built.
39 // define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
40 // the library is being built (possibly exporting rather than importing code)
42 #define BOOST_FILESYSTEM_SOURCE
44 #ifndef BOOST_SYSTEM_NO_DEPRECATED
45 # define BOOST_SYSTEM_NO_DEPRECATED
48 #ifndef _POSIX_PTHREAD_SEMANTICS
49 # define _POSIX_PTHREAD_SEMANTICS // Sun readdir_r()needs this
52 #include <boost/filesystem/v3/operations.hpp>
53 #include <boost/scoped_array.hpp>
54 #include <boost/detail/workaround.hpp>
56 #include <cstdlib> // for malloc, free
57 #include <sys/stat.h> // even on Windows some functions use stat()
59 #include <cstdio> // for remove, rename
60 #if defined(__QNXNTO__) // see ticket #5355
65 #ifdef BOOST_FILEYSTEM_INCLUDE_IOSTREAM
69 namespace fs
= boost::filesystem3
;
70 using boost::filesystem3::path
;
71 using boost::filesystem3::filesystem_error
;
72 using boost::filesystem3::perms
;
73 using boost::system::error_code
;
74 using boost::system::error_category
;
75 using boost::system::system_category
;
79 # ifdef BOOST_POSIX_API
81 const fs::path
dot_path(".");
82 const fs::path
dot_dot_path("..");
83 # include <sys/types.h>
84 # if !defined(__APPLE__) && !defined(__OpenBSD__)
85 # include <sys/statvfs.h>
86 # define BOOST_STATVFS statvfs
87 # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize
90 # include <sys/param.h>
92 # include <sys/mount.h>
93 # define BOOST_STATVFS statfs
94 # define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>(vfs.f_bsize)
102 # else // BOOST_WINDOW_API
104 const fs::path
dot_path(L
".");
105 const fs::path
dot_dot_path(L
"..");
106 # if (defined(__MINGW32__) || defined(__CYGWIN__)) && !defined(WINVER)
107 // Versions of MinGW or Cygwin that support Filesystem V3 support at least WINVER 0x501.
108 // See MinGW's windef.h
109 # define WINVER 0x501
112 # include <windows.h>
114 # if !defined(_WIN32_WINNT)
115 # define _WIN32_WINNT 0x0500
117 # if defined(__BORLANDC__) || defined(__MWERKS__)
118 # if defined(__BORLANDC__)
123 # include <sys/utime.h>
126 // REPARSE_DATA_BUFFER related definitions are found in ntifs.h, which is part of the
127 // Windows Device Driver Kit. Since that's inconvenient, the definitions are provided
128 // here. See http://msdn.microsoft.com/en-us/library/ms791514.aspx
130 #if !defined(REPARSE_DATA_BUFFER_HEADER_SIZE) // mingw winnt.h does provide the defs
132 #define SYMLINK_FLAG_RELATIVE 1
134 typedef struct _REPARSE_DATA_BUFFER
{
136 USHORT ReparseDataLength
;
140 USHORT SubstituteNameOffset
;
141 USHORT SubstituteNameLength
;
142 USHORT PrintNameOffset
;
143 USHORT PrintNameLength
;
146 /* Example of distinction between substitute and print names:
148 SubstituteName: c:\\??\
151 } SymbolicLinkReparseBuffer
;
153 USHORT SubstituteNameOffset
;
154 USHORT SubstituteNameLength
;
155 USHORT PrintNameOffset
;
156 USHORT PrintNameLength
;
158 } MountPointReparseBuffer
;
161 } GenericReparseBuffer
;
163 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
165 #define REPARSE_DATA_BUFFER_HEADER_SIZE \
166 FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
170 #ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
171 #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
174 # ifndef FSCTL_GET_REPARSE_POINT
175 # define FSCTL_GET_REPARSE_POINT 0x900a8
178 # ifndef IO_REPARSE_TAG_SYMLINK
179 # define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
182 # endif // BOOST_WINDOWS_API
184 // BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in
185 // dir_itr_increment. The config tests are placed here because some of the
186 // macros being tested come from dirent.h.
188 // TODO: find out what macros indicate dirent::d_type present in more libraries
189 # if defined(BOOST_WINDOWS_API)\
190 || defined(_DIRENT_HAVE_D_TYPE)// defined by GNU C library if d_type present
191 # define BOOST_FILESYSTEM_STATUS_CACHE
194 // POSIX/Windows macros ----------------------------------------------------//
196 // Portions of the POSIX and Windows API's are very similar, except for name,
197 // order of arguments, and meaning of zero/non-zero returns. The macros below
198 // abstract away those differences. They follow Windows naming and order of
199 // arguments, and return true to indicate no error occurred. [POSIX naming,
200 // order of arguments, and meaning of return were followed initially, but
201 // found to be less clear and cause more coding errors.]
203 # if defined(BOOST_POSIX_API)
205 // POSIX uses a 0 return to indicate success
206 # define BOOST_ERRNO errno
207 # define BOOST_SET_CURRENT_DIRECTORY(P)(::chdir(P)== 0)
208 # define BOOST_CREATE_DIRECTORY(P)(::mkdir(P, S_IRWXU|S_IRWXG|S_IRWXO)== 0)
209 # define BOOST_CREATE_HARD_LINK(F,T)(::link(T, F)== 0)
210 # define BOOST_CREATE_SYMBOLIC_LINK(F,T,Flag)(::symlink(T, F)== 0)
211 # define BOOST_REMOVE_DIRECTORY(P)(::rmdir(P)== 0)
212 # define BOOST_DELETE_FILE(P)(::unlink(P)== 0)
213 # define BOOST_COPY_DIRECTORY(F,T)(!(::stat(from.c_str(), &from_stat)!= 0\
214 || ::mkdir(to.c_str(),from_stat.st_mode)!= 0))
215 # define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool)
216 # define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0)
217 # define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0)
219 # define BOOST_ERROR_NOT_SUPPORTED ENOSYS
220 # define BOOST_ERROR_ALREADY_EXISTS EEXIST
222 # else // BOOST_WINDOWS_API
224 // Windows uses a non-0 return to indicate success
225 # define BOOST_ERRNO ::GetLastError()
226 # define BOOST_SET_CURRENT_DIRECTORY(P)(::SetCurrentDirectoryW(P)!= 0)
227 # define BOOST_CREATE_DIRECTORY(P)(::CreateDirectoryW(P, 0)!= 0)
228 # define BOOST_CREATE_HARD_LINK(F,T)(create_hard_link_api(F, T, 0)!= 0)
229 # define BOOST_CREATE_SYMBOLIC_LINK(F,T,Flag)(create_symbolic_link_api(F, T, Flag)!= 0)
230 # define BOOST_REMOVE_DIRECTORY(P)(::RemoveDirectoryW(P)!= 0)
231 # define BOOST_DELETE_FILE(P)(::DeleteFileW(P)!= 0)
232 # define BOOST_COPY_DIRECTORY(F,T)(::CreateDirectoryExW(F, T, 0)!= 0)
233 # define BOOST_COPY_FILE(F,T,FailIfExistsBool)(::CopyFileW(F, T, FailIfExistsBool)!= 0)
234 # define BOOST_MOVE_FILE(OLD,NEW)(::MoveFileExW(OLD, NEW, MOVEFILE_REPLACE_EXISTING)!= 0)
235 # define BOOST_RESIZE_FILE(P,SZ)(resize_file_api(P, SZ)!= 0)
236 # define BOOST_READ_SYMLINK(P,T)
238 # define BOOST_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS
239 # define BOOST_ERROR_NOT_SUPPORTED ERROR_NOT_SUPPORTED
243 //--------------------------------------------------------------------------------------//
245 // helpers (all operating systems) //
247 //--------------------------------------------------------------------------------------//
252 fs::file_type
query_file_type(const path
& p
, error_code
* ec
);
254 boost::filesystem3::directory_iterator end_dir_itr
;
256 const std::size_t buf_size(128);
259 bool error(bool was_error
, error_code
* ec
, const string
& message
)
263 if (ec
!= 0) ec
->clear();
268 BOOST_FILESYSTEM_THROW(filesystem_error(message
,
269 error_code(BOOST_ERRNO
, system_category())));
271 ec
->assign(BOOST_ERRNO
, system_category());
276 bool error(bool was_error
, const path
& p
, error_code
* ec
, const string
& message
)
280 if (ec
!= 0) ec
->clear();
285 BOOST_FILESYSTEM_THROW(filesystem_error(message
,
286 p
, error_code(BOOST_ERRNO
, system_category())));
288 ec
->assign(BOOST_ERRNO
, system_category());
293 bool error(bool was_error
, const path
& p1
, const path
& p2
, error_code
* ec
,
294 const string
& message
)
298 if (ec
!= 0) ec
->clear();
303 BOOST_FILESYSTEM_THROW(filesystem_error(message
,
304 p1
, p2
, error_code(BOOST_ERRNO
, system_category())));
306 ec
->assign(BOOST_ERRNO
, system_category());
311 bool error(bool was_error
, const error_code
& result
,
312 const path
& p
, error_code
* ec
, const string
& message
)
313 // Overwrites ec if there has already been an error
317 if (ec
!= 0) ec
->clear();
322 BOOST_FILESYSTEM_THROW(filesystem_error(message
, p
, result
));
329 bool error(bool was_error
, const error_code
& result
,
330 const path
& p1
, const path
& p2
, error_code
* ec
, const string
& message
)
331 // Overwrites ec if there has already been an error
335 if (ec
!= 0) ec
->clear();
340 BOOST_FILESYSTEM_THROW(filesystem_error(message
, p1
, p2
, result
));
347 bool is_empty_directory(const path
& p
)
349 return fs::directory_iterator(p
)== end_dir_itr
;
352 bool remove_directory(const path
& p
) // true if succeeds
353 { return BOOST_REMOVE_DIRECTORY(p
.c_str()); }
355 bool remove_file(const path
& p
) // true if succeeds
356 { return BOOST_DELETE_FILE(p
.c_str()); }
358 // called by remove and remove_all_aux
359 bool remove_file_or_directory(const path
& p
, fs::file_type type
, error_code
* ec
)
360 // return true if file removed, false if not removed
362 if (type
== fs::file_not_found
)
364 if (ec
!= 0) ec
->clear();
368 if (type
== fs::directory_file
369 # ifdef BOOST_WINDOWS_API
370 || type
== fs::_detail_directory_symlink
374 if (error(!remove_directory(p
), p
, ec
, "boost::filesystem::remove"))
379 if (error(!remove_file(p
), p
, ec
, "boost::filesystem::remove"))
385 boost::uintmax_t remove_all_aux(const path
& p
, fs::file_type type
,
388 boost::uintmax_t count
= 1;
390 if (type
== fs::directory_file
) // but not a directory symlink
392 for (fs::directory_iterator
itr(p
);
393 itr
!= end_dir_itr
; ++itr
)
395 fs::file_type tmp_type
= query_file_type(itr
->path(), ec
);
398 count
+= remove_all_aux(itr
->path(), tmp_type
, ec
);
401 remove_file_or_directory(p
, type
, ec
);
405 #ifdef BOOST_POSIX_API
407 //--------------------------------------------------------------------------------------//
409 // POSIX-specific helpers //
411 //--------------------------------------------------------------------------------------//
413 const char dot
= '.';
415 bool not_found_error(int errval
)
417 return errno
== ENOENT
|| errno
== ENOTDIR
;
421 copy_file_api(const std::string
& from_p
,
422 const std::string
& to_p
, bool fail_if_exists
)
424 const std::size_t buf_sz
= 32768;
425 boost::scoped_array
<char> buf(new char [buf_sz
]);
426 int infile
=-1, outfile
=-1; // -1 means not open
428 // bug fixed: code previously did a stat()on the from_file first, but that
429 // introduced a gratuitous race condition; the stat()is now done after the open()
431 if ((infile
= ::open(from_p
.c_str(), O_RDONLY
))< 0)
434 struct stat from_stat
;
435 if (::stat(from_p
.c_str(), &from_stat
)!= 0)
441 int oflag
= O_CREAT
| O_WRONLY
| O_TRUNC
;
444 if ((outfile
= ::open(to_p
.c_str(), oflag
, from_stat
.st_mode
))< 0)
446 int open_errno
= errno
;
447 BOOST_ASSERT(infile
>= 0);
453 ssize_t sz
, sz_read
=1, sz_write
;
455 && (sz_read
= ::read(infile
, buf
.get(), buf_sz
))> 0)
457 // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
458 // Marc Rochkind, Addison-Wesley, 2004, page 94
462 if ((sz
= ::write(outfile
, buf
.get() + sz_write
,
463 sz_read
- sz_write
))< 0)
465 sz_read
= sz
; // cause read loop termination
466 break; // and error to be thrown after closes
469 } while (sz_write
< sz_read
);
472 if (::close(infile
)< 0)sz_read
= -1;
473 if (::close(outfile
)< 0)sz_read
= -1;
478 inline fs::file_type
query_file_type(const path
& p
, error_code
* ec
)
480 return fs::detail::symlink_status(p
, ec
).type();
485 //--------------------------------------------------------------------------------------//
487 // Windows-specific helpers //
489 //--------------------------------------------------------------------------------------//
491 const wchar_t dot
= L
'.';
493 bool not_found_error(int errval
)
495 return errval
== ERROR_FILE_NOT_FOUND
496 || errval
== ERROR_PATH_NOT_FOUND
497 || errval
== ERROR_INVALID_NAME
// "tools/jam/src/:sys:stat.h", "//foo"
498 || errval
== ERROR_INVALID_DRIVE
// USB card reader with no card inserted
499 || errval
== ERROR_NOT_READY
// CD/DVD drive with no disc inserted
500 || errval
== ERROR_INVALID_PARAMETER
// ":sys:stat.h"
501 || errval
== ERROR_BAD_PATHNAME
// "//nosuch" on Win64
502 || errval
== ERROR_BAD_NETPATH
; // "//nosuch" on Win32
505 // some distributions of mingw as early as GLIBCXX__ 20110325 have _stricmp, but the
506 // offical 4.6.2 release with __GLIBCXX__ 20111026 doesn't. Play it safe for now, and
507 // only use _stricmp if _MSC_VER is defined
508 #if defined(_MSC_VER) // || (defined(__GLIBCXX__) && __GLIBCXX__ >= 20110325)
509 # define BOOST_FILESYSTEM_STRICMP _stricmp
511 # define BOOST_FILESYSTEM_STRICMP strcmp
514 perms
make_permissions(const path
& p
, DWORD attr
)
516 perms prms
= fs::owner_read
| fs::group_read
| fs::others_read
;
517 if ((attr
& FILE_ATTRIBUTE_READONLY
) == 0)
518 prms
|= fs::owner_write
| fs::group_write
| fs::others_write
;
519 if (BOOST_FILESYSTEM_STRICMP(p
.extension().string().c_str(), ".exe") == 0
520 || BOOST_FILESYSTEM_STRICMP(p
.extension().string().c_str(), ".com") == 0
521 || BOOST_FILESYSTEM_STRICMP(p
.extension().string().c_str(), ".bat") == 0
522 || BOOST_FILESYSTEM_STRICMP(p
.extension().string().c_str(), ".cmd") == 0)
523 prms
|= fs::owner_exe
| fs::group_exe
| fs::others_exe
;
527 // these constants come from inspecting some Microsoft sample code
528 std::time_t to_time_t(const FILETIME
& ft
)
530 __int64 t
= (static_cast<__int64
>(ft
.dwHighDateTime
)<< 32)
532 # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // > VC++ 7.0
533 t
-= 116444736000000000LL;
535 t
-= 116444736000000000;
538 return static_cast<std::time_t>(t
);
541 void to_FILETIME(std::time_t t
, FILETIME
& ft
)
545 # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // > VC++ 7.0
546 temp
+= 116444736000000000LL;
548 temp
+= 116444736000000000;
550 ft
.dwLowDateTime
= static_cast<DWORD
>(temp
);
551 ft
.dwHighDateTime
= static_cast<DWORD
>(temp
>> 32);
554 // Thanks to Jeremy Maitin-Shepard for much help and for permission to
555 // base the equivalent()implementation on portions of his
556 // file-equivalence-win32.cpp experimental code.
558 struct handle_wrapper
561 handle_wrapper(HANDLE h
)
565 if (handle
!= INVALID_HANDLE_VALUE
)
566 ::CloseHandle(handle
);
570 HANDLE
create_file_handle(const path
& p
, DWORD dwDesiredAccess
,
571 DWORD dwShareMode
, LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
572 DWORD dwCreationDisposition
, DWORD dwFlagsAndAttributes
,
573 HANDLE hTemplateFile
)
575 return ::CreateFileW(p
.c_str(), dwDesiredAccess
, dwShareMode
,
576 lpSecurityAttributes
, dwCreationDisposition
, dwFlagsAndAttributes
,
580 bool is_reparse_point_a_symlink(const path
& p
)
582 handle_wrapper
h(create_file_handle(p
, FILE_READ_EA
,
583 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
,
584 FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_OPEN_REPARSE_POINT
, NULL
));
585 if (h
.handle
== INVALID_HANDLE_VALUE
)
588 boost::scoped_array
<char> buf(new char [MAXIMUM_REPARSE_DATA_BUFFER_SIZE
]);
590 // Query the reparse data
592 BOOL result
= ::DeviceIoControl(h
.handle
, FSCTL_GET_REPARSE_POINT
, NULL
, 0, buf
.get(),
593 MAXIMUM_REPARSE_DATA_BUFFER_SIZE
, &dwRetLen
, NULL
);
594 if (!result
) return false;
596 return reinterpret_cast<const REPARSE_DATA_BUFFER
*>(buf
.get())
597 ->ReparseTag
== IO_REPARSE_TAG_SYMLINK
;
600 inline std::size_t get_full_path_name(
601 const path
& src
, std::size_t len
, wchar_t* buf
, wchar_t** p
)
603 return static_cast<std::size_t>(
604 ::GetFullPathNameW(src
.c_str(), static_cast<DWORD
>(len
), buf
, p
));
607 fs::file_status
process_status_failure(const path
& p
, error_code
* ec
)
609 int errval(::GetLastError());
610 if (ec
!= 0) // always report errval, even though some
611 ec
->assign(errval
, system_category()); // errval values are not status_errors
613 if (not_found_error(errval
))
615 return fs::file_status(fs::file_not_found
, fs::no_perms
);
617 else if ((errval
== ERROR_SHARING_VIOLATION
))
619 return fs::file_status(fs::type_unknown
);
622 BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
623 p
, error_code(errval
, system_category())));
624 return fs::file_status(fs::status_error
);
627 // differs from symlink_status() in that directory symlinks are reported as
628 // _detail_directory_symlink, as required on Windows by remove() and its helpers.
629 fs::file_type
query_file_type(const path
& p
, error_code
* ec
)
631 DWORD
attr(::GetFileAttributesW(p
.c_str()));
632 if (attr
== 0xFFFFFFFF)
634 return process_status_failure(p
, ec
).type();
637 if (ec
!= 0) ec
->clear();
639 if (attr
& FILE_ATTRIBUTE_REPARSE_POINT
)
641 if (is_reparse_point_a_symlink(p
))
642 return (attr
& FILE_ATTRIBUTE_DIRECTORY
)
643 ? fs::_detail_directory_symlink
645 return fs::reparse_file
;
648 return (attr
& FILE_ATTRIBUTE_DIRECTORY
)
653 BOOL
resize_file_api(const wchar_t* p
, boost::uintmax_t size
)
655 HANDLE handle
= CreateFileW(p
, GENERIC_WRITE
, 0, 0, OPEN_EXISTING
,
656 FILE_ATTRIBUTE_NORMAL
, 0);
659 return handle
!= INVALID_HANDLE_VALUE
660 && ::SetFilePointerEx(handle
, sz
, 0, FILE_BEGIN
)
661 && ::SetEndOfFile(handle
)
662 && ::CloseHandle(handle
);
665 // Windows kernel32.dll functions that may or may not be present
666 // must be accessed through pointers
668 typedef BOOL (WINAPI
*PtrCreateHardLinkW
)(
669 /*__in*/ LPCWSTR lpFileName
,
670 /*__in*/ LPCWSTR lpExistingFileName
,
671 /*__reserved*/ LPSECURITY_ATTRIBUTES lpSecurityAttributes
674 PtrCreateHardLinkW create_hard_link_api
= PtrCreateHardLinkW(
676 ::GetModuleHandle(TEXT("kernel32.dll")), "CreateHardLinkW"));
678 typedef BOOLEAN (WINAPI
*PtrCreateSymbolicLinkW
)(
679 /*__in*/ LPCWSTR lpSymlinkFileName
,
680 /*__in*/ LPCWSTR lpTargetFileName
,
681 /*__in*/ DWORD dwFlags
684 PtrCreateSymbolicLinkW create_symbolic_link_api
= PtrCreateSymbolicLinkW(
686 ::GetModuleHandle(TEXT("kernel32.dll")), "CreateSymbolicLinkW"));
690 //#ifdef BOOST_WINDOWS_API
693 // inline bool get_free_disk_space(const std::wstring& ph,
694 // PULARGE_INTEGER avail, PULARGE_INTEGER total, PULARGE_INTEGER free)
695 // { return ::GetDiskFreeSpaceExW(ph.c_str(), avail, total, free)!= 0; }
699 } // unnamed namespace
701 //--------------------------------------------------------------------------------------//
703 // operations functions declared in operations.hpp //
704 // in alphabetic order //
706 //--------------------------------------------------------------------------------------//
710 namespace filesystem3
713 BOOST_FILESYSTEM_DECL
714 path
absolute(const path
& p
, const path
& base
)
716 // if ( p.empty() || p.is_absolute() )
718 // // recursively calling absolute is sub-optimal, but is simple
719 // path abs_base(base.is_absolute() ? base : absolute(base));
720 //# ifdef BOOST_WINDOWS_API
721 // if (p.has_root_directory())
722 // return abs_base.root_name() / p;
723 // // !p.has_root_directory
724 // if (p.has_root_name())
725 // return p.root_name()
726 // / abs_base.root_directory() / abs_base.relative_path() / p.relative_path();
727 // // !p.has_root_name()
729 // return abs_base / p;
731 // recursively calling absolute is sub-optimal, but is sure and simple
732 path
abs_base(base
.is_absolute() ? base
: absolute(base
));
734 // store expensive to compute values that are needed multiple times
735 path
p_root_name (p
.root_name());
736 path
base_root_name (abs_base
.root_name());
737 path
p_root_directory (p
.root_directory());
742 if (!p_root_name
.empty()) // p.has_root_name()
744 if (p_root_directory
.empty()) // !p.has_root_directory()
745 return p_root_name
/ abs_base
.root_directory()
746 / abs_base
.relative_path() / p
.relative_path();
747 // p is absolute, so fall through to return p at end of block
750 else if (!p_root_directory
.empty()) // p.has_root_directory()
752 # ifdef BOOST_POSIX_API
753 // POSIX can have root name it it is a network path
754 if (base_root_name
.empty()) // !abs_base.has_root_name()
757 return base_root_name
/ p
;
765 return p
; // p.is_absolute() is true
770 BOOST_FILESYSTEM_DECL
bool possible_large_file_size_support()
772 # ifdef BOOST_POSIX_API
773 struct stat lcl_stat
;
774 return sizeof(lcl_stat
.st_size
)> 4;
780 BOOST_FILESYSTEM_DECL
781 path
canonical(const path
& p
, const path
& base
, system::error_code
* ec
)
783 path
source (p
.is_absolute() ? p
: absolute(p
, base
));
786 system::error_code local_ec
;
787 file_status
stat (status(source
, local_ec
));
789 if (stat
.type() == fs::file_not_found
)
792 BOOST_FILESYSTEM_THROW(filesystem_error(
793 "boost::filesystem::canonical", source
,
794 error_code(system::errc::no_such_file_or_directory
, system::generic_category())));
795 ec
->assign(system::errc::no_such_file_or_directory
, system::generic_category());
801 BOOST_FILESYSTEM_THROW(filesystem_error(
802 "boost::filesystem::canonical", source
, local_ec
));
812 for (path::iterator itr
= source
.begin(); itr
!= source
.end(); ++itr
)
814 if (*itr
== dot_path
)
816 if (*itr
== dot_dot_path
)
818 result
.remove_filename();
824 bool is_sym (is_symlink(detail::symlink_status(result
, ec
)));
830 path
link(detail::read_symlink(result
, ec
));
833 result
.remove_filename();
835 if (link
.is_absolute())
837 for (++itr
; itr
!= source
.end(); ++itr
)
841 else // link is relative
843 path
new_source(result
);
845 for (++itr
; itr
!= source
.end(); ++itr
)
849 scan
= true; // symlink causes scan to be restarted
856 BOOST_ASSERT_MSG(result
.is_absolute(), "canonical() implementation error; please report");
860 BOOST_FILESYSTEM_DECL
861 void copy(const path
& from
, const path
& to
, system::error_code
* ec
)
863 file_status
s(symlink_status(from
, *ec
));
864 if (ec
!= 0 && *ec
) return;
868 copy_symlink(from
, to
, *ec
);
870 else if(is_directory(s
))
872 copy_directory(from
, to
, *ec
);
874 else if(is_regular_file(s
))
876 copy_file(from
, to
, copy_option::fail_if_exists
, *ec
);
881 BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::copy",
882 from
, to
, error_code(BOOST_ERROR_NOT_SUPPORTED
, system_category())));
883 ec
->assign(BOOST_ERROR_NOT_SUPPORTED
, system_category());
887 BOOST_FILESYSTEM_DECL
888 void copy_directory(const path
& from
, const path
& to
, system::error_code
* ec
)
890 # ifdef BOOST_POSIX_API
891 struct stat from_stat
;
893 error(!BOOST_COPY_DIRECTORY(from
.c_str(), to
.c_str()),
894 from
, to
, ec
, "boost::filesystem::copy_directory");
897 BOOST_FILESYSTEM_DECL
898 void copy_file(const path
& from
, const path
& to
,
899 BOOST_SCOPED_ENUM(copy_option
)option
,
902 error(!BOOST_COPY_FILE(from
.c_str(), to
.c_str(),
903 option
== copy_option::fail_if_exists
),
904 from
, to
, ec
, "boost::filesystem::copy_file");
907 BOOST_FILESYSTEM_DECL
908 void copy_symlink(const path
& existing_symlink
, const path
& new_symlink
,
909 system::error_code
* ec
)
911 # if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
912 error(true, error_code(BOOST_ERROR_NOT_SUPPORTED
, system_category()),
913 new_symlink
, existing_symlink
, ec
,
914 "boost::filesystem::copy_symlink");
916 # else // modern Windows or BOOST_POSIX_API
917 path
p(read_symlink(existing_symlink
, ec
));
918 if (ec
!= 0 && *ec
) return;
919 create_symlink(p
, new_symlink
, ec
);
924 BOOST_FILESYSTEM_DECL
925 bool create_directories(const path
& p
, system::error_code
* ec
)
927 if (p
.empty() || exists(p
))
929 if (!p
.empty() && !is_directory(p
))
932 BOOST_FILESYSTEM_THROW(filesystem_error(
933 "boost::filesystem::create_directories", p
,
934 error_code(system::errc::file_exists
, system::generic_category())));
935 else ec
->assign(system::errc::file_exists
, system::generic_category());
940 // First create branch, by calling ourself recursively
941 create_directories(p
.parent_path(), ec
);
942 // Now that parent's path exists, create the directory
943 create_directory(p
, ec
);
947 BOOST_FILESYSTEM_DECL
948 bool create_directory(const path
& p
, error_code
* ec
)
950 if (BOOST_CREATE_DIRECTORY(p
.c_str()))
952 if (ec
!= 0) ec
->clear();
956 // attempt to create directory failed
957 int errval(BOOST_ERRNO
); // save reason for failure
959 if (errval
== BOOST_ERROR_ALREADY_EXISTS
&& is_directory(p
, dummy
))
961 if (ec
!= 0) ec
->clear();
965 // attempt to create directory failed && it doesn't already exist
967 BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directory",
968 p
, error_code(errval
, system_category())));
970 ec
->assign(errval
, system_category());
974 BOOST_FILESYSTEM_DECL
975 void create_directory_symlink(const path
& to
, const path
& from
,
976 system::error_code
* ec
)
978 # if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008
980 error(true, error_code(BOOST_ERROR_NOT_SUPPORTED
, system_category()), to
, from
, ec
,
981 "boost::filesystem::create_directory_symlink");
984 # if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600
985 // see if actually supported by Windows runtime dll
986 if (error(!create_symbolic_link_api
,
987 error_code(BOOST_ERROR_NOT_SUPPORTED
, system_category()),
989 "boost::filesystem::create_directory_symlink"))
993 error(!BOOST_CREATE_SYMBOLIC_LINK(from
.c_str(), to
.c_str(), SYMBOLIC_LINK_FLAG_DIRECTORY
),
994 to
, from
, ec
, "boost::filesystem::create_directory_symlink");
998 BOOST_FILESYSTEM_DECL
999 void create_hard_link(const path
& to
, const path
& from
, error_code
* ec
)
1002 # if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0500 // SDK earlier than Win 2K
1004 error(true, error_code(BOOST_ERROR_NOT_SUPPORTED
, system_category()), to
, from
, ec
,
1005 "boost::filesystem::create_hard_link");
1008 # if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0500
1009 // see if actually supported by Windows runtime dll
1010 if (error(!create_hard_link_api
,
1011 error_code(BOOST_ERROR_NOT_SUPPORTED
, system_category()),
1013 "boost::filesystem::create_hard_link"))
1017 error(!BOOST_CREATE_HARD_LINK(from
.c_str(), to
.c_str()), to
, from
, ec
,
1018 "boost::filesystem::create_hard_link");
1022 BOOST_FILESYSTEM_DECL
1023 void create_symlink(const path
& to
, const path
& from
, error_code
* ec
)
1025 # if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008
1026 error(true, error_code(BOOST_ERROR_NOT_SUPPORTED
, system_category()), to
, from
, ec
,
1027 "boost::filesystem::create_directory_symlink");
1030 # if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600
1031 // see if actually supported by Windows runtime dll
1032 if (error(!create_symbolic_link_api
,
1033 error_code(BOOST_ERROR_NOT_SUPPORTED
, system_category()),
1035 "boost::filesystem::create_symlink"))
1039 error(!BOOST_CREATE_SYMBOLIC_LINK(from
.c_str(), to
.c_str(), 0),
1040 to
, from
, ec
, "boost::filesystem::create_symlink");
1044 BOOST_FILESYSTEM_DECL
1045 path
current_path(error_code
* ec
)
1047 # ifdef BOOST_POSIX_API
1049 for (long path_max
= 128;; path_max
*=2)// loop 'til buffer large enough
1051 boost::scoped_array
<char>
1052 buf(new char[static_cast<std::size_t>(path_max
)]);
1053 if (::getcwd(buf
.get(), static_cast<std::size_t>(path_max
))== 0)
1055 if (error(errno
!= ERANGE
1056 // bug in some versions of the Metrowerks C lib on the Mac: wrong errno set
1057 # if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
1060 , ec
, "boost::filesystem::current_path"))
1068 if (ec
!= 0) ec
->clear();
1076 if ((sz
= ::GetCurrentDirectoryW(0, NULL
))== 0)sz
= 1;
1077 boost::scoped_array
<path::value_type
> buf(new path::value_type
[sz
]);
1078 error(::GetCurrentDirectoryW(sz
, buf
.get())== 0, ec
,
1079 "boost::filesystem::current_path");
1080 return path(buf
.get());
1085 BOOST_FILESYSTEM_DECL
1086 void current_path(const path
& p
, system::error_code
* ec
)
1088 error(!BOOST_SET_CURRENT_DIRECTORY(p
.c_str()),
1089 p
, ec
, "boost::filesystem::current_path");
1092 BOOST_FILESYSTEM_DECL
1093 bool equivalent(const path
& p1
, const path
& p2
, system::error_code
* ec
)
1095 # ifdef BOOST_POSIX_API
1097 int e2(::stat(p2
.c_str(), &s2
));
1099 int e1(::stat(p1
.c_str(), &s1
));
1101 if (e1
!= 0 || e2
!= 0)
1103 // if one is invalid and the other isn't then they aren't equivalent,
1104 // but if both are invalid then it is an error
1105 error (e1
!= 0 && e2
!= 0, p1
, p2
, ec
, "boost::filesystem::equivalent");
1109 // both stats now known to be valid
1110 return s1
.st_dev
== s2
.st_dev
&& s1
.st_ino
== s2
.st_ino
1111 // According to the POSIX stat specs, "The st_ino and st_dev fields
1112 // taken together uniquely identify the file within the system."
1113 // Just to be sure, size and mod time are also checked.
1114 && s1
.st_size
== s2
.st_size
&& s1
.st_mtime
== s2
.st_mtime
;
1118 // Note well: Physical location on external media is part of the
1119 // equivalence criteria. If there are no open handles, physical location
1120 // can change due to defragmentation or other relocations. Thus handles
1121 // must be held open until location information for both paths has
1124 // p2 is done first, so any error reported is for p1
1129 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1132 FILE_FLAG_BACKUP_SEMANTICS
,
1139 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1142 FILE_FLAG_BACKUP_SEMANTICS
,
1145 if (h1
.handle
== INVALID_HANDLE_VALUE
1146 || h2
.handle
== INVALID_HANDLE_VALUE
)
1148 // if one is invalid and the other isn't, then they aren't equivalent,
1149 // but if both are invalid then it is an error
1150 error(h1
.handle
== INVALID_HANDLE_VALUE
1151 && h2
.handle
== INVALID_HANDLE_VALUE
, p1
, p2
, ec
,
1152 "boost::filesystem::equivalent");
1156 // at this point, both handles are known to be valid
1158 BY_HANDLE_FILE_INFORMATION info1
, info2
;
1160 if (error(!::GetFileInformationByHandle(h1
.handle
, &info1
),
1161 p1
, p2
, ec
, "boost::filesystem::equivalent"))
1164 if (error(!::GetFileInformationByHandle(h2
.handle
, &info2
),
1165 p1
, p2
, ec
, "boost::filesystem::equivalent"))
1168 // In theory, volume serial numbers are sufficient to distinguish between
1169 // devices, but in practice VSN's are sometimes duplicated, so last write
1170 // time and file size are also checked.
1172 info1
.dwVolumeSerialNumber
== info2
.dwVolumeSerialNumber
1173 && info1
.nFileIndexHigh
== info2
.nFileIndexHigh
1174 && info1
.nFileIndexLow
== info2
.nFileIndexLow
1175 && info1
.nFileSizeHigh
== info2
.nFileSizeHigh
1176 && info1
.nFileSizeLow
== info2
.nFileSizeLow
1177 && info1
.ftLastWriteTime
.dwLowDateTime
1178 == info2
.ftLastWriteTime
.dwLowDateTime
1179 && info1
.ftLastWriteTime
.dwHighDateTime
1180 == info2
.ftLastWriteTime
.dwHighDateTime
;
1185 BOOST_FILESYSTEM_DECL
1186 boost::uintmax_t file_size(const path
& p
, error_code
* ec
)
1188 # ifdef BOOST_POSIX_API
1190 struct stat path_stat
;
1191 if (error(::stat(p
.c_str(), &path_stat
)!= 0,
1192 p
, ec
, "boost::filesystem::file_size"))
1193 return static_cast<boost::uintmax_t>(-1);
1194 if (error(!S_ISREG(path_stat
.st_mode
),
1195 error_code(EPERM
, system_category()),
1196 p
, ec
, "boost::filesystem::file_size"))
1197 return static_cast<boost::uintmax_t>(-1);
1199 return static_cast<boost::uintmax_t>(path_stat
.st_size
);
1203 // assume uintmax_t is 64-bits on all Windows compilers
1205 WIN32_FILE_ATTRIBUTE_DATA fad
;
1207 if (error(::GetFileAttributesExW(p
.c_str(), ::GetFileExInfoStandard
, &fad
)== 0,
1208 p
, ec
, "boost::filesystem::file_size"))
1209 return static_cast<boost::uintmax_t>(-1);
1211 if (error((fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)!= 0,
1212 error_code(ERROR_NOT_SUPPORTED
, system_category()),
1213 p
, ec
, "boost::filesystem::file_size"))
1214 return static_cast<boost::uintmax_t>(-1);
1216 return (static_cast<boost::uintmax_t>(fad
.nFileSizeHigh
)
1217 << (sizeof(fad
.nFileSizeLow
)*8)) + fad
.nFileSizeLow
;
1221 BOOST_FILESYSTEM_DECL
1222 boost::uintmax_t hard_link_count(const path
& p
, system::error_code
* ec
)
1224 # ifdef BOOST_POSIX_API
1226 struct stat path_stat
;
1227 return error(::stat(p
.c_str(), &path_stat
)!= 0,
1228 p
, ec
, "boost::filesystem::hard_link_count")
1230 : static_cast<boost::uintmax_t>(path_stat
.st_nlink
);
1234 // Link count info is only available through GetFileInformationByHandle
1235 BY_HANDLE_FILE_INFORMATION info
;
1237 create_file_handle(p
.c_str(), 0,
1238 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0,
1239 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0));
1241 !error(h
.handle
== INVALID_HANDLE_VALUE
,
1242 p
, ec
, "boost::filesystem::hard_link_count")
1243 && !error(::GetFileInformationByHandle(h
.handle
, &info
)== 0,
1244 p
, ec
, "boost::filesystem::hard_link_count")
1245 ? info
.nNumberOfLinks
1250 BOOST_FILESYSTEM_DECL
1251 path
initial_path(error_code
* ec
)
1253 static path init_path
;
1254 if (init_path
.empty())
1255 init_path
= current_path(ec
);
1256 else if (ec
!= 0) ec
->clear();
1260 BOOST_FILESYSTEM_DECL
1261 bool is_empty(const path
& p
, system::error_code
* ec
)
1263 # ifdef BOOST_POSIX_API
1265 struct stat path_stat
;
1266 if (error(::stat(p
.c_str(), &path_stat
)!= 0,
1267 p
, ec
, "boost::filesystem::is_empty"))
1269 return S_ISDIR(path_stat
.st_mode
)
1270 ? is_empty_directory(p
)
1271 : path_stat
.st_size
== 0;
1274 WIN32_FILE_ATTRIBUTE_DATA fad
;
1275 if (error(::GetFileAttributesExW(p
.c_str(), ::GetFileExInfoStandard
, &fad
)== 0,
1276 p
, ec
, "boost::filesystem::is_empty"))
1279 if (ec
!= 0) ec
->clear();
1281 (fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1282 ? is_empty_directory(p
)
1283 : (!fad
.nFileSizeHigh
&& !fad
.nFileSizeLow
);
1287 BOOST_FILESYSTEM_DECL
1288 std::time_t last_write_time(const path
& p
, system::error_code
* ec
)
1290 # ifdef BOOST_POSIX_API
1292 struct stat path_stat
;
1293 if (error(::stat(p
.c_str(), &path_stat
)!= 0,
1294 p
, ec
, "boost::filesystem::last_write_time"))
1295 return std::time_t(-1);
1296 return path_stat
.st_mtime
;
1301 create_file_handle(p
.c_str(), 0,
1302 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0,
1303 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0));
1305 if (error(hw
.handle
== INVALID_HANDLE_VALUE
,
1306 p
, ec
, "boost::filesystem::last_write_time"))
1307 return std::time_t(-1);
1311 if (error(::GetFileTime(hw
.handle
, 0, 0, &lwt
)== 0,
1312 p
, ec
, "boost::filesystem::last_write_time"))
1313 return std::time_t(-1);
1315 return to_time_t(lwt
);
1319 BOOST_FILESYSTEM_DECL
1320 void last_write_time(const path
& p
, const std::time_t new_time
,
1321 system::error_code
* ec
)
1323 # ifdef BOOST_POSIX_API
1325 struct stat path_stat
;
1326 if (error(::stat(p
.c_str(), &path_stat
)!= 0,
1327 p
, ec
, "boost::filesystem::last_write_time"))
1330 buf
.actime
= path_stat
.st_atime
; // utime()updates access time too:-(
1331 buf
.modtime
= new_time
;
1332 error(::utime(p
.c_str(), &buf
)!= 0,
1333 p
, ec
, "boost::filesystem::last_write_time");
1338 create_file_handle(p
.c_str(), FILE_WRITE_ATTRIBUTES
,
1339 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0,
1340 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0));
1342 if (error(hw
.handle
== INVALID_HANDLE_VALUE
,
1343 p
, ec
, "boost::filesystem::last_write_time"))
1347 to_FILETIME(new_time
, lwt
);
1349 error(::SetFileTime(hw
.handle
, 0, 0, &lwt
)== 0,
1350 p
, ec
, "boost::filesystem::last_write_time");
1354 # ifdef BOOST_POSIX_API
1355 const perms
active_bits(all_all
| set_uid_on_exe
| set_gid_on_exe
| sticky_bit
);
1356 inline mode_t
mode_cast(perms prms
) { return prms
& active_bits
; }
1359 BOOST_FILESYSTEM_DECL
1360 void permissions(const path
& p
, perms prms
, system::error_code
* ec
)
1362 BOOST_ASSERT_MSG(!((prms
& add_perms
) && (prms
& remove_perms
)),
1363 "add_perms and remove_perms are mutually exclusive");
1365 if ((prms
& add_perms
) && (prms
& remove_perms
)) // precondition failed
1368 # ifdef BOOST_POSIX_API
1369 error_code local_ec
;
1370 file_status
current_status((prms
& symlink_perms
)
1371 ? fs::symlink_status(p
, local_ec
)
1372 : fs::status(p
, local_ec
));
1376 BOOST_FILESYSTEM_THROW(filesystem_error(
1377 "boost::filesystem::permissions", p
, local_ec
));
1383 if (prms
& add_perms
)
1384 prms
|= current_status
.permissions();
1385 else if (prms
& remove_perms
)
1386 prms
= current_status
.permissions() & ~prms
;
1388 // Mac OS X Lion and some other platforms don't support fchmodat()
1389 # if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW) \
1390 && (!defined(__SUNPRO_CC) || __SUNPRO_CC > 0x5100)
1391 if (::fchmodat(AT_FDCWD
, p
.c_str(), mode_cast(prms
),
1392 !(prms
& symlink_perms
) ? 0 : AT_SYMLINK_NOFOLLOW
))
1393 # else // fallback if fchmodat() not supported
1394 if (::chmod(p
.c_str(), mode_cast(prms
)))
1398 BOOST_FILESYSTEM_THROW(filesystem_error(
1399 "boost::filesystem::permissions", p
,
1400 error_code(errno
, system::generic_category())));
1402 ec
->assign(errno
, system::generic_category());
1407 // if not going to alter FILE_ATTRIBUTE_READONLY, just return
1408 if (!(!((prms
& (add_perms
| remove_perms
)))
1409 || (prms
& (owner_write
|group_write
|others_write
))))
1412 DWORD attr
= ::GetFileAttributesW(p
.c_str());
1414 if (error(attr
== 0, p
, ec
, "boost::filesystem::permissions"))
1417 if (prms
& add_perms
)
1418 attr
&= ~FILE_ATTRIBUTE_READONLY
;
1419 else if (prms
& remove_perms
)
1420 attr
|= FILE_ATTRIBUTE_READONLY
;
1421 else if (prms
& (owner_write
|group_write
|others_write
))
1422 attr
&= ~FILE_ATTRIBUTE_READONLY
;
1424 attr
|= FILE_ATTRIBUTE_READONLY
;
1426 error(::SetFileAttributesW(p
.c_str(), attr
) == 0,
1427 p
, ec
, "boost::filesystem::permissions");
1431 BOOST_FILESYSTEM_DECL
1432 path
read_symlink(const path
& p
, system::error_code
* ec
)
1436 # ifdef BOOST_POSIX_API
1438 for (std::size_t path_max
= 64;; path_max
*= 2)// loop 'til buffer large enough
1440 boost::scoped_array
<char> buf(new char[path_max
]);
1442 if ((result
=::readlink(p
.c_str(), buf
.get(), path_max
))== -1)
1445 BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::read_symlink",
1446 p
, error_code(errno
, system_category())));
1447 else ec
->assign(errno
, system_category());
1452 if(result
!= static_cast<ssize_t
>(path_max
))
1454 symlink_path
.assign(buf
.get(), buf
.get() + result
);
1455 if (ec
!= 0) ec
->clear();
1461 # elif _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008
1462 error(true, error_code(BOOST_ERROR_NOT_SUPPORTED
, system_category()), p
, ec
,
1463 "boost::filesystem::read_symlink");
1464 # else // Vista and Server 2008 SDK, or later
1468 char buf
[REPARSE_DATA_BUFFER_HEADER_SIZE
+MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
1469 REPARSE_DATA_BUFFER rdb
;
1473 create_file_handle(p
.c_str(), GENERIC_READ
, 0, 0, OPEN_EXISTING
,
1474 FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_OPEN_REPARSE_POINT
, 0));
1476 if (error(h
.handle
== INVALID_HANDLE_VALUE
, p
, ec
, "boost::filesystem::read_symlink"))
1477 return symlink_path
;
1481 if (!error(::DeviceIoControl(h
.handle
, FSCTL_GET_REPARSE_POINT
,
1482 0, 0, info
.buf
, sizeof(info
), &sz
, 0) == 0, p
, ec
,
1483 "boost::filesystem::read_symlink" ))
1484 symlink_path
.assign(
1485 static_cast<wchar_t*>(info
.rdb
.SymbolicLinkReparseBuffer
.PathBuffer
)
1486 + info
.rdb
.SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(wchar_t),
1487 static_cast<wchar_t*>(info
.rdb
.SymbolicLinkReparseBuffer
.PathBuffer
)
1488 + info
.rdb
.SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(wchar_t)
1489 + info
.rdb
.SymbolicLinkReparseBuffer
.PrintNameLength
/sizeof(wchar_t));
1491 return symlink_path
;
1494 BOOST_FILESYSTEM_DECL
1495 bool remove(const path
& p
, error_code
* ec
)
1498 file_type type
= query_file_type(p
, &tmp_ec
);
1499 if (error(type
== status_error
, tmp_ec
, p
, ec
,
1500 "boost::filesystem::remove"))
1503 // Since POSIX remove() is specified to work with either files or directories, in a
1504 // perfect world it could just be called. But some important real-world operating
1505 // systems (Windows, Mac OS X, for example) don't implement the POSIX spec. So
1506 // remove_file_or_directory() is always called to kep it simple.
1507 return remove_file_or_directory(p
, type
, ec
);
1510 BOOST_FILESYSTEM_DECL
1511 boost::uintmax_t remove_all(const path
& p
, error_code
* ec
)
1514 file_type type
= query_file_type(p
, &tmp_ec
);
1515 if (error(type
== status_error
, tmp_ec
, p
, ec
,
1516 "boost::filesystem::remove_all"))
1519 return (type
!= status_error
&& type
!= file_not_found
) // exists
1520 ? remove_all_aux(p
, type
, ec
)
1524 BOOST_FILESYSTEM_DECL
1525 void rename(const path
& old_p
, const path
& new_p
, error_code
* ec
)
1527 error(!BOOST_MOVE_FILE(old_p
.c_str(), new_p
.c_str()), old_p
, new_p
, ec
,
1528 "boost::filesystem::rename");
1531 BOOST_FILESYSTEM_DECL
1532 void resize_file(const path
& p
, uintmax_t size
, system::error_code
* ec
)
1534 error(!BOOST_RESIZE_FILE(p
.c_str(), size
), p
, ec
, "boost::filesystem::resize_file");
1537 BOOST_FILESYSTEM_DECL
1538 space_info
space(const path
& p
, error_code
* ec
)
1540 # ifdef BOOST_POSIX_API
1541 struct BOOST_STATVFS vfs
;
1543 if (!error(::BOOST_STATVFS(p
.c_str(), &vfs
)!= 0,
1544 p
, ec
, "boost::filesystem::space"))
1547 = static_cast<boost::uintmax_t>(vfs
.f_blocks
)* BOOST_STATVFS_F_FRSIZE
;
1549 = static_cast<boost::uintmax_t>(vfs
.f_bfree
)* BOOST_STATVFS_F_FRSIZE
;
1551 = static_cast<boost::uintmax_t>(vfs
.f_bavail
)* BOOST_STATVFS_F_FRSIZE
;
1555 ULARGE_INTEGER avail
, total
, free
;
1558 if (!error(::GetDiskFreeSpaceExW(p
.c_str(), &avail
, &total
, &free
)== 0,
1559 p
, ec
, "boost::filesystem::space"))
1562 = (static_cast<boost::uintmax_t>(total
.HighPart
)<< 32)
1565 = (static_cast<boost::uintmax_t>(free
.HighPart
)<< 32)
1568 = (static_cast<boost::uintmax_t>(avail
.HighPart
)<< 32)
1576 info
.capacity
= info
.free
= info
.available
= 0;
1581 BOOST_FILESYSTEM_DECL
1582 file_status
status(const path
& p
, error_code
* ec
)
1584 # ifdef BOOST_POSIX_API
1586 struct stat path_stat
;
1587 if (::stat(p
.c_str(), &path_stat
)!= 0)
1589 if (ec
!= 0) // always report errno, even though some
1590 ec
->assign(errno
, system_category()); // errno values are not status_errors
1592 if (not_found_error(errno
))
1594 return fs::file_status(fs::file_not_found
, fs::no_perms
);
1597 BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
1598 p
, error_code(errno
, system_category())));
1599 return fs::file_status(fs::status_error
);
1601 if (ec
!= 0) ec
->clear();;
1602 if (S_ISDIR(path_stat
.st_mode
))
1603 return fs::file_status(fs::directory_file
,
1604 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1605 if (S_ISREG(path_stat
.st_mode
))
1606 return fs::file_status(fs::regular_file
,
1607 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1608 if (S_ISBLK(path_stat
.st_mode
))
1609 return fs::file_status(fs::block_file
,
1610 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1611 if (S_ISCHR(path_stat
.st_mode
))
1612 return fs::file_status(fs::character_file
,
1613 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1614 if (S_ISFIFO(path_stat
.st_mode
))
1615 return fs::file_status(fs::fifo_file
,
1616 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1617 if (S_ISSOCK(path_stat
.st_mode
))
1618 return fs::file_status(fs::socket_file
,
1619 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1620 return fs::file_status(fs::type_unknown
);
1624 DWORD
attr(::GetFileAttributesW(p
.c_str()));
1625 if (attr
== 0xFFFFFFFF)
1627 return process_status_failure(p
, ec
);
1630 // reparse point handling;
1631 // since GetFileAttributesW does not resolve symlinks, try to open a file
1632 // handle to discover if the file exists
1633 if (attr
& FILE_ATTRIBUTE_REPARSE_POINT
)
1638 0, // dwDesiredAccess; attributes only
1639 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1640 0, // lpSecurityAttributes
1642 FILE_FLAG_BACKUP_SEMANTICS
,
1643 0)); // hTemplateFile
1644 if (h
.handle
== INVALID_HANDLE_VALUE
)
1646 return process_status_failure(p
, ec
);
1649 if (!is_reparse_point_a_symlink(p
))
1650 return file_status(reparse_file
, make_permissions(p
, attr
));
1653 if (ec
!= 0) ec
->clear();
1654 return (attr
& FILE_ATTRIBUTE_DIRECTORY
)
1655 ? file_status(directory_file
, make_permissions(p
, attr
))
1656 : file_status(regular_file
, make_permissions(p
, attr
));
1661 BOOST_FILESYSTEM_DECL
1662 file_status
symlink_status(const path
& p
, error_code
* ec
)
1664 # ifdef BOOST_POSIX_API
1666 struct stat path_stat
;
1667 if (::lstat(p
.c_str(), &path_stat
)!= 0)
1669 if (ec
!= 0) // always report errno, even though some
1670 ec
->assign(errno
, system_category()); // errno values are not status_errors
1672 if (errno
== ENOENT
|| errno
== ENOTDIR
) // these are not errors
1674 return fs::file_status(fs::file_not_found
, fs::no_perms
);
1677 BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status",
1678 p
, error_code(errno
, system_category())));
1679 return fs::file_status(fs::status_error
);
1681 if (ec
!= 0) ec
->clear();
1682 if (S_ISREG(path_stat
.st_mode
))
1683 return fs::file_status(fs::regular_file
,
1684 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1685 if (S_ISDIR(path_stat
.st_mode
))
1686 return fs::file_status(fs::directory_file
,
1687 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1688 if (S_ISLNK(path_stat
.st_mode
))
1689 return fs::file_status(fs::symlink_file
,
1690 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1691 if (S_ISBLK(path_stat
.st_mode
))
1692 return fs::file_status(fs::block_file
,
1693 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1694 if (S_ISCHR(path_stat
.st_mode
))
1695 return fs::file_status(fs::character_file
,
1696 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1697 if (S_ISFIFO(path_stat
.st_mode
))
1698 return fs::file_status(fs::fifo_file
,
1699 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1700 if (S_ISSOCK(path_stat
.st_mode
))
1701 return fs::file_status(fs::socket_file
,
1702 static_cast<perms
>(path_stat
.st_mode
) & fs::perms_mask
);
1703 return fs::file_status(fs::type_unknown
);
1707 DWORD
attr(::GetFileAttributesW(p
.c_str()));
1708 if (attr
== 0xFFFFFFFF)
1710 return process_status_failure(p
, ec
);
1713 if (ec
!= 0) ec
->clear();
1715 if (attr
& FILE_ATTRIBUTE_REPARSE_POINT
)
1716 return is_reparse_point_a_symlink(p
)
1717 ? file_status(symlink_file
, make_permissions(p
, attr
))
1718 : file_status(reparse_file
, make_permissions(p
, attr
));
1720 return (attr
& FILE_ATTRIBUTE_DIRECTORY
)
1721 ? file_status(directory_file
, make_permissions(p
, attr
))
1722 : file_status(regular_file
, make_permissions(p
, attr
));
1727 // contributed by Jeff Flinn
1728 BOOST_FILESYSTEM_DECL
1729 path
temp_directory_path(system::error_code
* ec
)
1731 # ifdef BOOST_POSIX_API
1732 const char* val
= 0;
1734 (val
= std::getenv("TMPDIR" )) ||
1735 (val
= std::getenv("TMP" )) ||
1736 (val
= std::getenv("TEMP" )) ||
1737 (val
= std::getenv("TEMPDIR"));
1739 path
p((val
!=0) ? val
: "/tmp");
1741 if (p
.empty() || (ec
&&!is_directory(p
, *ec
))||(!ec
&&!is_directory(p
)))
1744 error(true, p
, ec
, "boost::filesystem::temp_directory_path");
1752 std::vector
<path::value_type
> buf(GetTempPathW(0, NULL
));
1754 if (buf
.empty() || GetTempPathW(buf
.size(), &buf
[0])==0)
1756 if(!buf
.empty()) ::SetLastError(ENOTDIR
);
1757 error(true, ec
, "boost::filesystem::temp_directory_path");
1763 path
p(buf
.begin(), buf
.end());
1765 if ((ec
&&!is_directory(p
, *ec
))||(!ec
&&!is_directory(p
)))
1767 ::SetLastError(ENOTDIR
);
1768 error(true, p
, ec
, "boost::filesystem::temp_directory_path");
1776 BOOST_FILESYSTEM_DECL
1777 path
system_complete(const path
& p
, system::error_code
* ec
)
1779 # ifdef BOOST_POSIX_API
1780 return (p
.empty() || p
.is_absolute())
1781 ? p
: current_path()/ p
;
1786 if (ec
!= 0) ec
->clear();
1789 wchar_t buf
[buf_size
];
1791 std::size_t len
= get_full_path_name(p
, buf_size
, buf
, &pfn
);
1793 if (error(len
== 0, p
, ec
, "boost::filesystem::system_complete"))
1796 if (len
< buf_size
)// len does not include null termination character
1797 return path(&buf
[0]);
1799 boost::scoped_array
<wchar_t> big_buf(new wchar_t[len
]);
1801 return error(get_full_path_name(p
, len
, big_buf
.get(), &pfn
)== 0,
1802 p
, ec
, "boost::filesystem::system_complete")
1804 : path(big_buf
.get());
1808 } // namespace detail
1810 //--------------------------------------------------------------------------------------//
1812 // directory_entry //
1814 //--------------------------------------------------------------------------------------//
1817 directory_entry::m_get_status(system::error_code
* ec
) const
1819 if (!status_known(m_status
))
1821 // optimization: if the symlink status is known, and it isn't a symlink,
1822 // then status and symlink_status are identical so just copy the
1823 // symlink status to the regular status.
1824 if (status_known(m_symlink_status
)
1825 && !is_symlink(m_symlink_status
))
1827 m_status
= m_symlink_status
;
1828 if (ec
!= 0) ec
->clear();
1830 else m_status
= detail::status(m_path
, ec
);
1832 else if (ec
!= 0) ec
->clear();
1837 directory_entry::m_get_symlink_status(system::error_code
* ec
) const
1839 if (!status_known(m_symlink_status
))
1840 m_symlink_status
= detail::symlink_status(m_path
, ec
);
1841 else if (ec
!= 0) ec
->clear();
1842 return m_symlink_status
;
1845 // dispatch directory_entry supplied here rather than in
1846 // <boost/filesystem/path_traits.hpp>, thus avoiding header circularity.
1847 // test cases are in operations_unit_test.cpp
1849 namespace path_traits
1851 void dispatch(const directory_entry
& de
,
1852 # ifdef BOOST_WINDOWS_API
1857 const codecvt_type
&)
1859 to
= de
.path().native();
1862 } // namespace path_traits
1863 } // namespace filesystem3
1864 } // namespace boost
1866 //--------------------------------------------------------------------------------------//
1868 // directory_iterator //
1870 //--------------------------------------------------------------------------------------//
1874 # ifdef BOOST_POSIX_API
1876 error_code
path_max(std::size_t & result
)
1877 // this code is based on Stevens and Rago, Advanced Programming in the
1878 // UNIX envirnment, 2nd Ed., ISBN 0-201-43307-9, page 49
1881 static std::size_t max
= PATH_MAX
;
1883 static std::size_t max
= 0;
1888 long tmp
= ::pathconf("/", _PC_NAME_MAX
);
1891 if (errno
== 0)// indeterminate
1892 max
= 4096; // guess
1893 else return error_code(errno
, system_category());
1895 else max
= static_cast<std::size_t>(tmp
+ 1); // relative root
1901 #if defined(__PGI) && defined(__USE_FILE_OFFSET64)
1902 #define dirent dirent64
1905 error_code
dir_itr_first(void *& handle
, void *& buffer
,
1906 const char* dir
, string
& target
,
1907 fs::file_status
&, fs::file_status
&)
1909 if ((handle
= ::opendir(dir
))== 0)
1910 return error_code(errno
, system_category());
1911 target
= string("."); // string was static but caused trouble
1912 // when iteration called from dtor, after
1913 // static had already been destroyed
1914 std::size_t path_size (0); // initialization quiets gcc warning (ticket #3509)
1915 error_code ec
= path_max(path_size
);
1918 buffer
= std::malloc((sizeof(dirent
) - sizeof(de
.d_name
))
1919 + path_size
+ 1); // + 1 for "/0"
1923 // warning: the only dirent member updated is d_name
1924 inline int readdir_r_simulator(DIR * dirp
, struct dirent
* entry
,
1925 struct dirent
** result
)// *result set to 0 on end of directory
1929 # if !defined(__CYGWIN__)\
1930 && defined(_POSIX_THREAD_SAFE_FUNCTIONS)\
1931 && defined(_SC_THREAD_SAFE_FUNCTIONS)\
1932 && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0)\
1933 && (!defined(__hpux) || defined(_REENTRANT)) \
1934 && (!defined(_AIX) || defined(__THREAD_SAFE))
1935 if (::sysconf(_SC_THREAD_SAFE_FUNCTIONS
)>= 0)
1936 { return ::readdir_r(dirp
, entry
, result
); }
1941 if ((p
= ::readdir(dirp
))== 0)
1943 std::strcpy(entry
->d_name
, p
->d_name
);
1948 error_code
dir_itr_increment(void *& handle
, void *& buffer
,
1949 string
& target
, fs::file_status
& sf
, fs::file_status
& symlink_sf
)
1951 BOOST_ASSERT(buffer
!= 0);
1952 dirent
* entry(static_cast<dirent
*>(buffer
));
1955 if ((return_code
= readdir_r_simulator(static_cast<DIR*>(handle
), entry
, &result
))!= 0)
1956 return error_code(errno
, system_category());
1958 return fs::detail::dir_itr_close(handle
, buffer
);
1959 target
= entry
->d_name
;
1960 # ifdef BOOST_FILESYSTEM_STATUS_CACHE
1961 if (entry
->d_type
== DT_UNKNOWN
) // filesystem does not supply d_type value
1963 sf
= symlink_sf
= fs::file_status(fs::status_error
);
1965 else // filesystem supplies d_type value
1967 if (entry
->d_type
== DT_DIR
)
1968 sf
= symlink_sf
= fs::file_status(fs::directory_file
);
1969 else if (entry
->d_type
== DT_REG
)
1970 sf
= symlink_sf
= fs::file_status(fs::regular_file
);
1971 else if (entry
->d_type
== DT_LNK
)
1973 sf
= fs::file_status(fs::status_error
);
1974 symlink_sf
= fs::file_status(fs::symlink_file
);
1976 else sf
= symlink_sf
= fs::file_status(fs::status_error
);
1979 sf
= symlink_sf
= fs::file_status(fs::status_error
);
1984 # else // BOOST_WINDOWS_API
1986 error_code
dir_itr_first(void *& handle
, const fs::path
& dir
,
1987 wstring
& target
, fs::file_status
& sf
, fs::file_status
& symlink_sf
)
1988 // Note: an empty root directory has no "." or ".." entries, so this
1989 // causes a ERROR_FILE_NOT_FOUND error which we do not considered an
1990 // error. It is treated as eof instead.
1992 // use a form of search Sebastian Martel reports will work with Win98
1993 wstring
dirpath(dir
.wstring());
1994 dirpath
+= (dirpath
.empty()
1995 || (dirpath
[dirpath
.size()-1] != L
'\\'
1996 && dirpath
[dirpath
.size()-1] != L
'/'
1997 && dirpath
[dirpath
.size()-1] != L
':'))? L
"\\*" : L
"*";
1999 WIN32_FIND_DATAW data
;
2000 if ((handle
= ::FindFirstFileW(dirpath
.c_str(), &data
))
2001 == INVALID_HANDLE_VALUE
)
2003 handle
= 0; // signal eof
2004 return error_code( (::GetLastError() == ERROR_FILE_NOT_FOUND
2005 // Windows Mobile returns ERROR_NO_MORE_FILES; see ticket #3551
2006 || ::GetLastError() == ERROR_NO_MORE_FILES
)
2007 ? 0 : ::GetLastError(), system_category() );
2009 target
= data
.cFileName
;
2010 if (data
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
)
2011 // reparse points are complex, so don't try to handle them here; instead just mark
2012 // them as status_error which causes directory_entry caching to call status()
2013 // and symlink_status() which do handle reparse points fully
2015 sf
.type(fs::status_error
);
2016 symlink_sf
.type(fs::status_error
);
2020 if (data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2022 sf
.type(fs::directory_file
);
2023 symlink_sf
.type(fs::directory_file
);
2027 sf
.type(fs::regular_file
);
2028 symlink_sf
.type(fs::regular_file
);
2030 sf
.permissions(make_permissions(data
.cFileName
, data
.dwFileAttributes
));
2031 symlink_sf
.permissions(sf
.permissions());
2033 return error_code();
2036 error_code
dir_itr_increment(void *& handle
, wstring
& target
,
2037 fs::file_status
& sf
, fs::file_status
& symlink_sf
)
2039 WIN32_FIND_DATAW data
;
2040 if (::FindNextFileW(handle
, &data
)== 0)// fails
2042 int error
= ::GetLastError();
2043 fs::detail::dir_itr_close(handle
);
2044 return error_code(error
== ERROR_NO_MORE_FILES
? 0 : error
, system_category());
2046 target
= data
.cFileName
;
2047 if (data
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
)
2048 // reparse points are complex, so don't try to handle them here; instead just mark
2049 // them as status_error which causes directory_entry caching to call status()
2050 // and symlink_status() which do handle reparse points fully
2052 sf
.type(fs::status_error
);
2053 symlink_sf
.type(fs::status_error
);
2057 if (data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2059 sf
.type(fs::directory_file
);
2060 symlink_sf
.type(fs::directory_file
);
2064 sf
.type(fs::regular_file
);
2065 symlink_sf
.type(fs::regular_file
);
2067 sf
.permissions(make_permissions(data
.cFileName
, data
.dwFileAttributes
));
2068 symlink_sf
.permissions(sf
.permissions());
2070 return error_code();
2074 const error_code
not_found_error_code (
2075 # ifdef BOOST_WINDOWS_API
2076 ERROR_PATH_NOT_FOUND
2080 , system_category());
2082 } // unnamed namespace
2086 namespace filesystem3
2091 // dir_itr_close is called both from the ~dir_itr_imp()destructor
2092 // and dir_itr_increment()
2093 BOOST_FILESYSTEM_DECL
2094 system::error_code
dir_itr_close( // never throws
2096 # if defined(BOOST_POSIX_API)
2101 # ifdef BOOST_POSIX_API
2104 if (handle
== 0)return ok
;
2105 DIR * h(static_cast<DIR*>(handle
));
2107 return error_code(::closedir(h
)== 0 ? 0 : errno
, system_category());
2112 ::FindClose(handle
);
2120 void directory_iterator_construct(directory_iterator
& it
,
2121 const path
& p
, system::error_code
* ec
)
2123 if (error(p
.empty(), not_found_error_code
, p
, ec
,
2124 "boost::filesystem::directory_iterator::construct"))
2127 path::string_type filename
;
2128 file_status file_stat
, symlink_file_stat
;
2129 error_code result
= dir_itr_first(it
.m_imp
->handle
,
2130 # if defined(BOOST_POSIX_API)
2133 p
.c_str(), filename
, file_stat
, symlink_file_stat
);
2138 error(true, result
, p
,
2139 ec
, "boost::filesystem::directory_iterator::construct");
2143 if (it
.m_imp
->handle
== 0)
2144 it
.m_imp
.reset(); // eof, so make end iterator
2147 it
.m_imp
->dir_entry
.assign(p
/ filename
, file_stat
, symlink_file_stat
);
2148 if (filename
[0] == dot
// dot or dot-dot
2149 && (filename
.size()== 1
2150 || (filename
[1] == dot
2151 && filename
.size()== 2)))
2152 { it
.increment(*ec
); }
2156 void directory_iterator_increment(directory_iterator
& it
,
2157 system::error_code
* ec
)
2159 BOOST_ASSERT_MSG(it
.m_imp
.get(), "attempt to increment end iterator");
2160 BOOST_ASSERT_MSG(it
.m_imp
->handle
!= 0, "internal program error");
2162 path::string_type filename
;
2163 file_status file_stat
, symlink_file_stat
;
2164 system::error_code temp_ec
;
2168 temp_ec
= dir_itr_increment(it
.m_imp
->handle
,
2169 # if defined(BOOST_POSIX_API)
2172 filename
, file_stat
, symlink_file_stat
);
2174 if (temp_ec
) // happens if filesystem is corrupt, such as on a damaged optical disc
2176 path
error_path(it
.m_imp
->dir_entry
.path().parent_path()); // fix ticket #5900
2179 BOOST_FILESYSTEM_THROW(
2180 filesystem_error("boost::filesystem::directory_iterator::operator++",
2182 error_code(BOOST_ERRNO
, system_category())));
2183 ec
->assign(BOOST_ERRNO
, system_category());
2186 else if (ec
!= 0) ec
->clear();
2188 if (it
.m_imp
->handle
== 0) // eof, make end
2194 if (!(filename
[0] == dot
// !(dot or dot-dot)
2195 && (filename
.size()== 1
2196 || (filename
[1] == dot
2197 && filename
.size()== 2))))
2199 it
.m_imp
->dir_entry
.replace_filename(
2200 filename
, file_stat
, symlink_file_stat
);
2205 } // namespace detail
2206 } // namespace filesystem3
2207 } // namespace boost
2209 #endif // no wide character support