1 // operations.cpp ----------------------------------------------------------//
3 // Copyright 2002-2005 Beman Dawes
4 // Copyright 2001 Dietmar Kuehl
5 // Use, modification, and distribution is subject to the Boost Software
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
7 // at http://www.boost.org/LICENSE_1_0.txt)
9 // See library home page at http://www.boost.org/libs/filesystem
11 //----------------------------------------------------------------------------//
13 // define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
14 // the library is being built (possibly exporting rather than importing code)
15 #define BOOST_FILESYSTEM_SOURCE
17 #ifndef BOOST_SYSTEM_NO_DEPRECATED
18 # define BOOST_SYSTEM_NO_DEPRECATED
21 #define _POSIX_PTHREAD_SEMANTICS // Sun readdir_r() needs this
23 #if !(defined(__HP_aCC) && defined(_ILP32) && \
24 !defined(_STATVFS_ACPP_PROBLEMS_FIXED))
25 #define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect,
28 #define __USE_FILE_OFFSET64 // but that is harmless on Windows and on POSIX
29 // 64-bit systems or on 32-bit systems which don't have files larger
30 // than can be represented by a traditional POSIX/UNIX off_t type.
31 // OTOH, defining them should kick in 64-bit off_t's (and thus
32 // st_size) on 32-bit systems that provide the Large File
33 // Support (LFS) interface, such as Linux, Solaris, and IRIX.
34 // The defines are given before any headers are included to
35 // ensure that they are available to all included headers.
36 // That is required at least on Solaris, and possibly on other
39 // for some compilers (CodeWarrior, for example), windows.h
40 // is getting included by some other boost header, so do this early:
41 #if !defined(_WIN32_WINNT)
42 #define _WIN32_WINNT 0x0500 // Default to Windows 2K or later
47 #include <boost/filesystem/v2/operations.hpp>
48 #include <boost/scoped_array.hpp>
49 #include <boost/assert.hpp>
50 #include <boost/detail/workaround.hpp>
51 #include <cstdlib> // for malloc, free
53 namespace fs
= boost::filesystem2
;
54 using boost::system::error_code
;
55 using boost::system::system_category
;
57 # if defined(BOOST_WINDOWS_API)
59 # include <ctime> // for time_t
61 # else // BOOST_POSIX_API
62 # include <sys/types.h>
63 # if !defined(__APPLE__) && !defined(__OpenBSD__)
64 # include <sys/statvfs.h>
65 # define BOOST_STATVFS statvfs
66 # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize
69 # include <sys/param.h>
71 # include <sys/mount.h>
72 # define BOOST_STATVFS statfs
73 # define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>( vfs.f_bsize )
82 // BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in
83 // dir_itr_increment. The config tests are placed here because some of the
84 // macros being tested come from dirent.h.
86 // TODO: find out what macros indicate dirent::d_type present in more libraries
87 # if defined(BOOST_WINDOWS_API) \
88 || (defined(_DIRENT_HAVE_D_TYPE) /* defined by GNU C library if d_type present */ \
89 && !(defined(__SUNPRO_CC) && !defined(__sun))) // _DIRENT_HAVE_D_TYPE wrong for Sun compiler on Linux
90 # define BOOST_FILESYSTEM_STATUS_CACHE
93 #include <sys/stat.h> // even on Windows some functions use stat()
96 #include <cstdio> // for remove, rename
98 // #include <iostream> // for debugging only; comment out when not in use
100 #ifdef BOOST_NO_STDC_NAMESPACE
101 namespace std
{ using ::strcmp
; using ::remove
; using ::rename
; }
104 // helpers -----------------------------------------------------------------//
110 bool is_empty_directory( const std::string
& dir_path
)
112 static const fs::directory_iterator end_itr
;
113 return fs::directory_iterator(fs::path(dir_path
)) == end_itr
;
116 #ifdef BOOST_WINDOWS_API
118 // For Windows, the xxxA form of various function names is used to avoid
119 // inadvertently getting wide forms of the functions. (The undecorated
120 // forms are actually macros, so can misfire if the user has various
121 // other macros defined. There was a bug report of this happening.)
123 inline DWORD
get_file_attributes( const char * ph
)
124 { return ::GetFileAttributesA( ph
); }
126 # ifndef BOOST_FILESYSTEM2_NARROW_ONLY
128 inline DWORD
get_file_attributes( const wchar_t * ph
)
129 { return ::GetFileAttributesW( ph
); }
131 bool is_empty_directory( const std::wstring
& dir_path
)
133 static const fs::wdirectory_iterator wend_itr
;
134 return fs::wdirectory_iterator(fs::wpath(dir_path
)) == wend_itr
;
137 inline BOOL
get_file_attributes_ex( const wchar_t * ph
,
138 WIN32_FILE_ATTRIBUTE_DATA
& fad
)
139 { return ::GetFileAttributesExW( ph
, ::GetFileExInfoStandard
, &fad
); }
141 HANDLE
create_file( const wchar_t * ph
, DWORD dwDesiredAccess
,
142 DWORD dwShareMode
, LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
143 DWORD dwCreationDisposition
, DWORD dwFlagsAndAttributes
,
144 HANDLE hTemplateFile
)
146 return ::CreateFileW( ph
, dwDesiredAccess
, dwShareMode
,
147 lpSecurityAttributes
, dwCreationDisposition
, dwFlagsAndAttributes
,
151 inline DWORD
get_current_directory( DWORD sz
, wchar_t * buf
)
152 { return ::GetCurrentDirectoryW( sz
, buf
); }
154 inline bool set_current_directory( const wchar_t * buf
)
155 { return ::SetCurrentDirectoryW( buf
) != 0 ; }
157 inline bool get_free_disk_space( const std::wstring
& ph
,
158 PULARGE_INTEGER avail
, PULARGE_INTEGER total
, PULARGE_INTEGER free
)
159 { return ::GetDiskFreeSpaceExW( ph
.c_str(), avail
, total
, free
) != 0; }
161 inline std::size_t get_full_path_name(
162 const std::wstring
& ph
, std::size_t len
, wchar_t * buf
, wchar_t ** p
)
164 return static_cast<std::size_t>(
165 ::GetFullPathNameW( ph
.c_str(),
166 static_cast<DWORD
>(len
), buf
, p
));
169 inline bool remove_directory( const std::wstring
& ph
)
170 { return ::RemoveDirectoryW( ph
.c_str() ) != 0; }
172 inline bool delete_file( const std::wstring
& ph
)
173 { return ::DeleteFileW( ph
.c_str() ) != 0; }
175 inline bool create_directory( const std::wstring
& dir
)
176 { return ::CreateDirectoryW( dir
.c_str(), 0 ) != 0; }
178 #if _WIN32_WINNT >= 0x500
179 inline bool create_hard_link( const std::wstring
& to_ph
,
180 const std::wstring
& from_ph
)
181 { return ::CreateHardLinkW( from_ph
.c_str(), to_ph
.c_str(), 0 ) != 0; }
184 # endif // ifndef BOOST_FILESYSTEM2_NARROW_ONLY
186 template< class String
>
187 fs::file_status
status_template( const String
& ph
, error_code
& ec
)
189 DWORD
attr( get_file_attributes( ph
.c_str() ) );
190 if ( attr
== 0xFFFFFFFF )
192 ec
= error_code( ::GetLastError(), system_category() );
193 if ((ec
.value() == ERROR_FILE_NOT_FOUND
)
194 || (ec
.value() == ERROR_PATH_NOT_FOUND
)
195 || (ec
.value() == ERROR_INVALID_NAME
) // "tools/jam/src/:sys:stat.h", "//foo"
196 || (ec
.value() == ERROR_INVALID_DRIVE
) // USB card reader with no card inserted
197 || (ec
.value() == ERROR_NOT_READY
) // CD/DVD drive with no disc inserted
198 || (ec
.value() == ERROR_INVALID_PARAMETER
) // ":sys:stat.h"
199 || (ec
.value() == ERROR_BAD_PATHNAME
) // "//nosuch" on Win64
200 || (ec
.value() == ERROR_BAD_NETPATH
)) // "//nosuch" on Win32
202 ec
= ok
; // these are not considered errors;
203 // the status is considered not found
204 return fs::file_status( fs::file_not_found
);
206 else if ((ec
.value() == ERROR_SHARING_VIOLATION
))
208 ec
= ok
; // these are not considered errors;
209 // the file exists but the type is not known
210 return fs::file_status( fs::type_unknown
);
212 return fs::file_status( fs::status_unknown
);
215 return (attr
& FILE_ATTRIBUTE_DIRECTORY
)
216 ? fs::file_status( fs::directory_file
)
217 : fs::file_status( fs::regular_file
);
220 BOOL
get_file_attributes_ex( const char * ph
,
221 WIN32_FILE_ATTRIBUTE_DATA
& fad
)
222 { return ::GetFileAttributesExA( ph
, ::GetFileExInfoStandard
, &fad
); }
224 template< class String
>
225 boost::filesystem2::detail::query_pair
226 is_empty_template( const String
& ph
)
228 WIN32_FILE_ATTRIBUTE_DATA fad
;
229 if ( get_file_attributes_ex( ph
.c_str(), fad
) == 0 )
230 return std::make_pair( error_code( ::GetLastError(), system_category() ), false );
231 return std::make_pair( ok
,
232 ( fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
233 ? is_empty_directory( ph
)
234 :( !fad
.nFileSizeHigh
&& !fad
.nFileSizeLow
) );
237 HANDLE
create_file( const char * ph
, DWORD dwDesiredAccess
,
238 DWORD dwShareMode
, LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
239 DWORD dwCreationDisposition
, DWORD dwFlagsAndAttributes
,
240 HANDLE hTemplateFile
)
242 return ::CreateFileA( ph
, dwDesiredAccess
, dwShareMode
,
243 lpSecurityAttributes
, dwCreationDisposition
, dwFlagsAndAttributes
,
247 // Thanks to Jeremy Maitin-Shepard for much help and for permission to
248 // base the equivalent() implementation on portions of his
249 // file-equivalence-win32.cpp experimental code.
250 struct handle_wrapper
253 handle_wrapper( HANDLE h
)
257 if ( handle
!= INVALID_HANDLE_VALUE
)
258 ::CloseHandle(handle
);
262 template< class String
>
263 boost::filesystem2::detail::query_pair
264 equivalent_template( const String
& ph1
, const String
& ph2
)
266 // Note well: Physical location on external media is part of the
267 // equivalence criteria. If there are no open handles, physical location
268 // can change due to defragmentation or other relocations. Thus handles
269 // must be held open until location information for both paths has
275 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
278 FILE_FLAG_BACKUP_SEMANTICS
,
280 int error1(0); // save error code in case we have to throw
281 if ( p1
.handle
== INVALID_HANDLE_VALUE
)
282 error1
= ::GetLastError();
287 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
290 FILE_FLAG_BACKUP_SEMANTICS
,
292 if ( p1
.handle
== INVALID_HANDLE_VALUE
293 || p2
.handle
== INVALID_HANDLE_VALUE
)
295 if ( p1
.handle
!= INVALID_HANDLE_VALUE
296 || p2
.handle
!= INVALID_HANDLE_VALUE
)
297 { return std::make_pair( ok
, false ); }
298 BOOST_ASSERT( p1
.handle
== INVALID_HANDLE_VALUE
299 && p2
.handle
== INVALID_HANDLE_VALUE
);
300 { return std::make_pair( error_code( error1
, system_category()), false ); }
302 // at this point, both handles are known to be valid
303 BY_HANDLE_FILE_INFORMATION info1
, info2
;
304 if ( !::GetFileInformationByHandle( p1
.handle
, &info1
) )
305 { return std::make_pair( error_code( ::GetLastError(), system_category() ), false ); }
306 if ( !::GetFileInformationByHandle( p2
.handle
, &info2
) )
307 { return std::make_pair( error_code( ::GetLastError(), system_category() ), false ); }
308 // In theory, volume serial numbers are sufficient to distinguish between
309 // devices, but in practice VSN's are sometimes duplicated, so last write
310 // time and file size are also checked.
311 return std::make_pair( ok
,
312 info1
.dwVolumeSerialNumber
== info2
.dwVolumeSerialNumber
313 && info1
.nFileIndexHigh
== info2
.nFileIndexHigh
314 && info1
.nFileIndexLow
== info2
.nFileIndexLow
315 && info1
.nFileSizeHigh
== info2
.nFileSizeHigh
316 && info1
.nFileSizeLow
== info2
.nFileSizeLow
317 && info1
.ftLastWriteTime
.dwLowDateTime
318 == info2
.ftLastWriteTime
.dwLowDateTime
319 && info1
.ftLastWriteTime
.dwHighDateTime
320 == info2
.ftLastWriteTime
.dwHighDateTime
);
323 template< class String
>
324 boost::filesystem2::detail::uintmax_pair
325 file_size_template( const String
& ph
)
327 WIN32_FILE_ATTRIBUTE_DATA fad
;
328 // by now, intmax_t is 64-bits on all Windows compilers
329 if ( get_file_attributes_ex( ph
.c_str(), fad
) == 0 )
330 return std::make_pair( error_code( ::GetLastError(), system_category() ), 0 );
331 if ( (fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) !=0 )
332 return std::make_pair( error_code( ERROR_FILE_NOT_FOUND
, system_category()), 0 );
333 return std::make_pair( ok
,
334 (static_cast<boost::uintmax_t>(fad
.nFileSizeHigh
)
335 << (sizeof(fad
.nFileSizeLow
)*8))
336 + fad
.nFileSizeLow
);
339 inline bool get_free_disk_space( const std::string
& ph
,
340 PULARGE_INTEGER avail
, PULARGE_INTEGER total
, PULARGE_INTEGER free
)
341 { return ::GetDiskFreeSpaceExA( ph
.c_str(), avail
, total
, free
) != 0; }
343 template< class String
>
344 boost::filesystem2::detail::space_pair
345 space_template( String
& ph
)
347 ULARGE_INTEGER avail
, total
, free
;
348 boost::filesystem2::detail::space_pair result
;
349 if ( get_free_disk_space( ph
, &avail
, &total
, &free
) )
352 result
.second
.capacity
353 = (static_cast<boost::uintmax_t>(total
.HighPart
) << 32)
356 = (static_cast<boost::uintmax_t>(free
.HighPart
) << 32)
358 result
.second
.available
359 = (static_cast<boost::uintmax_t>(avail
.HighPart
) << 32)
364 result
.first
= error_code( ::GetLastError(), system_category() );
365 result
.second
.capacity
= result
.second
.free
366 = result
.second
.available
= 0;
371 inline DWORD
get_current_directory( DWORD sz
, char * buf
)
372 { return ::GetCurrentDirectoryA( sz
, buf
); }
374 template< class String
>
376 get_current_path_template( String
& ph
)
379 if ( (sz
= get_current_directory( 0,
380 static_cast<typename
String::value_type
*>(0) )) == 0 )
382 typedef typename
String::value_type value_type
;
383 boost::scoped_array
<value_type
> buf( new value_type
[sz
] );
384 if ( get_current_directory( sz
, buf
.get() ) == 0 )
385 return error_code( ::GetLastError(), system_category() );
390 inline bool set_current_directory( const char * buf
)
391 { return ::SetCurrentDirectoryA( buf
) != 0; }
393 template< class String
>
395 set_current_path_template( const String
& ph
)
397 return error_code( set_current_directory( ph
.c_str() )
398 ? 0 : ::GetLastError(), system_category() );
401 inline std::size_t get_full_path_name(
402 const std::string
& ph
, std::size_t len
, char * buf
, char ** p
)
404 return static_cast<std::size_t>(
405 ::GetFullPathNameA( ph
.c_str(),
406 static_cast<DWORD
>(len
), buf
, p
));
409 const std::size_t buf_size( 128 );
411 template<class String
>
413 get_full_path_name_template( const String
& ph
, String
& target
)
415 typename
String::value_type buf
[buf_size
];
416 typename
String::value_type
* pfn
;
417 std::size_t len
= get_full_path_name( ph
,
418 buf_size
, buf
, &pfn
);
419 if ( len
== 0 ) return error_code( ::GetLastError(), system_category() );
420 if ( len
> buf_size
)
422 typedef typename
String::value_type value_type
;
423 boost::scoped_array
<value_type
> big_buf( new value_type
[len
] );
424 if ( (len
=get_full_path_name( ph
, len
, big_buf
.get(), &pfn
))
425 == 0 ) return error_code( ::GetLastError(), system_category() );
427 target
= big_buf
.get();
435 template<class String
>
437 get_file_write_time( const String
& ph
, FILETIME
& last_write_time
)
440 create_file( ph
.c_str(), 0,
441 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0,
442 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 ) );
443 if ( hw
.handle
== INVALID_HANDLE_VALUE
)
444 return error_code( ::GetLastError(), system_category() );
445 return error_code( ::GetFileTime( hw
.handle
, 0, 0, &last_write_time
) != 0
446 ? 0 : ::GetLastError(), system_category() );
449 template<class String
>
451 set_file_write_time( const String
& ph
, const FILETIME
& last_write_time
)
454 create_file( ph
.c_str(), FILE_WRITE_ATTRIBUTES
,
455 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0,
456 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0 ) );
457 if ( hw
.handle
== INVALID_HANDLE_VALUE
)
458 return error_code( ::GetLastError(), system_category() );
459 return error_code( ::SetFileTime( hw
.handle
, 0, 0, &last_write_time
) != 0
460 ? 0 : ::GetLastError(), system_category() );
463 // these constants come from inspecting some Microsoft sample code
464 std::time_t to_time_t( const FILETIME
& ft
)
466 __int64 t
= (static_cast<__int64
>( ft
.dwHighDateTime
) << 32)
468 # if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0
469 t
-= 116444736000000000LL;
471 t
-= 116444736000000000;
474 return static_cast<std::time_t>( t
);
477 void to_FILETIME( std::time_t t
, FILETIME
& ft
)
481 # if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0
482 temp
+= 116444736000000000LL;
484 temp
+= 116444736000000000;
486 ft
.dwLowDateTime
= static_cast<DWORD
>( temp
);
487 ft
.dwHighDateTime
= static_cast<DWORD
>( temp
>> 32 );
490 template<class String
>
491 boost::filesystem2::detail::time_pair
492 last_write_time_template( const String
& ph
)
496 get_file_write_time( ph
, lwt
) );
497 return std::make_pair( ec
, to_time_t( lwt
) );
500 template<class String
>
502 last_write_time_template( const String
& ph
, const std::time_t new_time
)
505 to_FILETIME( new_time
, lwt
);
506 return set_file_write_time( ph
, lwt
);
509 bool remove_directory( const std::string
& ph
)
510 { return ::RemoveDirectoryA( ph
.c_str() ) != 0; }
512 bool delete_file( const std::string
& ph
)
513 { return ::DeleteFileA( ph
.c_str() ) != 0; }
515 template<class String
>
517 remove_template( const String
& ph
)
519 // TODO: test this code in the presence of Vista symlinks,
520 // including dangling, self-referal, and cyclic symlinks
522 fs::file_status
sf( fs::detail::status_api( ph
, ec
) );
525 if ( sf
.type() == fs::file_not_found
)
527 if ( fs::is_directory( sf
) )
529 if ( !remove_directory( ph
) )
530 return error_code(::GetLastError(), system_category());
534 if ( !delete_file( ph
) ) return error_code(::GetLastError(), system_category());
539 inline bool create_directory( const std::string
& dir
)
540 { return ::CreateDirectoryA( dir
.c_str(), 0 ) != 0; }
542 template<class String
>
543 boost::filesystem2::detail::query_pair
544 create_directory_template( const String
& dir_ph
)
546 error_code error
, dummy
;
547 if ( create_directory( dir_ph
) ) return std::make_pair( error
, true );
548 error
= error_code( ::GetLastError(), system_category() );
549 // an error here may simply mean the postcondition is already met
550 if ( error
.value() == ERROR_ALREADY_EXISTS
551 && fs::is_directory( fs::detail::status_api( dir_ph
, dummy
) ) )
552 return std::make_pair( ok
, false );
553 return std::make_pair( error
, false );
556 #if _WIN32_WINNT >= 0x500
557 inline bool create_hard_link( const std::string
& to_ph
,
558 const std::string
& from_ph
)
559 { return ::CreateHardLinkA( from_ph
.c_str(), to_ph
.c_str(), 0 ) != 0; }
562 #if _WIN32_WINNT >= 0x500
563 template<class String
>
565 create_hard_link_template( const String
& to_ph
,
566 const String
& from_ph
)
568 return error_code( create_hard_link( to_ph
.c_str(), from_ph
.c_str() )
569 ? 0 : ::GetLastError(), system_category() );
573 #else // BOOST_POSIX_API
575 int posix_remove( const char * p
)
577 # if defined(__QNXNTO__) || (defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)))
578 // Some Metrowerks C library versions fail on directories because of a
579 // known Metrowerks coding error in ::remove. Workaround is to call
580 // rmdir() or unlink() as indicated.
581 // Same bug also reported for QNX, with the same fix.
582 int err
= ::unlink( p
);
583 if ( err
== 0 || errno
!= EPERM
)
587 return std::remove( p
);
592 } // unnamed namespace
596 namespace filesystem2
600 BOOST_FILESYSTEM_DECL
system::error_code throws
;
602 // free functions ----------------------------------------------------------//
604 BOOST_FILESYSTEM_DECL error_code
not_found_error()
606 # ifdef BOOST_WINDOWS_API
607 return error_code(ERROR_PATH_NOT_FOUND
, system_category());
609 return error_code(ENOENT
, system_category());
613 BOOST_FILESYSTEM_DECL
bool possible_large_file_size_support()
615 # ifdef BOOST_POSIX_API
616 struct stat lcl_stat
;
617 return sizeof( lcl_stat
.st_size
) > 4;
623 # ifdef BOOST_WINDOWS_API
625 BOOST_FILESYSTEM_DECL
fs::file_status
626 status_api( const std::string
& ph
, error_code
& ec
)
627 { return status_template( ph
, ec
); }
629 # ifndef BOOST_FILESYSTEM2_NARROW_ONLY
631 BOOST_FILESYSTEM_DECL
fs::file_status
632 status_api( const std::wstring
& ph
, error_code
& ec
)
633 { return status_template( ph
, ec
); }
635 BOOST_FILESYSTEM_DECL
bool symbolic_link_exists_api( const std::wstring
& )
638 BOOST_FILESYSTEM_DECL
639 fs::detail::query_pair
is_empty_api( const std::wstring
& ph
)
640 { return is_empty_template( ph
); }
642 BOOST_FILESYSTEM_DECL
643 fs::detail::query_pair
644 equivalent_api( const std::wstring
& ph1
, const std::wstring
& ph2
)
645 { return equivalent_template( ph1
, ph2
); }
647 BOOST_FILESYSTEM_DECL
648 fs::detail::uintmax_pair
file_size_api( const std::wstring
& ph
)
649 { return file_size_template( ph
); }
651 BOOST_FILESYSTEM_DECL
652 fs::detail::space_pair
space_api( const std::wstring
& ph
)
653 { return space_template( ph
); }
655 BOOST_FILESYSTEM_DECL
657 get_current_path_api( std::wstring
& ph
)
658 { return get_current_path_template( ph
); }
660 BOOST_FILESYSTEM_DECL
662 set_current_path_api( const std::wstring
& ph
)
663 { return set_current_path_template( ph
); }
665 BOOST_FILESYSTEM_DECL error_code
666 get_full_path_name_api( const std::wstring
& ph
, std::wstring
& target
)
667 { return get_full_path_name_template( ph
, target
); }
669 BOOST_FILESYSTEM_DECL time_pair
670 last_write_time_api( const std::wstring
& ph
)
671 { return last_write_time_template( ph
); }
673 BOOST_FILESYSTEM_DECL error_code
674 last_write_time_api( const std::wstring
& ph
, std::time_t new_value
)
675 { return last_write_time_template( ph
, new_value
); }
677 BOOST_FILESYSTEM_DECL
fs::detail::query_pair
678 create_directory_api( const std::wstring
& ph
)
679 { return create_directory_template( ph
); }
681 #if _WIN32_WINNT >= 0x500
682 BOOST_FILESYSTEM_DECL error_code
683 create_hard_link_api( const std::wstring
& to_ph
,
684 const std::wstring
& from_ph
)
685 { return create_hard_link_template( to_ph
, from_ph
); }
688 BOOST_FILESYSTEM_DECL error_code
689 create_symlink_api( const std::wstring
& /*to_ph*/,
690 const std::wstring
& /*from_ph*/ )
691 { return error_code( ERROR_NOT_SUPPORTED
, system_category() ); }
693 BOOST_FILESYSTEM_DECL error_code
694 remove_api( const std::wstring
& ph
) { return remove_template( ph
); }
696 BOOST_FILESYSTEM_DECL error_code
697 rename_api( const std::wstring
& from
, const std::wstring
& to
)
699 return error_code( ::MoveFileW( from
.c_str(), to
.c_str() )
700 ? 0 : ::GetLastError(), system_category() );
703 BOOST_FILESYSTEM_DECL error_code
704 copy_file_api( const std::wstring
& from
, const std::wstring
& to
, bool fail_if_exists
)
706 return error_code( ::CopyFileW( from
.c_str(), to
.c_str(), fail_if_exists
)
707 ? 0 : ::GetLastError(), system_category() );
710 BOOST_FILESYSTEM_DECL
bool create_file_api( const std::wstring
& ph
,
711 std::ios_base::openmode mode
) // true if succeeds
714 ((mode
& std::ios_base::in
) == 0 ? 0 : GENERIC_READ
)
715 | ((mode
& std::ios_base::out
) == 0 ? 0 : GENERIC_WRITE
) );
717 DWORD
disposition(0); // see 27.8.1.3 Table 92
718 if ( (mode
&~std::ios_base::binary
)
719 == (std::ios_base::out
|std::ios_base::app
) )
720 disposition
= OPEN_ALWAYS
;
721 else if ( (mode
&~(std::ios_base::binary
|std::ios_base::out
))
722 == std::ios_base::in
) disposition
= OPEN_EXISTING
;
723 else if ( ((mode
&~(std::ios_base::binary
|std::ios_base::trunc
))
724 == std::ios_base::out
)
725 || ((mode
&~std::ios_base::binary
)
726 == (std::ios_base::in
|std::ios_base::out
|std::ios_base::trunc
)) )
727 disposition
= CREATE_ALWAYS
;
728 else BOOST_ASSERT( 0 && "invalid mode argument" );
730 HANDLE
handle ( ::CreateFileW( ph
.c_str(), access
,
731 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0,
732 disposition
, (mode
&std::ios_base::out
) != 0
733 ? FILE_ATTRIBUTE_ARCHIVE
: FILE_ATTRIBUTE_NORMAL
, 0 ) );
734 if ( handle
== INVALID_HANDLE_VALUE
) return false;
735 ::CloseHandle( handle
);
739 BOOST_FILESYSTEM_DECL
std::string
narrow_path_api(
740 const std::wstring
& ph
) // return is empty if fails
742 std::string narrow_short_form
;
743 std::wstring short_form
;
744 for ( DWORD
buf_sz( static_cast<DWORD
>( ph
.size()+1 ));; )
746 boost::scoped_array
<wchar_t> buf( new wchar_t[buf_sz
] );
747 DWORD
sz( ::GetShortPathNameW( ph
.c_str(), buf
.get(), buf_sz
) );
748 if ( sz
== 0 ) return narrow_short_form
;
751 short_form
+= buf
.get();
756 // contributed by Takeshi Mouri:
757 int narrow_sz( ::WideCharToMultiByte( CP_ACP
, 0,
758 short_form
.c_str(), static_cast<int>(short_form
.size()), 0, 0, 0, 0 ) );
759 boost::scoped_array
<char> narrow_buf( new char[narrow_sz
] );
760 ::WideCharToMultiByte( CP_ACP
, 0,
761 short_form
.c_str(), static_cast<int>(short_form
.size()),
762 narrow_buf
.get(), narrow_sz
, 0, 0 );
763 narrow_short_form
.assign(narrow_buf
.get(), narrow_sz
);
765 return narrow_short_form
;
768 BOOST_FILESYSTEM_DECL error_code
769 dir_itr_first( void *& handle
, const std::wstring
& dir
,
770 std::wstring
& target
, file_status
& sf
, file_status
& symlink_sf
)
772 // use a form of search Sebastian Martel reports will work with Win98
773 std::wstring
dirpath( dir
);
774 dirpath
+= (dirpath
.empty()
775 || dirpath
[dirpath
.size()-1] != L
'\\') ? L
"\\*" : L
"*";
777 WIN32_FIND_DATAW data
;
778 if ( (handle
= ::FindFirstFileW( dirpath
.c_str(), &data
))
779 == INVALID_HANDLE_VALUE
)
782 return error_code( ::GetLastError() == ERROR_FILE_NOT_FOUND
783 ? 0 : ::GetLastError(), system_category() );
785 target
= data
.cFileName
;
786 if ( data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
787 { sf
.type( directory_file
); symlink_sf
.type( directory_file
); }
788 else { sf
.type( regular_file
); symlink_sf
.type( regular_file
); }
792 BOOST_FILESYSTEM_DECL error_code
793 dir_itr_increment( void *& handle
, std::wstring
& target
,
794 file_status
& sf
, file_status
& symlink_sf
)
796 WIN32_FIND_DATAW data
;
797 if ( ::FindNextFileW( handle
, &data
) == 0 ) // fails
799 int error
= ::GetLastError();
800 dir_itr_close( handle
);
801 return error_code( error
== ERROR_NO_MORE_FILES
? 0 : error
, system_category() );
803 target
= data
.cFileName
;
804 if ( data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
805 { sf
.type( directory_file
); symlink_sf
.type( directory_file
); }
806 else { sf
.type( regular_file
); symlink_sf
.type( regular_file
); }
810 # endif // ifndef BOOST_FILESYSTEM2_NARROW_ONLY
812 // suggested by Walter Landry
813 BOOST_FILESYSTEM_DECL
bool symbolic_link_exists_api( const std::string
& )
816 BOOST_FILESYSTEM_DECL
817 fs::detail::query_pair
is_empty_api( const std::string
& ph
)
818 { return is_empty_template( ph
); }
820 BOOST_FILESYSTEM_DECL
821 fs::detail::query_pair
822 equivalent_api( const std::string
& ph1
, const std::string
& ph2
)
823 { return equivalent_template( ph1
, ph2
); }
825 BOOST_FILESYSTEM_DECL
826 fs::detail::uintmax_pair
file_size_api( const std::string
& ph
)
827 { return file_size_template( ph
); }
829 BOOST_FILESYSTEM_DECL
830 fs::detail::space_pair
space_api( const std::string
& ph
)
831 { return space_template( ph
); }
833 BOOST_FILESYSTEM_DECL
835 get_current_path_api( std::string
& ph
)
836 { return get_current_path_template( ph
); }
838 BOOST_FILESYSTEM_DECL
840 set_current_path_api( const std::string
& ph
)
841 { return set_current_path_template( ph
); }
843 BOOST_FILESYSTEM_DECL error_code
844 get_full_path_name_api( const std::string
& ph
, std::string
& target
)
845 { return get_full_path_name_template( ph
, target
); }
847 BOOST_FILESYSTEM_DECL time_pair
848 last_write_time_api( const std::string
& ph
)
849 { return last_write_time_template( ph
); }
851 BOOST_FILESYSTEM_DECL error_code
852 last_write_time_api( const std::string
& ph
, std::time_t new_value
)
853 { return last_write_time_template( ph
, new_value
); }
855 BOOST_FILESYSTEM_DECL
fs::detail::query_pair
856 create_directory_api( const std::string
& ph
)
857 { return create_directory_template( ph
); }
859 #if _WIN32_WINNT >= 0x500
860 BOOST_FILESYSTEM_DECL error_code
861 create_hard_link_api( const std::string
& to_ph
,
862 const std::string
& from_ph
)
864 return create_hard_link_template( to_ph
, from_ph
);
868 BOOST_FILESYSTEM_DECL error_code
869 create_symlink_api( const std::string
& /*to_ph*/,
870 const std::string
& /*from_ph*/ )
871 { return error_code( ERROR_NOT_SUPPORTED
, system_category() ); }
873 BOOST_FILESYSTEM_DECL error_code
874 remove_api( const std::string
& ph
) { return remove_template( ph
); }
876 BOOST_FILESYSTEM_DECL error_code
877 rename_api( const std::string
& from
, const std::string
& to
)
879 return error_code( ::MoveFileA( from
.c_str(), to
.c_str() )
880 ? 0 : ::GetLastError(), system_category() );
883 BOOST_FILESYSTEM_DECL error_code
884 copy_file_api( const std::string
& from
, const std::string
& to
, bool fail_if_exists
)
886 return error_code( ::CopyFileA( from
.c_str(), to
.c_str(), fail_if_exists
)
887 ? 0 : ::GetLastError(), system_category() );
890 BOOST_FILESYSTEM_DECL error_code
891 dir_itr_first( void *& handle
, const std::string
& dir
,
892 std::string
& target
, file_status
& sf
, file_status
& symlink_sf
)
893 // Note: an empty root directory has no "." or ".." entries, so this
894 // causes a ERROR_FILE_NOT_FOUND error which we do not considered an
895 // error. It is treated as eof instead.
897 // use a form of search Sebastian Martel reports will work with Win98
898 std::string
dirpath( dir
);
899 dirpath
+= (dirpath
.empty()
900 || (dirpath
[dirpath
.size()-1] != '\\'
901 && dirpath
[dirpath
.size()-1] != ':')) ? "\\*" : "*";
903 WIN32_FIND_DATAA data
;
904 if ( (handle
= ::FindFirstFileA( dirpath
.c_str(), &data
))
905 == INVALID_HANDLE_VALUE
)
908 return error_code( (::GetLastError() == ERROR_FILE_NOT_FOUND
909 // Windows Mobile returns ERROR_NO_MORE_FILES; see ticket #3551
910 || ::GetLastError() == ERROR_NO_MORE_FILES
)
911 ? 0 : ::GetLastError(), system_category() );
913 target
= data
.cFileName
;
914 if ( data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
915 { sf
.type( directory_file
); symlink_sf
.type( directory_file
); }
916 else { sf
.type( regular_file
); symlink_sf
.type( regular_file
); }
920 BOOST_FILESYSTEM_DECL error_code
921 dir_itr_close( void *& handle
)
925 bool ok
= ::FindClose( handle
) != 0;
927 return error_code( ok
? 0 : ::GetLastError(), system_category() );
932 BOOST_FILESYSTEM_DECL error_code
933 dir_itr_increment( void *& handle
, std::string
& target
,
934 file_status
& sf
, file_status
& symlink_sf
)
936 WIN32_FIND_DATAA data
;
937 if ( ::FindNextFileA( handle
, &data
) == 0 ) // fails
939 int error
= ::GetLastError();
940 dir_itr_close( handle
);
941 return error_code( error
== ERROR_NO_MORE_FILES
? 0 : error
, system_category() );
943 target
= data
.cFileName
;
944 if ( data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
945 { sf
.type( directory_file
); symlink_sf
.type( directory_file
); }
946 else { sf
.type( regular_file
); symlink_sf
.type( regular_file
); }
950 # else // BOOST_POSIX_API
952 BOOST_FILESYSTEM_DECL
fs::file_status
953 status_api( const std::string
& ph
, error_code
& ec
)
955 struct stat path_stat
;
956 if ( ::stat( ph
.c_str(), &path_stat
) != 0 )
958 if ( errno
== ENOENT
|| errno
== ENOTDIR
)
961 return fs::file_status( fs::file_not_found
);
963 ec
= error_code( errno
, system_category() );
964 return fs::file_status( fs::status_unknown
);
967 if ( S_ISDIR( path_stat
.st_mode
) )
968 return fs::file_status( fs::directory_file
);
969 if ( S_ISREG( path_stat
.st_mode
) )
970 return fs::file_status( fs::regular_file
);
971 if ( S_ISBLK( path_stat
.st_mode
) )
972 return fs::file_status( fs::block_file
);
973 if ( S_ISCHR( path_stat
.st_mode
) )
974 return fs::file_status( fs::character_file
);
975 if ( S_ISFIFO( path_stat
.st_mode
) )
976 return fs::file_status( fs::fifo_file
);
977 if ( S_ISSOCK( path_stat
.st_mode
) )
978 return fs::file_status( fs::socket_file
);
979 return fs::file_status( fs::type_unknown
);
982 BOOST_FILESYSTEM_DECL
fs::file_status
983 symlink_status_api( const std::string
& ph
, error_code
& ec
)
985 struct stat path_stat
;
986 if ( ::lstat( ph
.c_str(), &path_stat
) != 0 )
988 if ( errno
== ENOENT
|| errno
== ENOTDIR
)
991 return fs::file_status( fs::file_not_found
);
993 ec
= error_code( errno
, system_category() );
994 return fs::file_status( fs::status_unknown
);
997 if ( S_ISREG( path_stat
.st_mode
) )
998 return fs::file_status( fs::regular_file
);
999 if ( S_ISDIR( path_stat
.st_mode
) )
1000 return fs::file_status( fs::directory_file
);
1001 if ( S_ISLNK( path_stat
.st_mode
) )
1002 return fs::file_status( fs::symlink_file
);
1003 if ( S_ISBLK( path_stat
.st_mode
) )
1004 return fs::file_status( fs::block_file
);
1005 if ( S_ISCHR( path_stat
.st_mode
) )
1006 return fs::file_status( fs::character_file
);
1007 if ( S_ISFIFO( path_stat
.st_mode
) )
1008 return fs::file_status( fs::fifo_file
);
1009 if ( S_ISSOCK( path_stat
.st_mode
) )
1010 return fs::file_status( fs::socket_file
);
1011 return fs::file_status( fs::type_unknown
);
1014 // suggested by Walter Landry
1015 BOOST_FILESYSTEM_DECL
bool
1016 symbolic_link_exists_api( const std::string
& ph
)
1018 struct stat path_stat
;
1019 return ::lstat( ph
.c_str(), &path_stat
) == 0
1020 && S_ISLNK( path_stat
.st_mode
);
1023 BOOST_FILESYSTEM_DECL query_pair
1024 is_empty_api( const std::string
& ph
)
1026 struct stat path_stat
;
1027 if ( (::stat( ph
.c_str(), &path_stat
)) != 0 )
1028 return std::make_pair( error_code( errno
, system_category() ), false );
1029 return std::make_pair( ok
, S_ISDIR( path_stat
.st_mode
)
1030 ? is_empty_directory( ph
)
1031 : path_stat
.st_size
== 0 );
1034 BOOST_FILESYSTEM_DECL query_pair
1035 equivalent_api( const std::string
& ph1
, const std::string
& ph2
)
1038 int e2( ::stat( ph2
.c_str(), &s2
) );
1040 int e1( ::stat( ph1
.c_str(), &s1
) );
1041 if ( e1
!= 0 || e2
!= 0 )
1042 return std::make_pair( error_code( e1
!= 0 && e2
!= 0 ? errno
: 0, system_category() ), false );
1043 // at this point, both stats are known to be valid
1044 return std::make_pair( ok
,
1045 s1
.st_dev
== s2
.st_dev
1046 && s1
.st_ino
== s2
.st_ino
1047 // According to the POSIX stat specs, "The st_ino and st_dev fields
1048 // taken together uniquely identify the file within the system."
1049 // Just to be sure, size and mod time are also checked.
1050 && s1
.st_size
== s2
.st_size
1051 && s1
.st_mtime
== s2
.st_mtime
);
1054 BOOST_FILESYSTEM_DECL uintmax_pair
1055 file_size_api( const std::string
& ph
)
1057 struct stat path_stat
;
1058 if ( ::stat( ph
.c_str(), &path_stat
) != 0 )
1059 return std::make_pair( error_code( errno
, system_category() ), 0 );
1060 if ( !S_ISREG( path_stat
.st_mode
) )
1061 return std::make_pair( error_code( EPERM
, system_category() ), 0 );
1062 return std::make_pair( ok
,
1063 static_cast<boost::uintmax_t>(path_stat
.st_size
) );
1066 BOOST_FILESYSTEM_DECL space_pair
1067 space_api( const std::string
& ph
)
1069 struct BOOST_STATVFS vfs
;
1071 if ( ::BOOST_STATVFS( ph
.c_str(), &vfs
) != 0 )
1073 result
.first
= error_code( errno
, system_category() );
1074 result
.second
.capacity
= result
.second
.free
1075 = result
.second
.available
= 0;
1080 result
.second
.capacity
1081 = static_cast<boost::uintmax_t>(vfs
.f_blocks
) * BOOST_STATVFS_F_FRSIZE
;
1083 = static_cast<boost::uintmax_t>(vfs
.f_bfree
) * BOOST_STATVFS_F_FRSIZE
;
1084 result
.second
.available
1085 = static_cast<boost::uintmax_t>(vfs
.f_bavail
) * BOOST_STATVFS_F_FRSIZE
;
1090 BOOST_FILESYSTEM_DECL time_pair
1091 last_write_time_api( const std::string
& ph
)
1093 struct stat path_stat
;
1094 if ( ::stat( ph
.c_str(), &path_stat
) != 0 )
1095 return std::make_pair( error_code( errno
, system_category() ), 0 );
1096 return std::make_pair( ok
, path_stat
.st_mtime
);
1099 BOOST_FILESYSTEM_DECL error_code
1100 last_write_time_api( const std::string
& ph
, std::time_t new_value
)
1102 struct stat path_stat
;
1103 if ( ::stat( ph
.c_str(), &path_stat
) != 0 )
1104 return error_code( errno
, system_category() );
1106 buf
.actime
= path_stat
.st_atime
; // utime() updates access time too:-(
1107 buf
.modtime
= new_value
;
1108 return error_code( ::utime( ph
.c_str(), &buf
) != 0 ? errno
: 0, system_category() );
1111 BOOST_FILESYSTEM_DECL error_code
1112 get_current_path_api( std::string
& ph
)
1114 for ( long path_max
= 32;; path_max
*=2 ) // loop 'til buffer large enough
1116 boost::scoped_array
<char>
1117 buf( new char[static_cast<std::size_t>(path_max
)] );
1118 if ( ::getcwd( buf
.get(), static_cast<std::size_t>(path_max
) ) == 0 )
1120 if ( errno
!= ERANGE
1121 // bug in some versions of the Metrowerks C lib on the Mac: wrong errno set
1122 # if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
1125 ) return error_code( errno
, system_category() );
1136 BOOST_FILESYSTEM_DECL error_code
1137 set_current_path_api( const std::string
& ph
)
1139 return error_code( ::chdir( ph
.c_str() )
1140 ? errno
: 0, system_category() );
1143 BOOST_FILESYSTEM_DECL
fs::detail::query_pair
1144 create_directory_api( const std::string
& ph
)
1146 if ( ::mkdir( ph
.c_str(), S_IRWXU
|S_IRWXG
|S_IRWXO
) == 0 )
1147 { return std::make_pair( ok
, true ); }
1151 || !fs::is_directory( status_api( ph
, dummy
) ) )
1152 { return std::make_pair( error_code( ec
, system_category() ), false ); }
1153 return std::make_pair( ok
, false );
1156 BOOST_FILESYSTEM_DECL error_code
1157 create_hard_link_api( const std::string
& to_ph
,
1158 const std::string
& from_ph
)
1160 return error_code( ::link( to_ph
.c_str(), from_ph
.c_str() ) == 0
1161 ? 0 : errno
, system_category() );
1164 BOOST_FILESYSTEM_DECL error_code
1165 create_symlink_api( const std::string
& to_ph
,
1166 const std::string
& from_ph
)
1168 return error_code( ::symlink( to_ph
.c_str(), from_ph
.c_str() ) == 0
1169 ? 0 : errno
, system_category() );
1172 BOOST_FILESYSTEM_DECL error_code
1173 remove_api( const std::string
& ph
)
1175 if ( posix_remove( ph
.c_str() ) == 0 )
1178 // POSIX says "If the directory is not an empty directory, rmdir()
1179 // shall fail and set errno to EEXIST or ENOTEMPTY."
1180 // Linux uses ENOTEMPTY, Solaris uses EEXIST.
1181 if ( error
== EEXIST
) error
= ENOTEMPTY
;
1185 // ignore errors if post-condition satisfied
1186 return status_api(ph
, ec
).type() == file_not_found
1187 ? ok
: error_code( error
, system_category() ) ;
1190 BOOST_FILESYSTEM_DECL error_code
1191 rename_api( const std::string
& from
, const std::string
& to
)
1193 // POSIX is too permissive so must check
1195 if ( fs::exists( status_api( to
, dummy
) ) )
1196 return error_code( EEXIST
, system_category() );
1197 return error_code( std::rename( from
.c_str(), to
.c_str() ) != 0
1198 ? errno
: 0, system_category() );
1201 BOOST_FILESYSTEM_DECL error_code
1202 copy_file_api( const std::string
& from_file_ph
,
1203 const std::string
& to_file_ph
, bool fail_if_exists
)
1205 const std::size_t buf_sz
= 32768;
1206 boost::scoped_array
<char> buf( new char [buf_sz
] );
1207 int infile
=-1, outfile
=-1; // -1 means not open
1209 // bug fixed: code previously did a stat() on the from_file first, but that
1210 // introduced a gratuitous race condition; the stat() is now done after the open()
1212 if ( (infile
= ::open( from_file_ph
.c_str(), O_RDONLY
)) < 0 )
1213 { return error_code( errno
, system_category() ); }
1215 struct stat from_stat
;
1216 if ( ::stat( from_file_ph
.c_str(), &from_stat
) != 0 )
1219 return error_code( errno
, system_category() );
1222 int oflag
= O_CREAT
| O_WRONLY
| O_TRUNC
;
1223 if ( fail_if_exists
)
1225 if ( (outfile
= ::open( to_file_ph
.c_str(), oflag
, from_stat
.st_mode
)) < 0 )
1227 int open_errno
= errno
;
1228 BOOST_ASSERT( infile
>= 0 );
1230 return error_code( open_errno
, system_category() );
1233 ssize_t sz
, sz_read
=1, sz_write
;
1235 && (sz_read
= ::read( infile
, buf
.get(), buf_sz
)) > 0 )
1237 // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
1238 // Marc Rochkind, Addison-Wesley, 2004, page 94
1242 if ( (sz
= ::write( outfile
, buf
.get() + sz_write
,
1243 sz_read
- sz_write
)) < 0 )
1245 sz_read
= sz
; // cause read loop termination
1246 break; // and error to be thrown after closes
1249 } while ( sz_write
< sz_read
);
1252 if ( ::close( infile
) < 0 ) sz_read
= -1;
1253 if ( ::close( outfile
) < 0 ) sz_read
= -1;
1255 return error_code( sz_read
< 0 ? errno
: 0, system_category() );
1258 // this code is based on Stevens and Rago, Advanced Programming in the
1259 // UNIX envirnment, 2nd Ed., ISBN 0-201-43307-9, page 49
1260 error_code
path_max( std::size_t & result
)
1263 static std::size_t max
= PATH_MAX
;
1265 static std::size_t max
= 0;
1270 long tmp
= ::pathconf( "/", _PC_NAME_MAX
);
1273 if ( errno
== 0 ) // indeterminate
1274 max
= 4096; // guess
1275 else return error_code( errno
, system_category() );
1277 else max
= static_cast<std::size_t>( tmp
+ 1 ); // relative root
1283 BOOST_FILESYSTEM_DECL error_code
1284 dir_itr_first( void *& handle
, void *& buffer
,
1285 const std::string
& dir
, std::string
& target
,
1286 file_status
&, file_status
& )
1288 if ( (handle
= ::opendir( dir
.c_str() )) == 0 )
1289 return error_code( errno
, system_category() );
1290 target
= std::string( "." ); // string was static but caused trouble
1291 // when iteration called from dtor, after
1292 // static had already been destroyed
1293 std::size_t path_size (0); // initialization quiets gcc warning
1294 error_code ec
= path_max( path_size
);
1295 if ( ec
) return ec
;
1297 buffer
= std::malloc( (sizeof(dirent
) - sizeof(de
.d_name
))
1298 + path_size
+ 1 ); // + 1 for "/0"
1302 BOOST_FILESYSTEM_DECL error_code
1303 dir_itr_close( void *& handle
, void*& buffer
)
1305 std::free( buffer
);
1307 if ( handle
== 0 ) return ok
;
1308 DIR * h( static_cast<DIR*>(handle
) );
1310 return error_code( ::closedir( h
) == 0 ? 0 : errno
, system_category() );
1313 #if defined(__PGI) && defined(__USE_FILE_OFFSET64)
1314 #define dirent dirent64
1317 // warning: the only dirent member updated is d_name
1318 inline int readdir_r_simulator( DIR * dirp
, struct dirent
* entry
,
1319 struct dirent
** result
) // *result set to 0 on end of directory
1323 # if !defined(__CYGWIN__) \
1324 && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
1325 && defined(_SC_THREAD_SAFE_FUNCTIONS) \
1326 && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0) \
1327 && (!defined(__hpux) || defined(_REENTRANT)) \
1328 && (!defined(_AIX) || defined(__THREAD_SAFE))
1329 if ( ::sysconf( _SC_THREAD_SAFE_FUNCTIONS
) >= 0 )
1330 { return ::readdir_r( dirp
, entry
, result
); }
1335 if ( (p
= ::readdir( dirp
)) == 0 )
1337 std::strcpy( entry
->d_name
, p
->d_name
);
1342 BOOST_FILESYSTEM_DECL error_code
1343 dir_itr_increment( void *& handle
, void *& buffer
,
1344 std::string
& target
, file_status
& sf
, file_status
& symlink_sf
)
1346 BOOST_ASSERT( buffer
!= 0 );
1347 dirent
* entry( static_cast<dirent
*>(buffer
) );
1350 if ( (return_code
= readdir_r_simulator( static_cast<DIR*>(handle
),
1351 entry
, &result
)) != 0 ) return error_code( errno
, system_category() );
1352 if ( result
== 0 ) return dir_itr_close( handle
, buffer
);
1353 target
= entry
->d_name
;
1354 # ifdef BOOST_FILESYSTEM_STATUS_CACHE
1355 if ( entry
->d_type
== DT_UNKNOWN
) // filesystem does not supply d_type value
1357 sf
= symlink_sf
= fs::file_status(fs::status_unknown
);
1359 else // filesystem supplies d_type value
1361 if ( entry
->d_type
== DT_DIR
)
1362 sf
= symlink_sf
= fs::file_status( fs::directory_file
);
1363 else if ( entry
->d_type
== DT_REG
)
1364 sf
= symlink_sf
= fs::file_status( fs::regular_file
);
1365 else if ( entry
->d_type
== DT_LNK
)
1367 sf
= fs::file_status( fs::status_unknown
);
1368 symlink_sf
= fs::file_status( fs::symlink_file
);
1370 else sf
= symlink_sf
= fs::file_status( fs::status_unknown
);
1373 sf
= symlink_sf
= fs::file_status( fs::status_unknown
);
1379 } // namespace detail
1380 } // namespace filesystem2
1381 } // namespace boost