~sircmpwn/btqd

2e6ffcca04773b268d3de344fba47f03608f6399 — Drew DeVault 2 years ago 6db5c13
btinfo: flesh out command
1 files changed, 67 insertions(+), 8 deletions(-)

M cmd/btinfo/main.ha
M cmd/btinfo/main.ha => cmd/btinfo/main.ha +67 -8
@@ 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()!;
		};
	};
};