From 434bd6b2879089484ff4737f7797173283c73ec6 Mon Sep 17 00:00:00 2001 From: Jordan Lee Date: Tue, 22 Jan 2013 00:25:42 +0000 Subject: [PATCH] (libT) #1220 'change top folder names' -- when the root file/folder is changed, update tr_info.name too. --- libtransmission/metainfo.c | 14 ++++++-- libtransmission/rename-test.c | 17 +++++++--- libtransmission/resume.c | 34 +++++++++++++++++++ libtransmission/resume.h | 6 +++- libtransmission/torrent-magnet.c | 1 + libtransmission/torrent.c | 57 ++++++++++++++++++++++++++++++++ libtransmission/transmission.h | 32 +++++++++++++++--- qt/session.cc | 2 +- 8 files changed, 150 insertions(+), 13 deletions(-) diff --git a/libtransmission/metainfo.c b/libtransmission/metainfo.c index 03fe83545..f91ac3869 100644 --- a/libtransmission/metainfo.c +++ b/libtransmission/metainfo.c @@ -36,8 +36,9 @@ char* tr_metainfoGetBasename (const tr_info * inf) { size_t i; - const size_t name_len = strlen (inf->name); - char * ret = tr_strdup_printf ("%s.%16.16s", inf->name, inf->hashString); + const char * name = inf->originalName; + const size_t name_len = strlen (name); + char * ret = tr_strdup_printf ("%s.%16.16s", name, inf->hashString); for (i=0; iname); + tr_free (inf->originalName); inf->name = tr_strndup (str, len); + inf->originalName = tr_strndup (str, len); } if (!inf->name) - inf->name = tr_strdup (inf->hashString); + inf->name = tr_strdup (inf->hashString); + if (!inf->originalName) + inf->originalName = tr_strdup (inf->hashString); } else /* not a magnet link and has no info dict... */ { @@ -439,7 +444,9 @@ tr_metainfoParseImpl (const tr_session * session, if (!str || !*str) return "name"; tr_free (inf->name); + tr_free (inf->originalName); inf->name = tr_utf8clean (str, len); + inf->originalName = tr_strdup (inf->name); } /* comment */ @@ -560,6 +567,7 @@ tr_metainfoFree (tr_info * inf) tr_free (inf->comment); tr_free (inf->creator); tr_free (inf->torrent); + tr_free (inf->originalName); tr_free (inf->name); for (i=0; itrackerCount; i++) diff --git a/libtransmission/rename-test.c b/libtransmission/rename-test.c index babc4b897..8d131654b 100644 --- a/libtransmission/rename-test.c +++ b/libtransmission/rename-test.c @@ -154,6 +154,7 @@ create_torrent_from_base64_metainfo (tr_ctor * ctor, const char * metainfo_base6 static int test_single_filename_torrent (void) { + uint64_t loaded; tr_torrent * tor; char * tmpstr; const size_t totalSize = 14; @@ -207,12 +208,22 @@ test_single_filename_torrent (void) tmpstr = tr_buildPath (tor->downloadDir, "hello-world.txt", NULL); check (tr_fileExists (tmpstr, NULL)); + check_streq ("hello-world.txt", tr_torrentName(tor)); 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_streq ("foobar", tr_torrentName(tor)); + check (strstr (tor->info.torrent, "foobar") == NULL); check (testFileExistsAndConsistsOfThisString (tor, 0, "hello, world!\n")); + tr_free (tmpstr); + + /* (while it's renamed: confirm that the .resume file remembers the changes) */ + tr_torrentSaveResume (tor); + sync (); + loaded = tr_torrentLoadResume (tor, ~0, ctor); + check_streq ("foobar", tr_torrentName(tor)); + check ((loaded & TR_FR_NAME) != 0); /*** **** ...and rename it back again @@ -224,6 +235,7 @@ test_single_filename_torrent (void) check (!tr_fileExists (tmpstr, NULL)); check (tor->info.files[0].is_renamed); check_streq ("hello-world.txt", tor->info.files[0].name); + check_streq ("hello-world.txt", tr_torrentName(tor)); tr_free (tmpstr); check (testFileExistsAndConsistsOfThisString (tor, 0, "hello, world!\n")); @@ -265,12 +277,9 @@ create_multifile_torrent_contents (const char * top) 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; diff --git a/libtransmission/resume.c b/libtransmission/resume.c index aa767a551..183ea0985 100644 --- a/libtransmission/resume.c +++ b/libtransmission/resume.c @@ -340,6 +340,36 @@ loadIdleLimits (tr_variant * dict, tr_torrent * tor) **** ***/ +static void +saveName (tr_variant * dict, const tr_torrent * tor) +{ + tr_variantDictAddStr (dict, TR_KEY_name, tr_torrentName(tor)); +} + +static uint64_t +loadName (tr_variant * dict, tr_torrent * tor) +{ + uint64_t ret = 0; + const char * name; + + if (tr_variantDictFindStr (dict, TR_KEY_name, &name, NULL)) + { + ret = TR_FR_NAME; + + if (tr_strcmp0 (tr_torrentName(tor), name)) + { + tr_free (tor->info.name); + tor->info.name = tr_strdup (name); + } + } + + return ret; +} + +/*** +**** +***/ + static void saveFilenames (tr_variant * dict, const tr_torrent * tor) { @@ -650,6 +680,7 @@ tr_torrentSaveResume (tr_torrent * tor) saveRatioLimits (&top, tor); saveIdleLimits (&top, tor); saveFilenames (&top, tor); + saveName (&top, tor); filename = getResumeFilename (tor); if ((err = tr_variantToFile (&top, TR_VARIANT_FMT_BENC, filename))) @@ -805,6 +836,9 @@ loadFromFile (tr_torrent * tor, uint64_t fieldsToLoad) if (fieldsToLoad & TR_FR_FILENAMES) fieldsLoaded |= loadFilenames (&top, tor); + if (fieldsToLoad & TR_FR_NAME) + fieldsLoaded |= loadName (&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... */ diff --git a/libtransmission/resume.h b/libtransmission/resume.h index e6b52bcd3..a4635bda2 100644 --- a/libtransmission/resume.h +++ b/libtransmission/resume.h @@ -39,7 +39,8 @@ enum TR_FR_IDLELIMIT = (1 << 17), TR_FR_TIME_SEEDING = (1 << 18), TR_FR_TIME_DOWNLOADING = (1 << 19), - TR_FR_FILENAMES = (1 << 20) + TR_FR_FILENAMES = (1 << 20), + TR_FR_NAME = (1 << 21), }; /** @@ -53,4 +54,7 @@ void tr_torrentSaveResume (tr_torrent * tor); void tr_torrentRemoveResume (const tr_torrent * tor); +int tr_torrentRenameResume (const tr_torrent * tor, + const char * newname); + #endif diff --git a/libtransmission/torrent-magnet.c b/libtransmission/torrent-magnet.c index c502f8611..98459f17b 100644 --- a/libtransmission/torrent-magnet.c +++ b/libtransmission/torrent-magnet.c @@ -374,6 +374,7 @@ tr_torrentGetMetadataPercent (const tr_torrent * tor) return ret; } +/* FIXME: this should be renamed tr_metainfoGetMagnetLink() and moved to metainfo.c for consistency */ char * tr_torrentInfoGetMagnetLink (const tr_info * inf) { diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index 19edcef1d..21e26648e 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -3440,6 +3440,16 @@ struct rename_data void * callback_user_data; }; +static void +torrentRenameDone (tr_torrent * tor UNUSED, + const char * oldpath UNUSED, + const char * newname UNUSED, + int error, + void * user_data) +{ + *(int*)user_data = error; +} + static void torrentRenamePath (void * vdata) { @@ -3477,8 +3487,14 @@ torrentRenamePath (void * vdata) if (!error) { + /* update tr_info.files */ for (i=0; iinfo.fileCount) && (strchr(oldpath,'/')==NULL)) + tr_torrentRename (tor, newname, torrentRenameDone, &error); + tr_torrentSetDirty (tor); } } @@ -3521,3 +3537,44 @@ tr_torrentRenamePath (tr_torrent * tor, tr_runInEventThread (tor->session, torrentRenamePath, data); } + +/** +*** +**/ + +static void +torrentRename (void * vdata) +{ + int error = 0; + struct rename_data * data = vdata; + tr_torrent * const tor = data->tor; + + tr_free (tor->info.name); + tor->info.name = data->newname; + tr_torrentSetDirty (tor); + tor->anyDate = tr_time (); + + /* callback */ + if (data->callback != NULL) + (*data->callback)(tor, data->oldpath, data->newname, error, data->callback_user_data); + + /* cleanup */ + tr_free (data); +} + +void +tr_torrentRename (tr_torrent * tor, + 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->newname = tr_strdup (newname); + data->callback = callback; + data->callback_user_data = callback_user_data; + + tr_runInEventThread (tor->session, torrentRename, data); +} diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index e816aed30..4e468ecb5 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -1109,6 +1109,9 @@ typedef void (tr_torrent_rename_done_func)(tr_torrent * torrent, * @callback: the callback invoked when the renaming finishes, or NULL * @callback_data: the pointer to pass in the callback's user_data arg * + * As a special case, renaming the root file in a torrent will call + * tr_torrentRename (tor, newname). + * * EXAMPLES * * Consider a tr_torrent where its @@ -1116,7 +1119,8 @@ typedef void (tr_torrent_rename_done_func)(tr_torrent * torrent, * info.files[1].name is "frobnitz-linux/frobnitz.iso". * * 1. tr_torrentRenamePath (tor, "frobnitz-linux", "foo") will rename - * the "frotbnitz-linux" folder as "foo" and update files[*].name. + * the "frotbnitz-linux" folder as "foo", update info.files[*].name, + * and also call tr_torrentRename(tor,"foo"). * * 2. tr_torrentRenamePath (tor, "frobnitz-linux/checksum", "foo") will * rename the "frobnitz-linux/checksum" file as "foo" and update @@ -1125,8 +1129,8 @@ typedef void (tr_torrent_rename_done_func)(tr_torrent * torrent, * 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. + * returns asynchronously to avoid blocking. If you don't want to be notified + * when the function has finished, you can pass NULL as the callback arg. * * On success, the callback's error argument will be 0. * @@ -1144,6 +1148,21 @@ void tr_torrentRenamePath (tr_torrent * tor, void * callback_user_data); +/** + * @brief Changes the torrent's name. + * @see-also tr_torrentRenamePath + * + * This function changes tr_info.name. + * + * Changing tr_info's contents requires a session lock, so this function + * returns asynchronously to avoid blocking. If you don't want to be notified + * when the function has finished, you can pass NULL as the callback arg. + */ +void tr_torrentRename (tr_torrent * tor, + const char * newname, + tr_torrent_rename_done_func callback, + void * callback_user_data); + enum { TR_LOC_MOVING, @@ -1757,7 +1776,12 @@ struct tr_info /* total size of the torrent, in bytes */ uint64_t totalSize; - /* the torrent's name */ + /* The original name that came in this torrent's metainfo. + * This may differ from "name" if tr_torrentRename() is called. + * CLIENT CODE: NOT USE THIS FIELD. */ + char * originalName; + + /* The torrent's name. */ char * name; /* Path to torrent Transmission's internal copy of the .torrent file. */ diff --git a/qt/session.cc b/qt/session.cc index 21a14cbe1..19f996023 100644 --- a/qt/session.cc +++ b/qt/session.cc @@ -827,7 +827,7 @@ Session :: parseResponse( const char * json, size_t jsonLength ) else if (tr_variantDictFindInt (args, TR_KEY_id, &id) && id) { // let's get the updated file list - char * req = tr_strdup_printf ("{ \"arguments\": { \"fields\": [ \"files\", \"id\" ], \"ids\": %d }, \"method\": \"torrent-get\", \"tag\": %d }", + char * req = tr_strdup_printf ("{ \"arguments\": { \"fields\": [ \"files\", \"id\", \"name\" ], \"ids\": %d }, \"method\": \"torrent-get\", \"tag\": %d }", int(id), int(TAG_SOME_TORRENTS)); exec (req); -- 2.40.0