fix resume file issue related to daylight savings time on windows
This commit is contained in:
parent
91799025f2
commit
290ce566b0
|
@ -45,6 +45,7 @@
|
|||
* fix uTP edge case where udp socket buffer fills up
|
||||
* fix nagle implementation in uTP
|
||||
|
||||
* fix resume file issue related to daylight savings time on windows
|
||||
* improve error checking in lazy_bdecode
|
||||
|
||||
0.16.16 release
|
||||
|
|
69
src/file.cpp
69
src/file.cpp
|
@ -173,6 +173,17 @@ namespace libtorrent
|
|||
if (p[i] == '/') p[i] = '\\';
|
||||
return p;
|
||||
}
|
||||
|
||||
time_t file_time_to_posix(FILETIME f)
|
||||
{
|
||||
const boost::uint64_t posix_time_offset = 11644473600LL;
|
||||
boost::uint64_t ft = (boost::uint64_t(f.dwHighDateTime) << 32)
|
||||
| f.dwLowDateTime;
|
||||
|
||||
// windows filetime is specified in 100 nanoseconds resolution.
|
||||
// convert to seconds
|
||||
return time_t(ft / 10000000 - posix_time_offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
void stat_file(std::string inf, file_status* s
|
||||
|
@ -185,26 +196,39 @@ namespace libtorrent
|
|||
if (!inf.empty() && (inf[inf.size() - 1] == '\\'
|
||||
|| inf[inf.size() - 1] == '/'))
|
||||
inf.resize(inf.size() - 1);
|
||||
#endif
|
||||
|
||||
#if TORRENT_USE_WSTRING && defined TORRENT_WINDOWS
|
||||
#define GetFileAttributesEx_ GetFileAttributesExW
|
||||
std::wstring f = convert_to_wstring(inf);
|
||||
#else
|
||||
#define GetFileAttributesEx_ GetFileAttributesExA
|
||||
std::string f = convert_to_native(inf);
|
||||
#endif
|
||||
|
||||
#if defined TORRENT_WINDOWS
|
||||
struct _stati64 ret;
|
||||
#if TORRENT_USE_WSTRING
|
||||
if (_wstati64(f.c_str(), &ret) < 0)
|
||||
#else
|
||||
if (_stati64(f.c_str(), &ret) < 0)
|
||||
#endif
|
||||
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||
if (!GetFileAttributesEx(f.c_str(), GetFileExInfoStandard, &data))
|
||||
{
|
||||
ec.assign(errno, generic_category());
|
||||
ec.assign(GetLastError(), boost::system::get_system_category());
|
||||
return;
|
||||
}
|
||||
|
||||
s->file_size = (boost::uint64_t(data.nFileSizeHigh) << 32) | data.nFileSizeLow;
|
||||
s->ctime = file_time_to_posix(data.ftCreationTime);
|
||||
s->atime = file_time_to_posix(data.ftLastAccessTime);
|
||||
s->mtime = file_time_to_posix(data.ftLastWriteTime);
|
||||
|
||||
s->mode = ((data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)
|
||||
? file_status::regular_file : 0)
|
||||
| ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
? file_status::directory : 0)
|
||||
| ((data.dwFileAttributes & FILE_ATTRIBUTE_DEVICE)
|
||||
? file_status::character_special : 0);
|
||||
|
||||
#else
|
||||
|
||||
// posix version
|
||||
|
||||
std::string f = convert_to_native(inf);
|
||||
|
||||
struct stat ret;
|
||||
int retval;
|
||||
if (flags & dont_follow_links)
|
||||
|
@ -216,26 +240,21 @@ namespace libtorrent
|
|||
ec.assign(errno, generic_category());
|
||||
return;
|
||||
}
|
||||
#endif // TORRENT_WINDOWS
|
||||
|
||||
s->file_size = ret.st_size;
|
||||
s->atime = ret.st_atime;
|
||||
s->mtime = ret.st_mtime;
|
||||
s->ctime = ret.st_ctime;
|
||||
#if defined TORRENT_WINDOWS
|
||||
s->mode = ((ret.st_mode & _S_IFREG) ? file_status::regular_file : 0)
|
||||
| ((ret.st_mode & _S_IFDIR) ? file_status::directory : 0)
|
||||
| ((ret.st_mode & _S_IFCHR) ? file_status::character_special : 0)
|
||||
| ((ret.st_mode & _S_IFIFO) ? file_status::fifo : 0);
|
||||
#else
|
||||
s->mode = (S_ISREG(ret.st_mode) ? file_status::regular_file : 0)
|
||||
| (S_ISDIR(ret.st_mode) ? file_status::directory : 0)
|
||||
| (S_ISLNK(ret.st_mode) ? file_status::link : 0)
|
||||
| (S_ISFIFO(ret.st_mode) ? file_status::fifo : 0)
|
||||
| (S_ISCHR(ret.st_mode) ? file_status::character_special : 0)
|
||||
| (S_ISBLK(ret.st_mode) ? file_status::block_special : 0)
|
||||
| (S_ISSOCK(ret.st_mode) ? file_status::socket : 0);
|
||||
#endif
|
||||
|
||||
s->mode = (S_ISREG(ret.st_mode) ? file_status::regular_file : 0)
|
||||
| (S_ISDIR(ret.st_mode) ? file_status::directory : 0)
|
||||
| (S_ISLNK(ret.st_mode) ? file_status::link : 0)
|
||||
| (S_ISFIFO(ret.st_mode) ? file_status::fifo : 0)
|
||||
| (S_ISCHR(ret.st_mode) ? file_status::character_special : 0)
|
||||
| (S_ISBLK(ret.st_mode) ? file_status::block_special : 0)
|
||||
| (S_ISSOCK(ret.st_mode) ? file_status::socket : 0);
|
||||
|
||||
#endif // TORRENT_WINDOWS
|
||||
}
|
||||
|
||||
void rename(std::string const& inf, std::string const& newf, error_code& ec)
|
||||
|
|
|
@ -32,6 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "libtorrent/file.hpp"
|
||||
#include "test.hpp"
|
||||
#include "setup_transfer.hpp" // for test_sleep
|
||||
#include <string.h> // for strcmp
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
@ -58,8 +59,55 @@ int touch_file(std::string const& filename, int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void test_create_directory()
|
||||
{
|
||||
error_code ec;
|
||||
create_directory("__foobar__", ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
file_status st;
|
||||
stat_file("__foobar__", &st, ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
TEST_CHECK(st.mode & file_status::directory);
|
||||
|
||||
remove("__foobar__", ec);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
|
||||
void test_stat()
|
||||
{
|
||||
error_code ec;
|
||||
|
||||
// test that the modification timestamps
|
||||
touch_file("__test_timestamp__", 10);
|
||||
|
||||
file_status st1;
|
||||
stat_file("__test_timestamp__", &st1, ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
// sleep for 3 seconds and then make sure the difference in timestamp is
|
||||
// between 2-4 seconds after touching it again
|
||||
test_sleep(3000);
|
||||
|
||||
touch_file("__test_timestamp__", 10);
|
||||
|
||||
file_status st2;
|
||||
stat_file("__test_timestamp__", &st2, ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
int diff = int(st2.mtime - st1.mtime);
|
||||
fprintf(stderr, "timestamp difference: %d seconds. expected approx. 3 seconds\n"
|
||||
, diff);
|
||||
|
||||
TEST_CHECK(diff >= 2 && diff <= 4);
|
||||
}
|
||||
|
||||
int test_main()
|
||||
{
|
||||
test_create_directory();
|
||||
test_stat();
|
||||
|
||||
error_code ec;
|
||||
|
||||
create_directory("file_test_dir", ec);
|
||||
|
|
Loading…
Reference in New Issue