(trunk) #1220 'change top folder names' -- added support for this in libtransmission's C and RPC APIs.
This commit is contained in:
parent
d2d3671e22
commit
016f38f066
|
@ -406,13 +406,32 @@
|
|||
|
||||
Request arguments:
|
||||
|
||||
string | value type & description
|
||||
---------------------------+-------------------------------------------------
|
||||
"ids" | array torrent list, as described in 3.1
|
||||
"location" | string the new torrent location
|
||||
"move" | boolean if true, move from previous location.
|
||||
| otherwise, search "location" for files
|
||||
| (default: false)
|
||||
string | value type & description
|
||||
---------------------------------+-------------------------------------------------
|
||||
"ids" | array torrent list, as described in 3.1
|
||||
"location" | string the new torrent location
|
||||
"move" | boolean if true, move from previous location.
|
||||
| otherwise, search "location" for files
|
||||
| (default: false)
|
||||
|
||||
Response arguments: none
|
||||
|
||||
|
||||
3.7. Renaming a Torrent's Path
|
||||
|
||||
Method name: "torrent-rename-path"
|
||||
|
||||
For more information on the use of this function, see the
|
||||
transmission.h documentation of tr_torrentRenamePath()
|
||||
|
||||
Request arguments:
|
||||
|
||||
string | value type & description
|
||||
---------------------------------+-------------------------------------------------
|
||||
"ids" | array the torrent torrent list, as described in 3.1
|
||||
| (though, this function doesn't make sense for >1 torrent)
|
||||
"path" | string the path to the file or folder that will be renamed
|
||||
"name" | string the file or folder's new name
|
||||
|
||||
Response arguments: none
|
||||
|
||||
|
@ -581,141 +600,142 @@
|
|||
|
||||
The following changes have been made to the RPC interface:
|
||||
|
||||
RPC | Release | Backwards | |
|
||||
Vers. | Version | Compat? | Method | Description
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
1 | 1.30 | n/a | n/a | Initial version
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
2 | 1.34 | yes | torrent-get | new arg "peers"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
3 | 1.41 | yes | torrent-get | added "port" to "peers"
|
||||
| | yes | torrent-get | new arg "downloaders"
|
||||
| | yes | session-get | new arg "version"
|
||||
| | yes | torrent-remove | new method
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
4 | 1.50 | yes | session-get | new arg "rpc-version"
|
||||
| | yes | session-get | new arg "rpc-version-minimum"
|
||||
| | yes | session-stats | added "cumulative-stats"
|
||||
| | yes | session-stats | added "current-stats"
|
||||
| | yes | torrent-get | new arg "downloadDir"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
5 | 1.60 | yes | | new method "torrent-reannounce"
|
||||
| | yes | | new method "blocklist-update"
|
||||
| | yes | | new method "port-test"
|
||||
| | | |
|
||||
| | yes | session-get | new arg "alt-speed-begin"
|
||||
| | yes | session-get | new arg "alt-speed-down"
|
||||
| | yes | session-get | new arg "alt-speed-enabled"
|
||||
| | yes | session-get | new arg "alt-speed-end"
|
||||
| | yes | session-get | new arg "alt-speed-time-enabled"
|
||||
| | yes | session-get | new arg "alt-speed-up"
|
||||
| | yes | session-get | new arg "blocklist-enabled"
|
||||
| | yes | session-get | new arg "blocklist-size"
|
||||
| | yes | session-get | new arg "peer-limit-per-torrent"
|
||||
| | yes | session-get | new arg "seedRatioLimit"
|
||||
| | yes | session-get | new arg "seedRatioLimited"
|
||||
| | NO | session-get | renamed "pex-allowed" to "pex-enabled"
|
||||
| | NO | session-get | renamed "port" to "peer-port"
|
||||
| | NO | session-get | renamed "peer-limit" to "peer-limit-global"
|
||||
| | | |
|
||||
| | yes | torrent-add | new arg "files-unwanted"
|
||||
| | yes | torrent-add | new arg "files-wanted"
|
||||
| | yes | torrent-add | new arg "priority-high"
|
||||
| | yes | torrent-add | new arg "priority-low"
|
||||
| | yes | torrent-add | new arg "priority-normal"
|
||||
| | | |
|
||||
| | yes | torrent-set | new arg "bandwidthPriority"
|
||||
| | yes | torrent-set | new arg "honorsSessionLimits"
|
||||
| | yes | torrent-set | new arg "seedRatioLimit"
|
||||
| | yes | torrent-set | new arg "seedRatioLimited"
|
||||
| | NO | torrent-set | renamed "speed-limit-down" to "downloadLimit"
|
||||
| | NO | torrent-set | renamed "speed-limit-down-enabled" to "downloadLimited"
|
||||
| | NO | torrent-set | renamed "speed-limit-up" to "uploadLimit"
|
||||
| | NO | torrent-set | renamed "speed-limit-up-enabled" to "uploadLimited"
|
||||
| | | |
|
||||
| | yes | torrent-get | new arg "bandwidthPriority"
|
||||
| | yes | torrent-get | new arg "fileStats"
|
||||
| | yes | torrent-get | new arg "honorsSessionLimits"
|
||||
| | yes | torrent-get | new arg "percentDone"
|
||||
| | yes | torrent-get | new arg "pieces"
|
||||
| | yes | torrent-get | new arg "seedRatioLimit"
|
||||
| | yes | torrent-get | new arg "seedRatioMode"
|
||||
| | yes | torrent-get | new arg "torrentFile"
|
||||
| | yes | torrent-get | new ids option "recently-active"
|
||||
| | NO | torrent-get | removed arg "downloadLimitMode"
|
||||
| | NO | torrent-get | removed arg "uploadLimitMode"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
6 | 1.70 | yes | | new "method torrent-set-location"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
7 | 1.80 | NO | torrent-get | removed arg "announceResponse"
|
||||
| | NO | torrent-get | removed arg "announceURL"
|
||||
| | NO | torrent-get | removed arg "downloaders"
|
||||
| | NO | torrent-get | removed arg "lastAnnounceTime"
|
||||
| | NO | torrent-get | removed arg "lastScrapeTime"
|
||||
| | NO | torrent-get | removed arg "leechers"
|
||||
| | NO | torrent-get | removed arg "nextAnnounceTime"
|
||||
| | NO | torrent-get | removed arg "nextScrapeTime"
|
||||
| | NO | torrent-get | removed arg "scrapeResponse"
|
||||
| | NO | torrent-get | removed arg "scrapeURL"
|
||||
| | NO | torrent-get | removed arg "seeders"
|
||||
| | NO | torrent-get | removed arg "timesCompleted"
|
||||
| | NO | torrent-get | removed arg "swarmSpeed"
|
||||
| | yes | torrent-get | new arg "magnetLink"
|
||||
| | yes | torrent-get | new arg "metadataPercentComplete"
|
||||
| | yes | torrent-get | new arg "trackerStats"
|
||||
| | yes | session-set | new arg "incomplete-dir"
|
||||
| | yes | session-set | new arg "incomplete-dir-enabled"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
8 | 1.90 | yes | session-set | new arg "rename-partial-files"
|
||||
| | yes | session-get | new arg "rename-partial-files"
|
||||
| | yes | session-get | new arg "config-dir"
|
||||
| | yes | torrent-add | new arg "bandwidthPriority"
|
||||
| | yes | torrent-get | new trackerStats arg "lastAnnounceTimedOut"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
8 | 1.92 | yes | torrent-get | new trackerStats arg "lastScrapeTimedOut"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
9 | 2.00 | yes | session-set | new arg "start-added-torrents"
|
||||
| | yes | session-set | new arg "trash-original-torrent-files"
|
||||
| | yes | session-get | new arg "start-added-torrents"
|
||||
| | yes | session-get | new arg "trash-original-torrent-files"
|
||||
| | yes | torrent-get | new arg "isFinished"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
10 | 2.10 | yes | session-get | new arg "cache-size-mb"
|
||||
| | yes | torrent-set | new arg "trackerAdd"
|
||||
| | yes | torrent-set | new arg "trackerRemove"
|
||||
| | yes | torrent-set | new arg "trackerReplace"
|
||||
| | yes | session-set | new arg "idle-seeding-limit"
|
||||
| | yes | session-set | new arg "idle-seeding-limit-enabled"
|
||||
| | yes | session-get | new arg "units"
|
||||
| | yes | torrent-set | new arg "seedIdleLimit"
|
||||
| | yes | torrent-set | new arg "seedIdleMode"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
11 | 2.12 | yes | session-get | new arg "blocklist-url"
|
||||
| | yes | session-set | new arg "blocklist-url"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
12 | 2.20 | yes | session-get | new arg "download-dir-free-space"
|
||||
| | yes | session-close | new method
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
13 | 2.30 | yes | session-get | new arg "isUTP" to the "peers" list
|
||||
| | yes | torrent-add | new arg "cookies"
|
||||
| | NO | torrent-get | removed arg "peersKnown"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
14 | 2.40 | NO | torrent-get | values of "status" field changed
|
||||
| | yes | torrent-get | new arg "queuePosition"
|
||||
| | yes | torrent-get | new arg "isStalled"
|
||||
| | yes | torrent-get | new arg "fromLpd" in peersFrom
|
||||
| | yes | torrent-set | new arg "queuePosition"
|
||||
| | yes | session-set | new arg "download-queue-size"
|
||||
| | yes | session-set | new arg "download-queue-enabled"
|
||||
| | yes | session-set | new arg "seed-queue-size"
|
||||
| | yes | session-set | new arg "seed-queue-enabled"
|
||||
| | yes | session-set | new arg "queue-stalled-enabled"
|
||||
| | yes | session-set | new arg "queue-stalled-minutes"
|
||||
| | yes | | new method "queue-move-top"
|
||||
| | yes | | new method "queue-move-up"
|
||||
| | yes | | new method "queue-move-down"
|
||||
| | yes | | new method "queue-move-bottom"
|
||||
| | yes | | new method "torrent-start-now"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
15 | 2.80 | yes | torrent-get | new arg "etaIdle"
|
||||
RPC | Release | Backwards | |
|
||||
Vers. | Version | Compat? | Method | Description
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
1 | 1.30 | n/a | n/a | Initial version
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
2 | 1.34 | yes | torrent-get | new arg "peers"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
3 | 1.41 | yes | torrent-get | added "port" to "peers"
|
||||
| | yes | torrent-get | new arg "downloaders"
|
||||
| | yes | session-get | new arg "version"
|
||||
| | yes | torrent-remove | new method
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
4 | 1.50 | yes | session-get | new arg "rpc-version"
|
||||
| | yes | session-get | new arg "rpc-version-minimum"
|
||||
| | yes | session-stats | added "cumulative-stats"
|
||||
| | yes | session-stats | added "current-stats"
|
||||
| | yes | torrent-get | new arg "downloadDir"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
5 | 1.60 | yes | | new method "torrent-reannounce"
|
||||
| | yes | | new method "blocklist-update"
|
||||
| | yes | | new method "port-test"
|
||||
| | | |
|
||||
| | yes | session-get | new arg "alt-speed-begin"
|
||||
| | yes | session-get | new arg "alt-speed-down"
|
||||
| | yes | session-get | new arg "alt-speed-enabled"
|
||||
| | yes | session-get | new arg "alt-speed-end"
|
||||
| | yes | session-get | new arg "alt-speed-time-enabled"
|
||||
| | yes | session-get | new arg "alt-speed-up"
|
||||
| | yes | session-get | new arg "blocklist-enabled"
|
||||
| | yes | session-get | new arg "blocklist-size"
|
||||
| | yes | session-get | new arg "peer-limit-per-torrent"
|
||||
| | yes | session-get | new arg "seedRatioLimit"
|
||||
| | yes | session-get | new arg "seedRatioLimited"
|
||||
| | NO | session-get | renamed "pex-allowed" to "pex-enabled"
|
||||
| | NO | session-get | renamed "port" to "peer-port"
|
||||
| | NO | session-get | renamed "peer-limit" to "peer-limit-global"
|
||||
| | | |
|
||||
| | yes | torrent-add | new arg "files-unwanted"
|
||||
| | yes | torrent-add | new arg "files-wanted"
|
||||
| | yes | torrent-add | new arg "priority-high"
|
||||
| | yes | torrent-add | new arg "priority-low"
|
||||
| | yes | torrent-add | new arg "priority-normal"
|
||||
| | | |
|
||||
| | yes | torrent-set | new arg "bandwidthPriority"
|
||||
| | yes | torrent-set | new arg "honorsSessionLimits"
|
||||
| | yes | torrent-set | new arg "seedRatioLimit"
|
||||
| | yes | torrent-set | new arg "seedRatioLimited"
|
||||
| | NO | torrent-set | renamed "speed-limit-down" to "downloadLimit"
|
||||
| | NO | torrent-set | renamed "speed-limit-down-enabled" to "downloadLimited"
|
||||
| | NO | torrent-set | renamed "speed-limit-up" to "uploadLimit"
|
||||
| | NO | torrent-set | renamed "speed-limit-up-enabled" to "uploadLimited"
|
||||
| | | |
|
||||
| | yes | torrent-get | new arg "bandwidthPriority"
|
||||
| | yes | torrent-get | new arg "fileStats"
|
||||
| | yes | torrent-get | new arg "honorsSessionLimits"
|
||||
| | yes | torrent-get | new arg "percentDone"
|
||||
| | yes | torrent-get | new arg "pieces"
|
||||
| | yes | torrent-get | new arg "seedRatioLimit"
|
||||
| | yes | torrent-get | new arg "seedRatioMode"
|
||||
| | yes | torrent-get | new arg "torrentFile"
|
||||
| | yes | torrent-get | new ids option "recently-active"
|
||||
| | NO | torrent-get | removed arg "downloadLimitMode"
|
||||
| | NO | torrent-get | removed arg "uploadLimitMode"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
6 | 1.70 | yes | | new "method torrent-set-location"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
7 | 1.80 | NO | torrent-get | removed arg "announceResponse"
|
||||
| | NO | torrent-get | removed arg "announceURL"
|
||||
| | NO | torrent-get | removed arg "downloaders"
|
||||
| | NO | torrent-get | removed arg "lastAnnounceTime"
|
||||
| | NO | torrent-get | removed arg "lastScrapeTime"
|
||||
| | NO | torrent-get | removed arg "leechers"
|
||||
| | NO | torrent-get | removed arg "nextAnnounceTime"
|
||||
| | NO | torrent-get | removed arg "nextScrapeTime"
|
||||
| | NO | torrent-get | removed arg "scrapeResponse"
|
||||
| | NO | torrent-get | removed arg "scrapeURL"
|
||||
| | NO | torrent-get | removed arg "seeders"
|
||||
| | NO | torrent-get | removed arg "timesCompleted"
|
||||
| | NO | torrent-get | removed arg "swarmSpeed"
|
||||
| | yes | torrent-get | new arg "magnetLink"
|
||||
| | yes | torrent-get | new arg "metadataPercentComplete"
|
||||
| | yes | torrent-get | new arg "trackerStats"
|
||||
| | yes | session-set | new arg "incomplete-dir"
|
||||
| | yes | session-set | new arg "incomplete-dir-enabled"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
8 | 1.90 | yes | session-set | new arg "rename-partial-files"
|
||||
| | yes | session-get | new arg "rename-partial-files"
|
||||
| | yes | session-get | new arg "config-dir"
|
||||
| | yes | torrent-add | new arg "bandwidthPriority"
|
||||
| | yes | torrent-get | new trackerStats arg "lastAnnounceTimedOut"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
8 | 1.92 | yes | torrent-get | new trackerStats arg "lastScrapeTimedOut"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
9 | 2.00 | yes | session-set | new arg "start-added-torrents"
|
||||
| | yes | session-set | new arg "trash-original-torrent-files"
|
||||
| | yes | session-get | new arg "start-added-torrents"
|
||||
| | yes | session-get | new arg "trash-original-torrent-files"
|
||||
| | yes | torrent-get | new arg "isFinished"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
10 | 2.10 | yes | session-get | new arg "cache-size-mb"
|
||||
| | yes | torrent-set | new arg "trackerAdd"
|
||||
| | yes | torrent-set | new arg "trackerRemove"
|
||||
| | yes | torrent-set | new arg "trackerReplace"
|
||||
| | yes | session-set | new arg "idle-seeding-limit"
|
||||
| | yes | session-set | new arg "idle-seeding-limit-enabled"
|
||||
| | yes | session-get | new arg "units"
|
||||
| | yes | torrent-set | new arg "seedIdleLimit"
|
||||
| | yes | torrent-set | new arg "seedIdleMode"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
11 | 2.12 | yes | session-get | new arg "blocklist-url"
|
||||
| | yes | session-set | new arg "blocklist-url"
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
12 | 2.20 | yes | session-get | new arg "download-dir-free-space"
|
||||
| | yes | session-close | new method
|
||||
------+---------+-----------+----------------------+-------------------------------
|
||||
13 | 2.30 | yes | session-get | new arg "isUTP" to the "peers" list
|
||||
| | yes | torrent-add | new arg "cookies"
|
||||
| | NO | torrent-get | removed arg "peersKnown"
|
||||
------+---------+-----------+--------------------------+-------------------------------
|
||||
14 | 2.40 | NO | torrent-get | values of "status" field changed
|
||||
| | yes | torrent-get | new arg "queuePosition"
|
||||
| | yes | torrent-get | new arg "isStalled"
|
||||
| | yes | torrent-get | new arg "fromLpd" in peersFrom
|
||||
| | yes | torrent-set | new arg "queuePosition"
|
||||
| | yes | session-set | new arg "download-queue-size"
|
||||
| | yes | session-set | new arg "download-queue-enabled"
|
||||
| | yes | session-set | new arg "seed-queue-size"
|
||||
| | yes | session-set | new arg "seed-queue-enabled"
|
||||
| | yes | session-set | new arg "queue-stalled-enabled"
|
||||
| | yes | session-set | new arg "queue-stalled-minutes"
|
||||
| | yes | | new method "queue-move-top"
|
||||
| | yes | | new method "queue-move-up"
|
||||
| | yes | | new method "queue-move-down"
|
||||
| | yes | | new method "queue-move-bottom"
|
||||
| | yes | | new method "torrent-start-now"
|
||||
------+---------+-----------+--------------------------+-------------------------------
|
||||
15 | 2.80 | yes | torrent-get | new arg "etaIdle"
|
||||
| | yes | torrent-rename-path | new method
|
||||
|
||||
|
|
|
@ -1,161 +1,162 @@
|
|||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir) \
|
||||
-D__TRANSMISSION__ \
|
||||
-DPACKAGE_DATA_DIR=\""$(datadir)"\"
|
||||
-I$(top_srcdir) \
|
||||
-D__TRANSMISSION__ \
|
||||
-DPACKAGE_DATA_DIR=\""$(datadir)"\"
|
||||
|
||||
AM_CFLAGS = \
|
||||
@DHT_CFLAGS@ \
|
||||
@LIBUTP_CFLAGS@ \
|
||||
@LIBUPNP_CFLAGS@ \
|
||||
@LIBNATPMP_CFLAGS@ \
|
||||
@LIBEVENT_CFLAGS@ \
|
||||
@LIBCURL_CFLAGS@ \
|
||||
@OPENSSL_CFLAGS@ \
|
||||
@PTHREAD_CFLAGS@ \
|
||||
@ZLIB_CFLAGS@
|
||||
@DHT_CFLAGS@ \
|
||||
@LIBUTP_CFLAGS@ \
|
||||
@LIBUPNP_CFLAGS@ \
|
||||
@LIBNATPMP_CFLAGS@ \
|
||||
@LIBEVENT_CFLAGS@ \
|
||||
@LIBCURL_CFLAGS@ \
|
||||
@OPENSSL_CFLAGS@ \
|
||||
@PTHREAD_CFLAGS@ \
|
||||
@ZLIB_CFLAGS@
|
||||
|
||||
noinst_LIBRARIES = libtransmission.a
|
||||
|
||||
libtransmission_a_SOURCES = \
|
||||
announcer.c \
|
||||
announcer-http.c \
|
||||
announcer-udp.c \
|
||||
bandwidth.c \
|
||||
bitfield.c \
|
||||
blocklist.c \
|
||||
cache.c \
|
||||
clients.c \
|
||||
completion.c \
|
||||
ConvertUTF.c \
|
||||
crypto.c \
|
||||
fdlimit.c \
|
||||
handshake.c \
|
||||
history.c \
|
||||
inout.c \
|
||||
list.c \
|
||||
magnet.c \
|
||||
makemeta.c \
|
||||
metainfo.c \
|
||||
natpmp.c \
|
||||
net.c \
|
||||
peer-io.c \
|
||||
peer-mgr.c \
|
||||
peer-msgs.c \
|
||||
platform.c \
|
||||
port-forwarding.c \
|
||||
ptrarray.c \
|
||||
quark.c \
|
||||
resume.c \
|
||||
rpcimpl.c \
|
||||
rpc-server.c \
|
||||
session.c \
|
||||
stats.c \
|
||||
torrent.c \
|
||||
torrent-ctor.c \
|
||||
torrent-magnet.c \
|
||||
tr-dht.c \
|
||||
tr-lpd.c \
|
||||
tr-udp.c \
|
||||
tr-utp.c \
|
||||
tr-getopt.c \
|
||||
trevent.c \
|
||||
upnp.c \
|
||||
utils.c \
|
||||
variant.c \
|
||||
variant-benc.c \
|
||||
variant-json.c \
|
||||
verify.c \
|
||||
web.c \
|
||||
webseed.c \
|
||||
wildmat.c
|
||||
announcer.c \
|
||||
announcer-http.c \
|
||||
announcer-udp.c \
|
||||
bandwidth.c \
|
||||
bitfield.c \
|
||||
blocklist.c \
|
||||
cache.c \
|
||||
clients.c \
|
||||
completion.c \
|
||||
ConvertUTF.c \
|
||||
crypto.c \
|
||||
fdlimit.c \
|
||||
handshake.c \
|
||||
history.c \
|
||||
inout.c \
|
||||
list.c \
|
||||
magnet.c \
|
||||
makemeta.c \
|
||||
metainfo.c \
|
||||
natpmp.c \
|
||||
net.c \
|
||||
peer-io.c \
|
||||
peer-mgr.c \
|
||||
peer-msgs.c \
|
||||
platform.c \
|
||||
port-forwarding.c \
|
||||
ptrarray.c \
|
||||
quark.c \
|
||||
resume.c \
|
||||
rpcimpl.c \
|
||||
rpc-server.c \
|
||||
session.c \
|
||||
stats.c \
|
||||
torrent.c \
|
||||
torrent-ctor.c \
|
||||
torrent-magnet.c \
|
||||
tr-dht.c \
|
||||
tr-lpd.c \
|
||||
tr-udp.c \
|
||||
tr-utp.c \
|
||||
tr-getopt.c \
|
||||
trevent.c \
|
||||
upnp.c \
|
||||
utils.c \
|
||||
variant.c \
|
||||
variant-benc.c \
|
||||
variant-json.c \
|
||||
verify.c \
|
||||
web.c \
|
||||
webseed.c \
|
||||
wildmat.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
announcer.h \
|
||||
announcer-common.h \
|
||||
bandwidth.h \
|
||||
bitfield.h \
|
||||
blocklist.h \
|
||||
cache.h \
|
||||
clients.h \
|
||||
ConvertUTF.h \
|
||||
crypto.h \
|
||||
completion.h \
|
||||
fdlimit.h \
|
||||
handshake.h \
|
||||
history.h \
|
||||
inout.h \
|
||||
jsonsl.c \
|
||||
jsonsl.h \
|
||||
libtransmission-test.h \
|
||||
list.h \
|
||||
magnet.h \
|
||||
makemeta.h \
|
||||
metainfo.h \
|
||||
natpmp_local.h \
|
||||
net.h \
|
||||
peer-common.h \
|
||||
peer-io.h \
|
||||
peer-mgr.h \
|
||||
peer-msgs.h \
|
||||
platform.h \
|
||||
port-forwarding.h \
|
||||
ptrarray.h \
|
||||
quark.h \
|
||||
resume.h \
|
||||
rpcimpl.h \
|
||||
rpc-server.h \
|
||||
session.h \
|
||||
stats.h \
|
||||
torrent.h \
|
||||
torrent-magnet.h \
|
||||
tr-getopt.h \
|
||||
transmission.h \
|
||||
tr-dht.h \
|
||||
tr-udp.h \
|
||||
tr-utp.h \
|
||||
tr-lpd.h \
|
||||
trevent.h \
|
||||
upnp.h \
|
||||
utils.h \
|
||||
variant.h \
|
||||
variant-common.h \
|
||||
verify.h \
|
||||
version.h \
|
||||
web.h \
|
||||
webseed.h
|
||||
announcer.h \
|
||||
announcer-common.h \
|
||||
bandwidth.h \
|
||||
bitfield.h \
|
||||
blocklist.h \
|
||||
cache.h \
|
||||
clients.h \
|
||||
ConvertUTF.h \
|
||||
crypto.h \
|
||||
completion.h \
|
||||
fdlimit.h \
|
||||
handshake.h \
|
||||
history.h \
|
||||
inout.h \
|
||||
jsonsl.c \
|
||||
jsonsl.h \
|
||||
libtransmission-test.h \
|
||||
list.h \
|
||||
magnet.h \
|
||||
makemeta.h \
|
||||
metainfo.h \
|
||||
natpmp_local.h \
|
||||
net.h \
|
||||
peer-common.h \
|
||||
peer-io.h \
|
||||
peer-mgr.h \
|
||||
peer-msgs.h \
|
||||
platform.h \
|
||||
port-forwarding.h \
|
||||
ptrarray.h \
|
||||
quark.h \
|
||||
resume.h \
|
||||
rpcimpl.h \
|
||||
rpc-server.h \
|
||||
session.h \
|
||||
stats.h \
|
||||
torrent.h \
|
||||
torrent-magnet.h \
|
||||
tr-getopt.h \
|
||||
transmission.h \
|
||||
tr-dht.h \
|
||||
tr-udp.h \
|
||||
tr-utp.h \
|
||||
tr-lpd.h \
|
||||
trevent.h \
|
||||
upnp.h \
|
||||
utils.h \
|
||||
variant.h \
|
||||
variant-common.h \
|
||||
verify.h \
|
||||
version.h \
|
||||
web.h \
|
||||
webseed.h
|
||||
|
||||
TESTS = \
|
||||
bitfield-test \
|
||||
blocklist-test \
|
||||
clients-test \
|
||||
history-test \
|
||||
json-test \
|
||||
magnet-test \
|
||||
metainfo-test \
|
||||
peer-msgs-test \
|
||||
quark-test \
|
||||
rpc-test \
|
||||
test-peer-id \
|
||||
utils-test \
|
||||
variant-test
|
||||
bitfield-test \
|
||||
blocklist-test \
|
||||
clients-test \
|
||||
history-test \
|
||||
json-test \
|
||||
magnet-test \
|
||||
metainfo-test \
|
||||
peer-msgs-test \
|
||||
quark-test \
|
||||
rename-test \
|
||||
rpc-test \
|
||||
test-peer-id \
|
||||
utils-test \
|
||||
variant-test
|
||||
|
||||
noinst_PROGRAMS = $(TESTS)
|
||||
|
||||
apps_ldflags = \
|
||||
@ZLIB_LDFLAGS@
|
||||
@ZLIB_LDFLAGS@
|
||||
|
||||
apps_ldadd = \
|
||||
./libtransmission.a \
|
||||
@LIBUPNP_LIBS@ \
|
||||
@LIBNATPMP_LIBS@ \
|
||||
@INTLLIBS@ \
|
||||
@DHT_LIBS@ \
|
||||
@LIBUTP_LIBS@ \
|
||||
@LIBCURL_LIBS@ \
|
||||
@LIBEVENT_LIBS@ \
|
||||
@OPENSSL_LIBS@ \
|
||||
@PTHREAD_LIBS@ \
|
||||
@ZLIB_LIBS@
|
||||
./libtransmission.a \
|
||||
@LIBUPNP_LIBS@ \
|
||||
@LIBNATPMP_LIBS@ \
|
||||
@INTLLIBS@ \
|
||||
@DHT_LIBS@ \
|
||||
@LIBUTP_LIBS@ \
|
||||
@LIBCURL_LIBS@ \
|
||||
@LIBEVENT_LIBS@ \
|
||||
@OPENSSL_LIBS@ \
|
||||
@PTHREAD_LIBS@ \
|
||||
@ZLIB_LIBS@
|
||||
|
||||
TEST_SOURCES = libtransmission-test.c
|
||||
|
||||
|
@ -210,3 +211,7 @@ utils_test_LDFLAGS = ${apps_ldflags}
|
|||
variant_test_SOURCES = variant-test.c $(TEST_SOURCES)
|
||||
variant_test_LDADD = ${apps_ldadd}
|
||||
variant_test_LDFLAGS = ${apps_ldflags}
|
||||
|
||||
rename_test_SOURCES = rename-test.c $(TEST_SOURCES)
|
||||
rename_test_LDADD = ${apps_ldadd}
|
||||
rename_test_LDFLAGS = ${apps_ldflags}
|
||||
|
|
|
@ -0,0 +1,520 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h> /* remove() */
|
||||
#include <string.h> /* strcmp() */
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h> /* stat(), opendir() */
|
||||
#include <sys/stat.h> /* stat() */
|
||||
#include <dirent.h> /* opendir() */
|
||||
#include <unistd.h> /* getcwd() */
|
||||
|
||||
#include "transmission.h"
|
||||
#include "resume.h"
|
||||
#include "torrent.h" /* tr_isTorrent() */
|
||||
#include "utils.h" /* tr_mkdirp() */
|
||||
#include "variant.h"
|
||||
|
||||
#include "libtransmission-test.h"
|
||||
|
||||
static tr_session * session = NULL;
|
||||
|
||||
static char*
|
||||
tr_getcwd (void)
|
||||
{
|
||||
char * result;
|
||||
char buf[2048];
|
||||
|
||||
#ifdef WIN32
|
||||
result = _getcwd (buf, sizeof (buf));
|
||||
#else
|
||||
result = getcwd (buf, sizeof (buf));
|
||||
#endif
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
fprintf (stderr, "getcwd error: \"%s\"", tr_strerror (errno));
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
return tr_strdup (buf);
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
#define verify_and_block_until_done(tor) \
|
||||
do { \
|
||||
tr_torrentVerify (tor); \
|
||||
do { \
|
||||
tr_wait_msec (10); \
|
||||
} while (tor->verifyState != TR_VERIFY_NONE); \
|
||||
} while (0)
|
||||
|
||||
#define check_have_none(tor, totalSize) \
|
||||
do { \
|
||||
const tr_stat * st = tr_torrentStat(tor); \
|
||||
check_int_eq (TR_STATUS_STOPPED, st->activity); \
|
||||
check_int_eq (TR_STAT_OK, st->error); \
|
||||
check_int_eq (totalSize, st->sizeWhenDone); \
|
||||
check_int_eq (totalSize, st->leftUntilDone); \
|
||||
check_int_eq (totalSize, tor->info.totalSize); \
|
||||
check_int_eq (0, st->haveValid); \
|
||||
} while (0)
|
||||
|
||||
#define check_have_all(tor, totalSize) \
|
||||
do { \
|
||||
const tr_stat * st = tr_torrentStat(tor); \
|
||||
check_int_eq (TR_STATUS_STOPPED, st->activity); \
|
||||
check_int_eq (TR_STAT_OK, st->error); \
|
||||
check_int_eq (0, st->leftUntilDone); \
|
||||
check_int_eq (0, st->haveUnchecked); \
|
||||
check_int_eq (0, st->desiredAvailable); \
|
||||
check_int_eq (totalSize, st->sizeWhenDone); \
|
||||
check_int_eq (totalSize, st->haveValid); \
|
||||
} while (0)
|
||||
|
||||
static bool
|
||||
testFileExistsAndConsistsOfThisString (const tr_torrent * tor, tr_file_index_t fileIndex, const char * str)
|
||||
{
|
||||
char * path;
|
||||
const size_t str_len = strlen (str);
|
||||
bool success = false;
|
||||
|
||||
path = tr_torrentFindFile (tor, fileIndex);
|
||||
if (path != NULL)
|
||||
{
|
||||
uint8_t * contents;
|
||||
size_t contents_len;
|
||||
|
||||
assert (tr_fileExists (path, NULL));
|
||||
|
||||
contents = tr_loadFile (path, &contents_len);
|
||||
|
||||
success = (str_len == contents_len)
|
||||
&& (!memcmp (contents, str, contents_len));
|
||||
|
||||
tr_free (contents);
|
||||
tr_free (path);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
onRenameDone (tr_torrent * tor UNUSED, const char * oldpath UNUSED, const char * newname UNUSED, int error, void * user_data)
|
||||
{
|
||||
*(int*)user_data = error;
|
||||
}
|
||||
|
||||
static int
|
||||
torrentRenameAndWait (tr_torrent * tor,
|
||||
const char * oldpath,
|
||||
const char * newname)
|
||||
{
|
||||
int error = -1;
|
||||
tr_torrentRenamePath (tor, oldpath, newname, onRenameDone, &error);
|
||||
do {
|
||||
tr_wait_msec (10);
|
||||
} while (error == -1);
|
||||
return error;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
create_file_with_contents (const char * path, const char * str)
|
||||
{
|
||||
FILE * fp;
|
||||
char * dir;
|
||||
|
||||
dir = tr_dirname (path);
|
||||
tr_mkdirp (dir, 0700);
|
||||
tr_free (dir);
|
||||
|
||||
remove (path);
|
||||
fp = fopen (path, "wb");
|
||||
fprintf (fp, "%s", str);
|
||||
fclose (fp);
|
||||
|
||||
sync ();
|
||||
}
|
||||
|
||||
static void
|
||||
create_single_file_torrent_contents (const char * top)
|
||||
{
|
||||
char * path = tr_buildPath (top, "hello-world.txt", NULL);
|
||||
create_file_with_contents (path, "hello, world!\n");
|
||||
tr_free (path);
|
||||
}
|
||||
|
||||
static tr_torrent *
|
||||
create_torrent_from_base64_metainfo (tr_ctor * ctor, const char * metainfo_base64)
|
||||
{
|
||||
int err;
|
||||
int metainfo_len;
|
||||
char * metainfo;
|
||||
tr_torrent * tor;
|
||||
|
||||
/* create the torrent ctor */
|
||||
metainfo = tr_base64_decode (metainfo_base64, -1, &metainfo_len);
|
||||
assert (metainfo != NULL);
|
||||
assert (metainfo_len > 0);
|
||||
assert (session != NULL);
|
||||
tr_ctorSetMetainfo (ctor, (uint8_t*)metainfo, metainfo_len);
|
||||
tr_ctorSetPaused (ctor, TR_FORCE, true);
|
||||
|
||||
/* create the torrent */
|
||||
err = 0;
|
||||
tor = tr_torrentNew (ctor, &err);
|
||||
assert (!err);
|
||||
|
||||
/* cleanup */
|
||||
tr_free (metainfo);
|
||||
return tor;
|
||||
}
|
||||
|
||||
static int
|
||||
test_single_filename_torrent (void)
|
||||
{
|
||||
tr_torrent * tor;
|
||||
char * tmpstr;
|
||||
const size_t totalSize = 14;
|
||||
tr_ctor * ctor;
|
||||
|
||||
/* this is a single-file torrent whose file is hello-world.txt, holding the string "hello, world!" */
|
||||
ctor = tr_ctorNew (session);
|
||||
tor = create_torrent_from_base64_metainfo (ctor,
|
||||
"ZDEwOmNyZWF0ZWQgYnkyNTpUcmFuc21pc3Npb24vMi42MSAoMTM0MDcpMTM6Y3JlYXRpb24gZGF0"
|
||||
"ZWkxMzU4NTQ5MDk4ZTg6ZW5jb2Rpbmc1OlVURi04NDppbmZvZDY6bGVuZ3RoaTE0ZTQ6bmFtZTE1"
|
||||
"OmhlbGxvLXdvcmxkLnR4dDEyOnBpZWNlIGxlbmd0aGkzMjc2OGU2OnBpZWNlczIwOukboJcrkFUY"
|
||||
"f6LvqLXBVvSHqCk6Nzpwcml2YXRlaTBlZWU=");
|
||||
check (tr_isTorrent (tor));
|
||||
tr_ctorFree (ctor);
|
||||
|
||||
/* sanity check the info */
|
||||
check_int_eq (1, tor->info.fileCount);
|
||||
check_streq ("hello-world.txt", tor->info.files[0].name);
|
||||
check (!tor->info.files[0].is_renamed);
|
||||
|
||||
/* sanity check the (empty) stats */
|
||||
verify_and_block_until_done (tor);
|
||||
check_have_none (tor, totalSize);
|
||||
|
||||
create_single_file_torrent_contents (tor->downloadDir);
|
||||
|
||||
/* sanity check the stats again, now that we've added the file */
|
||||
verify_and_block_until_done (tor);
|
||||
check_have_all (tor, totalSize);
|
||||
|
||||
/**
|
||||
*** okay! we've finally put together all the scaffolding to test
|
||||
*** renaming a single-file torrent
|
||||
**/
|
||||
|
||||
/* confirm that bad inputs get caught */
|
||||
|
||||
check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", NULL));
|
||||
check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", ""));
|
||||
check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", "."));
|
||||
check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", ".."));
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "hello-world.txt", "hello-world.txt"));
|
||||
check_int_eq (EINVAL, torrentRenameAndWait (tor, "hello-world.txt", "hello/world.txt"));
|
||||
|
||||
check (!tor->info.files[0].is_renamed);
|
||||
check_streq ("hello-world.txt", tor->info.files[0].name);
|
||||
|
||||
/***
|
||||
**** Now try a rename that should succeed
|
||||
***/
|
||||
|
||||
tmpstr = tr_buildPath (tor->downloadDir, "hello-world.txt", NULL);
|
||||
check (tr_fileExists (tmpstr, NULL));
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "hello-world.txt", "foobar"));
|
||||
check (!tr_fileExists (tmpstr, NULL));
|
||||
check (tor->info.files[0].is_renamed);
|
||||
check_streq ("foobar", tor->info.files[0].name);
|
||||
tr_free (tmpstr);
|
||||
check (testFileExistsAndConsistsOfThisString (tor, 0, "hello, world!\n"));
|
||||
|
||||
/***
|
||||
**** ...and rename it back again
|
||||
***/
|
||||
|
||||
tmpstr = tr_buildPath (tor->downloadDir, "foobar", NULL);
|
||||
check (tr_fileExists (tmpstr, NULL));
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "foobar", "hello-world.txt"));
|
||||
check (!tr_fileExists (tmpstr, NULL));
|
||||
check (tor->info.files[0].is_renamed);
|
||||
check_streq ("hello-world.txt", tor->info.files[0].name);
|
||||
tr_free (tmpstr);
|
||||
check (testFileExistsAndConsistsOfThisString (tor, 0, "hello, world!\n"));
|
||||
|
||||
/* cleanup */
|
||||
tr_torrentRemove (tor, false, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
****
|
||||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
create_multifile_torrent_contents (const char * top)
|
||||
{
|
||||
char * path;
|
||||
|
||||
path = tr_buildPath (top, "Felidae", "Felinae", "Acinonyx", "Cheetah", "Chester", NULL);
|
||||
create_file_with_contents (path, "It ain't easy bein' cheesy.\n");
|
||||
tr_free (path);
|
||||
|
||||
path = tr_buildPath (top, "Felidae", "Pantherinae", "Panthera", "Tiger", "Tony", NULL);
|
||||
create_file_with_contents (path, "They’re Grrrrreat!\n");
|
||||
tr_free (path);
|
||||
|
||||
path = tr_buildPath (top, "Felidae", "Felinae", "Felis", "catus", "Kyphi", NULL);
|
||||
create_file_with_contents (path, "Inquisitive\n");
|
||||
tr_free (path);
|
||||
|
||||
path = tr_buildPath (top, "Felidae", "Felinae", "Felis", "catus", "Saffron", NULL);
|
||||
create_file_with_contents (path, "Tough\n");
|
||||
tr_free (path);
|
||||
|
||||
sync ();
|
||||
}
|
||||
|
||||
static int
|
||||
test_multifile_torrent (void)
|
||||
{
|
||||
//tr_file_stat * file_stats;
|
||||
//tr_file_index_t n;
|
||||
tr_file_index_t i;
|
||||
uint64_t loaded;
|
||||
tr_torrent * tor;
|
||||
//tr_file_index_t i;
|
||||
tr_ctor * ctor;
|
||||
char * str;
|
||||
char * tmp;
|
||||
static const size_t totalSize = 67;
|
||||
const tr_file * files;
|
||||
const char * expected_files[4] = {
|
||||
"Felidae/Felinae/Acinonyx/Cheetah/Chester",
|
||||
"Felidae/Felinae/Felis/catus/Kyphi",
|
||||
"Felidae/Felinae/Felis/catus/Saffron",
|
||||
"Felidae/Pantherinae/Panthera/Tiger/Tony"
|
||||
};
|
||||
const char * expected_contents[4] = {
|
||||
"It ain't easy bein' cheesy.\n",
|
||||
"Inquisitive\n",
|
||||
"Tough\n",
|
||||
"They’re Grrrrreat!\n"
|
||||
};
|
||||
|
||||
ctor = tr_ctorNew (session);
|
||||
tor = create_torrent_from_base64_metainfo (ctor,
|
||||
"ZDEwOmNyZWF0ZWQgYnkyNTpUcmFuc21pc3Npb24vMi42MSAoMTM0MDcpMTM6Y3JlYXRpb24gZGF0"
|
||||
"ZWkxMzU4NTU1NDIwZTg6ZW5jb2Rpbmc1OlVURi04NDppbmZvZDU6ZmlsZXNsZDY6bGVuZ3RoaTI4"
|
||||
"ZTQ6cGF0aGw3OkZlbGluYWU4OkFjaW5vbnl4NzpDaGVldGFoNzpDaGVzdGVyZWVkNjpsZW5ndGhp"
|
||||
"MTJlNDpwYXRobDc6RmVsaW5hZTU6RmVsaXM1OmNhdHVzNTpLeXBoaWVlZDY6bGVuZ3RoaTZlNDpw"
|
||||
"YXRobDc6RmVsaW5hZTU6RmVsaXM1OmNhdHVzNzpTYWZmcm9uZWVkNjpsZW5ndGhpMjFlNDpwYXRo"
|
||||
"bDExOlBhbnRoZXJpbmFlODpQYW50aGVyYTU6VGlnZXI0OlRvbnllZWU0Om5hbWU3OkZlbGlkYWUx"
|
||||
"MjpwaWVjZSBsZW5ndGhpMzI3NjhlNjpwaWVjZXMyMDp27buFkmy8ICfNX4nsJmt0Ckm2Ljc6cHJp"
|
||||
"dmF0ZWkwZWVl");
|
||||
check (tr_isTorrent (tor));
|
||||
files = tor->info.files;
|
||||
|
||||
/* sanity check the info */
|
||||
check_streq (tor->info.name, "Felidae");
|
||||
check_int_eq (totalSize, tor->info.totalSize);
|
||||
check_int_eq (4, tor->info.fileCount);
|
||||
for (i=0; i<4; ++i)
|
||||
check_streq (expected_files[i], files[i].name);
|
||||
|
||||
/* sanity check the (empty) stats */
|
||||
verify_and_block_until_done (tor);
|
||||
check_have_none (tor, totalSize);
|
||||
|
||||
/* build the local data */
|
||||
create_multifile_torrent_contents (tor->downloadDir);
|
||||
|
||||
/* sanity check the (full) stats */
|
||||
verify_and_block_until_done (tor);
|
||||
check_have_all (tor, totalSize);
|
||||
|
||||
/**
|
||||
*** okay! let's test renaming.
|
||||
**/
|
||||
|
||||
/* rename a leaf... */
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/catus/Kyphi", "placeholder"));
|
||||
check_streq (files[1].name, "Felidae/Felinae/Felis/catus/placeholder");
|
||||
check (testFileExistsAndConsistsOfThisString (tor, 1, "Inquisitive\n"));
|
||||
|
||||
/* ...and back again */
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/catus/placeholder", "Kyphi"));
|
||||
check_streq (files[1].name, "Felidae/Felinae/Felis/catus/Kyphi");
|
||||
testFileExistsAndConsistsOfThisString (tor, 1, "Inquisitive\n");
|
||||
|
||||
/* rename a branch... */
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/catus", "placeholder"));
|
||||
check_streq (expected_files[0], files[0].name);
|
||||
check_streq ("Felidae/Felinae/Felis/placeholder/Kyphi", files[1].name);
|
||||
check_streq ("Felidae/Felinae/Felis/placeholder/Saffron", files[2].name);
|
||||
check_streq (expected_files[3], files[3].name);
|
||||
check (testFileExistsAndConsistsOfThisString (tor, 1, expected_contents[1]));
|
||||
check (testFileExistsAndConsistsOfThisString (tor, 2, expected_contents[2]));
|
||||
check (files[0].is_renamed == false);
|
||||
check (files[1].is_renamed == true);
|
||||
check (files[2].is_renamed == true);
|
||||
check (files[3].is_renamed == false);
|
||||
|
||||
/* (while the branch is renamed: confirm that the .resume file remembers the changes) */
|
||||
tr_torrentSaveResume (tor);
|
||||
/* this is a bit dodgy code-wise, but let's make sure the .resume file got the name */
|
||||
tr_free (files[1].name);
|
||||
tor->info.files[1].name = tr_strdup ("gabba gabba hey");
|
||||
loaded = tr_torrentLoadResume (tor, ~0, ctor);
|
||||
check ((loaded & TR_FR_FILENAMES) != 0);
|
||||
check_streq (expected_files[0], files[0].name);
|
||||
check_streq ("Felidae/Felinae/Felis/placeholder/Kyphi", files[1].name);
|
||||
check_streq ("Felidae/Felinae/Felis/placeholder/Saffron", files[2].name);
|
||||
check_streq (expected_files[3], files[3].name);
|
||||
|
||||
/* ...and back again */
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/placeholder", "catus"));
|
||||
for (i=0; i<4; ++i)
|
||||
{
|
||||
check_streq (expected_files[i], files[i].name);
|
||||
check (testFileExistsAndConsistsOfThisString (tor, 1, expected_contents[1]));
|
||||
}
|
||||
check (files[0].is_renamed == false);
|
||||
check (files[1].is_renamed == true);
|
||||
check (files[2].is_renamed == true);
|
||||
check (files[3].is_renamed == false);
|
||||
|
||||
/***
|
||||
**** Test it an incomplete torrent...
|
||||
***/
|
||||
|
||||
/* remove the directory Felidae/Felinae/Felis/catus */
|
||||
str = tr_buildPath (tor->downloadDir, files[1].name, NULL);
|
||||
remove (str);
|
||||
tr_free (str);
|
||||
str = tr_buildPath (tor->downloadDir, files[2].name, NULL);
|
||||
remove (str);
|
||||
tmp = tr_dirname (str);
|
||||
remove (tmp);
|
||||
tr_free (tmp);
|
||||
tr_free (str);
|
||||
verify_and_block_until_done (tor);
|
||||
testFileExistsAndConsistsOfThisString (tor, 0, expected_contents[0]);
|
||||
check (tr_torrentFindFile (tor, 1) == NULL);
|
||||
check (tr_torrentFindFile (tor, 2) == NULL);
|
||||
testFileExistsAndConsistsOfThisString (tor, 3, expected_contents[3]);
|
||||
|
||||
/* rename a branch... */
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/catus", "foo"));
|
||||
check_streq (expected_files[0], files[0].name);
|
||||
check_streq ("Felidae/Felinae/Felis/foo/Kyphi", files[1].name);
|
||||
check_streq ("Felidae/Felinae/Felis/foo/Saffron", files[2].name);
|
||||
check_streq (expected_files[3], files[3].name);
|
||||
|
||||
/* ...and back again */
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "Felidae/Felinae/Felis/foo", "catus"));
|
||||
for (i=0; i<4; ++i)
|
||||
check_streq (expected_files[i], files[i].name);
|
||||
|
||||
check_int_eq (0, torrentRenameAndWait (tor, "Felidae", "gabba"));
|
||||
check_streq ("gabba/Felinae/Acinonyx/Cheetah/Chester", files[0].name);
|
||||
check_streq ("gabba/Felinae/Felis/catus/Kyphi", files[1].name);
|
||||
check_streq ("gabba/Felinae/Felis/catus/Saffron", files[2].name);
|
||||
check_streq ("gabba/Pantherinae/Panthera/Tiger/Tony", files[3].name);
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
/* cleanup */
|
||||
tr_ctorFree (ctor);
|
||||
tr_torrentRemove (tor, false, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
rm_rf (const char * killme)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (!stat (killme, &sb))
|
||||
{
|
||||
DIR * odir;
|
||||
|
||||
if (S_ISDIR (sb.st_mode) && ((odir = opendir (killme))))
|
||||
{
|
||||
struct dirent *d;
|
||||
for (d = readdir(odir); d != NULL; d=readdir(odir))
|
||||
{
|
||||
if (d->d_name && strcmp(d->d_name,".") && strcmp(d->d_name,".."))
|
||||
{
|
||||
char * tmp = tr_buildPath (killme, d->d_name, NULL);
|
||||
rm_rf (tmp);
|
||||
tr_free (tmp);
|
||||
}
|
||||
}
|
||||
closedir (odir);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf (stderr, "cleanup: removing %s\n", killme);
|
||||
|
||||
remove (killme);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int ret;
|
||||
char * cwd;
|
||||
char * sandbox;
|
||||
char * downloadDir;
|
||||
tr_variant dict;
|
||||
const testFunc tests[] = { test_single_filename_torrent,
|
||||
test_multifile_torrent };
|
||||
|
||||
/* create a sandbox for the test session */
|
||||
cwd = tr_getcwd ();
|
||||
sandbox = tr_buildPath (cwd, "sandbox-XXXXXX", NULL);
|
||||
tr_mkdtemp (sandbox);
|
||||
downloadDir = tr_buildPath (sandbox, "Downloads", NULL);
|
||||
tr_mkdirp (downloadDir, 0700);
|
||||
|
||||
/* create a test session */
|
||||
tr_variantInitDict (&dict, 3);
|
||||
tr_variantDictAddStr (&dict, TR_KEY_download_dir, downloadDir);
|
||||
tr_variantDictAddBool (&dict, TR_KEY_port_forwarding_enabled, false);
|
||||
tr_variantDictAddBool (&dict, TR_KEY_dht_enabled, false);
|
||||
session = tr_sessionInit ("rename-test", sandbox, true, &dict);
|
||||
|
||||
/* run the tests */
|
||||
ret = runTests (tests, NUM_TESTS (tests));
|
||||
|
||||
/* cleanup */
|
||||
tr_sessionClose (session);
|
||||
tr_freeMessageList (tr_getQueuedMessages ());
|
||||
tr_variantFree (&dict);
|
||||
rm_rf (sandbox);
|
||||
tr_free (downloadDir);
|
||||
tr_free (sandbox);
|
||||
tr_free (cwd);
|
||||
return ret;
|
||||
}
|
|
@ -335,6 +335,62 @@ loadIdleLimits (tr_variant * dict, tr_torrent * tor)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
saveFilenames (tr_variant * dict, const tr_torrent * tor)
|
||||
{
|
||||
tr_file_index_t i;
|
||||
bool any_renamed;
|
||||
const tr_file_index_t n = tor->info.fileCount;
|
||||
const tr_file * files = tor->info.files;
|
||||
|
||||
any_renamed = false;
|
||||
for (i=0; !any_renamed && i<n; ++i)
|
||||
any_renamed = files[i].is_renamed;
|
||||
|
||||
if (any_renamed)
|
||||
{
|
||||
tr_variant * list = tr_variantDictAddList (dict, TR_KEY_files, n);
|
||||
|
||||
for (i=0; i<n; ++i)
|
||||
tr_variantListAddStr (list, files[i].is_renamed ? files[i].name : "");
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
loadFilenames (tr_variant * dict, tr_torrent * tor)
|
||||
{
|
||||
tr_variant * list;
|
||||
uint64_t ret = 0;
|
||||
|
||||
if (tr_variantDictFindList (dict, TR_KEY_files, &list))
|
||||
{
|
||||
size_t i;
|
||||
const size_t n = tr_variantListSize (list);
|
||||
tr_file * files = tor->info.files;
|
||||
|
||||
for (i=0; i<tor->info.fileCount && i<n; ++i)
|
||||
{
|
||||
const char * str;
|
||||
size_t str_len;
|
||||
if (tr_variantGetStr (tr_variantListChild (list, i), &str, &str_len) && str && str_len)
|
||||
{
|
||||
tr_free (files[i].name);
|
||||
files[i].name = tr_strndup (str, str_len);
|
||||
files[i].is_renamed = true;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TR_FR_FILENAMES;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
@ -593,6 +649,7 @@ tr_torrentSaveResume (tr_torrent * tor)
|
|||
saveSpeedLimits (&top, tor);
|
||||
saveRatioLimits (&top, tor);
|
||||
saveIdleLimits (&top, tor);
|
||||
saveFilenames (&top, tor);
|
||||
|
||||
filename = getResumeFilename (tor);
|
||||
if ((err = tr_variantToFile (&top, TR_VARIANT_FMT_BENC, filename)))
|
||||
|
@ -745,6 +802,9 @@ loadFromFile (tr_torrent * tor, uint64_t fieldsToLoad)
|
|||
if (fieldsToLoad & TR_FR_IDLELIMIT)
|
||||
fieldsLoaded |= loadIdleLimits (&top, tor);
|
||||
|
||||
if (fieldsToLoad & TR_FR_FILENAMES)
|
||||
fieldsLoaded |= loadFilenames (&top, tor);
|
||||
|
||||
/* loading the resume file triggers of a lot of changes,
|
||||
* but none of them needs to trigger a re-saving of the
|
||||
* same resume information... */
|
||||
|
|
|
@ -38,7 +38,8 @@ enum
|
|||
TR_FR_RATIOLIMIT = (1 << 16),
|
||||
TR_FR_IDLELIMIT = (1 << 17),
|
||||
TR_FR_TIME_SEEDING = (1 << 18),
|
||||
TR_FR_TIME_DOWNLOADING = (1 << 19)
|
||||
TR_FR_TIME_DOWNLOADING = (1 << 19),
|
||||
TR_FR_FILENAMES = (1 << 20)
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,8 +84,8 @@ notify (tr_session * session,
|
|||
struct tr_rpc_idle_data
|
||||
{
|
||||
tr_session * session;
|
||||
tr_variant * response;
|
||||
tr_variant * args_out;
|
||||
tr_variant * response;
|
||||
tr_variant * args_out;
|
||||
tr_rpc_response_func callback;
|
||||
void * callback_user_data;
|
||||
};
|
||||
|
@ -114,7 +114,7 @@ tr_idle_function_done (struct tr_rpc_idle_data * data, const char * result)
|
|||
|
||||
static tr_torrent **
|
||||
getTorrents (tr_session * session,
|
||||
tr_variant * args,
|
||||
tr_variant * args,
|
||||
int * setmeCount)
|
||||
{
|
||||
int torrentCount = 0;
|
||||
|
@ -196,8 +196,8 @@ notifyBatchQueueChange (tr_session * session, tr_torrent ** torrents, int n)
|
|||
|
||||
static const char*
|
||||
queueMoveTop (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int n;
|
||||
|
@ -210,8 +210,8 @@ queueMoveTop (tr_session * session,
|
|||
|
||||
static const char*
|
||||
queueMoveUp (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int n;
|
||||
|
@ -224,8 +224,8 @@ queueMoveUp (tr_session * session,
|
|||
|
||||
static const char*
|
||||
queueMoveDown (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int n;
|
||||
|
@ -238,8 +238,8 @@ queueMoveDown (tr_session * session,
|
|||
|
||||
static const char*
|
||||
queueMoveBottom (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int n;
|
||||
|
@ -252,8 +252,8 @@ queueMoveBottom (tr_session * session,
|
|||
|
||||
static const char*
|
||||
torrentStart (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int i, torrentCount;
|
||||
|
@ -276,8 +276,8 @@ torrentStart (tr_session * session,
|
|||
|
||||
static const char*
|
||||
torrentStartNow (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int i, torrentCount;
|
||||
|
@ -300,8 +300,8 @@ torrentStartNow (tr_session * session,
|
|||
|
||||
static const char*
|
||||
torrentStop (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int i, torrentCount;
|
||||
|
@ -325,8 +325,8 @@ torrentStop (tr_session * session,
|
|||
|
||||
static const char*
|
||||
torrentRemove (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int i;
|
||||
|
@ -353,10 +353,63 @@ torrentRemove (tr_session * session,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
torrentRenamePathDone (tr_torrent * tor UNUSED,
|
||||
const char * oldpath UNUSED,
|
||||
const char * newname UNUSED,
|
||||
int error,
|
||||
void * user_data)
|
||||
{
|
||||
*(int*)user_data = error;
|
||||
}
|
||||
|
||||
static const char *
|
||||
torrentRenamePath (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
const char * oldpath;
|
||||
const char * newname;
|
||||
const char * ret = NULL;
|
||||
|
||||
if (!tr_variantDictFindStr (args_in, TR_KEY_path, &oldpath, NULL))
|
||||
{
|
||||
ret = "no path specified";
|
||||
}
|
||||
else if (!tr_variantDictFindStr (args_in, TR_KEY_name, &newname, NULL))
|
||||
{
|
||||
ret = "no name specified";
|
||||
}
|
||||
else
|
||||
{
|
||||
int torrentCount;
|
||||
tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
|
||||
|
||||
if (torrentCount != 1)
|
||||
{
|
||||
ret = "torent-rename-path requires 1 torrent";
|
||||
}
|
||||
else
|
||||
{
|
||||
int error = -1;
|
||||
tr_torrentRenamePath (torrents[0], oldpath, newname, torrentRenamePathDone, &error);
|
||||
assert (error != -1);
|
||||
|
||||
if (error != 0)
|
||||
ret = tr_strerror (error);
|
||||
}
|
||||
|
||||
tr_free (torrents);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char*
|
||||
torrentReannounce (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int i, torrentCount;
|
||||
|
@ -380,8 +433,8 @@ torrentReannounce (tr_session * session,
|
|||
|
||||
static const char*
|
||||
torrentVerify (tr_session * session,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
tr_variant * args_in,
|
||||
tr_variant * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED)
|
||||
{
|
||||
int i, torrentCount;
|
||||
|
@ -1933,6 +1986,7 @@ methods[] =
|
|||
{ "torrent-add", false, torrentAdd },
|
||||
{ "torrent-get", true, torrentGet },
|
||||
{ "torrent-remove", true, torrentRemove },
|
||||
{ "torrent-rename-path", true, torrentRenamePath },
|
||||
{ "torrent-set", true, torrentSet },
|
||||
{ "torrent-set-location", true, torrentSetLocation },
|
||||
{ "torrent-start", true, torrentStart },
|
||||
|
|
|
@ -3302,3 +3302,220 @@ tr_torrentSetQueueStartCallback (tr_torrent * torrent, void (*callback)(tr_torre
|
|||
}
|
||||
|
||||
|
||||
/***
|
||||
****
|
||||
**** RENAME
|
||||
****
|
||||
***/
|
||||
|
||||
static bool
|
||||
renameArgsAreValid (const char * oldpath, const char * newname)
|
||||
{
|
||||
return (oldpath && *oldpath)
|
||||
&& (newname && *newname)
|
||||
&& (strcmp (newname, "."))
|
||||
&& (strcmp (newname, ".."))
|
||||
&& (strchr (newname, TR_PATH_DELIMITER) == NULL);
|
||||
}
|
||||
|
||||
static tr_file_index_t *
|
||||
renameFindAffectedFiles (tr_torrent * tor, const char * oldpath, size_t * setme_n)
|
||||
{
|
||||
size_t n;
|
||||
size_t oldpath_len;
|
||||
tr_file_index_t i;
|
||||
tr_file_index_t * indices = tr_new0 (tr_file_index_t, tor->info.fileCount);
|
||||
|
||||
n = 0;
|
||||
oldpath_len = strlen (oldpath);
|
||||
for (i=0; i!=tor->info.fileCount; ++i)
|
||||
{
|
||||
const char * name = tor->info.files[i].name;
|
||||
const size_t len = strlen (name);
|
||||
if ((len >= oldpath_len) && !memcmp (oldpath, name, oldpath_len))
|
||||
indices[n++] = i;
|
||||
}
|
||||
|
||||
*setme_n = n;
|
||||
return indices;
|
||||
}
|
||||
|
||||
static int
|
||||
renamePath (tr_torrent * tor,
|
||||
const char * oldpath,
|
||||
const char * newname)
|
||||
{
|
||||
char * src;
|
||||
const char * base;
|
||||
int error = 0;
|
||||
|
||||
if (!tr_torrentIsSeed(tor) && (tor->incompleteDir != NULL))
|
||||
base = tor->incompleteDir;
|
||||
else
|
||||
base = tor->downloadDir;
|
||||
|
||||
src = tr_buildPath (base, oldpath, NULL);
|
||||
/*fprintf (stderr, "%s:%d src \"%s\"\n", __FILE__, __LINE__, src);*/
|
||||
|
||||
if (tr_fileExists (src, NULL))
|
||||
{
|
||||
int tmp;
|
||||
bool tgt_exists;
|
||||
char * parent = tr_dirname (src);
|
||||
char * tgt = tr_buildPath (parent, newname, NULL);
|
||||
|
||||
tmp = errno;
|
||||
tgt_exists = tr_fileExists (tgt, NULL);
|
||||
errno = tmp;
|
||||
/*fprintf (stderr, "%s:%d tgt \"%s\"\n", __FILE__, __LINE__, tgt);*/
|
||||
|
||||
if (!tgt_exists)
|
||||
{
|
||||
int rv;
|
||||
|
||||
tmp = errno;
|
||||
rv = rename (src, tgt);
|
||||
/*fprintf (stderr, "%s:%d rv \"%d\"\n", __FILE__, __LINE__, rv);*/
|
||||
if (rv != 0)
|
||||
error = errno;
|
||||
errno = tmp;
|
||||
}
|
||||
|
||||
tr_free (tgt);
|
||||
tr_free (parent);
|
||||
}
|
||||
|
||||
tr_free (src);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
renameTorrentFileString (tr_torrent * tor,
|
||||
const char * oldpath,
|
||||
const char * newname,
|
||||
tr_file_index_t fileIndex)
|
||||
{
|
||||
char * name;
|
||||
tr_file * file = &tor->info.files[fileIndex];
|
||||
const size_t oldpath_len = strlen (oldpath);
|
||||
|
||||
if (strchr (oldpath, TR_PATH_DELIMITER) == NULL)
|
||||
{
|
||||
if (oldpath_len >= strlen(file->name))
|
||||
name = tr_buildPath (newname, NULL);
|
||||
else
|
||||
name = tr_buildPath (newname, file->name + oldpath_len + 1, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
char * tmp = tr_dirname (oldpath);
|
||||
|
||||
if (oldpath_len >= strlen(file->name))
|
||||
name = tr_buildPath (tmp, newname, NULL);
|
||||
else
|
||||
name = tr_buildPath (tmp, newname, file->name + oldpath_len + 1, NULL);
|
||||
|
||||
tr_free (tmp);
|
||||
}
|
||||
|
||||
if (!strcmp (file->name, name))
|
||||
{
|
||||
tr_free (name);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_free (file->name);
|
||||
file->name = name;
|
||||
file->is_renamed = true;
|
||||
}
|
||||
}
|
||||
|
||||
struct rename_data
|
||||
{
|
||||
tr_torrent * tor;
|
||||
char * oldpath;
|
||||
char * newname;
|
||||
tr_torrent_rename_done_func * callback;
|
||||
void * callback_user_data;
|
||||
};
|
||||
|
||||
static void
|
||||
torrentRenamePath (void * vdata)
|
||||
{
|
||||
int error = 0;
|
||||
struct rename_data * data = vdata;
|
||||
tr_torrent * const tor = data->tor;
|
||||
const char * const oldpath = data->oldpath;
|
||||
const char * const newname = data->newname;
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
if (!renameArgsAreValid (oldpath, newname))
|
||||
{
|
||||
error = EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t n;
|
||||
tr_file_index_t * file_indices;
|
||||
|
||||
file_indices = renameFindAffectedFiles (tor, oldpath, &n);
|
||||
if (n == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i;
|
||||
|
||||
error = renamePath (tor, oldpath, newname);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
for (i=0; i<n; ++i)
|
||||
renameTorrentFileString(tor, oldpath, newname, file_indices[i]);
|
||||
tr_torrentSetDirty (tor);
|
||||
}
|
||||
}
|
||||
|
||||
tr_free (file_indices);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
/* callback */
|
||||
if (data->callback != NULL)
|
||||
(*data->callback)(tor, data->oldpath, data->newname, error, data->callback_user_data);
|
||||
|
||||
/* cleanup */
|
||||
tr_free (data->oldpath);
|
||||
tr_free (data->newname);
|
||||
tr_free (data);
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentRenamePath (tr_torrent * tor,
|
||||
const char * oldpath,
|
||||
const char * newname,
|
||||
tr_torrent_rename_done_func callback,
|
||||
void * callback_user_data)
|
||||
{
|
||||
struct rename_data * data;
|
||||
|
||||
data = tr_new0 (struct rename_data, 1);
|
||||
data->tor = tor;
|
||||
data->oldpath = tr_strdup (oldpath);
|
||||
data->newname = tr_strdup (newname);
|
||||
data->callback = callback;
|
||||
data->callback_user_data = callback_user_data;
|
||||
|
||||
tr_runInEventThread (tor->session, torrentRenamePath, data);
|
||||
}
|
||||
|
|
|
@ -1093,6 +1093,57 @@ void tr_torrentStart (tr_torrent * torrent);
|
|||
/** @brief Stop (pause) a torrent */
|
||||
void tr_torrentStop (tr_torrent * torrent);
|
||||
|
||||
|
||||
typedef void (tr_torrent_rename_done_func)(tr_torrent * torrent,
|
||||
const char * oldpath,
|
||||
const char * newname,
|
||||
int error,
|
||||
void * user_data);
|
||||
|
||||
/**
|
||||
* @brief Rename a file or directory in a torrent.
|
||||
*
|
||||
* @tor: the torrent whose path will be renamed.
|
||||
* @oldpath: the path to the file or folder that will be renamed
|
||||
* @newname: the file or folder's new name
|
||||
* @callback: the callback invoked when the renaming finishes, or NULL
|
||||
* @callback_data: the pointer to pass in the callback's user_data arg
|
||||
*
|
||||
* EXAMPLES
|
||||
*
|
||||
* Consider a torrent where
|
||||
* files[0].path is "frobnitz-linux/checksum" and
|
||||
* files[1].path is "frobnitz-linux/frobnitz.iso".
|
||||
*
|
||||
* 1. tr_torrentRenamePath (tor, "frobnitz-linux", "foo") will rename
|
||||
* the "frotbnitz-linux" folder as "foo" and update files[*].path.
|
||||
*
|
||||
* 2. tr_torrentRenamePath (tor, "frobnitz-linux/checksum", "foo") will
|
||||
* rename the "frobnitz-linux/checksum" file as "foo" and update
|
||||
* files[0].path to "frobnitz-linux/foo".
|
||||
*
|
||||
* RETURN
|
||||
*
|
||||
* Changing tr_info's contents requires a session lock, so this function
|
||||
* returns asynchronously to avoid blocking. If you don't care about error
|
||||
* checking, you can pass NULL as the callback and callback_user_data arg.
|
||||
*
|
||||
* On success, the callback's error argument will be 0.
|
||||
*
|
||||
* If oldpath can't be found in files[*].path, or if newname is already
|
||||
* in files[*].path, or contains a directory separator, or is NULL, "",
|
||||
* ".", or "..", the error argument will be EINVAL.
|
||||
*
|
||||
* If the path exists on disk but can't be renamed, the error argument
|
||||
* will be the errno set by rename().
|
||||
*/
|
||||
void tr_torrentRenamePath (tr_torrent * tor,
|
||||
const char * oldpath,
|
||||
const char * newname,
|
||||
tr_torrent_rename_done_func callback,
|
||||
void * callback_user_data);
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
TR_LOC_MOVING,
|
||||
|
@ -1353,15 +1404,15 @@ tr_completeness;
|
|||
* it changed its completeness state
|
||||
*/
|
||||
typedef void (tr_torrent_completeness_func)(tr_torrent * torrent,
|
||||
tr_completeness completeness,
|
||||
bool wasRunning,
|
||||
void * user_data);
|
||||
tr_completeness completeness,
|
||||
bool wasRunning,
|
||||
void * user_data);
|
||||
|
||||
typedef void (tr_torrent_ratio_limit_hit_func)(tr_torrent * torrent,
|
||||
void * user_data);
|
||||
void * user_data);
|
||||
|
||||
typedef void (tr_torrent_idle_limit_hit_func)(tr_torrent * torrent,
|
||||
void * user_data);
|
||||
void * user_data);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1683,6 +1734,7 @@ typedef struct tr_file
|
|||
char * name; /* Path to the file */
|
||||
int8_t priority; /* TR_PRI_HIGH, _NORMAL, or _LOW */
|
||||
int8_t dnd; /* "do not download" flag */
|
||||
int8_t is_renamed; /* true if we're using a different path from the one in the metainfo; ie, if the user has renamed it */
|
||||
tr_piece_index_t firstPiece; /* We need pieces [firstPiece... */
|
||||
tr_piece_index_t lastPiece; /* ...lastPiece] to dl this file */
|
||||
uint64_t offset; /* file begins at the torrent's nth byte */
|
||||
|
|
Loading…
Reference in New Issue