@@ 1,31 1,90 @@
use crypto::sha1;
use encoding::hex;
use fmt;
+use fs;
+use getopt;
+use io;
use os;
+use strings;
use torrent;
+type config = struct {
+ files: bool,
+ pieces: bool,
+};
+
export fn main() void = {
- const tor = match (torrent::read(os::stdin)) {
+ const cmd = getopt::parse(os::args,
+ "print bittorrent file details",
+ ('f', "print list of files"),
+ ('p', "print list of pieces"),
+ "<files...>",
+ );
+ defer getopt::finish(&cmd);
+
+ let conf = config { ... };
+ for (let i = 0z; i < len(cmd.opts); i += 1) {
+ const opt = cmd.opts[i];
+ switch (opt.0) {
+ case 'f' =>
+ conf.files = true;
+ case 'p' =>
+ conf.pieces = true;
+ case => abort();
+ };
+ };
+
+ if (len(cmd.args) == 0) {
+ dump(&conf, os::stdin);
+ };
+
+ for (let i = 0z; i < len(cmd.args); i += 1) {
+ const file = match (os::open(cmd.args[i])) {
+ case let f: io::file =>
+ yield f;
+ case let err: fs::error =>
+ fmt::fatal("Error opening {}: {}",
+ cmd.args[i], fs::strerror(err));
+ };
+ dump(&conf, file);
+ };
+};
+
+fn dump(conf: *config, in: io::handle) void = {
+ const tor = match (torrent::read(in)) {
case let err: torrent::error =>
fmt::fatal(torrent::strerror(err));
case let tor: *torrent::torrent =>
yield tor;
};
defer torrent::torrent_free(tor);
- fmt::printfln("announce: {}", tor.announce)!;
+
fmt::printfln("name: {}", tor.info.name)!;
+ fmt::printfln("announce: {}", tor.announce)!;
match (tor.info.length) {
case void =>
yield;
case let z: size =>
- fmt::printfln("bytes: {}", z)!;
+ fmt::printfln("{} bytes", z)!;
+ };
+
+ if (conf.files) {
+ for (let i = 0z; i < len(tor.info.files); i += 1) {
+ const file = tor.info.files[i];
+ // XXX: Could avoid this allocation
+ const path = strings::join("/", file.path...);
+ fmt::printfln("{} ({} bytes)", path, file.length)!;
+ free(path);
+ };
};
- for (let i = 0z; i < len(tor.info.pieces); i += sha1::SIZE) {
- const piece = tor.info.pieces[i..i + sha1::SIZE];
- fmt::printf("{}: ", i)!;
- hex::encode(os::stdout, piece)!;
- fmt::println()!;
+ if (conf.pieces) {
+ for (let i = 0z; i < len(tor.info.pieces); i += sha1::SIZE) {
+ const piece = tor.info.pieces[i..i + sha1::SIZE];
+ fmt::printf("{}: ", i)!;
+ hex::encode(os::stdout, piece)!;
+ fmt::println()!;
+ };
};
};