📄 operations.cpp
字号:
// operations.cpp ----------------------------------------------------------//// Copyright 2002-2005 Beman Dawes// Copyright 2001 Dietmar Kuehl// Use, modification, and distribution is subject to the Boost Software// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy// at http://www.boost.org/LICENSE_1_0.txt)// See library home page at http://www.boost.org/libs/filesystem//----------------------------------------------------------------------------// // define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows// the library is being built (possibly exporting rather than importing code)#define BOOST_FILESYSTEM_SOURCE #define _POSIX_PTHREAD_SEMANTICS // Sun readdir_r() needs this// enable the XPG-compliant version of readdir_r() on AIX#if defined(_AIX)# define _LINUX_SOURCE_COMPAT#endif#if !(defined(__HP_aCC) && defined(_ILP32) && \ !defined(_STATVFS_ACPP_PROBLEMS_FIXED))#define _FILE_OFFSET_BITS 64 // at worst, these defines may have no effect,#endif#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.// for some compilers (CodeWarrior, for example), windows.h// is getting included by some other boost header, so do this early:#if !defined(_WIN32_WINNT)#define _WIN32_WINNT 0x0500 // Default to Windows 2K or later#endif#include <boost/filesystem/operations.hpp>#include <boost/scoped_array.hpp>#include <boost/throw_exception.hpp>#include <boost/detail/workaround.hpp>namespace fs = boost::filesystem;using boost::system::error_code;using boost::system::system_category;# if defined(BOOST_WINDOWS_API)# include <windows.h># if defined(__BORLANDC__) || defined(__MWERKS__)# if defined(__BORLANDC__) using std::time_t;# endif# include <utime.h># else# include <sys/utime.h># endif# else // BOOST_POSIX_API# include <sys/types.h># if !defined(__APPLE__) && !defined(__OpenBSD__)# include <sys/statvfs.h># define BOOST_STATVFS statvfs# define BOOST_STATVFS_F_FRSIZE vfs.f_frsize# else#ifdef __OpenBSD__# include <sys/param.h>#endif# include <sys/mount.h># define BOOST_STATVFS statfs# define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>( vfs.f_bsize )# endif# include <dirent.h># include <unistd.h># include <fcntl.h># include <utime.h># include "limits.h"# endif// BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in// dir_itr_increment. The config tests are placed here because some of the// macros being tested come from dirent.h.//// TODO: find out what macros indicate dirent::d_type present in more libraries# if defined(BOOST_WINDOWS_API) \ || defined(_DIRENT_HAVE_D_TYPE) // defined by GNU C library if d_type present# define BOOST_FILESYSTEM_STATUS_CACHE# endif#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_NAMESPACEnamespace std { using ::strcmp; using ::remove; using ::rename; }#endif// helpers -----------------------------------------------------------------//namespace{ const error_code ok; bool is_empty_directory( const std::string & dir_path ) { static const fs::directory_iterator end_itr; return fs::directory_iterator(fs::path(dir_path)) == end_itr; }#ifdef BOOST_WINDOWS_API // For Windows, the xxxA form of various function names is used to avoid// inadvertently getting wide forms of the functions. (The undecorated// forms are actually macros, so can misfire if the user has various// other macros defined. There was a bug report of this happening.) inline DWORD get_file_attributes( const char * ph ) { return ::GetFileAttributesA( ph ); }# ifndef BOOST_FILESYSTEM_NARROW_ONLY inline DWORD get_file_attributes( const wchar_t * ph ) { return ::GetFileAttributesW( ph ); } bool is_empty_directory( const std::wstring & dir_path ) { static const fs::wdirectory_iterator wend_itr; return fs::wdirectory_iterator(fs::wpath(dir_path)) == wend_itr; } inline BOOL get_file_attributes_ex( const wchar_t * ph, WIN32_FILE_ATTRIBUTE_DATA & fad ) { return ::GetFileAttributesExW( ph, ::GetFileExInfoStandard, &fad ); } HANDLE create_file( const wchar_t * ph, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ) { return ::CreateFileW( ph, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile ); } inline DWORD get_current_directory( DWORD sz, wchar_t * buf ) { return ::GetCurrentDirectoryW( sz, buf ); } inline bool set_current_directory( const wchar_t * buf ) { return ::SetCurrentDirectoryW( buf ) != 0 ; } inline bool get_free_disk_space( const std::wstring & ph, PULARGE_INTEGER avail, PULARGE_INTEGER total, PULARGE_INTEGER free ) { return ::GetDiskFreeSpaceExW( ph.c_str(), avail, total, free ) != 0; } inline std::size_t get_full_path_name( const std::wstring & ph, std::size_t len, wchar_t * buf, wchar_t ** p ) { return static_cast<std::size_t>( ::GetFullPathNameW( ph.c_str(), static_cast<DWORD>(len), buf, p )); } inline bool remove_directory( const std::wstring & ph ) { return ::RemoveDirectoryW( ph.c_str() ) != 0; } inline bool delete_file( const std::wstring & ph ) { return ::DeleteFileW( ph.c_str() ) != 0; } inline bool create_directory( const std::wstring & dir ) { return ::CreateDirectoryW( dir.c_str(), 0 ) != 0; }#if _WIN32_WINNT >= 0x500 inline bool create_hard_link( const std::wstring & to_ph, const std::wstring & from_ph ) { return ::CreateHardLinkW( from_ph.c_str(), to_ph.c_str(), 0 ) != 0; }#endif # endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY template< class String > fs::file_status status_template( const String & ph, error_code & ec ) { DWORD attr( get_file_attributes( ph.c_str() ) ); if ( attr == 0xFFFFFFFF ) { ec = error_code( ::GetLastError(), system_category ); if ((ec.value() == ERROR_FILE_NOT_FOUND) || (ec.value() == ERROR_PATH_NOT_FOUND) || (ec.value() == ERROR_INVALID_NAME) // "tools/jam/src/:sys:stat.h", "//foo" || (ec.value() == ERROR_INVALID_PARAMETER) // ":sys:stat.h" || (ec.value() == ERROR_BAD_PATHNAME) // "//nosuch" on Win64 || (ec.value() == ERROR_BAD_NETPATH)) // "//nosuch" on Win32 { ec = ok; // these are not considered errors; // the status is considered not found return fs::file_status( fs::file_not_found ); } else if ((ec.value() == ERROR_SHARING_VIOLATION)) { ec = ok; // these are not considered errors; // the file exists but the type is not known return fs::file_status( fs::type_unknown ); } return fs::file_status( fs::status_unknown ); } ec = ok;; return (attr & FILE_ATTRIBUTE_DIRECTORY) ? fs::file_status( fs::directory_file ) : fs::file_status( fs::regular_file ); } BOOL get_file_attributes_ex( const char * ph, WIN32_FILE_ATTRIBUTE_DATA & fad ) { return ::GetFileAttributesExA( ph, ::GetFileExInfoStandard, &fad ); } template< class String > boost::filesystem::detail::query_pair is_empty_template( const String & ph ) { WIN32_FILE_ATTRIBUTE_DATA fad; if ( get_file_attributes_ex( ph.c_str(), fad ) == 0 ) return std::make_pair( error_code( ::GetLastError(), system_category ), false ); return std::make_pair( ok, ( fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ? is_empty_directory( ph ) :( !fad.nFileSizeHigh && !fad.nFileSizeLow ) ); } HANDLE create_file( const char * ph, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ) { return ::CreateFileA( ph, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile ); } // Thanks to Jeremy Maitin-Shepard for much help and for permission to // base the equivalent() implementation on portions of his // file-equivalence-win32.cpp experimental code. struct handle_wrapper { HANDLE handle; handle_wrapper( HANDLE h ) : handle(h) {} ~handle_wrapper() { if ( handle != INVALID_HANDLE_VALUE ) ::CloseHandle(handle); } }; template< class String > boost::filesystem::detail::query_pair equivalent_template( const String & ph1, const String & ph2 ) { // Note well: Physical location on external media is part of the // equivalence criteria. If there are no open handles, physical location // can change due to defragmentation or other relocations. Thus handles // must be held open until location information for both paths has // been retrieved. handle_wrapper p1( create_file( ph1.c_str(), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ) ); int error1(0); // save error code in case we have to throw if ( p1.handle == INVALID_HANDLE_VALUE ) error1 = ::GetLastError(); handle_wrapper p2( create_file( ph2.c_str(), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ) ); if ( p1.handle == INVALID_HANDLE_VALUE || p2.handle == INVALID_HANDLE_VALUE ) { if ( p1.handle != INVALID_HANDLE_VALUE || p2.handle != INVALID_HANDLE_VALUE ) { return std::make_pair( ok, false ); } assert( p1.handle == INVALID_HANDLE_VALUE && p2.handle == INVALID_HANDLE_VALUE ); { return std::make_pair( error_code( error1, system_category), false ); } } // at this point, both handles are known to be valid BY_HANDLE_FILE_INFORMATION info1, info2; if ( !::GetFileInformationByHandle( p1.handle, &info1 ) ) { return std::make_pair( error_code( ::GetLastError(), system_category ), false ); } if ( !::GetFileInformationByHandle( p2.handle, &info2 ) ) { return std::make_pair( error_code( ::GetLastError(), system_category ), false ); } // 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 std::make_pair( ok, 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 ); } template< class String > boost::filesystem::detail::uintmax_pair file_size_template( const String & ph ) { WIN32_FILE_ATTRIBUTE_DATA fad; // by now, intmax_t is 64-bits on all Windows compilers if ( get_file_attributes_ex( ph.c_str(), fad ) == 0 ) return std::make_pair( error_code( ::GetLastError(), system_category ), 0 ); if ( (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0 ) return std::make_pair( error_code( ERROR_FILE_NOT_FOUND, system_category), 0 ); return std::make_pair( ok, (static_cast<boost::uintmax_t>(fad.nFileSizeHigh) << (sizeof(fad.nFileSizeLow)*8)) + fad.nFileSizeLow ); } inline bool get_free_disk_space( const std::string & ph,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -