Angus Leeming a écrit :
Abdelrazak Younes <[EMAIL PROTECTED]> writes:
Yes. One of the files in boost/libs/filesystem/src (Sorry, no viewsvn...)
#includes and uses NewAPIs.h. I can dig out the details if you can't track the
change down.
Well, I don't have enough disk space to get the 1.4 tree. Bo, Enrico, could you track that down please?

There'll be a description in the ChangeLog in the boost directory.
Probably ;-) Search on "Angus"...

Here are the relevant logs and the diff against current svn, please tell me what I should do:

2006-04-11  Jean-Marc Lasgouttes  <[EMAIL PROTECTED]>

        * libs/filesystem/src/operations_posix_windows.cpp: change needed
        to enable compilation against NewAPIs.h. Ie, LyX 1.4 will work for
        Win98 users.

2005-09-30  Angus Leeming  <[EMAIL PROTECTED]>

        * libs/filesystem/src/operations_posix_windows.cpp (exists):
        add ERROR_ACCESS_DENIED to the list of "recognised" errors. It
        appears that Win98SE returns such an error from GetFileAttributes
        if asked to query a path on a drive that doesn't exist.

        The "correct" fix is currently being discussed on the boost-devel
        list, but this work around will do for us for now.

2005-09-30  Angus Leeming  <[EMAIL PROTECTED]>

        * libs/filesystem/src/operations_posix_windows.cpp: add a block
        of preprocessor code to include NewAPIs.h conditioned on the
        WANT_GETFILEATTRIBUTESEX_WRAPPER macro. Enables runtime support
        for Windows 95.
        (_is_empty, file_size): replace GetFileAttributesExA with the
        macro GetFileAttributesEx to enable the stub magic in NewAPIs.h
        to work.


Abdel.
Index: operations_posix_windows.cpp
===================================================================
--- operations_posix_windows.cpp        (revision 13773)
+++ operations_posix_windows.cpp        (working copy)
@@ -21,25 +21,18 @@
 // the library is being built (possibly exporting rather than importing code)
 #define BOOST_FILESYSTEM_SOURCE 
 
-#define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect,
-#define __USE_FILE_OFFSET64 // but that is harmless on Windows and on POSIX
-      // 64-bit systems or on 32-bit systems which don't have files larger 
-      // than can be represented by a traditional POSIX/UNIX off_t type. 
-      // OTOH, defining them should kick in 64-bit off_t's (and thus 
-      // st_size) on 32-bit systems that provide the Large File
-      // Support (LFS) interface, such as Linux, Solaris, and IRIX.
-      // The defines are given before any headers are included to
-      // ensure that they are available to all included headers.
-      // That is required at least on Solaris, and possibly on other
-      // systems as well.
-
 #include <boost/filesystem/config.hpp>
 #include <boost/filesystem/operations.hpp>
 #include <boost/filesystem/exception.hpp>
 #include <boost/scoped_array.hpp>
 #include <boost/throw_exception.hpp>
 #include <boost/detail/workaround.hpp>
+#include <cstring>
 
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std { using ::strcmp; using ::remove; using ::rename; }
+#endif
+
 namespace fs = boost::filesystem;
 
 // BOOST_POSIX or BOOST_WINDOWS specify which API to use.
@@ -53,6 +46,51 @@
 
 # if defined(BOOST_WINDOWS)
 #   include "windows.h"
