From 92cf13c2c222455639c8e1a1bd10c10a1e63b2e1 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 19 Apr 2007 03:06:15 +0000 Subject: [PATCH] sparse files fixes. now sets the size of the files in case sparse files are supported --- include/libtorrent/file.hpp | 1 + include/libtorrent/storage.hpp | 4 ++ src/file.cpp | 16 ++++++++ src/file_win.cpp | 15 ++++++++ src/storage.cpp | 69 +++++++++++++++++++++------------- 5 files changed, 79 insertions(+), 26 deletions(-) diff --git a/include/libtorrent/file.hpp b/include/libtorrent/file.hpp index 1b71c66f5..d11496b28 100755 --- a/include/libtorrent/file.hpp +++ b/include/libtorrent/file.hpp @@ -110,6 +110,7 @@ namespace libtorrent void open(boost::filesystem::path const& p, open_mode m); void close(); + void set_size(size_type size); size_type write(const char*, size_type num_bytes); size_type read(char*, size_type num_bytes); diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index a9a834889..885403776 100755 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -89,6 +89,10 @@ namespace libtorrent struct TORRENT_EXPORT storage_interface { + // create directories and set file sizes + // (if sparse files are supported) + virtual void initialize() = 0; + // may throw file_error if storage for slot does not exist virtual size_type read(char* buf, int slot, int offset, int size) = 0; diff --git a/src/file.cpp b/src/file.cpp index 28fea84b6..71bc795a4 100755 --- a/src/file.cpp +++ b/src/file.cpp @@ -245,6 +245,17 @@ namespace libtorrent return ret; } + void set_size(size_type s) + { + size_type pos = tell(); + seek(1, 0); + char dummy = 0; + read(&dummy, 1); + seek(1, 0); + write(&dummy, 1); + seek(pos, 1); + } + size_type seek(size_type offset, int m) { assert(m_open_mode); @@ -318,6 +329,11 @@ namespace libtorrent return m_impl->read(buf, num_bytes); } + void file::set_size(size_type s) + { + m_impl->set_size(s); + } + size_type file::seek(size_type pos, file::seek_mode m) { return m_impl->seek(pos, m.m_val); diff --git a/src/file_win.cpp b/src/file_win.cpp index 7189e09e5..9d2c2f4bf 100644 --- a/src/file_win.cpp +++ b/src/file_win.cpp @@ -238,6 +238,16 @@ namespace libtorrent return bytes_read; } + void set_size(size_type s) + { + size_type pos = tell(); + seek(s, seek_begin); + if (FALSE == ::SetEndOfFile(m_file_handle)) + throw_exception("file::set_size"); + + seek(pos, seek_begin); + } + size_type seek(size_type pos, seek_mode from_where) { assert(pos >= 0 || from_where != seek_begin); @@ -339,6 +349,11 @@ namespace libtorrent return m_impl->read(buffer, num_bytes); } + void file::set_size(size_type s) + { + m_impl->set_size(s); + } + size_type file::seek(size_type pos, seek_mode m) { return m_impl->seek(pos,impl::seek_mode(m.m_val)); diff --git a/src/storage.cpp b/src/storage.cpp index 66e761655..5e440b13c 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -372,6 +372,7 @@ namespace libtorrent void release_files(); + void initialize(); bool move_storage(path save_path); size_type read(char* buf, int slot, int offset, int size); void write(const char* buf, int slot, int offset, int size); @@ -391,6 +392,45 @@ namespace libtorrent file_pool& m_files; }; + void storage::initialize() + { + // first, create all missing directories + bool sparse = supports_sparse_files(m_save_path); + path last_path; + for (torrent_info::file_iterator file_iter = m_info.begin_files(), + end_iter = m_info.end_files(); file_iter != end_iter; ++file_iter) + { + path dir = (m_save_path / file_iter->path).branch_path(); + + if (dir != last_path) + { + last_path = dir; + +#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 13400 + if (!exists_win(last_path)) + create_directories_win(last_path); +#else + if (!exists(last_path)) + create_directories(last_path); +#endif + } + + // if the file is empty, just create it. But also make sure + // the directory exits. + if (file_iter->size == 0) + { + file(m_save_path / file_iter->path, file::out); + continue; + } + + if (sparse) + { + m_files.open_file(this, m_save_path / file_iter->path, file::out) + ->set_size(file_iter->size); + } + } + } + void storage::release_files() { m_files.release(this); @@ -830,6 +870,8 @@ namespace libtorrent { return true; } + + return true; #endif #if defined(__linux__) @@ -1522,33 +1564,8 @@ namespace libtorrent if (m_state == state_create_files) { - // first, create all missing directories - path last_path; - for (torrent_info::file_iterator file_iter = m_info.begin_files(), - end_iter = m_info.end_files(); file_iter != end_iter; ++file_iter) - { - path dir = (m_save_path / file_iter->path).branch_path(); + m_storage->initialize(); - // if the file is empty, just create it. But also make sure - // the directory exits. - if (dir == last_path - && file_iter->size == 0) - file(m_save_path / file_iter->path, file::out); - - if (dir == last_path) continue; - last_path = dir; - -#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 13400 - if (!exists_win(last_path)) - create_directories_win(last_path); -#else - if (!exists(last_path)) - create_directories(last_path); -#endif - - if (file_iter->size == 0) - file(m_save_path / file_iter->path, file::out); - } m_current_slot = 0; m_state = state_full_check; m_piece_data.resize(int(m_info.piece_length()));