diff options
Diffstat (limited to 'libs/filesystem/src/operations.cpp')
-rw-r--r-- | libs/filesystem/src/operations.cpp | 313 |
1 files changed, 164 insertions, 149 deletions
diff --git a/libs/filesystem/src/operations.cpp b/libs/filesystem/src/operations.cpp index 6c04ce091..d8e8840c8 100644 --- a/libs/filesystem/src/operations.cpp +++ b/libs/filesystem/src/operations.cpp @@ -71,17 +71,20 @@ using std::wstring; # include <sys/types.h> # include <sys/stat.h> -# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) +# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) \ + && !defined(__VXWORKS__) # include <sys/statvfs.h> # define BOOST_STATVFS statvfs # define BOOST_STATVFS_F_FRSIZE vfs.f_frsize # else # ifdef __OpenBSD__ -# include <sys/param.h> +# include <sys/param.h> # elif defined(__ANDROID__) -# include <sys/vfs.h> +# include <sys/vfs.h> +# endif +# if !defined(__VXWORKS__) +# include <sys/mount.h> # endif -# include <sys/mount.h> # define BOOST_STATVFS statfs # define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>(vfs.f_bsize) # endif @@ -169,6 +172,17 @@ typedef struct _REPARSE_DATA_BUFFER { # define IO_REPARSE_TAG_SYMLINK (0xA000000CL) # endif +inline std::wstring wgetenv(const wchar_t* name) +{ + // use vector since for C++03 basic_string is not required to be contiguous + std::vector<wchar_t> buf(::GetEnvironmentVariableW(name, NULL, 0)); + + // C++03 vector does not have data() so use &buf[0] + return (buf.empty() + || ::GetEnvironmentVariableW(name, &buf[0], static_cast<DWORD>(buf.size())) == 0) + ? std::wstring() : std::wstring(&buf[0]); +} + # endif // BOOST_WINDOWS_API // BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in @@ -192,6 +206,8 @@ typedef struct _REPARSE_DATA_BUFFER { # if defined(BOOST_POSIX_API) +typedef int err_t; + // POSIX uses a 0 return to indicate success # define BOOST_ERRNO errno # define BOOST_SET_CURRENT_DIRECTORY(P)(::chdir(P)== 0) @@ -211,6 +227,8 @@ typedef struct _REPARSE_DATA_BUFFER { # else // BOOST_WINDOWS_API +typedef DWORD err_t; + // Windows uses a non-0 return to indicate success # define BOOST_ERRNO ::GetLastError() # define BOOST_SET_CURRENT_DIRECTORY(P)(::SetCurrentDirectoryW(P)!= 0) @@ -232,7 +250,7 @@ typedef struct _REPARSE_DATA_BUFFER { //--------------------------------------------------------------------------------------// // // -// helpers (all operating systems) // +// helpers (all operating systems) // // // //--------------------------------------------------------------------------------------// @@ -243,11 +261,22 @@ namespace boost::filesystem::directory_iterator end_dir_itr; + // error handling helpers ----------------------------------------------------------// + + bool error(err_t error_num, error_code* ec, const string& message); + bool error(err_t error_num, const path& p, error_code* ec, const string& message); + bool error(err_t error_num, const path& p1, const path& p2, error_code* ec, + const string& message); + const error_code ok; - bool error(bool was_error, error_code* ec, const string& message) + // error_num is value of errno on POSIX, error code (from ::GetLastError()) on Windows. + // Interface changed 30 Jan 15 to have caller supply error_num as ::SetLastError() + // values were apparently getting cleared before they could be retrieved by error(). + + bool error(err_t error_num, error_code* ec, const string& message) { - if (!was_error) + if (!error_num) { if (ec != 0) ec->clear(); } @@ -255,16 +284,16 @@ namespace { // error if (ec == 0) BOOST_FILESYSTEM_THROW(filesystem_error(message, - error_code(BOOST_ERRNO, system_category()))); + error_code(error_num, system_category()))); else - ec->assign(BOOST_ERRNO, system_category()); + ec->assign(error_num, system_category()); } - return was_error; + return error_num != 0; } - bool error(bool was_error, const path& p, error_code* ec, const string& message) + bool error(err_t error_num, const path& p, error_code* ec, const string& message) { - if (!was_error) + if (!error_num) { if (ec != 0) ec->clear(); } @@ -272,17 +301,17 @@ namespace { // error if (ec == 0) BOOST_FILESYSTEM_THROW(filesystem_error(message, - p, error_code(BOOST_ERRNO, system_category()))); + p, error_code(error_num, system_category()))); else - ec->assign(BOOST_ERRNO, system_category()); + ec->assign(error_num, system_category()); } - return was_error; + return error_num != 0; } - bool error(bool was_error, const path& p1, const path& p2, error_code* ec, + bool error(err_t error_num, const path& p1, const path& p2, error_code* ec, const string& message) { - if (!was_error) + if (!error_num) { if (ec != 0) ec->clear(); } @@ -290,48 +319,14 @@ namespace { // error if (ec == 0) BOOST_FILESYSTEM_THROW(filesystem_error(message, - p1, p2, error_code(BOOST_ERRNO, system_category()))); + p1, p2, error_code(error_num, system_category()))); else - ec->assign(BOOST_ERRNO, system_category()); + ec->assign(error_num, system_category()); } - return was_error; + return error_num != 0; } - 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; - } + // general helpers -----------------------------------------------------------------// bool is_empty_directory(const path& p) { @@ -360,13 +355,15 @@ namespace # endif ) { - if (error(!remove_directory(p), p, ec, "boost::filesystem::remove")) - return false; + if (error(!remove_directory(p) ? BOOST_ERRNO : 0, p, ec, + "boost::filesystem::remove")) + return false; } else { - if (error(!remove_file(p), p, ec, "boost::filesystem::remove")) - return false; + if (error(!remove_file(p) ? BOOST_ERRNO : 0, p, ec, + "boost::filesystem::remove")) + return false; } return true; } @@ -441,25 +438,33 @@ namespace ssize_t sz, sz_read=1, sz_write; while (sz_read > 0 - && (sz_read = ::read(infile, buf.get(), buf_sz))> 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 { + BOOST_ASSERT(sz_read - sz_write > 0); // #1 + // ticket 4438 claimed possible infinite loop if write returns 0. My analysis + // is that POSIX specifies 0 return only if 3rd arg is 0, and that will never + // happen due to loop entry and coninuation conditions. BOOST_ASSERT #1 above + // and #2 below added to verify that analysis. if ((sz = ::write(outfile, buf.get() + sz_write, - sz_read - sz_write))< 0) + sz_read - sz_write)) < 0) { sz_read = sz; // cause read loop termination - break; // and error to be thrown after closes + break; // and error reported after closes } + BOOST_ASSERT(sz > 0); // #2 sz_write += sz; } while (sz_write < sz_read); } - if (::close(infile)< 0)sz_read = -1; - if (::close(outfile)< 0)sz_read = -1; + if (::close(infile)< 0) + sz_read = -1; + if (::close(outfile)< 0) + sz_read = -1; return sz_read >= 0; } @@ -652,14 +657,13 @@ namespace 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); + handle_wrapper h(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); + return h.handle != INVALID_HANDLE_VALUE + && ::SetFilePointerEx(h.handle, sz, 0, FILE_BEGIN) + && ::SetEndOfFile(h.handle); } // Windows kernel32.dll functions that may or may not be present @@ -892,7 +896,7 @@ namespace detail # ifdef BOOST_POSIX_API struct stat from_stat; # endif - error(!BOOST_COPY_DIRECTORY(from.c_str(), to.c_str()), + error(!BOOST_COPY_DIRECTORY(from.c_str(), to.c_str()) ? BOOST_ERRNO : 0, from, to, ec, "boost::filesystem::copy_directory"); } @@ -900,7 +904,7 @@ namespace detail void copy_file(const path& from, const path& to, copy_option option, error_code* ec) { error(!BOOST_COPY_FILE(from.c_str(), to.c_str(), - option == fail_if_exists), + option == fail_if_exists) ? BOOST_ERRNO : 0, from, to, ec, "boost::filesystem::copy_file"); } @@ -909,8 +913,7 @@ namespace detail 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, + error(BOOST_ERROR_NOT_SUPPORTED, new_symlink, existing_symlink, ec, "boost::filesystem::copy_symlink"); # else // modern Windows or BOOST_POSIX_API @@ -996,20 +999,19 @@ namespace detail { # 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, + error(BOOST_ERROR_NOT_SUPPORTED, 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, + if (error(!create_symbolic_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, 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), + error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(), + SYMBOLIC_LINK_FLAG_DIRECTORY) ? BOOST_ERRNO : 0, to, from, ec, "boost::filesystem::create_directory_symlink"); # endif } @@ -1020,20 +1022,18 @@ namespace detail # 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, + error(BOOST_ERROR_NOT_SUPPORTED, 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, + if (error(!create_hard_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec, "boost::filesystem::create_hard_link")) return; # endif - error(!BOOST_CREATE_HARD_LINK(from.c_str(), to.c_str()), to, from, ec, + error(!BOOST_CREATE_HARD_LINK(from.c_str(), to.c_str()) ? BOOST_ERRNO : 0, to, from, ec, "boost::filesystem::create_hard_link"); # endif } @@ -1042,20 +1042,18 @@ namespace detail 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, + error(BOOST_ERROR_NOT_SUPPORTED, 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, + if (error(!create_symbolic_link_api ? BOOST_ERROR_NOT_SUPPORTED : 0, to, from, ec, "boost::filesystem::create_symlink")) return; # endif - error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(), 0), + error(!BOOST_CREATE_SYMBOLIC_LINK(from.c_str(), to.c_str(), 0) ? BOOST_ERRNO : 0, to, from, ec, "boost::filesystem::create_symlink"); # endif } @@ -1071,7 +1069,7 @@ namespace detail 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 + if (error(errno != ERANGE ? errno : 0 // 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 @@ -1092,9 +1090,9 @@ namespace detail # else DWORD sz; - if ((sz = ::GetCurrentDirectoryW(0, NULL))== 0)sz = 1; + 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, + error(::GetCurrentDirectoryW(sz, buf.get()) == 0 ? BOOST_ERRNO : 0, ec, "boost::filesystem::current_path"); return path(buf.get()); # endif @@ -1104,7 +1102,7 @@ namespace detail BOOST_FILESYSTEM_DECL void current_path(const path& p, system::error_code* ec) { - error(!BOOST_SET_CURRENT_DIRECTORY(p.c_str()), + error(!BOOST_SET_CURRENT_DIRECTORY(p.c_str()) ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::current_path"); } @@ -1166,8 +1164,8 @@ namespace detail { // 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, + error((h1.handle == INVALID_HANDLE_VALUE + && h2.handle == INVALID_HANDLE_VALUE) ? BOOST_ERROR_NOT_SUPPORTED : 0, p1, p2, ec, "boost::filesystem::equivalent"); return false; } @@ -1176,11 +1174,11 @@ namespace detail BY_HANDLE_FILE_INFORMATION info1, info2; - if (error(!::GetFileInformationByHandle(h1.handle, &info1), + if (error(!::GetFileInformationByHandle(h1.handle, &info1) ? BOOST_ERRNO : 0, p1, p2, ec, "boost::filesystem::equivalent")) return false; - if (error(!::GetFileInformationByHandle(h2.handle, &info2), + if (error(!::GetFileInformationByHandle(h2.handle, &info2) ? BOOST_ERRNO : 0, p1, p2, ec, "boost::filesystem::equivalent")) return false; @@ -1207,11 +1205,10 @@ namespace detail # ifdef BOOST_POSIX_API struct stat path_stat; - if (error(::stat(p.c_str(), &path_stat)!= 0, + if (error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 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()), + if (error(!S_ISREG(path_stat.st_mode) ? EPERM : 0, p, ec, "boost::filesystem::file_size")) return static_cast<boost::uintmax_t>(-1); @@ -1223,13 +1220,12 @@ namespace detail 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(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0 + ? BOOST_ERRNO : 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")) + if (error((fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!= 0 + ? ERROR_NOT_SUPPORTED : 0, p, ec, "boost::filesystem::file_size")) return static_cast<boost::uintmax_t>(-1); return (static_cast<boost::uintmax_t>(fad.nFileSizeHigh) @@ -1243,7 +1239,7 @@ namespace detail # ifdef BOOST_POSIX_API struct stat path_stat; - return error(::stat(p.c_str(), &path_stat)!= 0, + return error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::hard_link_count") ? 0 : static_cast<boost::uintmax_t>(path_stat.st_nlink); @@ -1257,9 +1253,9 @@ namespace detail FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); return - !error(h.handle == INVALID_HANDLE_VALUE, + !error(h.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::hard_link_count") - && !error(::GetFileInformationByHandle(h.handle, &info)== 0, + && !error(::GetFileInformationByHandle(h.handle, &info)== 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::hard_link_count") ? info.nNumberOfLinks : 0; @@ -1291,8 +1287,8 @@ namespace detail # else WIN32_FILE_ATTRIBUTE_DATA fad; - if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0, - p, ec, "boost::filesystem::is_empty")) + if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0 + ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::is_empty")) return false; if (ec != 0) ec->clear(); @@ -1309,7 +1305,7 @@ namespace detail # ifdef BOOST_POSIX_API struct stat path_stat; - if (error(::stat(p.c_str(), &path_stat)!= 0, + if (error(::stat(p.c_str(), &path_stat)!= 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::last_write_time")) return std::time_t(-1); return path_stat.st_mtime; @@ -1321,13 +1317,13 @@ namespace detail FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); - if (error(hw.handle == INVALID_HANDLE_VALUE, + if (error(hw.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::last_write_time")) return std::time_t(-1); FILETIME lwt; - if (error(::GetFileTime(hw.handle, 0, 0, &lwt)== 0, + if (error(::GetFileTime(hw.handle, 0, 0, &lwt)== 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::last_write_time")) return std::time_t(-1); @@ -1348,7 +1344,7 @@ namespace detail ::utimbuf buf; buf.actime = path_stat.st_atime; // utime()updates access time too:-( buf.modtime = new_time; - error(::utime(p.c_str(), &buf)!= 0, + error(::utime(p.c_str(), &buf)!= 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::last_write_time"); # else @@ -1358,14 +1354,14 @@ namespace detail FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); - if (error(hw.handle == INVALID_HANDLE_VALUE, + if (error(hw.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::last_write_time")) return; FILETIME lwt; to_FILETIME(new_time, lwt); - error(::SetFileTime(hw.handle, 0, 0, &lwt)== 0, + error(::SetFileTime(hw.handle, 0, 0, &lwt)== 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::last_write_time"); # endif } @@ -1441,7 +1437,7 @@ namespace detail DWORD attr = ::GetFileAttributesW(p.c_str()); - if (error(attr == 0, p, ec, "boost::filesystem::permissions")) + if (error(attr == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::permissions")) return; if (prms & add_perms) @@ -1453,7 +1449,7 @@ namespace detail else attr |= FILE_ATTRIBUTE_READONLY; - error(::SetFileAttributesW(p.c_str(), attr) == 0, + error(::SetFileAttributesW(p.c_str(), attr) == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::permissions"); # endif } @@ -1489,7 +1485,7 @@ namespace detail } # elif _WIN32_WINNT < 0x0600 // SDK earlier than Vista and Server 2008 - error(true, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()), p, ec, + error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::read_symlink"); # else // Vista and Server 2008 SDK, or later @@ -1503,13 +1499,14 @@ namespace detail 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; + if (error(h.handle == INVALID_HANDLE_VALUE ? BOOST_ERRNO : 0, + 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, + 0, 0, info.buf, sizeof(info), &sz, 0) == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::read_symlink" )) symlink_path.assign( static_cast<wchar_t*>(info.rdb.SymbolicLinkReparseBuffer.PathBuffer) @@ -1526,7 +1523,7 @@ namespace detail { error_code tmp_ec; file_type type = query_file_type(p, &tmp_ec); - if (error(type == status_error, tmp_ec, p, ec, + if (error(type == status_error ? tmp_ec.value() : 0, p, ec, "boost::filesystem::remove")) return false; @@ -1542,7 +1539,7 @@ namespace detail { error_code tmp_ec; file_type type = query_file_type(p, &tmp_ec); - if (error(type == status_error, tmp_ec, p, ec, + if (error(type == status_error ? tmp_ec.value() : 0, p, ec, "boost::filesystem::remove_all")) return 0; @@ -1554,14 +1551,15 @@ namespace detail 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"); + error(!BOOST_MOVE_FILE(old_p.c_str(), new_p.c_str()) ? BOOST_ERRNO : 0, 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"); + error(!BOOST_RESIZE_FILE(p.c_str(), size) ? BOOST_ERRNO : 0, p, ec, + "boost::filesystem::resize_file"); } BOOST_FILESYSTEM_DECL @@ -1770,8 +1768,7 @@ namespace detail if (p.empty() || (ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p))) { - errno = ENOTDIR; - error(true, p, ec, "boost::filesystem::temp_directory_path"); + error(ENOTDIR, p, ec, "boost::filesystem::temp_directory_path"); return p; } @@ -1779,27 +1776,45 @@ namespace detail # else // Windows - std::vector<path::value_type> buf(GetTempPathW(0, NULL)); + const wchar_t* tmp_env = L"TMP"; + const wchar_t* temp_env = L"TEMP"; + const wchar_t* localappdata_env = L"LOCALAPPDATA"; + const wchar_t* userprofile_env = L"USERPROFILE"; + const wchar_t* env_list[] + = {tmp_env, temp_env, localappdata_env, userprofile_env, 0}; - if (buf.empty() || GetTempPathW(buf.size(), &buf[0])==0) + path p; + for (int i = 0; env_list[i]; ++i) { - if(!buf.empty()) ::SetLastError(ENOTDIR); - error(true, ec, "boost::filesystem::temp_directory_path"); - return path(); + std::wstring env = wgetenv(env_list[i]); + if (!env.empty()) + { + p = env; + if (i >= 2) + p /= L"Temp"; + error_code lcl_ec; + if (exists(p, lcl_ec) && !lcl_ec && is_directory(p, lcl_ec) && !lcl_ec) + break; + p.clear(); + } } - - buf.pop_back(); - - path p(buf.begin(), buf.end()); - - if ((ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p))) + + if (p.empty()) { - ::SetLastError(ENOTDIR); - error(true, p, ec, "boost::filesystem::temp_directory_path"); - return path(); + // use vector since in C++03 a string is not required to be contiguous + std::vector<wchar_t> buf(::GetWindowsDirectoryW(NULL, 0)); + + if (buf.empty() + || ::GetWindowsDirectoryW(&buf[0], static_cast<UINT>(buf.size())) == 0) + { + error(::GetLastError(), ec, "boost::filesystem::temp_directory_path"); + return path(); + } + p = &*buf.begin(); // do not depend on buf.size(); see ticket #10388 + p /= L"Temp"; } - return p; + # endif } @@ -1820,7 +1835,7 @@ namespace detail 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")) + if (error(len == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::system_complete")) return path(); if (len < buf_size)// len does not include null termination character @@ -1828,7 +1843,7 @@ namespace detail boost::scoped_array<wchar_t> big_buf(new wchar_t[len]); - return error(get_full_path_name(p, len , big_buf.get(), &pfn)== 0, + return error(get_full_path_name(p, len , big_buf.get(), &pfn)== 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::system_complete") ? path() : path(big_buf.get()); @@ -2160,7 +2175,7 @@ namespace detail void directory_iterator_construct(directory_iterator& it, const path& p, system::error_code* ec) { - if (error(p.empty(), not_found_error_code, p, ec, + if (error(p.empty() ? not_found_error_code.value() : 0, p, ec, "boost::filesystem::directory_iterator::construct")) return; @@ -2175,7 +2190,7 @@ namespace detail if (result) { it.m_imp.reset(); - error(true, result, p, + error(result.value(), p, ec, "boost::filesystem::directory_iterator::construct"); return; } |