diff options
author | Remko Tronçon <git@el-tramo.be> | 2012-12-23 13:16:26 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2012-12-23 14:43:26 (GMT) |
commit | 491ddd570a752cf9bda85933bed0c6942e39b1f9 (patch) | |
tree | 10c25c1be8cc08d0497df1dccd56a10fbb30beee /3rdParty/Boost/src/libs/filesystem/v3/src/operations.cpp | |
parent | da7d7a0ca71b80281aa9ff2526290b61ccb0cc60 (diff) | |
download | swift-491ddd570a752cf9bda85933bed0c6942e39b1f9.zip swift-491ddd570a752cf9bda85933bed0c6942e39b1f9.tar.bz2 |
Update Boost to 1.52.0.
Change-Id: I1e56bea2600bf2ed9c5b3aba8c4f9d2a0f350e77
Diffstat (limited to '3rdParty/Boost/src/libs/filesystem/v3/src/operations.cpp')
-rw-r--r-- | 3rdParty/Boost/src/libs/filesystem/v3/src/operations.cpp | 1975 |
1 files changed, 0 insertions, 1975 deletions
diff --git a/3rdParty/Boost/src/libs/filesystem/v3/src/operations.cpp b/3rdParty/Boost/src/libs/filesystem/v3/src/operations.cpp deleted file mode 100644 index 2460c1d..0000000 --- a/3rdParty/Boost/src/libs/filesystem/v3/src/operations.cpp +++ /dev/null @@ -1,1975 +0,0 @@ -// operations.cpp --------------------------------------------------------------------// - -// Copyright 2002-2009 Beman Dawes -// Copyright 2001 Dietmar Kuehl - -// Distributed under the Boost Software License, Version 1.0. -// See http://www.boost.org/LICENSE_1_0.txt - -// See library home page at http://www.boost.org/libs/filesystem - -//--------------------------------------------------------------------------------------// - -#include <boost/config.hpp> -#if !defined( BOOST_NO_STD_WSTRING ) -// Boost.Filesystem V3 and later requires std::wstring support. -// During the transition to V3, libraries are compiled with both V2 and V3 sources. -// On old compilers that don't support V3 anyhow, we just skip everything so the compile -// will succeed and the library can be built. - -// 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 - -#ifndef BOOST_SYSTEM_NO_DEPRECATED -# define BOOST_SYSTEM_NO_DEPRECATED -#endif - -#ifndef _POSIX_PTHREAD_SEMANTICS -# define _POSIX_PTHREAD_SEMANTICS // Sun readdir_r()needs this -#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 -#if !defined(__PGI) -#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. -#else -#define _FILE_OFFSET_BITS 64 -#endif - -#include <boost/filesystem/v3/operations.hpp> -#include <boost/scoped_array.hpp> -#include <boost/detail/workaround.hpp> -#include <cstdlib> // for malloc, free -#include <vector> - -#ifdef BOOST_FILEYSTEM_INCLUDE_IOSTREAM -# include <iostream> -#endif - -namespace fs = boost::filesystem3; -using boost::filesystem3::path; -using boost::filesystem3::filesystem_error; -using boost::system::error_code; -using boost::system::error_category; -using boost::system::system_category; -using std::string; -using std::wstring; - -# ifdef 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" - -# else // BOOST_WINDOW_API - -# if (defined(__MINGW32__) || defined(__CYGWIN__)) && !defined(WINVER) - // Versions of MinGW or Cygwin that support Filesystem V3 support at least WINVER 0x501. - // See MinGW's windef.h -# define WINVER 0x501 -# endif -# include <windows.h> -# include <winnt.h> -# if !defined(_WIN32_WINNT) -# define _WIN32_WINNT 0x0500 -# endif -# if defined(__BORLANDC__) || defined(__MWERKS__) -# if defined(__BORLANDC__) - using std::time_t; -# endif -# include <utime.h> -# else -# include <sys/utime.h> -# endif - -// REPARSE_DATA_BUFFER related definitions are found in ntifs.h, which is part of the -// Windows Device Driver Kit. Since that's inconvenient, the definitions are provided -// here. See http://msdn.microsoft.com/en-us/library/ms791514.aspx - -#if !defined(REPARSE_DATA_BUFFER_HEADER_SIZE) // mingw winnt.h does provide the defs - -#define SYMLINK_FLAG_RELATIVE 1 - -typedef struct _REPARSE_DATA_BUFFER { - ULONG ReparseTag; - USHORT ReparseDataLength; - USHORT Reserved; - union { - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - ULONG Flags; - WCHAR PathBuffer[1]; - /* Example of distinction between substitute and print names: - mklink /d ldrive c:\ - SubstituteName: c:\\??\ - PrintName: c:\ - */ - } SymbolicLinkReparseBuffer; - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - WCHAR PathBuffer[1]; - } MountPointReparseBuffer; - struct { - UCHAR DataBuffer[1]; - } GenericReparseBuffer; - }; -} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; - -#define REPARSE_DATA_BUFFER_HEADER_SIZE \ - FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) - -#endif - -#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE -#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 ) -#endif - -# ifndef FSCTL_GET_REPARSE_POINT -# define FSCTL_GET_REPARSE_POINT 0x900a8 -# endif - -# ifndef IO_REPARSE_TAG_SYMLINK -# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) -# endif - -# endif // BOOST_WINDOWS_API - -// 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 - -// POSIX/Windows macros ----------------------------------------------------// - -// Portions of the POSIX and Windows API's are very similar, except for name, -// order of arguments, and meaning of zero/non-zero returns. The macros below -// abstract away those differences. They follow Windows naming and order of -// arguments, and return true to indicate no error occurred. [POSIX naming, -// order of arguments, and meaning of return were followed initially, but -// found to be less clear and cause more coding errors.] - -# if defined(BOOST_POSIX_API) - -// POSIX uses a 0 return to indicate success -# define BOOST_ERRNO errno -# define BOOST_SET_CURRENT_DIRECTORY(P)(::chdir(P)== 0) -# define BOOST_CREATE_DIRECTORY(P)(::mkdir(P, S_IRWXU|S_IRWXG|S_IRWXO)== 0) -# define BOOST_CREATE_HARD_LINK(F,T)(::link(T, F)== 0) -# define BOOST_CREATE_SYMBOLIC_LINK(F,T,Flag)(::symlink(T, F)== 0) -# define BOOST_REMOVE_DIRECTORY(P)(::rmdir(P)== 0) -# define BOOST_DELETE_FILE(P)(::unlink(P)== 0) -# define BOOST_COPY_DIRECTORY(F,T)(!(::stat(from.c_str(), &from_stat)!= 0\ - || ::mkdir(to.c_str(),from_stat.st_mode)!= 0)) -# define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool) -# define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0) -# define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0) - -# define BOOST_ERROR_NOT_SUPPORTED ENOSYS -# define BOOST_ERROR_ALREADY_EXISTS EEXIST - -# else // BOOST_WINDOWS_API - -// Windows uses a non-0 return to indicate success -# define BOOST_ERRNO ::GetLastError() -# define BOOST_SET_CURRENT_DIRECTORY(P)(::SetCurrentDirectoryW(P)!= 0) -# define BOOST_CREATE_DIRECTORY(P)(::CreateDirectoryW(P, 0)!= 0) -# define BOOST_CREATE_HARD_LINK(F,T)(create_hard_link_api(F, T, 0)!= 0) -# define BOOST_CREATE_SYMBOLIC_LINK(F,T,Flag)(create_symbolic_link_api(F, T, Flag)!= 0) -# define BOOST_REMOVE_DIRECTORY(P)(::RemoveDirectoryW(P)!= 0) -# define BOOST_DELETE_FILE(P)(::DeleteFileW(P)!= 0) -# define BOOST_COPY_DIRECTORY(F,T)(::CreateDirectoryExW(F, T, 0)!= 0) -# define BOOST_COPY_FILE(F,T,FailIfExistsBool)(::CopyFileW(F, T, FailIfExistsBool)!= 0) -# define BOOST_MOVE_FILE(OLD,NEW)(::MoveFileExW(OLD, NEW, MOVEFILE_REPLACE_EXISTING)!= 0) -# define BOOST_RESIZE_FILE(P,SZ)(resize_file_api(P, SZ)!= 0) -# define BOOST_READ_SYMLINK(P,T) - -# define BOOST_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS -# define BOOST_ERROR_NOT_SUPPORTED ERROR_NOT_SUPPORTED - -# endif - -//--------------------------------------------------------------------------------------// -// // -// helpers (all operating systems) // -// // -//--------------------------------------------------------------------------------------// - -namespace -{ - -# ifdef BOOST_POSIX_API - const char dot = '.'; -# else - const wchar_t dot = L'.'; -# endif - - fs::file_type query_file_type(const path& p, error_code* ec); - - boost::filesystem3::directory_iterator end_dir_itr; - - const std::size_t buf_size(128); - const error_code ok; - - bool error(bool was_error, error_code* ec, const string& message) - { - if (!was_error) - { - if (ec != 0) ec->clear(); - } - else - { // error - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error(message, - error_code(BOOST_ERRNO, system_category()))); - else - ec->assign(BOOST_ERRNO, system_category()); - } - return was_error; - } - - bool error(bool was_error, const path& p, error_code* ec, const string& message) - { - if (!was_error) - { - if (ec != 0) ec->clear(); - } - else - { // error - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error(message, - p, error_code(BOOST_ERRNO, system_category()))); - else - ec->assign(BOOST_ERRNO, system_category()); - } - return was_error; - } - - bool error(bool was_error, const path& p1, const path& p2, error_code* ec, - const string& message) - { - if (!was_error) - { - if (ec != 0) ec->clear(); - } - else - { // error - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error(message, - p1, p2, error_code(BOOST_ERRNO, system_category()))); - else - ec->assign(BOOST_ERRNO, system_category()); - } - return was_error; - } - - bool error(bool was_error, const error_code& result, - const path& p, error_code* ec, const string& message) - // Overwrites ec if there has already been an error - { - if (!was_error) - { - if (ec != 0) ec->clear(); - } - else - { // error - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error(message, p, result)); - else - *ec = result; - } - return was_error; - } - - bool error(bool was_error, const error_code& result, - const path& p1, const path& p2, error_code* ec, const string& message) - // Overwrites ec if there has already been an error - { - if (!was_error) - { - if (ec != 0) ec->clear(); - } - else - { // error - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error(message, p1, p2, result)); - else - *ec = result; - } - return was_error; - } - - bool is_empty_directory(const path& p) - { - return fs::directory_iterator(p)== end_dir_itr; - } - - bool remove_directory(const path& p) // true if succeeds - { return BOOST_REMOVE_DIRECTORY(p.c_str()); } - - bool remove_file(const path& p) // true if succeeds - { return BOOST_DELETE_FILE(p.c_str()); } - - // called by remove and remove_all_aux - bool remove_file_or_directory(const path& p, fs::file_type type, error_code* ec) - // return true if file removed, false if not removed - { - if (type == fs::file_not_found) - { - if (ec != 0) ec->clear(); - return false; - } - - if (type == fs::directory_file -# ifdef BOOST_WINDOWS_API - || type == fs::_detail_directory_symlink -# endif - ) - { - if (error(!remove_directory(p), p, ec, "boost::filesystem::remove")) - return false; - } - else - { - if (error(!remove_file(p), p, ec, "boost::filesystem::remove")) - return false; - } - return true; - } - - boost::uintmax_t remove_all_aux(const path& p, fs::file_type type, - error_code* ec) - { - boost::uintmax_t count = 1; - - if (type == fs::directory_file) // but not a directory symlink - { - for (fs::directory_iterator itr(p); - itr != end_dir_itr; ++itr) - { - fs::file_type tmp_type = query_file_type(itr->path(), ec); - if (ec != 0 && *ec) - return count; - count += remove_all_aux(itr->path(), tmp_type, ec); - } - } - remove_file_or_directory(p, type, ec); - return count; - } - -#ifdef BOOST_POSIX_API - -//--------------------------------------------------------------------------------------// -// // -// POSIX-specific helpers // -// // -//--------------------------------------------------------------------------------------// - - bool not_found_error(int errval) - { - return errno == ENOENT || errno == ENOTDIR; - } - - bool // true if ok - copy_file_api(const std::string& from_p, - const std::string& to_p, bool fail_if_exists) - { - const std::size_t buf_sz = 32768; - boost::scoped_array<char> buf(new char [buf_sz]); - int infile=-1, outfile=-1; // -1 means not open - - // bug fixed: code previously did a stat()on the from_file first, but that - // introduced a gratuitous race condition; the stat()is now done after the open() - - if ((infile = ::open(from_p.c_str(), O_RDONLY))< 0) - { return false; } - - struct stat from_stat; - if (::stat(from_p.c_str(), &from_stat)!= 0) - { return false; } - - int oflag = O_CREAT | O_WRONLY | O_TRUNC; - if (fail_if_exists) - oflag |= O_EXCL; - if ((outfile = ::open(to_p.c_str(), oflag, from_stat.st_mode))< 0) - { - int open_errno = errno; - BOOST_ASSERT(infile >= 0); - ::close(infile); - errno = open_errno; - return false; - } - - 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_write, - 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); - } - - if (::close(infile)< 0)sz_read = -1; - if (::close(outfile)< 0)sz_read = -1; - - return sz_read >= 0; - } - - inline fs::file_type query_file_type(const path& p, error_code* ec) - { - return fs::detail::symlink_status(p, ec).type(); - } - -# else - -//--------------------------------------------------------------------------------------// -// // -// Windows-specific helpers // -// // -//--------------------------------------------------------------------------------------// - - bool not_found_error(int errval) - { - return errval == ERROR_FILE_NOT_FOUND - || errval == ERROR_PATH_NOT_FOUND - || errval == ERROR_INVALID_NAME // "tools/jam/src/:sys:stat.h", "//foo" - || errval == ERROR_INVALID_DRIVE // USB card reader with no card inserted - || errval == ERROR_NOT_READY // CD/DVD drive with no disc inserted - || errval == ERROR_INVALID_PARAMETER // ":sys:stat.h" - || errval == ERROR_BAD_PATHNAME // "//nosuch" on Win64 - || errval == ERROR_BAD_NETPATH; // "//nosuch" on Win32 - } - - // these constants come from inspecting some Microsoft sample code - std::time_t to_time_t(const FILETIME & ft) - { - __int64 t = (static_cast<__int64>(ft.dwHighDateTime)<< 32) - + ft.dwLowDateTime; -# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // > VC++ 7.0 - t -= 116444736000000000LL; -# else - t -= 116444736000000000; -# endif - t /= 10000000; - return static_cast<std::time_t>(t); - } - - void to_FILETIME(std::time_t t, FILETIME & ft) - { - __int64 temp = t; - temp *= 10000000; -# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // > VC++ 7.0 - temp += 116444736000000000LL; -# else - temp += 116444736000000000; -# endif - ft.dwLowDateTime = static_cast<DWORD>(temp); - ft.dwHighDateTime = static_cast<DWORD>(temp >> 32); - } - - // 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); - } - }; - - HANDLE create_file_handle(const path& p, DWORD dwDesiredAccess, - DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, - HANDLE hTemplateFile) - { - return ::CreateFileW(p.c_str(), dwDesiredAccess, dwShareMode, - lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, - hTemplateFile); - } - - bool is_reparse_point_a_symlink(const path& p) - { - handle_wrapper h(create_file_handle(p, FILE_READ_EA, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL)); - if (h.handle == INVALID_HANDLE_VALUE) - return false; - - boost::scoped_array<char> buf(new char [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]); - - // Query the reparse data - DWORD dwRetLen; - BOOL result = ::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(), - MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRetLen, NULL); - if (!result) return false; - - return reinterpret_cast<const REPARSE_DATA_BUFFER*>(buf.get()) - ->ReparseTag == IO_REPARSE_TAG_SYMLINK; - } - - inline std::size_t get_full_path_name( - const path& src, std::size_t len, wchar_t* buf, wchar_t** p) - { - return static_cast<std::size_t>( - ::GetFullPathNameW(src.c_str(), static_cast<DWORD>(len), buf, p)); - } - - fs::file_status process_status_failure(const path& p, error_code* ec) - { - int errval(::GetLastError()); - if (ec != 0) // always report errval, even though some - ec->assign(errval, system_category()); // errval values are not status_errors - - if (not_found_error(errval)) - { - return fs::file_status(fs::file_not_found); - } - else if ((errval == ERROR_SHARING_VIOLATION)) - { - return fs::file_status(fs::type_unknown); - } - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status", - p, error_code(errval, system_category()))); - return fs::file_status(fs::status_error); - } - - // differs from symlink_status() in that directory symlinks are reported as - // _detail_directory_symlink, as required on Windows by remove() and its helpers. - fs::file_type query_file_type(const path& p, error_code* ec) - { - DWORD attr(::GetFileAttributesW(p.c_str())); - if (attr == 0xFFFFFFFF) - { - return process_status_failure(p, ec).type(); - } - - if (ec != 0) ec->clear(); - - if (attr & FILE_ATTRIBUTE_REPARSE_POINT) - { - if (is_reparse_point_a_symlink(p)) - return (attr & FILE_ATTRIBUTE_DIRECTORY) - ? fs::_detail_directory_symlink - : fs::symlink_file; - return fs::reparse_file; - } - - return (attr & FILE_ATTRIBUTE_DIRECTORY) - ? fs::directory_file - : fs::regular_file; - } - - BOOL resize_file_api(const wchar_t* p, boost::uintmax_t size) - { - HANDLE handle = CreateFileW(p, GENERIC_WRITE, 0, 0, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, 0); - LARGE_INTEGER sz; - sz.QuadPart = size; - return handle != INVALID_HANDLE_VALUE - && ::SetFilePointerEx(handle, sz, 0, FILE_BEGIN) - && ::SetEndOfFile(handle) - && ::CloseHandle(handle); - } - - // Windows kernel32.dll functions that may or may not be present - // must be accessed through pointers - - typedef BOOL (WINAPI *PtrCreateHardLinkW)( - /*__in*/ LPCWSTR lpFileName, - /*__in*/ LPCWSTR lpExistingFileName, - /*__reserved*/ LPSECURITY_ATTRIBUTES lpSecurityAttributes - ); - - PtrCreateHardLinkW create_hard_link_api = PtrCreateHardLinkW( - ::GetProcAddress( - ::GetModuleHandle(TEXT("kernel32.dll")), "CreateHardLinkW")); - - typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)( - /*__in*/ LPCWSTR lpSymlinkFileName, - /*__in*/ LPCWSTR lpTargetFileName, - /*__in*/ DWORD dwFlags - ); - - PtrCreateSymbolicLinkW create_symbolic_link_api = PtrCreateSymbolicLinkW( - ::GetProcAddress( - ::GetModuleHandle(TEXT("kernel32.dll")), "CreateSymbolicLinkW")); - -#endif - -//#ifdef BOOST_WINDOWS_API -// -// -// 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; } -// -//#endif - -} // unnamed namespace - -//--------------------------------------------------------------------------------------// -// // -// operations functions declared in operations.hpp // -// in alphabetic order // -// // -//--------------------------------------------------------------------------------------// - -namespace boost -{ -namespace filesystem3 -{ - - BOOST_FILESYSTEM_DECL - path absolute(const path& p, const path& base) - { -// if ( p.empty() || p.is_absolute() ) -// return p; -// // recursively calling absolute is sub-optimal, but is simple -// path abs_base(base.is_absolute() ? base : absolute(base)); -//# ifdef BOOST_WINDOWS_API -// if (p.has_root_directory()) -// return abs_base.root_name() / p; -// // !p.has_root_directory -// if (p.has_root_name()) -// return p.root_name() -// / abs_base.root_directory() / abs_base.relative_path() / p.relative_path(); -// // !p.has_root_name() -//# endif -// return abs_base / p; - - // recursively calling absolute is sub-optimal, but is sure and simple - path abs_base(base.is_absolute() ? base : absolute(base)); - - // store expensive to compute values that are needed multiple times - path p_root_name (p.root_name()); - path base_root_name (abs_base.root_name()); - path p_root_directory (p.root_directory()); - - if (p.empty()) - return abs_base; - - if (!p_root_name.empty()) // p.has_root_name() - { - if (p_root_directory.empty()) // !p.has_root_directory() - return p_root_name / abs_base.root_directory() - / abs_base.relative_path() / p.relative_path(); - // p is absolute, so fall through to return p at end of block - } - - else if (!p_root_directory.empty()) // p.has_root_directory() - { -# ifdef BOOST_POSIX_API - // POSIX can have root name it it is a network path - if (base_root_name.empty()) // !abs_base.has_root_name() - return p; -# endif - return base_root_name / p; - } - - else - { - return abs_base / p; - } - - return p; // p.is_absolute() is true - } - -namespace detail -{ - BOOST_FILESYSTEM_DECL bool possible_large_file_size_support() - { -# ifdef BOOST_POSIX_API - struct stat lcl_stat; - return sizeof(lcl_stat.st_size)> 4; -# else - return true; -# endif - } - - BOOST_FILESYSTEM_DECL - void copy(const path& from, const path& to, system::error_code* ec) - { - file_status s(symlink_status(from, *ec)); - if (ec != 0 && *ec) return; - - if(is_symlink(s)) - { - copy_symlink(from, to, *ec); - } - else if(is_directory(s)) - { - copy_directory(from, to, *ec); - } - else if(is_regular_file(s)) - { - copy_file(from, to, copy_option::fail_if_exists, *ec); - } - else - { - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::copy", - from, to, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()))); - ec->assign(BOOST_ERROR_NOT_SUPPORTED, system_category()); - } - } - - BOOST_FILESYSTEM_DECL - void copy_directory(const path& from, const path& to, system::error_code* ec) - { -# ifdef BOOST_POSIX_API - struct stat from_stat; -# endif - error(!BOOST_COPY_DIRECTORY(from.c_str(), to.c_str()), - from, to, ec, "boost::filesystem::copy_directory"); - } - - BOOST_FILESYSTEM_DECL - void copy_file(const path& from, const path& to, - BOOST_SCOPED_ENUM(copy_option)option, - error_code* ec) - { - error(!BOOST_COPY_FILE(from.c_str(), to.c_str(), - option == copy_option::fail_if_exists), - from, to, ec, "boost::filesystem::copy_file"); - } - - BOOST_FILESYSTEM_DECL - void copy_symlink(const path& existing_symlink, const path& new_symlink, - system::error_code* ec) - { -# if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600 - error(true, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), - new_symlink, existing_symlink, ec, - "boost::filesystem::copy_symlink"); - -# else // modern Windows or BOOST_POSIX_API - path p(read_symlink(existing_symlink, ec)); - if (ec != 0 && *ec) return; - create_symlink(p, new_symlink, ec); - -# endif - } - - BOOST_FILESYSTEM_DECL - bool create_directories(const path& p, system::error_code* ec) - { - if (p.empty() || exists(p)) - { - if (!p.empty() && !is_directory(p)) - { - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error( - "boost::filesystem::create_directories", p, - error_code(system::errc::file_exists, system::generic_category()))); - else ec->assign(system::errc::file_exists, system::generic_category()); - } - return false; - } - - // First create branch, by calling ourself recursively - create_directories(p.parent_path(), ec); - // Now that parent's path exists, create the directory - create_directory(p, ec); - return true; - } - - BOOST_FILESYSTEM_DECL - bool create_directory(const path& p, error_code* ec) - { - if (BOOST_CREATE_DIRECTORY(p.c_str())) - { - if (ec != 0) ec->clear(); - return true; - } - - // attempt to create directory failed - int errval(BOOST_ERRNO); // save reason for failure - error_code dummy; - if (errval == BOOST_ERROR_ALREADY_EXISTS && is_directory(p, dummy)) - { - if (ec != 0) ec->clear(); - return false; - } - - // attempt to create directory failed && it doesn't already exist - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directory", - p, error_code(errval, system_category()))); - else - ec->assign(errval, system_category()); - return false; - } - - BOOST_FILESYSTEM_DECL - void create_directory_symlink(const path& to, const path& from, - system::error_code* ec) - { -# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008 - - error(true, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), to, from, ec, - "boost::filesystem::create_directory_symlink"); -# else - -# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600 - // see if actually supported by Windows runtime dll - if (error(!create_symbolic_link_api, - error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), - to, from, ec, - "boost::filesystem::create_directory_symlink")) - return; -# endif - - error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(), SYMBOLIC_LINK_FLAG_DIRECTORY), - to, from, ec, "boost::filesystem::create_directory_symlink"); -# endif - } - - BOOST_FILESYSTEM_DECL - void create_hard_link(const path& to, const path& from, error_code* ec) - { - -# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0500 // SDK earlier than Win 2K - - error(true, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), to, from, ec, - "boost::filesystem::create_hard_link"); -# else - -# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0500 - // see if actually supported by Windows runtime dll - if (error(!create_hard_link_api, - error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), - to, from, ec, - "boost::filesystem::create_hard_link")) - return; -# endif - - error(!BOOST_CREATE_HARD_LINK(from.c_str(), to.c_str()), to, from, ec, - "boost::filesystem::create_hard_link"); -# endif - } - - BOOST_FILESYSTEM_DECL - void create_symlink(const path& to, const path& from, error_code* ec) - { -# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008 - error(true, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), to, from, ec, - "boost::filesystem::create_directory_symlink"); -# else - -# if defined(BOOST_WINDOWS_API) && _WIN32_WINNT >= 0x0600 - // see if actually supported by Windows runtime dll - if (error(!create_symbolic_link_api, - error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), - to, from, ec, - "boost::filesystem::create_symlink")) - return; -# endif - - error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(), 0), - to, from, ec, "boost::filesystem::create_symlink"); -# endif - } - - BOOST_FILESYSTEM_DECL - path current_path(error_code* ec) - { -# ifdef BOOST_POSIX_API - path cur; - for (long path_max = 128;; path_max *=2)// loop 'til buffer large enough - { - boost::scoped_array<char> - buf(new char[static_cast<std::size_t>(path_max)]); - if (::getcwd(buf.get(), static_cast<std::size_t>(path_max))== 0) - { - if (error(errno != ERANGE - // 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 - , ec, "boost::filesystem::current_path")) - { - break; - } - } - else - { - cur = buf.get(); - if (ec != 0) ec->clear(); - break; - } - } - return cur; - -# else - DWORD sz; - if ((sz = ::GetCurrentDirectoryW(0, NULL))== 0)sz = 1; - boost::scoped_array<path::value_type> buf(new path::value_type[sz]); - error(::GetCurrentDirectoryW(sz, buf.get())== 0, ec, - "boost::filesystem::current_path"); - return path(buf.get()); -# endif - } - - - BOOST_FILESYSTEM_DECL - void current_path(const path& p, system::error_code* ec) - { - error(!BOOST_SET_CURRENT_DIRECTORY(p.c_str()), - p, ec, "boost::filesystem::current_path"); - } - - BOOST_FILESYSTEM_DECL - bool equivalent(const path& p1, const path& p2, system::error_code* ec) - { -# ifdef BOOST_POSIX_API - struct stat s2; - int e2(::stat(p2.c_str(), &s2)); - struct stat s1; - int e1(::stat(p1.c_str(), &s1)); - - if (e1 != 0 || e2 != 0) - { - // if one is invalid and the other isn't then they aren't equivalent, - // but if both are invalid then it is an error - error (e1 != 0 && e2 != 0, p1, p2, ec, "boost::filesystem::equivalent"); - return false; - } - - // both stats now known to be valid - return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino - // According to the POSIX stat specs, "The st_ino and st_dev fields - // taken together uniquely identify the file within the system." - // Just to be sure, size and mod time are also checked. - && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime; - -# else // Windows - - // 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. - - // p2 is done first, so any error reported is for p1 - handle_wrapper h2( - create_file_handle( - p2.c_str(), - 0, - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - 0, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - 0)); - - handle_wrapper h1( - create_file_handle( - p1.c_str(), - 0, - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - 0, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - 0)); - - if (h1.handle == INVALID_HANDLE_VALUE - || h2.handle == INVALID_HANDLE_VALUE) - { - // if one is invalid and the other isn't, then they aren't equivalent, - // but if both are invalid then it is an error - error(h1.handle == INVALID_HANDLE_VALUE - && h2.handle == INVALID_HANDLE_VALUE, p1, p2, ec, - "boost::filesystem::equivalent"); - return false; - } - - // at this point, both handles are known to be valid - - BY_HANDLE_FILE_INFORMATION info1, info2; - - if (error(!::GetFileInformationByHandle(h1.handle, &info1), - p1, p2, ec, "boost::filesystem::equivalent")) - return false; - - if (error(!::GetFileInformationByHandle(h2.handle, &info2), - p1, p2, ec, "boost::filesystem::equivalent")) - return 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 - 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; - -# endif - } - - BOOST_FILESYSTEM_DECL - boost::uintmax_t file_size(const path& p, error_code* ec) - { -# ifdef BOOST_POSIX_API - - struct stat path_stat; - if (error(::stat(p.c_str(), &path_stat)!= 0, - p, ec, "boost::filesystem::file_size")) - return static_cast<boost::uintmax_t>(-1); - if (error(!S_ISREG(path_stat.st_mode), - error_code(EPERM, system_category()), - p, ec, "boost::filesystem::file_size")) - return static_cast<boost::uintmax_t>(-1); - - return static_cast<boost::uintmax_t>(path_stat.st_size); - -# else // Windows - - // assume uintmax_t is 64-bits on all Windows compilers - - WIN32_FILE_ATTRIBUTE_DATA fad; - - if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0, - p, ec, "boost::filesystem::file_size")) - return static_cast<boost::uintmax_t>(-1); - - if (error((fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!= 0, - error_code(ERROR_NOT_SUPPORTED, system_category()), - p, ec, "boost::filesystem::file_size")) - return static_cast<boost::uintmax_t>(-1); - - return (static_cast<boost::uintmax_t>(fad.nFileSizeHigh) - << (sizeof(fad.nFileSizeLow)*8)) + fad.nFileSizeLow; -# endif - } - - BOOST_FILESYSTEM_DECL - boost::uintmax_t hard_link_count(const path& p, system::error_code* ec) - { -# ifdef BOOST_POSIX_API - - struct stat path_stat; - return error(::stat(p.c_str(), &path_stat)!= 0, - p, ec, "boost::filesystem::hard_link_count") - ? 0 - : static_cast<boost::uintmax_t>(path_stat.st_nlink); - -# else // Windows - - // Link count info is only available through GetFileInformationByHandle - BY_HANDLE_FILE_INFORMATION info; - handle_wrapper h( - create_file_handle(p.c_str(), 0, - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); - return - !error(h.handle == INVALID_HANDLE_VALUE, - p, ec, "boost::filesystem::hard_link_count") - && !error(::GetFileInformationByHandle(h.handle, &info)== 0, - p, ec, "boost::filesystem::hard_link_count") - ? info.nNumberOfLinks - : 0; -# endif - } - - BOOST_FILESYSTEM_DECL - path initial_path(error_code* ec) - { - static path init_path; - if (init_path.empty()) - init_path = current_path(ec); - else if (ec != 0) ec->clear(); - return init_path; - } - - BOOST_FILESYSTEM_DECL - bool is_empty(const path& p, system::error_code* ec) - { -# ifdef BOOST_POSIX_API - - struct stat path_stat; - if (error(::stat(p.c_str(), &path_stat)!= 0, - p, ec, "boost::filesystem::is_empty")) - return false; - return S_ISDIR(path_stat.st_mode) - ? is_empty_directory(p) - : path_stat.st_size == 0; -# else - - WIN32_FILE_ATTRIBUTE_DATA fad; - if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0, - p, ec, "boost::filesystem::is_empty")) - return false; - - if (ec != 0) ec->clear(); - return - (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - ? is_empty_directory(p) - : (!fad.nFileSizeHigh && !fad.nFileSizeLow); -# endif - } - - BOOST_FILESYSTEM_DECL - std::time_t last_write_time(const path& p, system::error_code* ec) - { -# ifdef BOOST_POSIX_API - - struct stat path_stat; - if (error(::stat(p.c_str(), &path_stat)!= 0, - p, ec, "boost::filesystem::last_write_time")) - return std::time_t(-1); - return path_stat.st_mtime; - -# else - - handle_wrapper hw( - create_file_handle(p.c_str(), 0, - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); - - if (error(hw.handle == INVALID_HANDLE_VALUE, - p, ec, "boost::filesystem::last_write_time")) - return std::time_t(-1); - - FILETIME lwt; - - if (error(::GetFileTime(hw.handle, 0, 0, &lwt)== 0, - p, ec, "boost::filesystem::last_write_time")) - return std::time_t(-1); - - return to_time_t(lwt); -# endif - } - - BOOST_FILESYSTEM_DECL - void last_write_time(const path& p, const std::time_t new_time, - system::error_code* ec) - { -# ifdef BOOST_POSIX_API - - struct stat path_stat; - if (error(::stat(p.c_str(), &path_stat)!= 0, - p, ec, "boost::filesystem::last_write_time")) - return; - ::utimbuf buf; - buf.actime = path_stat.st_atime; // utime()updates access time too:-( - buf.modtime = new_time; - error(::utime(p.c_str(), &buf)!= 0, - p, ec, "boost::filesystem::last_write_time"); - -# else - - handle_wrapper hw( - create_file_handle(p.c_str(), FILE_WRITE_ATTRIBUTES, - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); - - if (error(hw.handle == INVALID_HANDLE_VALUE, - p, ec, "boost::filesystem::last_write_time")) - return; - - FILETIME lwt; - to_FILETIME(new_time, lwt); - - error(::SetFileTime(hw.handle, 0, 0, &lwt)== 0, - p, ec, "boost::filesystem::last_write_time"); -# endif - } - - BOOST_FILESYSTEM_DECL - path read_symlink(const path& p, system::error_code* ec) - { - path symlink_path; - -# ifdef BOOST_POSIX_API - - for (std::size_t path_max = 64;; path_max *= 2)// loop 'til buffer large enough - { - boost::scoped_array<char> buf(new char[path_max]); - ssize_t result; - if ((result=::readlink(p.c_str(), buf.get(), path_max))== -1) - { - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::read_symlink", - p, error_code(errno, system_category()))); - else ec->assign(errno, system_category()); - break; - } - else - { - if(result != static_cast<ssize_t>(path_max)) - { - symlink_path.assign(buf.get(), buf.get() + result); - if (ec != 0) ec->clear(); - break; - } - } - } - -# elif _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008 - error(true, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), p, ec, - "boost::filesystem::read_symlink"); -# else // Vista and Server 2008 SDK, or later - - union info_t - { - char buf[REPARSE_DATA_BUFFER_HEADER_SIZE+MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER rdb; - } info; - - handle_wrapper h( - create_file_handle(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0)); - - if (error(h.handle == INVALID_HANDLE_VALUE, p, ec, "boost::filesystem::read_symlink")) - return symlink_path; - - DWORD sz; - - if (!error(::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, - 0, 0, info.buf, sizeof(info), &sz, 0) == 0, p, ec, - "boost::filesystem::read_symlink" )) - symlink_path.assign( - static_cast<wchar_t*>(info.rdb.SymbolicLinkReparseBuffer.PathBuffer) - + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t), - static_cast<wchar_t*>(info.rdb.SymbolicLinkReparseBuffer.PathBuffer) - + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(wchar_t) - + info.rdb.SymbolicLinkReparseBuffer.PrintNameLength/sizeof(wchar_t)); -# endif - return symlink_path; - } - - BOOST_FILESYSTEM_DECL - bool remove(const path& p, error_code* ec) - { - error_code tmp_ec; - file_type type = query_file_type(p, &tmp_ec); - if (error(type == status_error, tmp_ec, p, ec, - "boost::filesystem::remove")) - return false; - - // Since POSIX remove() is specified to work with either files or directories, in a - // perfect world it could just be called. But some important real-world operating - // systems (Windows, Mac OS X, for example) don't implement the POSIX spec. So - // remove_file_or_directory() is always called to kep it simple. - return remove_file_or_directory(p, type, ec); - } - - BOOST_FILESYSTEM_DECL - boost::uintmax_t remove_all(const path& p, error_code* ec) - { - error_code tmp_ec; - file_type type = query_file_type(p, &tmp_ec); - if (error(type == status_error, tmp_ec, p, ec, - "boost::filesystem::remove_all")) - return 0; - - return (type != status_error && type != file_not_found) // exists - ? remove_all_aux(p, type, ec) - : 0; - } - - BOOST_FILESYSTEM_DECL - void rename(const path& old_p, const path& new_p, error_code* ec) - { - error(!BOOST_MOVE_FILE(old_p.c_str(), new_p.c_str()), old_p, new_p, ec, - "boost::filesystem::rename"); - } - - BOOST_FILESYSTEM_DECL - void resize_file(const path& p, uintmax_t size, system::error_code* ec) - { - error(!BOOST_RESIZE_FILE(p.c_str(), size), p, ec, "boost::filesystem::resize_file"); - } - - BOOST_FILESYSTEM_DECL - space_info space(const path& p, error_code* ec) - { -# ifdef BOOST_POSIX_API - struct BOOST_STATVFS vfs; - space_info info; - if (!error(::BOOST_STATVFS(p.c_str(), &vfs)!= 0, - p, ec, "boost::filesystem::space")) - { - info.capacity - = static_cast<boost::uintmax_t>(vfs.f_blocks)* BOOST_STATVFS_F_FRSIZE; - info.free - = static_cast<boost::uintmax_t>(vfs.f_bfree)* BOOST_STATVFS_F_FRSIZE; - info.available - = static_cast<boost::uintmax_t>(vfs.f_bavail)* BOOST_STATVFS_F_FRSIZE; - } - -# else - ULARGE_INTEGER avail, total, free; - space_info info; - - if (!error(::GetDiskFreeSpaceExW(p.c_str(), &avail, &total, &free)== 0, - p, ec, "boost::filesystem::space")) - { - info.capacity - = (static_cast<boost::uintmax_t>(total.HighPart)<< 32) - + total.LowPart; - info.free - = (static_cast<boost::uintmax_t>(free.HighPart)<< 32) - + free.LowPart; - info.available - = (static_cast<boost::uintmax_t>(avail.HighPart)<< 32) - + avail.LowPart; - } - -# endif - - else - { - info.capacity = info.free = info.available = 0; - } - return info; - } - - BOOST_FILESYSTEM_DECL - file_status status(const path& p, error_code* ec) - { -# ifdef BOOST_POSIX_API - - struct stat path_stat; - if (::stat(p.c_str(), &path_stat)!= 0) - { - if (ec != 0) // always report errno, even though some - ec->assign(errno, system_category()); // errno values are not status_errors - - if (not_found_error(errno)) - { - return fs::file_status(fs::file_not_found); - } - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status", - p, error_code(errno, system_category()))); - return fs::file_status(fs::status_error); - } - if (ec != 0) ec->clear();; - if (S_ISDIR(path_stat.st_mode)) - return fs::file_status(fs::directory_file); - if (S_ISREG(path_stat.st_mode)) - return fs::file_status(fs::regular_file); - if (S_ISBLK(path_stat.st_mode)) - return fs::file_status(fs::block_file); - if (S_ISCHR(path_stat.st_mode)) - return fs::file_status(fs::character_file); - if (S_ISFIFO(path_stat.st_mode)) - return fs::file_status(fs::fifo_file); - if (S_ISSOCK(path_stat.st_mode)) - return fs::file_status(fs::socket_file); - return fs::file_status(fs::type_unknown); - -# else // Windows - - DWORD attr(::GetFileAttributesW(p.c_str())); - if (attr == 0xFFFFFFFF) - { - return process_status_failure(p, ec); - } - - // reparse point handling - if (attr & FILE_ATTRIBUTE_REPARSE_POINT) - { - handle_wrapper h( - create_file_handle( - p.c_str(), - 0, // dwDesiredAccess; attributes only - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - 0, // lpSecurityAttributes - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - 0)); // hTemplateFile - if (h.handle == INVALID_HANDLE_VALUE) - { - return process_status_failure(p, ec); - } - - if (!is_reparse_point_a_symlink(p)) - return file_status(reparse_file); - } - - if (ec != 0) ec->clear(); - return (attr & FILE_ATTRIBUTE_DIRECTORY) - ? file_status(directory_file) - : file_status(regular_file); - -# endif - } - - BOOST_FILESYSTEM_DECL - file_status symlink_status(const path& p, error_code* ec) - { -# ifdef BOOST_POSIX_API - - struct stat path_stat; - if (::lstat(p.c_str(), &path_stat)!= 0) - { - if (ec != 0) // always report errno, even though some - ec->assign(errno, system_category()); // errno values are not status_errors - - if (errno == ENOENT || errno == ENOTDIR) // these are not errors - { - return fs::file_status(fs::file_not_found); - } - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status", - p, error_code(errno, system_category()))); - return fs::file_status(fs::status_error); - } - if (ec != 0) ec->clear(); - if (S_ISREG(path_stat.st_mode)) - return fs::file_status(fs::regular_file); - if (S_ISDIR(path_stat.st_mode)) - return fs::file_status(fs::directory_file); - if (S_ISLNK(path_stat.st_mode)) - return fs::file_status(fs::symlink_file); - if (S_ISBLK(path_stat.st_mode)) - return fs::file_status(fs::block_file); - if (S_ISCHR(path_stat.st_mode)) - return fs::file_status(fs::character_file); - if (S_ISFIFO(path_stat.st_mode)) - return fs::file_status(fs::fifo_file); - if (S_ISSOCK(path_stat.st_mode)) - return fs::file_status(fs::socket_file); - return fs::file_status(fs::type_unknown); - -# else // Windows - - DWORD attr(::GetFileAttributesW(p.c_str())); - if (attr == 0xFFFFFFFF) - { - return process_status_failure(p, ec); - } - - if (ec != 0) ec->clear(); - - if (attr & FILE_ATTRIBUTE_REPARSE_POINT) - return is_reparse_point_a_symlink(p) - ? file_status(symlink_file) - : file_status(reparse_file); - - return (attr & FILE_ATTRIBUTE_DIRECTORY) - ? file_status(directory_file) - : file_status(regular_file); - -# endif - } - - // contributed by Jeff Flinn - BOOST_FILESYSTEM_DECL - path temp_directory_path(system::error_code* ec) - { -# ifdef BOOST_POSIX_API - const char* val = 0; - - (val = std::getenv("TMPDIR" )) || - (val = std::getenv("TMP" )) || - (val = std::getenv("TEMP" )) || - (val = std::getenv("TEMPDIR")); - - path p((val!=0) ? val : "/tmp"); - - if (p.empty() || (ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p))) - { - errno = ENOTDIR; - error(true, p, ec, "boost::filesystem::temp_directory_path"); - return p; - } - - return p; - -# else // Windows - - std::vector<path::value_type> buf(GetTempPathW(0, NULL)); - - if (buf.empty() || GetTempPathW(buf.size(), &buf[0])==0) - { - if(!buf.empty()) ::SetLastError(ENOTDIR); - error(true, ec, "boost::filesystem::temp_directory_path"); - return path(); - } - - buf.pop_back(); - - path p(buf.begin(), buf.end()); - - if ((ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p))) - { - ::SetLastError(ENOTDIR); - error(true, p, ec, "boost::filesystem::temp_directory_path"); - return path(); - } - - return p; -# endif - } - - BOOST_FILESYSTEM_DECL - path system_complete(const path& p, system::error_code* ec) - { -# ifdef BOOST_POSIX_API - return (p.empty() || p.is_absolute()) - ? p : current_path()/ p; - -# else - if (p.empty()) - { - if (ec != 0) ec->clear(); - return p; - } - wchar_t buf[buf_size]; - wchar_t* pfn; - std::size_t len = get_full_path_name(p, buf_size, buf, &pfn); - - if (error(len == 0, p, ec, "boost::filesystem::system_complete")) - return path(); - - if (len < buf_size)// len does not include null termination character - return path(&buf[0]); - - boost::scoped_array<wchar_t> big_buf(new wchar_t[len]); - - return error(get_full_path_name(p, len , big_buf.get(), &pfn)== 0, - p, ec, "boost::filesystem::system_complete") - ? path() - : path(big_buf.get()); -# endif - } - -} // namespace detail - -//--------------------------------------------------------------------------------------// -// // -// directory_entry // -// // -//--------------------------------------------------------------------------------------// - - file_status - directory_entry::m_get_status(system::error_code* ec) const - { - if (!status_known(m_status)) - { - // optimization: if the symlink status is known, and it isn't a symlink, - // then status and symlink_status are identical so just copy the - // symlink status to the regular status. - if (status_known(m_symlink_status) - && !is_symlink(m_symlink_status)) - { - m_status = m_symlink_status; - if (ec != 0) ec->clear(); - } - else m_status = detail::status(m_path, ec); - } - else if (ec != 0) ec->clear(); - return m_status; - } - - file_status - directory_entry::m_get_symlink_status(system::error_code* ec) const - { - if (!status_known(m_symlink_status)) - m_symlink_status = detail::symlink_status(m_path, ec); - else if (ec != 0) ec->clear(); - return m_symlink_status; - } - -// dispatch directory_entry supplied here rather than in -// <boost/filesystem/path_traits.hpp>, thus avoiding header circularity. -// test cases are in operations_unit_test.cpp - -namespace path_traits -{ - void dispatch(const directory_entry & de, -# ifdef BOOST_WINDOWS_API - std::wstring& to, -# else - std::string& to, -# endif - const codecvt_type &) - { - to = de.path().native(); - } - -} // namespace path_traits -} // namespace filesystem3 -} // namespace boost - -//--------------------------------------------------------------------------------------// -// // -// directory_iterator // -// // -//--------------------------------------------------------------------------------------// - -namespace -{ -# ifdef BOOST_POSIX_API - - error_code path_max(std::size_t & result) - // this code is based on Stevens and Rago, Advanced Programming in the - // UNIX envirnment, 2nd Ed., ISBN 0-201-43307-9, page 49 - { -# ifdef PATH_MAX - static std::size_t max = PATH_MAX; -# else - static std::size_t max = 0; -# endif - if (max == 0) - { - errno = 0; - long tmp = ::pathconf("/", _PC_NAME_MAX); - if (tmp < 0) - { - if (errno == 0)// indeterminate - max = 4096; // guess - else return error_code(errno, system_category()); - } - else max = static_cast<std::size_t>(tmp + 1); // relative root - } - result = max; - return ok; - } - -#if defined(__PGI) && defined(__USE_FILE_OFFSET64) -#define dirent dirent64 -#endif - - error_code dir_itr_first(void *& handle, void *& buffer, - const char* dir, string& target, - fs::file_status &, fs::file_status &) - { - if ((handle = ::opendir(dir))== 0) - return error_code(errno, system_category()); - target = string("."); // string was static but caused trouble - // when iteration called from dtor, after - // static had already been destroyed - std::size_t path_size (0); // initialization quiets gcc warning (ticket #3509) - error_code ec = path_max(path_size); - if (ec)return ec; - dirent de; - buffer = std::malloc((sizeof(dirent) - sizeof(de.d_name)) - + path_size + 1); // + 1 for "/0" - return ok; - } - - // 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 - { - errno = 0; - -# if !defined(__CYGWIN__)\ - && defined(_POSIX_THREAD_SAFE_FUNCTIONS)\ - && defined(_SC_THREAD_SAFE_FUNCTIONS)\ - && (_POSIX_THREAD_SAFE_FUNCTIONS+0 >= 0)\ - && (!defined(__hpux) || defined(_REENTRANT)) \ - && (!defined(_AIX) || defined(__THREAD_SAFE)) - if (::sysconf(_SC_THREAD_SAFE_FUNCTIONS)>= 0) - { return ::readdir_r(dirp, entry, result); } -# endif - - struct dirent * p; - *result = 0; - if ((p = ::readdir(dirp))== 0) - return errno; - std::strcpy(entry->d_name, p->d_name); - *result = entry; - return 0; - } - - error_code dir_itr_increment(void *& handle, void *& buffer, - string& target, fs::file_status & sf, fs::file_status & symlink_sf) - { - BOOST_ASSERT(buffer != 0); - dirent * entry(static_cast<dirent *>(buffer)); - dirent * result; - int return_code; - if ((return_code = readdir_r_simulator(static_cast<DIR*>(handle), - entry, &result))!= 0)return error_code(errno, system_category()); - if (result == 0) - return fs::detail::dir_itr_close(handle, buffer); - target = entry->d_name; -# ifdef BOOST_FILESYSTEM_STATUS_CACHE - if (entry->d_type == DT_UNKNOWN) // filesystem does not supply d_type value - { - sf = symlink_sf = fs::file_status(fs::status_error); - } - else // filesystem supplies d_type value - { - if (entry->d_type == DT_DIR) - sf = symlink_sf = fs::file_status(fs::directory_file); - else if (entry->d_type == DT_REG) - sf = symlink_sf = fs::file_status(fs::regular_file); - else if (entry->d_type == DT_LNK) - { - sf = fs::file_status(fs::status_error); - symlink_sf = fs::file_status(fs::symlink_file); - } - else sf = symlink_sf = fs::file_status(fs::status_error); - } -# else - sf = symlink_sf = fs::file_status(fs::status_error); -# endif - return ok; - } - -# else // BOOST_WINDOWS_API - - error_code dir_itr_first(void *& handle, const fs::path& dir, - wstring& target, fs::file_status & sf, fs::file_status & symlink_sf) - // 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. It is treated as eof instead. - { - // use a form of search Sebastian Martel reports will work with Win98 - wstring dirpath(dir.wstring()); - dirpath += (dirpath.empty() - || (dirpath[dirpath.size()-1] != L'\\' - && dirpath[dirpath.size()-1] != L'/' - && dirpath[dirpath.size()-1] != L':'))? L"\\*" : L"*"; - - WIN32_FIND_DATAW data; - if ((handle = ::FindFirstFileW(dirpath.c_str(), &data)) - == INVALID_HANDLE_VALUE) - { - handle = 0; - return error_code( (::GetLastError() == ERROR_FILE_NOT_FOUND - // Windows Mobile returns ERROR_NO_MORE_FILES; see ticket #3551 - || ::GetLastError() == ERROR_NO_MORE_FILES) - ? 0 : ::GetLastError(), system_category() ); - } - target = data.cFileName; - if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - // reparse points are complex, so don't try to handle them here - { sf.type(fs::status_error); symlink_sf.type(fs::status_error); } - else if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { sf.type(fs::directory_file); symlink_sf.type(fs::directory_file); } - else - { sf.type(fs::regular_file); symlink_sf.type(fs::regular_file); } - return error_code(); - } - - error_code dir_itr_increment(void *& handle, wstring& target, - fs::file_status & sf, fs::file_status & symlink_sf) - { - WIN32_FIND_DATAW data; - if (::FindNextFileW(handle, &data)== 0)// fails - { - int error = ::GetLastError(); - fs::detail::dir_itr_close(handle); - return error_code(error == ERROR_NO_MORE_FILES ? 0 : error, system_category()); - } - target = data.cFileName; - if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - // reparse points are complex, so don't try to handle them here - { sf.type(fs::status_error); symlink_sf.type(fs::status_error); } - else if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { sf.type(fs::directory_file); symlink_sf.type(fs::directory_file); } - else - { sf.type(fs::regular_file); symlink_sf.type(fs::regular_file); } - return error_code(); - } -#endif - - const error_code not_found_error_code ( -# ifdef BOOST_WINDOWS_API - ERROR_PATH_NOT_FOUND -# else - ENOENT -# endif - , system_category()); - -} // unnamed namespace - -namespace boost -{ -namespace filesystem3 -{ - -namespace detail -{ - // dir_itr_close is called both from the ~dir_itr_imp()destructor - // and dir_itr_increment() - BOOST_FILESYSTEM_DECL - system::error_code dir_itr_close( // never throws - void *& handle -# if defined(BOOST_POSIX_API) - , void *& buffer -# endif - ) - { -# ifdef BOOST_POSIX_API - std::free(buffer); - buffer = 0; - if (handle == 0)return ok; - DIR * h(static_cast<DIR*>(handle)); - handle = 0; - return error_code(::closedir(h)== 0 ? 0 : errno, system_category()); - -# else - if (handle != 0) - { - ::FindClose(handle); - handle = 0; - } - return ok; - -# endif - } - - void directory_iterator_construct(directory_iterator& it, - const path& p, system::error_code* ec) - { - if (error(p.empty(), not_found_error_code, p, ec, - "boost::filesystem::directory_iterator::construct"))return; - - path::string_type filename; - file_status file_stat, symlink_file_stat; - error_code result = dir_itr_first(it.m_imp->handle, -# if defined(BOOST_POSIX_API) - it.m_imp->buffer, -# endif - p.c_str(), filename, file_stat, symlink_file_stat); - - if (result) - { - it.m_imp.reset(); - error(true, result, p, - ec, "boost::filesystem::directory_iterator::construct"); - return; - } - - if (it.m_imp->handle == 0)it.m_imp.reset(); // eof, so make end iterator - else // not eof - { - it.m_imp->dir_entry.assign(p / filename, - file_stat, symlink_file_stat); - if (filename[0] == dot // dot or dot-dot - && (filename.size()== 1 - || (filename[1] == dot - && filename.size()== 2))) - { it.increment(); } - } - } - - void directory_iterator_increment(directory_iterator& it, - system::error_code* ec) - { - BOOST_ASSERT(it.m_imp.get() && "attempt to increment end iterator"); - BOOST_ASSERT(it.m_imp->handle != 0 && "internal program error"); - - path::string_type filename; - file_status file_stat, symlink_file_stat; - system::error_code temp_ec; - - for (;;) - { - temp_ec = dir_itr_increment(it.m_imp->handle, -# if defined(BOOST_POSIX_API) - it.m_imp->buffer, -# endif - filename, file_stat, symlink_file_stat); - - if (temp_ec) - { - it.m_imp.reset(); - if (ec == 0) - BOOST_FILESYSTEM_THROW( - filesystem_error("boost::filesystem::directory_iterator::operator++", - it.m_imp->dir_entry.path().parent_path(), - error_code(BOOST_ERRNO, system_category()))); - ec->assign(BOOST_ERRNO, system_category()); - return; - } - else if (ec != 0) ec->clear(); - - if (it.m_imp->handle == 0) // eof, make end - { - it.m_imp.reset(); - return; - } - - if (!(filename[0] == dot // !(dot or dot-dot) - && (filename.size()== 1 - || (filename[1] == dot - && filename.size()== 2)))) - { - it.m_imp->dir_entry.replace_filename( - filename, file_stat, symlink_file_stat); - return; - } - } - } -} // namespace detail -} // namespace filesystem3 -} // namespace boost - -#endif // no wide character support |