shithub: riscv

Download patch

ref: d8bde8f7b35078dd07ee76bc493031aac315fcbb
parent: 45cc898e4a626cc67312629ae6fe2d25e6cfd733
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Tue Oct 25 10:09:41 EDT 2011

torrent: fix \0 escaping bug, add -c option to create new torrents

--- a/sys/man/1/torrent
+++ b/sys/man/1/torrent
@@ -5,21 +5,21 @@
 .B ip/torrent
 [
 .B -d
-]
-[
+] [
 .B -v
-]
-[
+] [
 .B -p
-]
-[
+] [
 .B -m
 .I mtpt
-]
-[
+] [
+.B -t
+.I url
+] [
 .B -s
-]
-[
+] [
+.B -c
+] [
 .I file
 ]
 .SH DESCRIPTION
@@ -36,7 +36,24 @@
 to be created describing the pieces of the files and
 other meta-data like network addresses of the trackers.
 .PP
-.I Torrent
+This is done with the
+.B -c
+option. If provided,
+.I torrent
+reads the file given at the final
+.I file
+argument (or standard-input when omited) and writes
+a torrent file to standard-output and exits.
+A tracker
+.I url
+should be given with the
+.B -t
+option in that case.
+.PP
+Without the
+.B -c
+option,
+.I torrent
 downloads the files that are described in the torrent-file
 given by the
 .I file
@@ -74,7 +91,13 @@
 option can be given to cause the completed and total number of
 pieces written as a line of text to standard-output in one
 second intervals.
-.SH EXAMPLE
+.SH EXAMPLES
+Create new torrent file
+.EX
+ip/torrent -t http://exodus.desync.com/announce \\
+	-c 9atom.iso >9atom.torrent
+.EE
+.LP
 Download the latest iso file of the distribution 
 .EX
 cd /tmp
--- a/sys/src/cmd/ip/torrent.c
+++ b/sys/src/cmd/ip/torrent.c
@@ -46,9 +46,10 @@
 	MAXIO = 16*1024,
 };
 
-int debug, sflag, pflag, vflag;
+int debug;
 int killgroup = -1;
 int port = 6881;
+char *deftrack = "http://exodus.desync.com/announce";
 char *mntweb = "/mnt/web";
 uchar infohash[20];
 uchar peerid[20];
@@ -736,7 +737,7 @@
 	else
 		e = s + strlen((char*)s);
 	for(; s < e; s++)
-		if(fmtprint(f, ((*s >= '0' && *s <= '9') || 
+		if(fmtprint(f, *s && ((*s >= '0' && *s <= '9') || 
 			(*s >= 'a' && *s <= 'z') ||
 			(*s >= 'A' && *s <= 'Z') || 
 			strchr(".-_~", *s)) ? "%c" : "%%%.2x", *s) < 0)
@@ -745,6 +746,55 @@
 }
 
 int
+mktorrent(int fd, char *url)
+{
+	uchar *b, h[20];
+	Dir *d;
+	int n;
+
+	if((d = dirfstat(fd)) == nil)
+		return -1;
+	if(d->qid.type == QTDIR){
+		free(d);
+		werrstr("file is a directory");
+		return -1;
+	}
+	if(d->length == 0){
+		free(d);
+		werrstr("empty file");
+		return -1;
+	}
+	blocksize = 1024*1024;
+	npieces = (d->length + blocksize-1) / blocksize;
+	print("d");
+	print("8:announce%ld:%s", strlen(url), url);
+	print("4:info");
+	print("d");
+	print("4:name%ld:%s", strlen(d->name), d->name);
+	print("6:lengthi%llde", d->length);
+	print("12:piece lengthi%de", blocksize);
+	print("6:pieces%d:", npieces*sizeof(h));
+	free(d);
+	b = malloc(blocksize);
+	while((n = readn(fd, b, blocksize)) > 0){
+		sha1(b, n, h, nil);
+		if(write(1, h, sizeof(h)) != sizeof(h)){
+			free(b);
+			return -1;
+		}
+		npieces--;
+	}
+	free(b);
+	if(npieces){
+		werrstr("read failed: %r");
+		return -1;
+	}
+	print("e");
+	print("e");
+	return 0;
+}
+
+int
 mkdirs(char *s)
 {
 	char *p;
@@ -800,7 +850,7 @@
 void
 usage(void)
 {
-	fprint(2, "usage: %s [ -vsdp ] [ -m mtpt ] [ torrentfile ]\n", argv0);
+	fprint(2, "usage: %s [ -vsdpc ] [ -m mtpt ] [ -t url ] [ file ]\n", argv0);
 	exits("usage");
 }
 
@@ -807,18 +857,22 @@
 void
 main(int argc, char *argv[])
 {
+	int sflag, pflag, vflag, cflag, fd, i, n;
 	Dict *info, *torrent, *d;
+	char *p, *s, *e, *url;
 	File **fp, *f;
-	char *p, *s, *e;
-	int fd, i, n;
 	vlong len;
 
 	fmtinstall('H', Hfmt);
-
+	url = nil;
+	sflag = pflag = vflag = cflag = 0;
 	ARGBEGIN {
 	case 'm':
 		mntweb = EARGF(usage());
 		break;
+	case 't':
+		url = EARGF(usage());
+		break;
 	case 's':
 		sflag = 1;
 		break;
@@ -828,6 +882,9 @@
 	case 'v':
 		vflag = 1;
 		break;
+	case 'c':
+		cflag = 1;
+		break;
 	case 'd':
 		debug++;
 		break;
@@ -838,7 +895,14 @@
 	fd = 0;
 	if(*argv)
 		if((fd = open(*argv, OREAD)) < 0)
-			sysfatal("open torrent: %r");
+			sysfatal("open: %r");
+	if(cflag){
+		if(url == nil)
+			url = deftrack;
+		if(mktorrent(fd, url) < 0)
+			sysfatal("%r");
+		exits(0);
+	}
 	if((n = readall(fd, &p)) <= 0)
 		sysfatal("read torrent: %r");
 	bparse(p, p+n, &torrent);
@@ -925,6 +989,7 @@
 		for(i=8; i<sizeof(peerid); i++)
 			peerid[i] = nrand(10)+'0';
 		server();
+		tracker(url);
 		tracker(dstr(dlook(torrent, "announce")));
 		for(d = dlook(torrent, "announce-list"); d && d->typ == 'l'; d = d->next)
 			if(d->val && d->val->typ == 'l')