+
+    //////////////////////////////////////////////////////////////////////
+    //
+    // Enable Boost.Filesystem to run on Win95 using the emulation
+    // of GetFileAttributesEx available in the Microsoft Platform SDK
+    // header file NewAPIs.h.
+    //
+    // The user needs only to define WANT_GETFILEATTRIBUTESEX_WRAPPER
+    // to enable this emulation.
+    //
+    // Please note, however, that this block of preprocessor code enables
+    // the user to compile against the emulation code. To link the
+    // executable the user must also compile the function definitions in
+    // NewAPIs.h. See NewAPIs.h for further details.
+    //
+    // This code should work both with Microsoft's native implementation
+    // of the winapi headers and also with MinGW/Cygwin's version.
+    //
+    //////////////////////////////////////////////////////////////////////
+#   if defined(WANT_GETFILEATTRIBUTESEX_WRAPPER)
+#     if (defined(__MINGW32__) || defined(__CYGWIN__)) && WINVER < 0x040A
+        // MinGW/Cygwin's winapi header files and NewAPIs.h do not live
+        // well together because NewAPIs.h redefines
+        // WIN32_FILE_ATTRIBUTE_DATA and GET_FILEEX_INFO_LEVELS
+        // if WINVER < 0x04A.
+#       include <w32api.h>
+#       if __W32API_MAJOR_VERSION < 3 || \
+           __W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION <= 6
+#         define BOOST_FILESYSTEM_WINVER WINVER
+#         undef WINVER
+#         define WINVER 0x040A
+#       endif
+#     endif
+
+#     include <NewAPIs.h>
+
+      // Return macro definitions to their original state.
+#     ifdef BOOST_FILESYSTEM_WINVER
+#       undef WINVER
+#       define WINVER BOOST_FILESYSTEM_WINVER
+#       undef BOOST_FILESYSTEM_WINVER
+#     endif
+#   endif
+    //////////////////////////////////////////////////////////////////////
+
 #   if defined(__BORLANDC__) || defined(__MWERKS__)
 #     if defined(__BORLANDC__)
         using std::time_t;
@@ -68,6 +106,14 @@
 // other macros defined. There was a bug report of this happening.)
 
 # else // BOOST_POSIX
+#   define _USE_FILE_OFFSET_BITS 64 // at worst,
+#   define __USE_FILE_OFFSET64 // these defines may do nothing,
+      // but that won't matter on 64-bit systems or on 32-bit systems which
+      // don't have files larger than can be represented by a traditional
+      // POSIX/UNIX off_t type. OTOH, defining them should kick
+      // in 64-bit off_t's (and thus st_size) on 32-bit systems that support
+      // the Large File Support (LFS) interface, such as Linux, Solaris, and 
IRIX.
+
 #   include <sys/types.h>
 #   include "dirent.h"
 #   include "unistd.h"
@@ -77,16 +123,10 @@
 
 #include <sys/stat.h>  // even on Windows some functions use stat()
 #include <string>
-#include <cstring>
 #include <cstdio>      // for remove, rename
 #include <cerrno>
 #include <cassert>
-//#include <iostream>    // for debugging only; comment out when not in use
 
-#ifdef BOOST_NO_STDC_NAMESPACE
-namespace std { using ::strcmp; using ::remove; using ::rename; }
-#endif
-
 #include <boost/config/abi_prefix.hpp> // must be the last header
 
 //  helpers  
-----------------------------------------------------------------//
@@ -97,7 +137,7 @@
 
 # define BOOST_HANDLE DIR *
 # define BOOST_INVALID_HANDLE_VALUE 0
-# define BOOST_SYSTEM_DIRECTORY_TYPE struct dirent
+# define BOOST_SYSTEM_DIRECTORY_TYPE struct dirent *
 
   inline const char *  find_first_file( const char * dir,
     BOOST_HANDLE & handle, BOOST_SYSTEM_DIRECTORY_TYPE & )
@@ -114,44 +154,29 @@
     ::closedir( handle );
   }
 
