33
33
#include "libtorrent/create_torrent.hpp"
34
34
#include "libtorrent/file_pool.hpp"
35
35
#include "libtorrent/storage.hpp"
36
#include "libtorrent/escape_string.hpp"
37
#include <boost/date_time/posix_time/posix_time.hpp>
38
#include <boost/date_time/gregorian/gregorian.hpp>
38
#include <boost/date_time/posix_time/posix_time_types.hpp>
39
#include <boost/date_time/gregorian/greg_date.hpp>
39
40
#include <boost/bind.hpp>
41
#include <boost/next_prior.hpp>
43
#include <sys/types.h>
46
#define MAX_SYMLINK_PATH 200
41
48
namespace gr = boost::gregorian;
43
50
namespace libtorrent
45
create_torrent::create_torrent(file_storage& fs, int size)
52
// defined in torrent_info.cpp
53
int merkle_num_leafs(int);
54
int merkle_num_nodes(int);
55
int merkle_get_parent(int);
56
int merkle_get_sibling(int);
60
int TORRENT_EXPORT get_file_attributes(boost::filesystem::path const& p)
62
#ifdef TORRENT_WINDOWS
65
std::wstring path = convert_to_wstring(p.external_file_string());
66
DWORD attr = GetFileAttributesW(path.c_str());
68
std::string path = convert_to_native(p.external_file_string());
69
DWORD attr = GetFileAttributesA(path.c_str());
71
if (attr & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden;
75
if (lstat(convert_to_native(p.external_file_string()).c_str(), &s) < 0) return 0;
77
if (s.st_mode & S_IXUSR)
78
file_attr += file_storage::attribute_executable;
79
if(S_ISLNK(s.st_mode))
80
file_attr += file_storage::attribute_symlink;
86
int TORRENT_EXPORT get_file_attributes(boost::filesystem::wpath const& p)
88
#ifdef TORRENT_WINDOWS
89
std::wstring const& path = p.external_file_string();
90
DWORD attr = GetFileAttributesW(path.c_str());
91
if (attr & FILE_ATTRIBUTE_HIDDEN) return file_storage::attribute_hidden;
95
wchar_utf8(p.string(), native);
96
native = convert_to_native(native);
99
if (lstat(native.c_str(), &s) < 0) return 0;
101
if (s.st_mode & S_IXUSR)
102
file_attr += file_storage::attribute_executable;
103
if (S_ISLNK(s.st_mode))
104
file_attr += file_storage::attribute_symlink;
108
#endif // TORRENT_USE_WPATH
110
std::time_t get_file_mtime(char const* path)
112
#ifdef TORRENT_WINDOWS
114
if (::_stat(path, &s) < 0) return 0;
117
if (lstat(path, &s) < 0) return 0;
122
std::time_t TORRENT_EXPORT get_file_mtime(boost::filesystem::path const& p)
124
#if defined TORRENT_WINDOWS && TORRENT_USE_WPATH
125
std::wstring path = convert_to_wstring(p.external_file_string());
127
if (::_wstat(path.c_str(), &s) < 0) return 0;
130
std::string path = convert_to_native(p.external_file_string());
131
return get_file_mtime(p.string().c_str());
135
#if TORRENT_USE_WPATH
136
std::time_t TORRENT_EXPORT get_file_mtime(boost::filesystem::wpath const& p)
138
#ifdef TORRENT_WINDOWS
140
if (::_wstat(p.string().c_str(), &s) < 0) return 0;
144
wchar_utf8(p.string(), utf8);
145
utf8 = convert_to_native(utf8);
146
return get_file_mtime(utf8.c_str());
149
#endif // TORRENT_USE_WPATH
151
#ifndef TORRENT_WINDOWS
152
boost::filesystem::path get_symlink_path_impl(char const* path)
154
char buf[MAX_SYMLINK_PATH];
155
int char_read = readlink(path,buf,MAX_SYMLINK_PATH);
156
if (char_read < 0) return "";
157
if (char_read < MAX_SYMLINK_PATH) buf[char_read] = 0;
163
boost::filesystem::path TORRENT_EXPORT get_symlink_path(boost::filesystem::path const& p)
165
#if defined TORRENT_WINDOWS
168
std::string path = convert_to_native(p.external_file_string());
169
return get_symlink_path_impl(p.string().c_str());
173
#if TORRENT_USE_WPATH
174
boost::filesystem::path TORRENT_EXPORT get_symlink_path(boost::filesystem::wpath const& p)
176
#ifdef TORRENT_WINDOWS
180
wchar_utf8(p.string(), utf8);
181
utf8 = convert_to_native(utf8);
182
return get_symlink_path_impl(utf8.c_str());
185
#endif // TORRENT_USE_WPATH
189
create_torrent::create_torrent(file_storage& fs, int piece_size, int pad_file_limit, int flags)
47
191
, m_creation_date(pt::second_clock::universal_time())
48
192
, m_multifile(fs.num_files() > 1)
49
193
, m_private(false)
194
, m_merkle_torrent(flags & merkle)
195
, m_include_mtime(flags & modification_time)
196
, m_include_symlinks(flags & symlinks)
51
198
TORRENT_ASSERT(fs.num_files() > 0);
59
206
if (!m_multifile && m_files.at(0).path.has_parent_path()) m_multifile = true;
209
// a piece_size of 0 means automatic
210
if (piece_size == 0 && !m_merkle_torrent)
212
const int target_size = 40 * 1024;
213
piece_size = fs.total_size() / (target_size / 20);
216
for (; i < 2*1024*1024; i *= 2)
218
if (piece_size > i) continue;
223
else if (piece_size == 0 && m_merkle_torrent)
225
piece_size = 64*1024;
62
228
// make sure the size is an even power of 2
64
230
for (int i = 0; i < 32; ++i)
232
if (piece_size & (1 << i))
68
TORRENT_ASSERT((size & ~(1 << i)) == 0);
234
TORRENT_ASSERT((piece_size & ~(1 << i)) == 0);
73
m_files.set_piece_length(size);
239
m_files.set_piece_length(piece_size);
240
if (flags & optimize)
241
m_files.optimize(pad_file_limit);
74
242
m_files.set_num_pieces(static_cast<int>(
75
243
(m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length()));
76
244
m_piece_hash.resize(m_files.num_pieces());
79
create_torrent::create_torrent(file_storage& fs)
247
create_torrent::create_torrent(torrent_info const& ti)
248
: m_files(const_cast<file_storage&>(ti.files()))
81
249
, m_creation_date(pt::second_clock::universal_time())
82
, m_multifile(fs.num_files() > 1)
250
, m_multifile(ti.num_files() > 1)
251
, m_private(ti.priv())
252
, m_merkle_torrent(ti.is_merkle_torrent())
253
, m_include_mtime(false)
254
, m_include_symlinks(false)
85
TORRENT_ASSERT(fs.num_files() > 0);
87
// return instead of crash in release mode
88
if (fs.num_files() == 0) return;
90
#if BOOST_VERSION < 103600
91
if (!m_multifile && m_files.at(0).path.has_branch_path()) m_multifile = true;
93
if (!m_multifile && m_files.at(0).path.has_parent_path()) m_multifile = true;
96
const int target_size = 40 * 1024;
97
int size = fs.total_size() / (target_size / 20);
99
for (int i = 4*1024*1024; i > 16*1024; i /= 2)
101
if (size < i) continue;
106
m_files.set_piece_length(size);
107
m_files.set_num_pieces(static_cast<int>(
108
(m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length()));
256
TORRENT_ASSERT(ti.is_valid());
257
if (ti.creation_date()) m_creation_date = *ti.creation_date();
259
if (!ti.creator().empty()) set_creator(ti.creator().c_str());
260
if (!ti.comment().empty()) set_comment(ti.comment().c_str());
262
torrent_info::nodes_t const& nodes = ti.nodes();
263
for (torrent_info::nodes_t::const_iterator i = nodes.begin()
264
, end(nodes.end()); i != end; ++i)
267
std::vector<libtorrent::announce_entry> const& trackers = ti.trackers();
268
for (std::vector<libtorrent::announce_entry>::const_iterator i = trackers.begin()
269
, end(trackers.end()); i != end; ++i)
270
add_tracker(i->url, i->tier);
272
std::vector<std::string> const& web_seeds = ti.url_seeds();
273
for (std::vector<std::string>::const_iterator i = web_seeds.begin()
274
, end(web_seeds.end()); i != end; ++i)
109
277
m_piece_hash.resize(m_files.num_pieces());
278
for (int i = 0; i < num_pieces(); ++i) set_hash(i, ti.hash_for_piece(i));
280
m_info_dict = bdecode(&ti.metadata()[0], &ti.metadata()[0] + ti.metadata_size());
281
m_info_hash = ti.info_hash();
112
284
entry create_torrent::generate() const
114
286
TORRENT_ASSERT(m_files.piece_length() > 0);
116
290
if (m_files.num_files() == 0)
118
// TODO: throw something here
125
293
if (!m_urls.empty()) dict["announce"] = m_urls.front().first;
187
355
entry& info = dict["info"];
356
if (m_info_dict.type() == entry::dictionary_t)
188
362
info["name"] = m_files.name();
190
364
if (m_private) info["private"] = 1;
192
366
if (!m_multifile)
368
if (m_include_mtime) info["mtime"] = m_files.at(0).mtime;
194
369
info["length"] = m_files.at(0).size;
370
if (m_files.at(0).pad_file || m_files.at(0).hidden_attribute || m_files.at(0).executable_attribute || m_files.at(0).symlink_attribute)
372
std::string& attr = info["attr"].string();
373
if (m_files.at(0).pad_file) attr += 'p';
374
if (m_files.at(0).hidden_attribute) attr += 'h';
375
if (m_files.at(0).executable_attribute) attr += 'x';
376
if (m_include_symlinks && m_files.at(0).symlink_attribute) attr += 'l';
378
if (m_include_symlinks && m_files.at(0).symlink_attribute)
380
entry& sympath_e = info["symlink path"];
382
for (fs::path::iterator j = (m_files.at(0).symlink_path.begin());
383
j != m_files.at(0).symlink_path.end(); ++j)
385
sympath_e.list().push_back(entry(*j));
220
414
path_e.list().push_back(entry(*j));
416
if (i->pad_file || i->hidden_attribute || i->executable_attribute || i->symlink_attribute)
418
std::string& attr = file_e["attr"].string();
419
if (i->pad_file) attr += 'p';
420
if (i->hidden_attribute) attr += 'h';
421
if (i->executable_attribute) attr += 'x';
422
if (m_include_symlinks && i->symlink_attribute) attr += 'l';
424
if (m_include_symlinks && i->symlink_attribute)
426
entry& sympath_e = file_e["symlink path"];
428
for (fs::path::iterator j = (i->symlink_path.begin());
429
j != i->symlink_path.end(); ++j)
431
sympath_e.list().push_back(entry(*j));
226
438
info["piece length"] = m_files.piece_length();
227
entry& pieces = info["pieces"];
229
std::string& p = pieces.string();
231
for (std::vector<sha1_hash>::const_iterator i = m_piece_hash.begin();
232
i != m_piece_hash.end(); ++i)
234
p.append((char*)i->begin(), (char*)i->end());
439
if (m_merkle_torrent)
441
std::vector<sha1_hash> merkle_tree;
443
int num_leafs = merkle_num_leafs(m_files.num_pieces());
444
int num_nodes = merkle_num_nodes(num_leafs);
445
int first_leaf = num_nodes - num_leafs;
446
merkle_tree.resize(num_nodes);
447
int num_pieces = m_piece_hash.size();
448
for (int i = 0; i < num_pieces; ++i)
449
merkle_tree[first_leaf + i] = m_piece_hash[i];
451
for (int i = num_pieces; i < num_leafs; ++i)
452
merkle_tree[first_leaf + i] = filler;
454
// now that we have initialized all leaves, build
455
// each level bottom-up
456
int level_start = first_leaf;
457
int level_size = num_leafs;
458
while (level_start > 0)
460
int parent = merkle_get_parent(level_start);
461
for (int i = level_start; i < level_start + level_size; i += 2, ++parent)
464
h.update((char const*)&merkle_tree[i][0], 20);
465
h.update((char const*)&merkle_tree[i+1][0], 20);
466
merkle_tree[parent] = h.final();
468
level_start = merkle_get_parent(level_start);
471
TORRENT_ASSERT(level_size == 1);
472
std::string& p = info["root hash"].string();
473
p.assign((char const*)&merkle_tree[0][0], 20);
477
std::string& p = info["pieces"].string();
479
for (std::vector<sha1_hash>::const_iterator i = m_piece_hash.begin();
480
i != m_piece_hash.end(); ++i)
482
p.append((char*)i->begin(), sha1_hash::size);
237
486
std::vector<char> buf;