Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/filesystem/src/operations.cpp @ 47

Last change on this file since 47 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 45.3 KB
Line 
1//  operations.cpp  ----------------------------------------------------------//
2
3//  Copyright 2002-2005 Beman Dawes
4//  Copyright 2001 Dietmar Kuehl
5
6// Distributed under the Boost Software License, Version 1.0.
7// (See accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9
10//  See library home page at http://www.boost.org/libs/filesystem/
11
12//----------------------------------------------------------------------------//
13
14// define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
15// the library is being built (possibly exporting rather than importing code)
16#define BOOST_FILESYSTEM_SOURCE
17
18#define _POSIX_PTHREAD_SEMANTICS  // Sun readdir_r() needs this
19
20// enable the XPG-compliant version of readdir_r() on AIX
21#if defined(_AIX)
22# define _LINUX_SOURCE_COMPAT
23#endif
24
25#if !(defined(__HP_aCC) && defined(_ILP32) && \
26      !defined(_STATVFS_ACPP_PROBLEMS_FIXED))
27# define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect,
28#endif
29
30#define __USE_FILE_OFFSET64 // but that is harmless on Windows and on POSIX
31      // 64-bit systems or on 32-bit systems which don't have files larger
32      // than can be represented by a traditional POSIX/UNIX off_t type.
33      // OTOH, defining them should kick in 64-bit off_t's (and thus
34      // st_size) on 32-bit systems that provide the Large File
35      // Support (LFS) interface, such as Linux, Solaris, and IRIX.
36      // The defines are given before any headers are included to
37      // ensure that they are available to all included headers.
38      // That is required at least on Solaris, and possibly on other
39      // systems as well.
40
41// for some compilers (CodeWarrior, for example), windows.h
42// is getting included by some other boost header, so do this early:
43#if !defined(_WIN32_WINNT)
44#define _WIN32_WINNT 0x0500 // Default to Windows 2K or later
45#endif
46
47
48#include <boost/filesystem/operations.hpp>
49#include <boost/scoped_array.hpp>
50#include <boost/throw_exception.hpp>
51#include <boost/detail/workaround.hpp>
52
53namespace fs = boost::filesystem;
54
55# if defined(BOOST_WINDOWS_API)
56#   include "windows.h"
57#   if defined(__BORLANDC__) || defined(__MWERKS__)
58#     if defined(__BORLANDC__)
59        using std::time_t;
60#     endif
61#     include "utime.h"
62#   else
63#     include "sys/utime.h"
64#   endif
65
66# else // BOOST_POSIX_API
67#   include <sys/types.h>
68#   ifndef __APPLE__
69#     include <sys/statvfs.h>
70#     define BOOST_STATVFS statvfs
71#     define BOOST_STATVFS_F_FRSIZE vfs.f_frsize
72#   else
73#     include <sys/mount.h>
74#     define BOOST_STATVFS statfs
75#     define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>( vfs.f_bsize )
76#   endif
77#   include "dirent.h"
78#   include "unistd.h"
79#   include "fcntl.h"
80#   include "utime.h"
81#   include "limits.h"
82# endif
83
84//  BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in
85//  dir_itr_increment. The config tests are placed here because some of the
86//  macros being tested come from dirent.h.
87//
88// TODO: find out what macros indicate dirent::d_type present in more libraries
89# if defined(BOOST_WINDOWS_API) \
90  || defined(_DIRENT_HAVE_D_TYPE) // defined by GNU C library if d_type present
91#   define BOOST_FILESYSTEM_STATUS_CACHE
92# endif
93
94#include <sys/stat.h>  // even on Windows some functions use stat()
95#include <string>
96#include <cstring>
97#include <cstdio>      // for remove, rename
98#include <cerrno>
99#include <cassert>
100// #include <iostream>    // for debugging only; comment out when not in use
101
102#ifdef BOOST_NO_STDC_NAMESPACE
103namespace std { using ::strcmp; using ::remove; using ::rename; }
104#endif
105
106//  helpers  -----------------------------------------------------------------//
107
108namespace
109{
110  static const fs::directory_iterator end_itr;
111  bool is_empty_directory( const std::string & dir_path )
112  {
113    return fs::directory_iterator(fs::path(dir_path)) == end_itr;
114  }
115
116#ifdef BOOST_WINDOWS_API
117 
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.)
122
123  inline DWORD get_file_attributes( const char * ph )
124    { return ::GetFileAttributesA( ph ); }
125
126# ifndef BOOST_FILESYSTEM_NARROW_ONLY
127
128  inline DWORD get_file_attributes( const wchar_t * ph )
129    { return ::GetFileAttributesW( ph ); }
130
131  static const fs::wdirectory_iterator wend_itr;
132  bool is_empty_directory( const std::wstring & dir_path )
133  {
134    return fs::wdirectory_iterator(fs::wpath(dir_path)) == wend_itr;
135  }
136
137  inline BOOL get_file_attributes_ex( const wchar_t * ph,
138    WIN32_FILE_ATTRIBUTE_DATA & fad )
139  { return ::GetFileAttributesExW( ph, ::GetFileExInfoStandard, &fad ); }
140     
141  HANDLE create_file( const wchar_t * ph, DWORD dwDesiredAccess,
142    DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
143    DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
144    HANDLE hTemplateFile )
145  {
146    return ::CreateFileW( ph, dwDesiredAccess, dwShareMode,
147      lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
148      hTemplateFile );
149  }
150
151  inline DWORD get_current_directory( DWORD sz, wchar_t * buf )
152    { return ::GetCurrentDirectoryW( sz, buf ); } 
153
154  inline bool get_free_disk_space( const std::wstring & ph,
155    PULARGE_INTEGER avail, PULARGE_INTEGER total, PULARGE_INTEGER free )
156    { return ::GetDiskFreeSpaceExW( ph.c_str(), avail, total, free ) != 0; }
157
158  inline std::size_t get_full_path_name(
159    const std::wstring & ph, std::size_t len, wchar_t * buf, wchar_t ** p )
160  {
161    return static_cast<std::size_t>(
162      ::GetFullPathNameW( ph.c_str(),
163        static_cast<DWORD>(len), buf, p ));
164  } 
165
166  inline bool remove_directory( const std::wstring & ph )
167    { return ::RemoveDirectoryW( ph.c_str() ) != 0; }
168
169  inline bool delete_file( const std::wstring & ph )
170    { return ::DeleteFileW( ph.c_str() ) != 0; }
171
172  inline bool create_directory( const std::wstring & dir )
173    {  return ::CreateDirectoryW( dir.c_str(), 0 ) != 0; }
174
175#if _WIN32_WINNT >= 0x500
176  inline bool create_hard_link( const std::wstring & to_ph,
177    const std::wstring & from_ph )
178    {  return ::CreateHardLinkW( from_ph.c_str(), to_ph.c_str(), 0 ) != 0; }
179#endif
180 
181# endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY
182
183  template< class String >
184  fs::file_status status_template( const String & ph, fs::system_error_type & ec )
185  {
186    DWORD attr( get_file_attributes( ph.c_str() ) );
187    if ( attr == 0xFFFFFFFF )
188    {
189      ec = ::GetLastError();
190      if ((ec == ERROR_FILE_NOT_FOUND)
191        || (ec == ERROR_PATH_NOT_FOUND)
192        || (ec == ERROR_INVALID_NAME) // "tools/jam/src/:sys:stat.h", "//foo"
193        || (ec == ERROR_INVALID_PARAMETER) // ":sys:stat.h"
194        || (ec == ERROR_BAD_NETPATH))
195      {
196        ec = 0; // these are not considered errors
197        return fs::file_status( fs::file_not_found );
198      }
199      return fs::file_status( fs::status_unknown );
200    }
201    ec = 0;
202    return (attr & FILE_ATTRIBUTE_DIRECTORY)
203      ? fs::file_status( fs::directory_file )
204      : fs::file_status( fs::regular_file );
205  }
206
207  BOOL get_file_attributes_ex( const char * ph,
208    WIN32_FILE_ATTRIBUTE_DATA & fad )
209  { return ::GetFileAttributesExA( ph, ::GetFileExInfoStandard, &fad ); }
210
211  template< class String >
212  boost::filesystem::detail::query_pair
213  is_empty_template( const String & ph )
214  {
215    WIN32_FILE_ATTRIBUTE_DATA fad;
216    if ( get_file_attributes_ex( ph.c_str(), fad ) == 0 )
217      return std::make_pair( ::GetLastError(), false );   
218    return std::make_pair( 0,
219      ( fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
220        ? is_empty_directory( ph )
221        :( !fad.nFileSizeHigh && !fad.nFileSizeLow ) );
222  }
223
224  HANDLE create_file( const char * ph, DWORD dwDesiredAccess,
225    DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
226    DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
227    HANDLE hTemplateFile )
228  {
229    return ::CreateFileA( ph, dwDesiredAccess, dwShareMode,
230      lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
231      hTemplateFile );
232  }
233
234  // Thanks to Jeremy Maitin-Shepard for much help and for permission to
235  // base the equivalent() implementation on portions of his
236  // file-equivalence-win32.cpp experimental code.
237  struct handle_wrapper
238  {
239    HANDLE handle;
240    handle_wrapper( HANDLE h )
241      : handle(h) {}
242    ~handle_wrapper()
243    {
244      if ( handle != INVALID_HANDLE_VALUE )
245        ::CloseHandle(handle);
246    }
247  };
248
249  template< class String >
250  boost::filesystem::detail::query_pair
251  equivalent_template( const String & ph1, const String & ph2 )
252  {
253    // Note well: Physical location on external media is part of the
254    // equivalence criteria. If there are no open handles, physical location
255    // can change due to defragmentation or other relocations. Thus handles
256    // must be held open until location information for both paths has
257    // been retrieved.
258    handle_wrapper p1(
259      create_file(
260          ph1.c_str(),
261          0,
262          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
263          0,
264          OPEN_EXISTING,
265          FILE_FLAG_BACKUP_SEMANTICS,
266          0 ) );
267    int error1(0); // save error code in case we have to throw
268    if ( p1.handle == INVALID_HANDLE_VALUE )
269      error1 = ::GetLastError();
270    handle_wrapper p2(
271      create_file(
272          ph2.c_str(),
273          0,
274          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
275          0,
276          OPEN_EXISTING,
277          FILE_FLAG_BACKUP_SEMANTICS,
278          0 ) );
279    if ( p1.handle == INVALID_HANDLE_VALUE
280      || p2.handle == INVALID_HANDLE_VALUE )
281    {
282      if ( p1.handle != INVALID_HANDLE_VALUE
283        || p2.handle != INVALID_HANDLE_VALUE )
284        { return std::make_pair( 0, false ); }
285      assert( p1.handle == INVALID_HANDLE_VALUE
286        && p2.handle == INVALID_HANDLE_VALUE );
287        { return std::make_pair( error1, false ); }
288    }
289    // at this point, both handles are known to be valid
290    BY_HANDLE_FILE_INFORMATION info1, info2;
291    if ( !::GetFileInformationByHandle( p1.handle, &info1 ) )
292      { return std::make_pair( ::GetLastError(), false ); }
293    if ( !::GetFileInformationByHandle( p2.handle, &info2 ) )
294      { return std::make_pair( ::GetLastError(), false ); }
295    // In theory, volume serial numbers are sufficient to distinguish between
296    // devices, but in practice VSN's are sometimes duplicated, so last write
297    // time and file size are also checked.
298      return std::make_pair( 0,
299        info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
300        && info1.nFileIndexHigh == info2.nFileIndexHigh
301        && info1.nFileIndexLow == info2.nFileIndexLow
302        && info1.nFileSizeHigh == info2.nFileSizeHigh
303        && info1.nFileSizeLow == info2.nFileSizeLow
304        && info1.ftLastWriteTime.dwLowDateTime
305          == info2.ftLastWriteTime.dwLowDateTime
306        && info1.ftLastWriteTime.dwHighDateTime
307          == info2.ftLastWriteTime.dwHighDateTime );
308  }
309
310  template< class String >
311  boost::filesystem::detail::uintmax_pair
312  file_size_template( const String & ph )
313  {
314    WIN32_FILE_ATTRIBUTE_DATA fad;
315    // by now, intmax_t is 64-bits on all Windows compilers
316    if ( get_file_attributes_ex( ph.c_str(), fad ) == 0 )
317      return std::make_pair( ::GetLastError(), 0 );   
318    if ( (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0 )
319      return std::make_pair( ERROR_FILE_NOT_FOUND, 0 );
320    return std::make_pair( 0,
321      (static_cast<boost::uintmax_t>(fad.nFileSizeHigh)
322        << (sizeof(fad.nFileSizeLow)*8))
323      + fad.nFileSizeLow );
324  }
325
326  inline bool get_free_disk_space( const std::string & ph,
327    PULARGE_INTEGER avail, PULARGE_INTEGER total, PULARGE_INTEGER free )
328    { return ::GetDiskFreeSpaceExA( ph.c_str(), avail, total, free ) != 0; }
329
330  template< class String >
331  boost::filesystem::detail::space_pair
332  space_template( String & ph )
333  {
334    ULARGE_INTEGER avail, total, free;
335    boost::filesystem::detail::space_pair result;
336    if ( get_free_disk_space( ph, &avail, &total, &free ) )
337    {
338      result.first = 0;
339      result.second.capacity
340        = (static_cast<boost::uintmax_t>(total.HighPart) << 32)
341          + total.LowPart;
342      result.second.free
343        = (static_cast<boost::uintmax_t>(free.HighPart) << 32)
344          + free.LowPart;
345      result.second.available
346        = (static_cast<boost::uintmax_t>(avail.HighPart) << 32)
347          + avail.LowPart;
348    }
349    else
350    {
351      result.first = ::GetLastError();
352      result.second.capacity = result.second.free
353        = result.second.available = 0;
354    }
355    return result;
356  }
357
358  inline DWORD get_current_directory( DWORD sz, char * buf )
359    { return ::GetCurrentDirectoryA( sz, buf ); } 
360
361  template< class String >
362  boost::filesystem::system_error_type
363  get_current_path_template( String & ph )
364  {
365    DWORD sz;
366    if ( (sz = get_current_directory( 0,
367      static_cast<typename String::value_type*>(0) )) == 0 )
368      { sz = 1; }
369    typedef typename String::value_type value_type;
370    boost::scoped_array<value_type> buf( new value_type[sz] );
371    if ( get_current_directory( sz, buf.get() ) == 0 )
372      return ::GetLastError();
373    ph = buf.get();
374    return 0;
375  }
376
377  inline std::size_t get_full_path_name(
378    const std::string & ph, std::size_t len, char * buf, char ** p )
379  {
380    return static_cast<std::size_t>(
381      ::GetFullPathNameA( ph.c_str(),
382        static_cast<DWORD>(len), buf, p ));
383  } 
384
385  const std::size_t buf_size( 128 );
386
387  template<class String>
388  boost::filesystem::system_error_type
389  get_full_path_name_template( const String & ph, String & target )
390  {
391    typename String::value_type buf[buf_size];
392    typename String::value_type * pfn;
393    std::size_t len = get_full_path_name( ph,
394      buf_size , buf, &pfn );
395    if ( len == 0 ) return ::GetLastError();
396    if ( len > buf_size )
397    {
398      typedef typename String::value_type value_type;
399      boost::scoped_array<value_type> big_buf( new value_type[len] );
400      if ( (len=get_full_path_name( ph, len , big_buf.get(), &pfn ))
401        == 0 ) return ::GetLastError();
402      big_buf[len] = '\0';
403      target = big_buf.get();
404      return 0;
405    }
406    buf[len] = '\0';
407    target = buf;
408    return 0;
409  }
410
411  template<class String>
412  boost::filesystem::system_error_type
413  get_file_write_time( const String & ph, FILETIME & last_write_time )
414  {
415    handle_wrapper hw(
416      create_file( ph.c_str(), 0,
417        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
418        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ) );
419    if ( hw.handle == INVALID_HANDLE_VALUE )
420      return ::GetLastError();
421    return ::GetFileTime( hw.handle, 0, 0, &last_write_time ) != 0
422      ? 0 : ::GetLastError();
423  }
424
425  template<class String>
426  boost::filesystem::system_error_type
427  set_file_write_time( const String & ph, const FILETIME & last_write_time )
428  {
429    handle_wrapper hw(
430      create_file( ph.c_str(), FILE_WRITE_ATTRIBUTES,
431        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
432        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ) );
433    if ( hw.handle == INVALID_HANDLE_VALUE )
434      return ::GetLastError();
435    return ::SetFileTime( hw.handle, 0, 0, &last_write_time ) != 0
436      ? 0 : ::GetLastError();
437  }
438
439  // these constants come from inspecting some Microsoft sample code
440  std::time_t to_time_t( const FILETIME & ft )
441  {
442    __int64 t = (static_cast<__int64>( ft.dwHighDateTime ) << 32)
443      + ft.dwLowDateTime;
444# if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0
445    t -= 116444736000000000LL;
446# else
447    t -= 116444736000000000;
448# endif
449    t /= 10000000;
450    return static_cast<std::time_t>( t );
451  }
452
453  void to_FILETIME( std::time_t t, FILETIME & ft )
454  {
455    __int64 temp = t;
456    temp *= 10000000;
457# if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 // > VC++ 7.0
458    temp += 116444736000000000LL;
459# else
460    temp += 116444736000000000;
461# endif
462    ft.dwLowDateTime = static_cast<DWORD>( temp );
463    ft.dwHighDateTime = static_cast<DWORD>( temp >> 32 );
464  }
465
466  template<class String>
467  boost::filesystem::detail::time_pair
468  last_write_time_template( const String & ph )
469  {
470    FILETIME lwt;
471    boost::filesystem::system_error_type result
472      = get_file_write_time( ph, lwt );
473    return std::make_pair( result, to_time_t( lwt ) );
474  }
475
476  template<class String>
477  boost::filesystem::system_error_type
478  last_write_time_template( const String & ph, const std::time_t new_time )
479  {
480    FILETIME lwt;
481    to_FILETIME( new_time, lwt );
482    return set_file_write_time( ph, lwt );
483  }
484
485  bool remove_directory( const std::string & ph )
486    { return ::RemoveDirectoryA( ph.c_str() ) != 0; }
487 
488  bool delete_file( const std::string & ph )
489    { return ::DeleteFileA( ph.c_str() ) != 0; }
490 
491  template<class String>
492  boost::filesystem::system_error_type
493  remove_template( const String & ph )
494  {
495    fs::system_error_type ec;
496    fs::file_status sf( fs::detail::status_api( ph, ec ) );
497    if ( ec ) return ec;
498    if ( fs::is_directory( sf ) )
499    {
500      if ( !remove_directory( ph ) )
501        return ::GetLastError();
502    }
503    else
504    {
505      if ( !delete_file( ph ) ) return ::GetLastError();
506    }
507    return 0;
508  }
509
510  inline bool create_directory( const std::string & dir )
511    {  return ::CreateDirectoryA( dir.c_str(), 0 ) != 0; }
512         
513  template<class String>
514  boost::filesystem::detail::query_pair
515  create_directory_template( const String & dir_ph )
516  {
517    boost::filesystem::system_error_type error(0), dummy;
518    if ( create_directory( dir_ph ) ) return std::make_pair( error, true );
519    error = ::GetLastError();
520    // an error here may simply mean the postcondition is already met
521    if ( error == ERROR_ALREADY_EXISTS
522      && fs::is_directory( fs::detail::status_api( dir_ph, dummy ) ) )
523      return std::make_pair( 0, false );
524    return std::make_pair( error, false );
525  }
526
527#if _WIN32_WINNT >= 0x500
528  inline bool create_hard_link( const std::string & to_ph,
529    const std::string & from_ph )
530    {  return ::CreateHardLinkA( from_ph.c_str(), to_ph.c_str(), 0 ) != 0; }
531#endif
532 
533#if _WIN32_WINNT >= 0x500
534  template<class String>
535  boost::filesystem::system_error_type
536  create_hard_link_template( const String & to_ph,
537    const String & from_ph )
538  {
539    return fs::system_error_type( create_hard_link( to_ph.c_str(), from_ph.c_str() )
540      ? 0 : ::GetLastError() );
541  }
542#endif
543
544#endif
545} // unnamed namespace
546
547namespace boost
548{
549  namespace filesystem
550  {
551    namespace detail
552    {
553
554#if   defined(BOOST_WINDOWS_API)
555        BOOST_FILESYSTEM_DECL system_error_type not_found_error = ERROR_PATH_NOT_FOUND;
556#else
557        BOOST_FILESYSTEM_DECL system_error_type not_found_error = ENOENT;
558#endif
559
560//  free functions  ----------------------------------------------------------//
561
562      BOOST_FILESYSTEM_DECL bool possible_large_file_size_support()
563      {
564#   ifdef BOOST_POSIX_API
565        struct stat lcl_stat;
566        return sizeof( lcl_stat.st_size ) > 4;
567#   else
568        return true;
569#   endif
570      }
571
572#   ifdef BOOST_WINDOWS_API
573
574      BOOST_FILESYSTEM_DECL fs::file_status
575        status_api( const std::string & ph, fs::system_error_type & ec )
576        { return status_template( ph, ec ); }
577
578#     ifndef BOOST_FILESYSTEM_NARROW_ONLY
579
580      BOOST_FILESYSTEM_DECL fs::file_status
581      status_api( const std::wstring & ph, fs::system_error_type & ec )
582        { return status_template( ph, ec ); }
583
584      BOOST_FILESYSTEM_DECL bool symbolic_link_exists_api( const std::wstring & )
585        { return false; }
586
587      BOOST_FILESYSTEM_DECL
588      fs::detail::query_pair is_empty_api( const std::wstring & ph )
589        { return is_empty_template( ph ); }
590
591      BOOST_FILESYSTEM_DECL
592      fs::detail::query_pair
593      equivalent_api( const std::wstring & ph1, const std::wstring & ph2 )
594        { return equivalent_template( ph1, ph2 ); }
595
596      BOOST_FILESYSTEM_DECL
597      fs::detail::uintmax_pair file_size_api( const std::wstring & ph )
598        { return file_size_template( ph ); }
599
600      BOOST_FILESYSTEM_DECL
601      fs::detail::space_pair space_api( const std::wstring & ph )
602        { return space_template( ph ); }
603
604      BOOST_FILESYSTEM_DECL
605      boost::filesystem::system_error_type
606      get_current_path_api( std::wstring & ph )
607        { return get_current_path_template( ph ); }
608
609      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
610        get_full_path_name_api( const std::wstring & ph, std::wstring & target )
611         { return get_full_path_name_template( ph, target ); }
612
613      BOOST_FILESYSTEM_DECL time_pair
614        last_write_time_api( const std::wstring & ph )
615          { return last_write_time_template( ph ); }
616 
617      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
618        last_write_time_api( const std::wstring & ph, std::time_t new_value )
619          { return last_write_time_template( ph, new_value ); }
620
621      BOOST_FILESYSTEM_DECL fs::detail::query_pair
622      create_directory_api( const std::wstring & ph )
623        { return create_directory_template( ph ); }
624
625#if _WIN32_WINNT >= 0x500
626      BOOST_FILESYSTEM_DECL fs::system_error_type
627      create_hard_link_api( const std::wstring & to_ph,
628        const std::wstring & from_ph )
629        { return create_hard_link_template( to_ph, from_ph ); }
630#endif
631     
632      BOOST_FILESYSTEM_DECL fs::system_error_type
633      create_symlink_api( const std::wstring & to_ph,
634        const std::wstring & from_ph )
635        { return ERROR_NOT_SUPPORTED; }
636
637      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
638      remove_api( const std::wstring & ph ) { return remove_template( ph ); }
639
640      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
641      rename_api( const std::wstring & from, const std::wstring & to )
642      {
643        return ::MoveFileW( from.c_str(), to.c_str() )
644          ? 0 : ::GetLastError();
645      }
646
647      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
648      copy_file_api( const std::wstring & from, const std::wstring & to )
649      {
650        return ::CopyFileW( from.c_str(), to.c_str(), /*fail_if_exists=*/true )
651          ? 0 : ::GetLastError();
652      }
653
654      BOOST_FILESYSTEM_DECL bool create_file_api( const std::wstring & ph,
655        std::ios_base::openmode mode ) // true if succeeds
656      {
657        DWORD access(
658          ((mode & std::ios_base::in) == 0 ? 0 : GENERIC_READ)
659          | ((mode & std::ios_base::out) == 0 ? 0 : GENERIC_WRITE) );
660
661        DWORD disposition(0); // see 27.8.1.3 Table 92
662        if ( (mode&~std::ios_base::binary)
663          == (std::ios_base::out|std::ios_base::app) )
664          disposition = OPEN_ALWAYS;
665        else if ( (mode&~(std::ios_base::binary|std::ios_base::out))
666          == std::ios_base::in ) disposition = OPEN_EXISTING;
667        else if ( ((mode&~(std::ios_base::binary|std::ios_base::trunc))
668          == std::ios_base::out )
669          || ((mode&~std::ios_base::binary)
670          == (std::ios_base::in|std::ios_base::out|std::ios_base::trunc)) )
671          disposition = CREATE_ALWAYS;
672        else assert( 0 && "invalid mode argument" );
673
674        HANDLE handle ( ::CreateFileW( ph.c_str(), access,
675          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
676          disposition, (mode &std::ios_base::out) != 0
677          ? FILE_ATTRIBUTE_ARCHIVE : FILE_ATTRIBUTE_NORMAL, 0 ) );
678        if ( handle == INVALID_HANDLE_VALUE ) return false;
679        ::CloseHandle( handle );
680        return true;
681      }
682
683      BOOST_FILESYSTEM_DECL std::string narrow_path_api(
684        const std::wstring & ph ) // return is empty if fails
685      {
686        std::string narrow_short_form;
687        std::wstring short_form;
688        for ( DWORD buf_sz( static_cast<DWORD>( ph.size()+1 ));; )
689        {
690          boost::scoped_array<wchar_t> buf( new wchar_t[buf_sz] );
691          DWORD sz( ::GetShortPathNameW( ph.c_str(), buf.get(), buf_sz ) );
692          if ( sz == 0 ) return narrow_short_form;
693          if ( sz <= buf_sz )
694          {
695            short_form += buf.get();
696            break;
697          }
698          buf_sz = sz + 1;
699        }
700        // contributed by Takeshi Mouri:
701        int narrow_sz( ::WideCharToMultiByte( CP_ACP, 0,
702          short_form.c_str(), static_cast<int>(short_form.size()), 0, 0, 0, 0 ) );
703        boost::scoped_array<char> narrow_buf( new char[narrow_sz] );
704        ::WideCharToMultiByte( CP_ACP, 0,
705          short_form.c_str(), static_cast<int>(short_form.size()),
706          narrow_buf.get(), narrow_sz, 0, 0 );
707        narrow_short_form.assign(narrow_buf.get(), narrow_sz);
708
709        return narrow_short_form;
710      }
711
712      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
713      dir_itr_first( void *& handle, const std::wstring & dir,
714        std::wstring & target, file_status & sf, file_status & symlink_sf )
715      {
716        // use a form of search Sebastian Martel reports will work with Win98
717        std::wstring dirpath( dir );
718        dirpath += (dirpath.empty()
719          || dirpath[dirpath.size()-1] != L'\\') ? L"\\*" : L"*";
720
721        WIN32_FIND_DATAW data;
722        if ( (handle = ::FindFirstFileW( dirpath.c_str(), &data ))
723          == INVALID_HANDLE_VALUE )
724        { 
725          handle = 0;
726          return ::GetLastError() == ERROR_FILE_NOT_FOUND
727            ? 0 : ::GetLastError();
728        }
729        target = data.cFileName;
730        if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
731          { sf.type( directory_file ); symlink_sf.type( directory_file ); }
732        else { sf.type( regular_file ); symlink_sf.type( regular_file ); }
733        return 0;
734      } 
735
736      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
737      dir_itr_increment( void *& handle, std::wstring & target,
738        file_status & sf, file_status & symlink_sf )
739      {
740        WIN32_FIND_DATAW data;
741        if ( ::FindNextFileW( handle, &data ) == 0 ) // fails
742        {
743          int error = ::GetLastError();
744          dir_itr_close( handle );
745          return error == ERROR_NO_MORE_FILES ? 0 : error;
746        }
747        target = data.cFileName;
748        if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
749          { sf.type( directory_file ); symlink_sf.type( directory_file ); }
750        else { sf.type( regular_file ); symlink_sf.type( regular_file ); }
751        return 0;
752      }
753
754#     endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY
755
756      // suggested by Walter Landry
757      BOOST_FILESYSTEM_DECL bool symbolic_link_exists_api( const std::string & )
758        { return false; }
759
760      BOOST_FILESYSTEM_DECL
761      fs::detail::query_pair is_empty_api( const std::string & ph )
762        { return is_empty_template( ph ); }
763
764      BOOST_FILESYSTEM_DECL
765      fs::detail::query_pair
766      equivalent_api( const std::string & ph1, const std::string & ph2 )
767        { return equivalent_template( ph1, ph2 ); }
768
769      BOOST_FILESYSTEM_DECL
770      fs::detail::uintmax_pair file_size_api( const std::string & ph )
771        { return file_size_template( ph ); }
772
773      BOOST_FILESYSTEM_DECL
774      fs::detail::space_pair space_api( const std::string & ph )
775        { return space_template( ph ); }
776
777      BOOST_FILESYSTEM_DECL
778      boost::filesystem::system_error_type
779      get_current_path_api( std::string & ph )
780        { return get_current_path_template( ph ); }
781
782      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
783        get_full_path_name_api( const std::string & ph, std::string & target )
784         { return get_full_path_name_template( ph, target ); }
785
786      BOOST_FILESYSTEM_DECL time_pair
787        last_write_time_api( const std::string & ph )
788          { return last_write_time_template( ph ); }
789 
790      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
791        last_write_time_api( const std::string & ph, std::time_t new_value )
792          { return last_write_time_template( ph, new_value ); }
793
794      BOOST_FILESYSTEM_DECL fs::detail::query_pair
795      create_directory_api( const std::string & ph )
796        { return create_directory_template( ph ); }
797
798#if _WIN32_WINNT >= 0x500
799      BOOST_FILESYSTEM_DECL fs::system_error_type
800      create_hard_link_api( const std::string & to_ph,
801        const std::string & from_ph )
802        { return system_error_type( create_hard_link_template( to_ph, from_ph ) ); }
803#endif
804
805      BOOST_FILESYSTEM_DECL fs::system_error_type
806      create_symlink_api( const std::string & to_ph,
807        const std::string & from_ph )
808        { return ERROR_NOT_SUPPORTED; }
809
810      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
811      remove_api( const std::string & ph ) { return remove_template( ph ); }
812
813      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
814      rename_api( const std::string & from, const std::string & to )
815      {
816        return ::MoveFileA( from.c_str(), to.c_str() )
817          ? 0 : ::GetLastError();
818      }
819
820      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
821      copy_file_api( const std::string & from, const std::string & to )
822      {
823        return ::CopyFileA( from.c_str(), to.c_str(), /*fail_if_exists=*/true )
824          ? 0 : ::GetLastError();
825      }
826
827      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
828      dir_itr_first( void *& handle, const std::string & dir,
829        std::string & target, file_status & sf, file_status & symlink_sf )
830      // Note: an empty root directory has no "." or ".." entries, so this
831      // causes a ERROR_FILE_NOT_FOUND error which we do not considered an
832      // error. It is treated as eof instead.
833      {
834        // use a form of search Sebastian Martel reports will work with Win98
835        std::string dirpath( dir );
836        dirpath += (dirpath.empty()
837          || (dirpath[dirpath.size()-1] != '\\'
838            && dirpath[dirpath.size()-1] != ':')) ? "\\*" : "*";
839
840        WIN32_FIND_DATAA data;
841        if ( (handle = ::FindFirstFileA( dirpath.c_str(), &data ))
842          == INVALID_HANDLE_VALUE )
843        { 
844          handle = 0;
845          return ::GetLastError() == ERROR_FILE_NOT_FOUND
846            ? 0 : ::GetLastError();
847        }
848        target = data.cFileName;
849        if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
850          { sf.type( directory_file ); symlink_sf.type( directory_file ); }
851        else { sf.type( regular_file ); symlink_sf.type( regular_file ); }
852        return 0;
853      }
854
855      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
856      dir_itr_close( void *& handle )
857      {
858        if ( handle != 0 )
859        {
860          bool ok = ::FindClose( handle ) != 0;
861          handle = 0;
862          return ok ? 0 : ::GetLastError();
863        }
864        return 0;
865      }
866
867      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
868      dir_itr_increment( void *& handle, std::string & target,
869        file_status & sf, file_status & symlink_sf )
870      {
871        WIN32_FIND_DATAA data;
872        if ( ::FindNextFileA( handle, &data ) == 0 ) // fails
873        {
874          int error = ::GetLastError();
875          dir_itr_close( handle );
876          return error == ERROR_NO_MORE_FILES ? 0 : error;
877        }
878        target = data.cFileName;
879        if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
880          { sf.type( directory_file ); symlink_sf.type( directory_file ); }
881        else { sf.type( regular_file ); symlink_sf.type( regular_file ); }
882        return 0;
883      }
884
885#   else // BOOST_POSIX_API
886
887      BOOST_FILESYSTEM_DECL fs::file_status
888      status_api( const std::string & ph, system_error_type & ec )
889      {
890        struct stat path_stat;
891        if ( ::stat( ph.c_str(), &path_stat ) != 0 )
892        {
893          if ( errno == ENOENT || errno == ENOTDIR )
894          {
895            ec = 0;
896            return fs::file_status( fs::file_not_found );
897          }
898          ec = errno;
899          return fs::file_status( fs::status_unknown );
900        }
901        ec = 0;
902        if ( S_ISDIR( path_stat.st_mode ) )
903          return fs::file_status( fs::directory_file );
904        if ( S_ISREG( path_stat.st_mode ) )
905          return fs::file_status( fs::regular_file );
906        if ( S_ISBLK( path_stat.st_mode ) )
907          return fs::file_status( fs::block_file );
908        if ( S_ISCHR( path_stat.st_mode ) )
909          return fs::file_status( fs::character_file );
910        if ( S_ISFIFO( path_stat.st_mode ) )
911          return fs::file_status( fs::fifo_file );
912        if ( S_ISSOCK( path_stat.st_mode ) )
913          return fs::file_status( fs::socket_file );
914        return fs::file_status( fs::type_unknown );
915      }
916
917      BOOST_FILESYSTEM_DECL fs::file_status
918      symlink_status_api( const std::string & ph, system_error_type & ec )
919      {
920        struct stat path_stat;
921        if ( ::lstat( ph.c_str(), &path_stat ) != 0 )
922        {
923          if ( errno == ENOENT || errno == ENOTDIR )
924          {
925            ec = 0;
926            return fs::file_status( fs::file_not_found );
927          }
928          ec = errno;
929          return fs::file_status( fs::status_unknown );
930        }
931        ec = 0;
932        if ( S_ISREG( path_stat.st_mode ) )
933          return fs::file_status( fs::regular_file );
934        if ( S_ISDIR( path_stat.st_mode ) )
935          return fs::file_status( fs::directory_file );
936        if ( S_ISLNK( path_stat.st_mode ) )
937          return fs::file_status( fs::symlink_file );
938        if ( S_ISBLK( path_stat.st_mode ) )
939          return fs::file_status( fs::block_file );
940        if ( S_ISCHR( path_stat.st_mode ) )
941          return fs::file_status( fs::character_file );
942        if ( S_ISFIFO( path_stat.st_mode ) )
943          return fs::file_status( fs::fifo_file );
944        if ( S_ISSOCK( path_stat.st_mode ) )
945          return fs::file_status( fs::socket_file );
946        return fs::file_status( fs::type_unknown );
947      }
948
949      // suggested by Walter Landry
950      BOOST_FILESYSTEM_DECL bool
951      symbolic_link_exists_api( const std::string & ph )
952      {
953        struct stat path_stat;
954        return ::lstat( ph.c_str(), &path_stat ) == 0
955          && S_ISLNK( path_stat.st_mode );
956      }
957
958      BOOST_FILESYSTEM_DECL query_pair
959      is_empty_api( const std::string & ph )
960      {
961        struct stat path_stat;
962        if ( (::stat( ph.c_str(), &path_stat )) != 0 )
963          return std::make_pair( errno, false );       
964        return std::make_pair( 0, S_ISDIR( path_stat.st_mode )
965          ? is_empty_directory( ph )
966          : path_stat.st_size == 0 );
967      }
968
969      BOOST_FILESYSTEM_DECL query_pair
970      equivalent_api( const std::string & ph1, const std::string & ph2 )
971      {
972        struct stat s2;
973        int e2( ::stat( ph2.c_str(), &s2 ) );
974        struct stat s1;
975        int e1( ::stat( ph1.c_str(), &s1 ) );
976        if ( e1 != 0 || e2 != 0 )
977          return std::make_pair( e1 != 0 && e2 != 0 ? errno : 0, false );
978        // at this point, both stats are known to be valid
979        return std::make_pair( 0,
980            s1.st_dev == s2.st_dev
981            && s1.st_ino == s2.st_ino
982            // According to the POSIX stat specs, "The st_ino and st_dev fields
983            // taken together uniquely identify the file within the system."
984            // Just to be sure, size and mod time are also checked.
985            && s1.st_size == s2.st_size
986            && s1.st_mtime == s2.st_mtime );
987      }
988 
989      BOOST_FILESYSTEM_DECL uintmax_pair
990      file_size_api( const std::string & ph )
991      {
992        struct stat path_stat;
993        if ( ::stat( ph.c_str(), &path_stat ) != 0 )
994          return std::make_pair( errno, 0 );
995        if ( !S_ISREG( path_stat.st_mode ) )
996          return std::make_pair( EPERM, 0 ); 
997        return std::make_pair( 0,
998          static_cast<boost::uintmax_t>(path_stat.st_size) );
999      }
1000
1001      BOOST_FILESYSTEM_DECL space_pair
1002      space_api( const std::string & ph )
1003      {
1004        struct BOOST_STATVFS vfs;
1005        space_pair result;
1006        if ( ::BOOST_STATVFS( ph.c_str(), &vfs ) != 0 )
1007        {
1008          result.first = errno;
1009          result.second.capacity = result.second.free
1010            = result.second.available = 0;
1011        }
1012        else
1013        {
1014          result.first = 0;
1015          result.second.capacity
1016            = static_cast<boost::uintmax_t>(vfs.f_blocks) * BOOST_STATVFS_F_FRSIZE;
1017          result.second.free
1018            = static_cast<boost::uintmax_t>(vfs.f_bfree) * BOOST_STATVFS_F_FRSIZE;
1019          result.second.available
1020            = static_cast<boost::uintmax_t>(vfs.f_bavail) * BOOST_STATVFS_F_FRSIZE;
1021        }
1022        return result;
1023      }
1024
1025      BOOST_FILESYSTEM_DECL time_pair
1026      last_write_time_api( const std::string & ph )
1027      {
1028        struct stat path_stat;
1029        if ( ::stat( ph.c_str(), &path_stat ) != 0 )
1030          return std::make_pair( errno, 0 );
1031        return std::make_pair( 0, path_stat.st_mtime );
1032      }
1033
1034      BOOST_FILESYSTEM_DECL fs::system_error_type
1035      last_write_time_api( const std::string & ph, std::time_t new_value )
1036      {
1037        struct stat path_stat;
1038        if ( ::stat( ph.c_str(), &path_stat ) != 0 ) return errno;
1039        ::utimbuf buf;
1040        buf.actime = path_stat.st_atime; // utime() updates access time too:-(
1041        buf.modtime = new_value;
1042        return ::utime( ph.c_str(), &buf ) != 0 ? errno : 0;
1043      }
1044
1045      BOOST_FILESYSTEM_DECL fs::system_error_type
1046      get_current_path_api( std::string & ph )
1047      {
1048        for ( long path_max = 32;; path_max *=2 ) // loop 'til buffer large enough
1049        {
1050          boost::scoped_array<char>
1051            buf( new char[static_cast<std::size_t>(path_max)] );
1052          if ( ::getcwd( buf.get(), static_cast<std::size_t>(path_max) ) == 0 )
1053          {
1054            if ( errno != ERANGE
1055          // bug in some versions of the Metrowerks C lib on the Mac: wrong errno set
1056#         if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
1057              && errno != 0
1058#         endif
1059              ) return errno;
1060          }
1061          else
1062          {
1063            ph = buf.get();
1064            break;
1065          }
1066        }
1067        return 0;
1068      }
1069
1070      BOOST_FILESYSTEM_DECL fs::detail::query_pair
1071      create_directory_api( const std::string & ph )
1072      {
1073        if ( ::mkdir( ph.c_str(), S_IRWXU|S_IRWXG|S_IRWXO ) == 0 )
1074          { return std::make_pair( 0, true ); }
1075        system_error_type ec=errno, dummy;
1076        if ( ec != EEXIST
1077          || !fs::is_directory( status_api( ph, dummy ) ) )
1078          { return std::make_pair( ec, false ); }
1079        return std::make_pair( 0, false );
1080      }
1081
1082      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
1083      create_hard_link_api( const std::string & to_ph,
1084          const std::string & from_ph )
1085      {
1086        return ::link( to_ph.c_str(), from_ph.c_str() ) == 0
1087          ? 0 : errno;
1088      }
1089
1090      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
1091      create_symlink_api( const std::string & to_ph,
1092          const std::string & from_ph )
1093      {
1094        return ::symlink( to_ph.c_str(), from_ph.c_str() ) == 0
1095          ? 0 : errno;
1096      }
1097
1098      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
1099      remove_api( const std::string & ph )
1100      {
1101#     if defined(__QNXNTO__) || (defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)))
1102        // Some Metrowerks C library versions fail on directories because of a
1103        // known Metrowerks coding error in ::remove. Workaround is to call
1104        // rmdir() or unlink() as indicated.
1105        // Same bug also reported for QNX, with the same fix.
1106        if ( (is_directory( ph )
1107          ? ::rmdir( ph.c_str() )
1108          : ::unlink( ph.c_str() )) != 0 )
1109#     else
1110        // note that the POSIX behavior for symbolic links is what we want;
1111        // the link rather than what it points to is deleted
1112        if ( std::remove( ph.c_str() ) != 0 )
1113#     endif
1114        {
1115          int error = errno;
1116          // POSIX says "If the directory is not an empty directory, rmdir()
1117          // shall fail and set errno to EEXIST or ENOTEMPTY."
1118          // Linux uses ENOTEMPTY, Solaris uses EEXIST.
1119          if ( error == EEXIST ) error = ENOTEMPTY;
1120          return error;
1121        }
1122        return 0;
1123      }
1124
1125      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
1126      rename_api( const std::string & from, const std::string & to )
1127      {
1128        // POSIX is too permissive so must check
1129        fs::system_error_type dummy;
1130        if ( fs::exists( status_api( to, dummy ) ) ) 
1131          return EEXIST;
1132        return std::rename( from.c_str(), to.c_str() ) != 0 
1133          ? errno : 0;
1134      }
1135
1136      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
1137      copy_file_api( const std::string & from_file_ph,
1138        const std::string & to_file_ph )
1139      {
1140        const std::size_t buf_sz = 32768;
1141        boost::scoped_array<char> buf( new char [buf_sz] );
1142        int infile=0, outfile=0;  // init quiets compiler warning
1143        struct stat from_stat;
1144
1145        if ( ::stat( from_file_ph.c_str(), &from_stat ) != 0
1146          || (infile = ::open( from_file_ph.c_str(),
1147                              O_RDONLY )) < 0
1148          || (outfile = ::open( to_file_ph.c_str(),
1149                                O_WRONLY | O_CREAT | O_EXCL,
1150                                from_stat.st_mode )) < 0 )
1151        {
1152          if ( infile >= 0 ) ::close( infile );
1153          return errno;
1154        }
1155
1156        ssize_t sz, sz_read=1, sz_write;
1157        while ( sz_read > 0
1158          && (sz_read = ::read( infile, buf.get(), buf_sz )) > 0 )
1159        {
1160          // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
1161          // Marc Rochkind, Addison-Wesley, 2004, page 94
1162          sz_write = 0;
1163          do
1164          {
1165            if ( (sz = ::write( outfile, buf.get() + sz_write,
1166              sz_read - sz_write )) < 0 )
1167            { 
1168              sz_read = sz; // cause read loop termination
1169              break;        //  and error to be thrown after closes
1170            }
1171            sz_write += sz;
1172          } while ( sz_write < sz_read );
1173        }
1174
1175        if ( ::close( infile) < 0 ) sz_read = -1;
1176        if ( ::close( outfile) < 0 ) sz_read = -1;
1177
1178        return sz_read < 0 ? errno : 0;
1179      }
1180 
1181      // this code is based on Stevens and Rago, Advanced Programming in the
1182      // UNIX envirnment, 2nd Ed., ISBN 0-201-43307-9, page 49
1183      fs::system_error_type
1184      path_max( std::size_t & result )
1185      {
1186#     ifdef PATH_MAX
1187        static std::size_t max = PATH_MAX;
1188#     else
1189        static std::size_t max = 0;
1190#     endif
1191        if ( max == 0 )
1192        {
1193          errno = 0;
1194          long tmp = ::pathconf( "/", _PC_NAME_MAX );
1195          if ( tmp < 0 )
1196          {
1197            if ( errno == 0 ) // indeterminate
1198              max = 4096; // guess
1199            else return errno;
1200          }
1201          else max = static_cast<std::size_t>( tmp + 1 ); // relative root
1202        }
1203        result = max;
1204        return 0;
1205      }
1206
1207      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
1208      dir_itr_first( void *& handle, void *& buffer,
1209        const std::string & dir, std::string & target,
1210        file_status &, file_status & )
1211      {
1212        static const std::string dummy_first_name( "." );
1213        if ( (handle = ::opendir( dir.c_str() )) == 0 ) return errno;
1214        target = dummy_first_name;
1215        std::size_t path_size;
1216        fs::system_error_type ec = path_max( path_size );
1217        if ( ec ) return ec;
1218        dirent de;
1219        buffer = std::malloc( (sizeof(dirent) - sizeof(de.d_name))
1220          +  path_size + 1 ); // + 1 for "/0"
1221        return buffer == 0 ? ENOMEM : 0;
1222      } 
1223
1224      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
1225      dir_itr_close( void *& handle, void*& buffer )
1226      {
1227        std::free( buffer );
1228        buffer = 0;
1229        if ( handle == 0 ) return 0;
1230        DIR * h( static_cast<DIR*>(handle) );
1231        handle = 0;
1232        return ::closedir( h ) == 0 ? 0 : errno;
1233      }
1234
1235      // warning: the only dirent member updated is d_name
1236      inline int readdir_r_simulator( DIR * dirp, struct dirent * entry,
1237        struct dirent ** result ) // *result set to 0 on end of directory
1238        {
1239          errno = 0;
1240
1241    #     if !defined(__CYGWIN__) \
1242          && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
1243          && defined(_SC_THREAD_SAFE_FUNCTIONS) \
1244          && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0) \
1245          && (!defined(__HP_aCC) || (defined(__HP_aCC) && defined(_REENTRANT)))
1246          if ( ::sysconf( _SC_THREAD_SAFE_FUNCTIONS ) >= 0 )
1247            { return ::readdir_r( dirp, entry, result ); }
1248    #     endif
1249
1250          struct dirent * p;
1251          *result = 0;
1252          if ( (p = ::readdir( dirp )) == 0 )
1253            return errno;
1254          std::strcpy( entry->d_name, p->d_name );
1255          *result = entry;
1256          return 0;
1257        }
1258
1259      BOOST_FILESYSTEM_DECL boost::filesystem::system_error_type
1260      dir_itr_increment( void *& handle, void *& buffer,
1261        std::string & target, file_status & sf, file_status & symlink_sf )
1262      {
1263        BOOST_ASSERT( buffer != 0 );
1264        dirent * entry( static_cast<dirent *>(buffer) );
1265        dirent * result;
1266        int return_code;
1267        if ( (return_code = readdir_r_simulator( static_cast<DIR*>(handle),
1268          entry, &result )) != 0 ) return errno;
1269        if ( result == 0 ) return dir_itr_close( handle, buffer );
1270        target = entry->d_name;
1271#     ifdef BOOST_FILESYSTEM_STATUS_CACHE
1272            if ( entry->d_type == DT_UNKNOWN )  // filesystem does not supply d_type value
1273        {
1274          sf = symlink_sf = fs::file_status(fs::status_unknown);
1275        }
1276          else  // filesystem supplies d_type value
1277            {
1278          if ( entry->d_type == DT_DIR )
1279            sf = symlink_sf = fs::file_status( fs::directory_file );
1280          else if ( entry->d_type == DT_REG )
1281            sf = symlink_sf = fs::file_status( fs::regular_file );
1282          else if ( entry->d_type == DT_LNK )
1283          {
1284            sf = fs::file_status( fs::status_unknown );
1285            symlink_sf = fs::file_status( fs::symlink_file );
1286          }
1287          else sf = symlink_sf = fs::file_status( fs::status_unknown );
1288            }
1289#     else
1290        sf = symlink_sf = fs::file_status( fs::status_unknown );
1291#     endif
1292        return 0;
1293      }
1294
1295#   endif
1296    } // namespace detail
1297  } // namespace filesystem
1298} // namespace boost
Note: See TracBrowser for help on using the repository browser.