-  // warning: the only dirent member updated is d_name
-  inline int readdir_r_simulator( DIR * dirp, struct dirent * entry,
-    struct dirent ** result ) // *result set to 0 on end of directory
-    {
-#     if defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
-      && defined(_SC_THREAD_SAFE_FUNCTIONS) \
-      && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0) \
-      && ( !defined(__HP_aCC) || ( defined(__HP_aCC) && defined(_REENTRANT) ) )
-      if ( ::sysconf( _SC_THREAD_SAFE_FUNCTIONS ) >= 0 )
-        { return ::readdir_r( dirp, entry, result ); }
-#     endif
-
-      struct dirent * p;
-      errno = 0;
-      *result = 0;
-      if ( (p = ::readdir( dirp )) == 0 )
-        return errno;
-      // POSIX specs require entry->d_name be large enough:
-      std::strcpy( entry->d_name, p->d_name );
-      *result = entry;
-      return 0;
-    }
-
-  inline const char * find_next_file( BOOST_HANDLE handle,
-    const fs::path & ph, BOOST_SYSTEM_DIRECTORY_TYPE & entry )
+  inline const char * find_next_file(
+    BOOST_HANDLE handle, const fs::path & ph, BOOST_SYSTEM_DIRECTORY_TYPE & )
   // Returns: if EOF 0, otherwise name
   // Throws: if system reports error
   {
-    struct dirent * result;
-    int return_code;
-    if ( (return_code = ::readdir_r_simulator( handle, &entry, &result )) != 0 
)
+
+//  TODO: use readdir_r() if available, so code is multi-thread safe.
+//  Fly-in-ointment: not all platforms support readdir_r().
+
+    struct dirent * dp;
+    errno = 0;
+    if ( (dp = ::readdir( handle )) == 0 )
     {
-      boost::throw_exception(
-        fs::filesystem_error(
-          "boost::filesystem::directory_iterator::operator++",
-          ph, return_code ) );
+      if ( errno != 0 )
+      {
+        boost::throw_exception(
+          fs::filesystem_error(
+            "boost::filesystem::directory_iterator::operator++",
+            ph, errno ) );
+      }
+      else { return 0; } // end reached
     }
-    return result ? entry.d_name : 0;
+    return dp->d_name;
   }
 #else // BOOST_WINDOWS
 
@@ -162,23 +187,16 @@
   inline const char *  find_first_file( const char * dir,
     BOOST_HANDLE & handle, BOOST_SYSTEM_DIRECTORY_TYPE & data )
   // Returns: 0 if error, otherwise name
-  // Note: an empty root directory has no "." or ".." entries, so this causes
-  // a ERROR_FILE_NOT_FOUND error which we do not considered an error. Instead,
-  // the handle is set to BOOST_INVALID_HANDLE_VALUE and a non-zero is 
returned.
   {
-    // use a form of search Sebastian Martel reports will work with Win98
-    std::string dirpath( dir );
-    dirpath += (dirpath.empty()
-      || (dirpath[dirpath.size()-1] != '\\'
-      && dirpath[dirpath.size()-1] != '/')) ? "\\*" : "*";
-
+//    std::cout << "find_first_file " << dir << std::endl;
+    std::string dirpath( std::string(dir) + "/*" );
     return ( (handle = ::FindFirstFileA( dirpath.c_str(), &data ))
-      == BOOST_INVALID_HANDLE_VALUE
-      && ::GetLastError() != ERROR_FILE_NOT_FOUND) ? 0 : data.cFileName;
+      == BOOST_INVALID_HANDLE_VALUE ) ? 0 : data.cFileName;
   }  
 
   inline void find_close( BOOST_HANDLE handle )
   {
+//    std::cout << "find_close" << std::endl;
     assert( handle != BOOST_INVALID_HANDLE_VALUE );
     ::FindClose( handle );
   }
@@ -277,18 +295,11 @@
         BOOST_SYSTEM_DIRECTORY_TYPE scratch;
         const char * name = 0;  // initialization quiets compiler warnings
         if ( dir_path.empty() )
-          m_imp->handle = BOOST_INVALID_HANDLE_VALUE;
+        m_imp->handle = BOOST_INVALID_HANDLE_VALUE;
         else
