torrent: fix \0 escaping bug, add -c option to create new torrents
This commit is contained in:
parent
45cc898e4a
commit
d8bde8f7b3
2 changed files with 107 additions and 19 deletions
|
@ -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
|
||||||
|
|
|
@ -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')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue