fixed inconsistency when creating torrents with symlinks

This commit is contained in:
Arvid Norberg 2010-04-01 00:44:29 +00:00
parent a0a8c695ab
commit c51e0a2a86
7 changed files with 64 additions and 28 deletions

View File

@ -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

View File

@ -58,12 +58,16 @@ add_files
::
template <class Pred>
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 <class Pred>
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

View File

@ -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);

View File

@ -180,22 +180,32 @@ namespace libtorrent
template <class Pred>
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 <class Pred>
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 <class Pred>
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 <class Fun>

View File

@ -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

View File

@ -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();

View File

@ -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;