-        {
           name = find_first_file( dir_path.native_directory_string().c_str(),
             m_imp->handle, scratch );  // sets handle
-          if ( m_imp->handle == BOOST_INVALID_HANDLE_VALUE
-            && name ) // eof
-          {
-            m_imp.reset(); // make end iterator
-            return;
-          }
-        }
+
         if ( m_imp->handle != BOOST_INVALID_HANDLE_VALUE )
         {
           m_imp->entry_path = dir_path;
@@ -358,12 +369,11 @@
       if(::GetFileAttributesA( ph.string().c_str() ) == 0xFFFFFFFF)
       {
          UINT err = ::GetLastError();
-         if((err == ERROR_FILE_NOT_FOUND)
-           || (err == ERROR_INVALID_PARAMETER)
-           || (err == ERROR_NOT_READY)
-           || (err == ERROR_PATH_NOT_FOUND)
-           || (err == ERROR_INVALID_NAME)
-           || (err == ERROR_BAD_NETPATH ))
+         if((err == ERROR_FILE_NOT_FOUND) ||
+           (err == ERROR_INVALID_PARAMETER) ||
+           (err == ERROR_PATH_NOT_FOUND) ||
+           (err == ERROR_INVALID_NAME) ||
+           (err == ERROR_ACCESS_DENIED))
             return false; // GetFileAttributes failed because the path does 
not exist
          // for any other error we assume the file does exist and fall through,
          // this may not be the best policy though...  (JM 20040330)
@@ -430,7 +440,7 @@
         : path_stat.st_size == 0;
 #   else
       WIN32_FILE_ATTRIBUTE_DATA fad;
-      if ( !::GetFileAttributesExA( ph.string().c_str(),
+      if ( !::GetFileAttributesEx( ph.string().c_str(),
         ::GetFileExInfoStandard, &fad ) )
         boost::throw_exception( filesystem_error(
           "boost::filesystem::is_empty",
@@ -534,17 +544,28 @@
             "boost::filesystem::equivalent",
             ph2, fs::detail::system_error_code() ) );
       // In theory, volume serial numbers are sufficient to distinguish between
-      // devices, but in practice VSN's are sometimes duplicated, so last write
-      // time and file size are also checked.
-      return info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
-        && info1.nFileIndexHigh == info2.nFileIndexHigh
-        && info1.nFileIndexLow == info2.nFileIndexLow
-        && info1.nFileSizeHigh == info2.nFileSizeHigh
-        && info1.nFileSizeLow == info2.nFileSizeLow
-        && info1.ftLastWriteTime.dwLowDateTime
-          == info2.ftLastWriteTime.dwLowDateTime
-        && info1.ftLastWriteTime.dwHighDateTime
-          == info2.ftLastWriteTime.dwHighDateTime;
+      // devices, but in practice VSN's are sometimes duplicated, so device id
+      // is also checked. Device id's alone aren't sufficient because network
+      // share devices on different machines will have the same id. 
Furthermore,
+      // cheap floppy disks often have 0 VSN's and are mounted on the same
+      // lettered drive across networks, so last write time and file size is
+      // checked to distinguish that case as far as is possible.
+      if ( info1.dwVolumeSerialNumber != info2.dwVolumeSerialNumber
+        || info1.nFileIndexHigh != info2.nFileIndexHigh
+        || info1.nFileIndexLow != info2.nFileIndexLow
+        || info1.nFileSizeHigh != info2.nFileSizeHigh
+        || info1.nFileSizeLow != info2.nFileSizeLow ) return false;
+      struct stat s1;
+      if ( ::stat( ph1.string().c_str(), &s1 ) != 0 )
+        boost::throw_exception( filesystem_error(
+          "boost::filesystem::equivalent",
+          ph1, fs::detail::system_error_code() ) );
+      struct stat s2;
+      if ( ::stat( ph2.string().c_str(), &s2 ) != 0 )
+        boost::throw_exception( filesystem_error(
+          "boost::filesystem::equivalent",
+          ph2, fs::detail::system_error_code() ) );
+      return s1.st_dev == s2.st_dev;
 #   endif
     }
 
@@ -566,7 +587,7 @@
 #   else
       // by now, intmax_t is 64-bits on all Windows compilers
       WIN32_FILE_ATTRIBUTE_DATA fad;
-      if ( !::GetFileAttributesExA( ph.string().c_str(),
+      if ( !::GetFileAttributesEx( ph.string().c_str(),
         ::GetFileExInfoStandard, &fad ) )
         boost::throw_exception( filesystem_error(
           "boost::filesystem::file_size",
@@ -637,20 +658,9 @@
 #   ifdef BOOST_POSIX
         || symbolic_link_exists( ph ) ) // handle dangling symbolic links
       {
-#     if defined(__QNXNTO__) || (defined(__MSL__) && (defined(macintosh) || 
defined(__APPLE__) || defined(__APPLE_CC__)))
-        // Some Metrowerks C library versions fail on directories because of a
-        // known Metrowerks coding error in ::remove. Workaround is to call
-        // rmdir() or unlink() as indicated.
-        // Same bug reported for QNX; same fix.
-        if ( (is_directory( ph )
-          ? ::rmdir( ph.string().c_str() )
-          : ::unlink( ph.string().c_str() )) != 0 )
-#     else
         // note that the POSIX behavior for symbolic links is what we want;
         // the link rather than what it points to is deleted
         if ( std::remove( ph.string().c_str() ) != 0 )
-#     endif
-
         {
           int error = fs::detail::system_error_code();
           // POSIX says "If the directory is not an empty directory, rmdir()
@@ -703,23 +713,12 @@
           old_path, new_path, fs::detail::system_error_code() ) );
     }
 
-#ifdef BOOST_POSIX
-    namespace detail
-    {
-      void throw_copy_file_error( const path & from_file_ph,
-                    const path & to_file_ph )
-      {
-        boost::throw_exception( fs::filesystem_error(
-          "boost::filesystem::copy_file",
-          from_file_ph, to_file_ph, system_error_code() ) );
-      }
-    }
-#endif
-
     BOOST_FILESYSTEM_DECL void copy_file( const path & from_file_ph,
                     const path & to_file_ph )
     {
 #   ifdef BOOST_POSIX
+      // TODO: Ask POSIX experts if this is the best way to copy a file
+
       const std::size_t buf_sz = 32768;
       boost::scoped_array<char> buf( new char [buf_sz] );
       int infile=0, outfile=0;  // init quiets compiler warning
@@ -732,40 +731,27 @@
                               O_WRONLY | O_CREAT | O_EXCL,
                               from_stat.st_mode )) < 0 )
       {
-        if ( infile >= 0 ) ::close( infile );
-        detail::throw_copy_file_error( from_file_ph, to_file_ph );
+        if ( infile != 0 ) ::close( infile );
+        boost::throw_exception( filesystem_error(
+          "boost::filesystem::copy_file",
+          from_file_ph, to_file_ph, fs::detail::system_error_code() ) );
       }
 
-      ssize_t sz, sz_read=1, sz_write;
-      while ( sz_read > 0
-        && (sz_read = ::read( infile, buf.get(), buf_sz )) > 0 )
-      {
-        // Allow for partial writes - see Advanced Unix Programming (2nd Ed.),
-        // Marc Rochkind, Addison-Wesley, 2004, page 94
-        sz_write = 0;
-        do
-        {
-          if ( (sz = ::write( outfile, buf.get(), sz_read - sz_write )) < 0 )
-          { 
-            sz_read = sz; // cause read loop termination
-            break;        //  and error to be thrown after closes
-          }
-          sz_write += sz;
-        } while ( sz_write < sz_read );
-      }
+      ssize_t sz;
+      while ( (sz = ::read( infile, buf.get(), buf_sz )) > 0
+        && (sz = ::write( outfile, buf.get(), sz )) > 0 ) {}
 
-      if ( ::close( infile) < 0 ) sz_read = -1;
-      if ( ::close( outfile) < 0 ) sz_read = -1;
+      ::close( infile );
+      ::close( outfile );
 
-      if ( sz_read < 0 )
-        detail::throw_copy_file_error( from_file_ph, to_file_ph );
+      if ( sz != 0 )
 #   else
       if ( !::CopyFileA( from_file_ph.string().c_str(),
                       to_file_ph.string().c_str(), /*fail_if_exists=*/true ) )
-        boost::throw_exception( fs::filesystem_error(
-          "boost::filesystem::copy_file",
-          from_file_ph, to_file_ph, detail::system_error_code() ) );
 #   endif
+        boost::throw_exception( filesystem_error(
+          "boost::filesystem::copy_file",
+          from_file_ph, to_file_ph, fs::detail::system_error_code() ) );
     }
 
     BOOST_FILESYSTEM_DECL path current_path()
@@ -777,12 +763,7 @@
           buf( new char[static_cast<std::size_t>(path_max)] );
         if ( ::getcwd( buf.get(), static_cast<std::size_t>(path_max) ) == 0 )
         {
-          if ( errno != ERANGE
-// there is a bug in some versions of the Metrowerks C lib on the Mac: wrong 
errno set 
-#if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || 
defined(__APPLE_CC__))
-            && errno != 0
-#endif
-            )
+          if ( errno != ERANGE )
             boost::throw_exception(
               filesystem_error( "boost::filesystem::current_path", path(),
                 fs::detail::system_error_code() ) );

Reply via email to