Changeset 10783
- Timestamp:
- Jun 16, 2010, 2:27:24 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 7 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Makefile.am
r9794 r10783 20 20 third-party \ 21 21 libtransmission \ 22 utils \ 22 23 $(DAEMON_DIR) \ 23 24 $(CLI_DIR) \ -
trunk/cli/cli.c
r10640 r10783 31 31 #include <libtransmission/transmission.h> 32 32 #include <libtransmission/bencode.h> 33 #include <libtransmission/makemeta.h>34 33 #include <libtransmission/tr-getopt.h> 35 34 #include <libtransmission/utils.h> /* tr_wait_msec */ … … 40 39 #define MY_NAME "transmissioncli" 41 40 42 static tr_bool showInfo = 0;43 static tr_bool showScrape = 0;44 static tr_bool isPrivate = 0;45 41 static tr_bool verify = 0; 46 42 static sig_atomic_t gotsig = 0; … … 48 44 49 45 static const char * torrentPath = NULL; 50 static const char * sourceFile = NULL;51 static const char * comment = NULL;52 53 #define MAX_ANNOUNCE 12854 static tr_tracker_info announce[MAX_ANNOUNCE];55 static int announceCount = 0;56 46 57 47 static const struct tr_option options[] = 58 48 { 59 { 'a', "announce", "Set the new torrent's announce URL", "a", 1, "<url>" },60 49 { 'b', "blocklist", "Enable peer blocklists", "b", 0, NULL }, 61 50 { 'B', "no-blocklist", "Disable peer blocklists", "B", 0, NULL }, 62 { 'c', "comment", "Set the new torrent's comment", "c", 1, "<comment>" },63 51 { 'd', "downlimit", "Set max download speed in KiB/s", "d", 1, "<speed>" }, 64 52 { 'D', "no-downlimit", "Don't limit the download speed", "D", 0, NULL }, … … 68 56 { 'f', "finish", "Run a script when the torrent finishes", "f", 1, "<script>" }, 69 57 { 'g', "config-dir", "Where to find configuration files", "g", 1, "<path>" }, 70 { 'i', "info", "Show torrent details and exit", "i", 0, NULL },71 58 { 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", 0, NULL }, 72 59 { 'M', "no-portmap", "Disable portmapping", "M", 0, NULL }, 73 { 'n', "new", "Create a new torrent", "n", 1, "<source>" },74 60 { 'p', "port", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")", "p", 1, "<port>" }, 75 { 'r', "private", "Set the new torrent's 'private' flag", "r", 0, NULL },76 { 's', "scrape", "Scrape the torrent and exit", "s", 0, NULL },77 61 { 't', "tos", "Peer socket TOS (0 to 255, default=" TR_DEFAULT_PEER_SOCKET_TOS_STR ")", "t", 1, "<tos>" }, 78 62 { 'u', "uplimit", "Set max upload speed in KiB/s", "u", 1, "<speed>" }, … … 113 97 } 114 98 115 static int116 is_rfc2396_alnum( char ch )117 {118 return ( '0' <= ch && ch <= '9' )119 || ( 'A' <= ch && ch <= 'Z' )120 || ( 'a' <= ch && ch <= 'z' );121 }122 123 static void124 escape( char * out,125 const uint8_t * in,126 int in_len ) /* rfc2396 */127 {128 const uint8_t *end = in + in_len;129 130 while( in != end )131 if( is_rfc2396_alnum( *in ) )132 *out++ = (char) *in++;133 else134 out += tr_snprintf( out, 4, "%%%02X", (unsigned int)*in++ );135 136 *out = '\0';137 }138 139 99 static tr_bool waitingOnWeb; 140 100 … … 148 108 tr_ctorSetMetainfo( ctor, response, response_byte_count ); 149 109 waitingOnWeb = FALSE; 150 }151 152 static int leftToScrape = 0;153 154 static void155 scrapeDoneFunc( tr_session * session UNUSED,156 long response_code,157 const void * response,158 size_t response_byte_count,159 void * host )160 {161 tr_benc top, *files;162 163 if( !tr_bencLoad( response, response_byte_count, &top, NULL )164 && tr_bencDictFindDict( &top, "files", &files )165 && files->val.l.count >= 2 )166 {167 int64_t complete = -1, incomplete = -1, downloaded = -1;168 tr_benc * hash = &files->val.l.vals[1];169 tr_bencDictFindInt( hash, "complete", &complete );170 tr_bencDictFindInt( hash, "incomplete", &incomplete );171 tr_bencDictFindInt( hash, "downloaded", &downloaded );172 printf( "%4d seeders, %4d leechers, %5d downloads at %s\n",173 (int)complete, (int)incomplete, (int)downloaded,174 (char*)host );175 tr_bencFree( &top );176 }177 else178 fprintf( stderr, "Unable to parse response (http code %lu) at %s",179 response_code,180 (char*)host );181 182 --leftToScrape;183 184 tr_free( host );185 }186 187 static void188 dumpInfo( FILE * out,189 const tr_info * inf )190 {191 int i;192 int prevTier = -1;193 tr_file_index_t ff;194 195 fprintf( out, "hash:\t" );196 for( i = 0; i < SHA_DIGEST_LENGTH; ++i )197 fprintf( out, "%02x", inf->hash[i] );198 fprintf( out, "\n" );199 200 fprintf( out, "name:\t%s\n", inf->name );201 202 for( i = 0; i < inf->trackerCount; ++i )203 {204 if( prevTier != inf->trackers[i].tier )205 {206 prevTier = inf->trackers[i].tier;207 fprintf( out, "\ntracker tier #%d:\n", ( prevTier + 1 ) );208 }209 fprintf( out, "\tannounce:\t%s\n", inf->trackers[i].announce );210 }211 212 fprintf( out, "size:\t%" PRIu64 " (%" PRIu64 " * %d + %" PRIu64 ")\n",213 inf->totalSize, inf->totalSize / inf->pieceSize,214 inf->pieceSize, inf->totalSize % inf->pieceSize );215 216 if( inf->comment && *inf->comment )217 fprintf( out, "comment:\t%s\n", inf->comment );218 if( inf->creator && *inf->creator )219 fprintf( out, "creator:\t%s\n", inf->creator );220 if( inf->isPrivate )221 fprintf( out, "private flag set\n" );222 223 fprintf( out, "file(s):\n" );224 for( ff = 0; ff < inf->fileCount; ++ff )225 fprintf( out, "\t%s (%" PRIu64 ")\n", inf->files[ff].name,226 inf->files[ff].length );227 110 } 228 111 … … 305 188 tr_benc settings; 306 189 const char * configDir; 307 tr_bool haveSource;308 tr_bool haveAnnounce;309 190 uint8_t * fileContents; 310 191 size_t fileLength; … … 334 215 } 335 216 336 /* don't bind the port if we're just running the CLI337 to get metainfo or to create a torrent */338 if( showInfo || showScrape || ( sourceFile != NULL ) )339 tr_bencDictAddInt( &settings, TR_PREFS_KEY_PEER_PORT, -1 );340 341 217 h = tr_sessionInit( "cli", configDir, FALSE, &settings ); 342 218 343 haveSource = sourceFile && *sourceFile;344 haveAnnounce = announceCount > 0;345 346 if( haveSource && !haveAnnounce )347 fprintf( stderr, "Did you mean to create a torrent without a tracker's announce URL?\n" );348 349 if( haveSource ) /* creating a torrent */350 {351 int err;352 tr_metainfo_builder * b;353 fprintf( stderr, "creating torrent \"%s\"\n", torrentPath );354 355 b = tr_metaInfoBuilderCreate( sourceFile );356 tr_makeMetaInfo( b, torrentPath, announce, announceCount, comment, isPrivate );357 while( !b->isDone )358 {359 tr_wait_msec( 1000 );360 printf( "." );361 }362 363 err = b->result;364 tr_metaInfoBuilderFree( b );365 return err;366 }367 368 219 ctor = tr_ctorNew( h ); 369 220 370 221 fileContents = tr_loadFile( torrentPath, &fileLength ); 371 tr_ctorSetPaused( ctor, TR_FORCE, showScrape);222 tr_ctorSetPaused( ctor, TR_FORCE, FALSE ); 372 223 if( fileContents != NULL ) { 373 224 tr_ctorSetMetainfo( ctor, fileContents, fileLength ); … … 380 231 } 381 232 tr_free( fileContents ); 382 383 if( showScrape )384 {385 tr_info info;386 387 if( !tr_torrentParse( ctor, &info ) )388 {389 int i;390 const time_t start = time( NULL );391 for( i = 0; i < info.trackerCount; ++i )392 {393 if( info.trackers[i].scrape )394 {395 const char * scrape = info.trackers[i].scrape;396 char escaped[SHA_DIGEST_LENGTH * 3 + 1];397 char * url, *host;398 escape( escaped, info.hash, SHA_DIGEST_LENGTH );399 url = tr_strdup_printf( "%s%cinfo_hash=%s",400 scrape,401 strchr( scrape,402 '?' ) ? '&' : '?',403 escaped );404 tr_urlParse( scrape, -1, NULL, &host, NULL, NULL );405 ++leftToScrape;406 407 tr_webRun( h, url, NULL, scrapeDoneFunc, host );408 tr_free( url );409 }410 }411 412 fprintf( stderr, "scraping %d trackers:\n", leftToScrape );413 414 while( leftToScrape > 0 && ( ( time( NULL ) - start ) < 20 ) )415 tr_wait_msec( 250 );416 }417 goto cleanup;418 }419 420 if( showInfo )421 {422 tr_info info;423 424 if( !tr_torrentParse( ctor, &info ) )425 {426 dumpInfo( stdout, &info );427 tr_metainfoFree( &info );428 }429 430 tr_ctorFree( ctor );431 goto cleanup;432 }433 233 434 234 tor = tr_torrentNew( ctor, &error ); … … 496 296 } 497 297 498 cleanup:499 500 298 tr_sessionSaveSettings( h, configDir, &settings ); 501 299 … … 522 320 switch( c ) 523 321 { 524 case 'a': if( announceCount + 1 < MAX_ANNOUNCE ) {525 announce[announceCount].tier = announceCount;526 announce[announceCount].announce = (char*) optarg;527 ++announceCount;528 }529 break;530 322 case 'b': tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, TRUE ); 531 323 break; 532 324 case 'B': tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, FALSE ); 533 break;534 case 'c': comment = optarg;535 325 break; 536 326 case 'd': tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED, atoi( optarg ) ); … … 544 334 case 'g': /* handled above */ 545 335 break; 546 case 'i': showInfo = 1;547 break;548 336 case 'm': tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, TRUE ); 549 337 break; 550 338 case 'M': tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, FALSE ); 551 339 break; 552 case 'n': sourceFile = optarg; break;553 340 case 'p': tr_bencDictAddInt( d, TR_PREFS_KEY_PEER_PORT, atoi( optarg ) ); 554 break;555 case 'r': isPrivate = 1;556 break;557 case 's': showScrape = 1;558 341 break; 559 342 case 't': tr_bencDictAddInt( d, TR_PREFS_KEY_PEER_SOCKET_TOS, atoi( optarg ) ); -
trunk/cli/transmissioncli.1
r9122 r10783 25 25 .Fl h 26 26 .Nm 27 .Fl i28 .Ar torrent-file29 .Nm30 .Fl s31 .Ar torrent-file32 .Nm33 .Fl n Ar sourcefile34 .Op Fl a Ar url35 .Op Fl c Ar comment36 .Op Fl r37 .Ar new-torrent-file38 .Nm39 27 .Op Fl b | B 40 28 .Op Fl d Ar number | Fl D … … 59 47 The options are as follows: 60 48 .Bl -tag -width Ds 61 .It Fl a, Fl -announce Ar announce-url62 When creating a new torrent, set its announce URL63 49 .It Fl b Fl -blocklist 64 50 Enable peer blocklists. Transmission understands the bluetack blocklist file format. … … 66 52 .It Fl B Fl -no-blocklist 67 53 Disble blocklists. 68 .It Fl c, Fl -comment Ar comment-text69 When creating a new torrent, set its comment field70 54 .It Fl d, -downlimit Ar number 71 55 Set the maximum download speed in KB/s … … 85 69 .It Fl h, Fl -help 86 70 Prints a short usage summary. 87 .It Fl i, Fl -info88 Shows torrent details and exit89 71 .It Fl m, Fl -portmap 90 72 Enable portmapping via NAT-PMP or UPnP … … 95 77 .It Fl p, -port Ar port 96 78 Set the port to listen for incoming peers. (Default: 51413) 97 .It Fl r, Fl -private98 When creating a new torrent, set its 'private' flag99 .It Fl s, -scrape100 Print the current number of seeders and leechers for the specified torrent101 79 .It Fl t, -tos 102 80 Set the peer socket TOS for local router-based traffic shaping. -
trunk/configure.ac
r10767 r10783 477 477 doc/Makefile 478 478 libtransmission/Makefile 479 utils/Makefile 479 480 third-party/Makefile 480 481 third-party/miniupnp/Makefile -
trunk/daemon/daemon.c
r10782 r10783 2 2 * This file Copyright (C) 2008-2010 Mnemosyne LLC 3 3 * 4 * This file is licensed by the GPL version 2. Works owned by the5 * Transmission project are granted a special exemption to clause 2(b)6 * so that the bulk of its code can remain under the MIT license.7 * This exemption does not extend to derived works not owned by8 * the Transmission project.4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 6 * as published by the Free Software Foundation. 7 * 8 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 9 9 * 10 10 * $Id$ -
trunk/daemon/remote.c
r10782 r10783 2 2 * This file Copyright (C) 2008-2010 Mnemosyne LLC 3 3 * 4 * This file is licensed by the GPL version 2. Works owned by the5 * Transmission project are granted a special exemption to clause 2(b)6 * so that the bulk of its code can remain under the MIT license.7 * This exemption does not extend to derived works not owned by8 * the Transmission project.4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 6 * as published by the Free Software Foundation. 7 * 8 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 9 9 * 10 10 * $Id$ -
trunk/daemon/watch.c
r10742 r10783 2 2 * This file Copyright (C) 2009-2010 Mnemosyne LLC 3 3 * 4 * This file is licensed by the GPL version 2. Works owned by the5 * Transmission project are granted a special exemption to clause 2(b)6 * so that the bulk of its code can remain under the MIT license.7 * This exemption does not extend to derived works not owned by8 * the Transmission project.4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 6 * as published by the Free Software Foundation. 7 * 8 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 9 9 * 10 10 * $Id$ -
trunk/libtransmission/bencode.c
r10634 r10783 422 422 ret = val->val.l.vals + i; 423 423 return ret; 424 } 425 426 int 427 tr_bencListRemove( tr_benc * list, size_t i ) 428 { 429 if( tr_bencIsList( list ) && ( i < list->val.l.count ) ) 430 { 431 tr_bencFree( &list->val.l.vals[i] ); 432 tr_removeElementFromArray( list->val.l.vals, i, sizeof( tr_benc ), list->val.l.count-- ); 433 return 1; 434 } 435 436 return 0; 424 437 } 425 438 -
trunk/libtransmission/bencode.h
r10084 r10783 157 157 tr_benc * tr_bencListChild( tr_benc * list, size_t n ); 158 158 159 int tr_bencListRemove( tr_benc *, size_t n ); 160 159 161 /*** 160 162 **** -
trunk/libtransmission/list.h
r10524 r10783 12 12 13 13 #ifndef __TRANSMISSION__ 14 #error only libtransmission should #include this header.14 #error only libtransmission should #include this header. 15 15 #endif 16 16 -
trunk/libtransmission/utils.c
r10736 r10783 115 115 tr_setMessageLevel( int level ) 116 116 { 117 tr_lockLock( messageLock );118 119 117 messageLevel = MAX( 0, level ); 120 121 tr_lockUnlock( messageLock );122 118 } 123 119
Note: See TracChangeset
for help on using the changeset viewer.