torrent: fix \0 escaping bug, add -c option to create new torrents
parent
45cc898e4a
commit
d8bde8f7b3
|
@ -5,21 +5,21 @@ torrent \- bittorrent client
|
|||
.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 @@ Before files can be transmitted, a torrent-file needs
|
|||
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 @@ To monitor the download progress, the
|
|||
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
|
||||
|
|
|
@ -46,9 +46,10 @@ enum {
|
|||
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 @@ Hfmt(Fmt *f)
|
|||
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)
|
||||
|
@ -744,6 +745,55 @@ Hfmt(Fmt *f)
|
|||
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
|
||||
mkdirs(char *s)
|
||||
{
|
||||
|
@ -800,25 +850,29 @@ killnote(void *, char *)
|
|||
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");
|
||||
}
|
||||
|
||||
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 @@ main(int argc, char *argv[])
|
|||
case 'v':
|
||||
vflag = 1;
|
||||
break;
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
debug++;
|
||||
break;
|
||||
|
@ -838,7 +895,14 @@ main(int argc, char *argv[])
|
|||
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 @@ main(int argc, char *argv[])
|
|||
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')
|
||||
|
|
Loading…
Reference in New Issue