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

This commit is contained in:
cinap_lenrek 2011-10-25 14:09:41 +02:00
parent 45cc898e4a
commit d8bde8f7b3
2 changed files with 107 additions and 19 deletions

View file

@ -5,21 +5,21 @@ torrent \- bittorrent client
.B ip/torrent .B ip/torrent
[ [
.B -d .B -d
] ] [
[
.B -v .B -v
] ] [
[
.B -p .B -p
] ] [
[
.B -m .B -m
.I mtpt .I mtpt
] ] [
[ .B -t
.I url
] [
.B -s .B -s
] ] [
[ .B -c
] [
.I file .I file
] ]
.SH DESCRIPTION .SH DESCRIPTION
@ -36,7 +36,24 @@ Before files can be transmitted, a torrent-file needs
to be created describing the pieces of the files and to be created describing the pieces of the files and
other meta-data like network addresses of the trackers. other meta-data like network addresses of the trackers.
.PP .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 downloads the files that are described in the torrent-file
given by the given by the
.I file .I file
@ -74,7 +91,13 @@ To monitor the download progress, the
option can be given to cause the completed and total number of option can be given to cause the completed and total number of
pieces written as a line of text to standard-output in one pieces written as a line of text to standard-output in one
second intervals. 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 Download the latest iso file of the distribution
.EX .EX
cd /tmp cd /tmp

View file

@ -46,9 +46,10 @@ enum {
MAXIO = 16*1024, MAXIO = 16*1024,
}; };
int debug, sflag, pflag, vflag; int debug;
int killgroup = -1; int killgroup = -1;
int port = 6881; int port = 6881;
char *deftrack = "http://exodus.desync.com/announce";
char *mntweb = "/mnt/web"; char *mntweb = "/mnt/web";
uchar infohash[20]; uchar infohash[20];
uchar peerid[20]; uchar peerid[20];
@ -736,7 +737,7 @@ Hfmt(Fmt *f)
else else
e = s + strlen((char*)s); e = s + strlen((char*)s);
for(; s < e; 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') ||
(*s >= 'A' && *s <= 'Z') || (*s >= 'A' && *s <= 'Z') ||
strchr(".-_~", *s)) ? "%c" : "%%%.2x", *s) < 0) strchr(".-_~", *s)) ? "%c" : "%%%.2x", *s) < 0)
@ -744,6 +745,55 @@ Hfmt(Fmt *f)
return 0; return 0;
} }
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 int
mkdirs(char *s) mkdirs(char *s)
{ {
@ -800,25 +850,29 @@ killnote(void *, char *)
void void
usage(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"); exits("usage");
} }
void void
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int sflag, pflag, vflag, cflag, fd, i, n;
Dict *info, *torrent, *d; Dict *info, *torrent, *d;
char *p, *s, *e, *url;
File **fp, *f; File **fp, *f;
char *p, *s, *e;
int fd, i, n;
vlong len; vlong len;
fmtinstall('H', Hfmt); fmtinstall('H', Hfmt);
url = nil;
sflag = pflag = vflag = cflag = 0;
ARGBEGIN { ARGBEGIN {
case 'm': case 'm':
mntweb = EARGF(usage()); mntweb = EARGF(usage());
break; break;
case 't':
url = EARGF(usage());
break;
case 's': case 's':
sflag = 1; sflag = 1;
break; break;
@ -828,6 +882,9 @@ main(int argc, char *argv[])
case 'v': case 'v':
vflag = 1; vflag = 1;
break; break;
case 'c':
cflag = 1;
break;
case 'd': case 'd':
debug++; debug++;
break; break;
@ -838,7 +895,14 @@ main(int argc, char *argv[])
fd = 0; fd = 0;
if(*argv) if(*argv)
if((fd = open(*argv, OREAD)) < 0) 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) if((n = readall(fd, &p)) <= 0)
sysfatal("read torrent: %r"); sysfatal("read torrent: %r");
bparse(p, p+n, &torrent); bparse(p, p+n, &torrent);
@ -925,6 +989,7 @@ main(int argc, char *argv[])
for(i=8; i<sizeof(peerid); i++) for(i=8; i<sizeof(peerid); i++)
peerid[i] = nrand(10)+'0'; peerid[i] = nrand(10)+'0';
server(); server();
tracker(url);
tracker(dstr(dlook(torrent, "announce"))); tracker(dstr(dlook(torrent, "announce")));
for(d = dlook(torrent, "announce-list"); d && d->typ == 'l'; d = d->next) for(d = dlook(torrent, "announce-list"); d && d->typ == 'l'; d = d->next)
if(d->val && d->val->typ == 'l') if(d->val && d->val->typ == 'l')