diff --git a/ChangeLog b/ChangeLog index 074ca95a9..20c31c92d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,6 +26,7 @@ incoming connection * added more detailed instrumentation of the disk I/O thread + * fixed inconsistency when creating torrents with symlinks * properly detect windows version to initialize half-open connection limit * fixed bug in url encoder where $ would not be encoded diff --git a/docs/make_torrent.rst b/docs/make_torrent.rst index bf97f3160..611edf379 100644 --- a/docs/make_torrent.rst +++ b/docs/make_torrent.rst @@ -58,12 +58,16 @@ add_files :: template - void add_files(file_storage& fs, boost::filesystem::path const& path, Pred p); + void add_files(file_storage& fs, boost::filesystem::path const& path, Pred p + , boost::uint32_t flags = 0); template - void add_files(file_storage& fs, boost::filesystem::wpath const& path, Pred p); + void add_files(file_storage& fs, boost::filesystem::wpath const& path, Pred p + , boost::uint32_t flags = 0); - void add_files(file_storage& fs, boost::filesystem::path const& path); - void add_files(file_storage& fs, boost::filesystem::wpath const& path); + void add_files(file_storage& fs, boost::filesystem::path const& path + , boost::uint32_t flags = 0); + void add_files(file_storage& fs, boost::filesystem::wpath const& path + , boost::uint32_t flags = 0); Adds the file specified by ``path`` to the ``file_storage`` object. In case ``path`` refers to a diretory, files will be added recursively from the directory. @@ -84,6 +88,9 @@ are traveresed. The ".." directory is never traversed. +The ``flags`` argument should be the same as the flags passed to the `create_torrent`_ +constructor. + set_piece_hashes() ================== @@ -224,7 +231,8 @@ The ``create_torrent`` class has the following synopsis:: , symlink = 8 , calculate_file_hashes = 16 }; - create_torrent(file_storage& fs, int piece_size = 0, int pad_size_limit = -1, int flags = optimize); + create_torrent(file_storage& fs, int piece_size = 0, int pad_size_limit = -1 + , int flags = optimize); create_torrent(torrent_info const& ti); entry generate() const; @@ -258,7 +266,8 @@ create_torrent() , symlink = 8 , calculate_file_hashes = 16 }; - create_torrent(file_storage& fs, int piece_size = 0, int pad_size_limit = -1, int flags = optimize); + create_torrent(file_storage& fs, int piece_size = 0, int pad_size_limit = -1 + , int flags = optimize); create_torrent(torrent_info const& ti); The ``piece_size`` is the size of each piece in bytes. It must @@ -300,11 +309,10 @@ modification_time files. symlink - If this flag is defined, files that are symlinks get a symlink attribute - set on them. The file data will still be the same, the symlink will always - be followed when opening the file, but the file list will include the path - of the symlink so that the original directory structure can be reproduced - on the downloading side. + If this flag is set, files that are symlinks get a symlink attribute + set on them and their data will not be included in the torrent. This + is useful if you need to reconstruct a file hierarchy which contains + symlinks. calculate_file_hashes If this is set, the `set_piece_hashes()`_ function will, as it calculates diff --git a/examples/make_torrent.cpp b/examples/make_torrent.cpp index d2bf67704..4cb939c81 100644 --- a/examples/make_torrent.cpp +++ b/examples/make_torrent.cpp @@ -77,6 +77,8 @@ void print_usage() " than bytes will be piece-aligned\n" "-s bytes specifies a piece size for the torrent\n" " This has to be a multiple of 16 kiB\n" + "-l Don't follow symlinks, instead encode them as\n" + " links in the torrent file\n" "-o file specifies the output filename of the torrent file\n" " If this is not specified, the torrent file is\n" " printed to the standard out, except on windows\n" @@ -150,6 +152,9 @@ int main(int argc, char* argv[]) case 'f': flags |= create_torrent::calculate_file_hashes; break; + case 'l': + flags |= create_torrent::symlinks; + break; default: print_usage(); return 1; @@ -160,7 +165,7 @@ int main(int argc, char* argv[]) file_pool fp; std::string full_path = libtorrent::complete(argv[1]); - add_files(fs, full_path, file_filter); + add_files(fs, full_path, file_filter, flags); if (fs.num_files() == 0) { fputs("no files specified.\n", stderr); diff --git a/include/libtorrent/create_torrent.hpp b/include/libtorrent/create_torrent.hpp index 32bf1743b..6af990811 100644 --- a/include/libtorrent/create_torrent.hpp +++ b/include/libtorrent/create_torrent.hpp @@ -180,22 +180,32 @@ namespace libtorrent template void add_files_impl(file_storage& fs, std::string const& p - , std::string const& l, Pred pred) + , std::string const& l, Pred pred, boost::uint32_t flags) { std::string f = combine_path(p, l); if (!pred(f)) return; error_code ec; file_status s; - stat_file(f, &s, ec); + stat_file(f, &s, ec, (flags & create_torrent::symlinks) ? dont_follow_links : 0); if (ec) return; - if (s.mode & file_status::directory) + // recurse into directories + bool recurse = s.mode & file_status::directory; + + // if the file is not a link or we're following links, and it's a directory + // only then should we recurse +#ifndef TORRENT_WINDOWS + if ((s.mode & file_status::link) && (flags & create_torrent::symlinks)) + recurse = false; +#endif + + if (recurse) { for (directory i(f, ec); !i.done(); i.next(ec)) { std::string leaf = i.file(); if (ignore_subdir(leaf)) continue; - add_files_impl(fs, p, combine_path(l, leaf), pred); + add_files_impl(fs, p, combine_path(l, leaf), pred, flags); } } else @@ -204,7 +214,8 @@ namespace libtorrent int file_flags = get_file_attributes(f); // mask all bits to check if the file is a symlink - if (file_flags & file_storage::attribute_symlink) + if ((file_flags & file_storage::attribute_symlink) + && (flags & create_torrent::symlinks)) { std::string sym_path = get_symlink_path(f); fs.add_file(l, 0, file_flags, s.mtime, sym_path); @@ -218,14 +229,15 @@ namespace libtorrent } template - void add_files(file_storage& fs, std::string const& file, Pred p) + void add_files(file_storage& fs, std::string const& file, Pred p, boost::uint32_t flags = 0) { - detail::add_files_impl(fs, parent_path(complete(file)), filename(file), p); + detail::add_files_impl(fs, parent_path(complete(file)), filename(file), p, flags); } - inline void add_files(file_storage& fs, std::string const& file) + inline void add_files(file_storage& fs, std::string const& file, boost::uint32_t flags = 0) { - detail::add_files_impl(fs, parent_path(complete(file)), filename(file), detail::default_pred); + detail::add_files_impl(fs, parent_path(complete(file)), filename(file) + , detail::default_pred, flags); } struct piece_holder @@ -318,18 +330,20 @@ namespace libtorrent // wstring versions template - void add_files(file_storage& fs, std::wstring const& wfile, Pred p) + void add_files(file_storage& fs, std::wstring const& wfile, Pred p, boost::uint32_t flags = 0) { std::string utf8; wchar_utf8(wfile, utf8); - detail::add_files_impl(fs, parent_path(complete(utf8)), filename(utf8), p); + detail::add_files_impl(fs, parent_path(complete(utf8)) + , filename(utf8), p, flags); } - inline void add_files(file_storage& fs, std::wstring const& wfile) + inline void add_files(file_storage& fs, std::wstring const& wfile, boost::uint32_t flags = 0) { std::string utf8; wchar_utf8(wfile, utf8); - detail::add_files_impl(fs, parent_path(complete(utf8)), filename(utf8), detail::default_pred); + detail::add_files_impl(fs, parent_path(complete(utf8)) + , filename(utf8), detail::default_pred, flags); } template diff --git a/include/libtorrent/file.hpp b/include/libtorrent/file.hpp index 7fb91b171..4cbab5c73 100644 --- a/include/libtorrent/file.hpp +++ b/include/libtorrent/file.hpp @@ -104,8 +104,9 @@ namespace libtorrent int mode; }; + enum stat_flags_t { dont_follow_links = 1 }; TORRENT_EXPORT void stat_file(std::string const& f, file_status* s - , error_code& ec); + , error_code& ec, int flags = 0); TORRENT_EXPORT void rename(std::string const& f , std::string const& newf, error_code& ec); TORRENT_EXPORT void create_directories(std::string const& f diff --git a/src/create_torrent.cpp b/src/create_torrent.cpp index 9226e6b4d..f8555c21d 100644 --- a/src/create_torrent.cpp +++ b/src/create_torrent.cpp @@ -170,6 +170,7 @@ namespace libtorrent , m_merkle_torrent(ti.is_merkle_torrent()) , m_include_mtime(false) , m_include_symlinks(false) + , m_calculate_file_hashes(false) { TORRENT_ASSERT(ti.is_valid()); if (ti.creation_date()) m_creation_date = *ti.creation_date(); diff --git a/src/file.cpp b/src/file.cpp index 7931255ad..21e950724 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -126,7 +126,8 @@ BOOST_STATIC_ASSERT((libtorrent::file::no_buffer & libtorrent::file::attribute_m namespace libtorrent { - void stat_file(std::string const& inf, file_status* s, error_code& ec) + void stat_file(std::string const& inf, file_status* s + , error_code& ec, int flags) { ec.clear(); @@ -149,7 +150,12 @@ namespace libtorrent } #else struct stat ret; - if (::stat(f.c_str(), &ret) < 0) + int retval; + if (flags & dont_follow_links) + retval = ::lstat(f.c_str(), &ret); + else + retval = ::stat(f.c_str(), &ret); + if (retval < 0) { ec.assign(errno, boost::system::get_generic_category()); return;