From ce4f20c9a683d552486826058ab6d2b13baebf09 Mon Sep 17 00:00:00 2001 From: Samathy Barratt Date: Fri, 16 Apr 2021 15:46:13 +0100 Subject: [PATCH 1/5] Use pthreads to download podcasts in parallel. Spin up as many threads as there are podcasts to download - which is potentially a LOT of threads. Also, progress bars don't work. --- configure.ac | 4 ++ src/Makefile.am | 6 ++- src/channel.c | 129 +++++++++++++++++++++++++++++++++++++++--------- src/channel.h | 23 +++++++++ 4 files changed, 136 insertions(+), 26 deletions(-) diff --git a/configure.ac b/configure.ac index 17f6c8e..5afd53c 100644 --- a/configure.ac +++ b/configure.ac @@ -46,6 +46,10 @@ else AC_SUBST(CURL_LIBS) fi +PTHREAD_LIBS=-lpthread +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_LIBS) + #AC_ARG_WITH(taglib, [ --without-taglib disable taglib support]) AC_ARG_WITH(taglib, AC_HELP_STRING([--without-taglib], [disable taglib support])]) if test "x$with_taglib" != "xno"; then diff --git a/src/Makefile.am b/src/Makefile.am index 1a47806..4e45ce9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -AM_CPPFLAGS = $(GLIBS_CFLAGS) $(CURL_CFLAGS) +AM_CPPFLAGS = $(GLIBS_CFLAGS) $(CURL_CFLAGS) $(PTHREAD_CFLAGS) bin_PROGRAMS = castget @@ -47,4 +47,6 @@ castget_SOURCES = \ castget_LDADD = \ $(CURL_LIBS) \ $(GLIBS_LIBS) \ - $(TAGLIB_LIBS) + $(TAGLIB_LIBS) \ + $(PTHREAD_LIBS) \ + diff --git a/src/channel.c b/src/channel.c index 09b9335..4336232 100644 --- a/src/channel.c +++ b/src/channel.c @@ -29,7 +29,10 @@ #include "urlget.h" #include "utils.h" +#include #include +#include +#include #include #include #include @@ -278,6 +281,16 @@ static int _do_download(channel *c, channel_info *channel_info, rss_item *item, return download_failed; } +void *_do_download_thread(void *arg) +{ + download_data *data = (download_data *)arg; + // Resume and progress bars are disabled, because + // those will be tricky with threading. + data->result = _do_download(data->c, data->channel_info, data->item, + data->user_data, data->cb, 0, data->debug, 0); + pthread_exit(NULL); +} + static int _do_catchup(channel *c, channel_info *channel_info, rss_item *item, void *user_data, channel_callback cb) { @@ -292,6 +305,14 @@ static int _do_catchup(channel *c, channel_info *channel_info, rss_item *item, return 0; } +void *_do_catchup_thread(void *arg) +{ + catchup_data *data = (catchup_data *)arg; + data->result = _do_catchup(data->c, data->channel_info, data->item, + data->user_data, data->cb); + pthread_exit(NULL); +} + int channel_update(channel *c, void *user_data, channel_callback cb, int no_download, int no_mark_read, int first_only, int resume, enclosure_filter *filter, int debug, @@ -299,10 +320,17 @@ int channel_update(channel *c, void *user_data, channel_callback cb, { int i, download_failed; rss_file *f; + int num_catchup = 0; + int num_download = 0; + void *status; + int t_result; /* Retrieve the RSS file. */ f = _get_rss(c, user_data, cb, debug); + catchup_data catchup_items[f->num_items]; + download_data download_items[f->num_items]; + if (!f) return 1; @@ -317,35 +345,88 @@ int channel_update(channel *c, void *user_data, channel_callback cb, item = f->items[i]; if (!filter || _enclosure_pattern_match(filter, item->enclosure)) { - if (no_download) - download_failed = - _do_catchup(c, &(f->channel_info), item, user_data, cb); - else - download_failed = - _do_download(c, &(f->channel_info), item, user_data, cb, resume, - debug, show_progress_bar); - - if (download_failed) - break; - - if (!no_mark_read) { - /* Mark enclosure as downloaded and immediately save channel - file to ensure that it reflects the change. */ - g_hash_table_insert(c->downloaded_enclosures, - f->items[i]->enclosure->url, - (gpointer)get_rfc822_time()); - - _cast_channel_save(c, debug); + if (no_download) { + // download_failed = + //_do_catchup(c, &(f->channel_info), item, user_data, cb); + catchup_items[num_catchup] = + (catchup_data){ .c = c, + .channel_info = &(f->channel_info), + .item = item, + .user_data = user_data, + .cb = cb }; + num_catchup++; + } else { + // download_failed = + //_do_download(c, &(f->channel_info), item, user_data, cb, resume, + // debug, show_progress_bar); + download_items[num_download] = + (download_data){ .c = c, + .channel_info = &(f->channel_info), + .item = item, + .user_data = user_data, + .cb = cb, + .resume = resume, + .debug = debug, + .show_progress_bar = show_progress_bar }; + num_download++; } - - /* If we have been instructed to deal only with the first - available enclosure, it is time to break out of the loop. */ - if (first_only) - break; } + + /* If we have been instructed to deal only with the first + available enclosure, it is time to break out of the loop. */ + if (first_only) + break; } } + pthread_t catchup_threads[num_catchup]; + + for (i = 0; i < num_catchup; i++) { + pthread_create(&catchup_threads[i], NULL, _do_catchup_thread, + (void *)&catchup_items[i]); + } + + pthread_t download_threads[num_download]; + for (i = 0; i < num_download; i++) { + pthread_create(&download_threads[i], NULL, _do_download_thread, + (void *)&download_items[i]); + } + + for (i = 0; i < num_catchup; i++) { + t_result = pthread_join(catchup_threads[i], NULL); + if (t_result != 0) + printf(strerror(t_result)); + if (catchup_items[i].result != 0) { + download_failed = 1; + break; + } + if (!no_mark_read) { + /* Mark enclosure as downloaded and immediately save channel + file to ensure that it reflects the change. */ + g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, + (gpointer)get_rfc822_time()); + + _cast_channel_save(c, debug); + } + } + + for (i = 0; i < num_download; i++) { + t_result = pthread_join(download_threads[i], NULL); + if (t_result != 0) + printf(strerror(t_result)); + if (download_items[i].result != 0 || download_failed) { + download_failed = 1; + printf("Download failed"); + break; + } + /* Mark enclosure as downloaded and immediately save channel + file to ensure that it reflects the change. */ + g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, + (gpointer)get_rfc822_time()); + + _cast_channel_save(c, debug); + } + if (!no_mark_read) { /* Update the RSS last fetched time and save the channel file again. */ diff --git a/src/channel.h b/src/channel.h index 786577a..919315e 100644 --- a/src/channel.h +++ b/src/channel.h @@ -72,4 +72,27 @@ int channel_update(channel *c, void *user_data, channel_callback cb, enclosure_filter *enclosure_filter_new(const gchar *pattern, gboolean caseless); void enclosure_filter_free(enclosure_filter *e); +typedef struct _rss_item rss_item; + +typedef struct _download_data { + channel *c; + channel_info *channel_info; + rss_item *item; + void *user_data; + channel_callback cb; + int resume; + int debug; + int show_progress_bar; + int result; +} download_data; + +typedef struct _catchup_data { + channel *c; + channel_info *channel_info; + rss_item *item; + void *user_data; + channel_callback cb; + int result; +} catchup_data; + #endif /* CHANNEL_H */ From f78ee4eefc46a6689ac8cb262419300686d14ef4 Mon Sep 17 00:00:00 2001 From: Samathy Barratt Date: Fri, 16 Apr 2021 15:56:22 +0100 Subject: [PATCH 2/5] Can't have progress bars, so just print the title --- src/channel.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/channel.c b/src/channel.c index 4336232..2427b39 100644 --- a/src/channel.c +++ b/src/channel.c @@ -286,8 +286,12 @@ void *_do_download_thread(void *arg) download_data *data = (download_data *)arg; // Resume and progress bars are disabled, because // those will be tricky with threading. + if (data->show_progress_bar) + printf("Downloading: %s\n", data->item->title); data->result = _do_download(data->c, data->channel_info, data->item, data->user_data, data->cb, 0, data->debug, 0); + if (data->show_progress_bar) + printf("Download Complete: %s\n", data->item->title); pthread_exit(NULL); } From 57d32f458787bd771b3e08676f88c72ef215c009 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Sat, 17 Apr 2021 15:28:31 +0000 Subject: [PATCH 3/5] Restyled by astyle --- src/channel.c | 652 +++++++++++++++++++++++++------------------------- src/channel.h | 68 +++--- 2 files changed, 362 insertions(+), 358 deletions(-) diff --git a/src/channel.c b/src/channel.c index 2427b39..8858c9f 100644 --- a/src/channel.c +++ b/src/channel.c @@ -43,278 +43,278 @@ static int _enclosure_pattern_match(enclosure_filter *filter, static void _enclosure_iterator(const void *user_data, int i, const xmlNode *node) { - const char *downloadtime; + const char *downloadtime; - channel *c = (channel *)user_data; + channel *c = (channel *)user_data; - downloadtime = libxmlutil_attr_as_string(node, "downloadtime"); + downloadtime = libxmlutil_attr_as_string(node, "downloadtime"); - if (downloadtime) - downloadtime = g_strdup(downloadtime); - else - downloadtime = get_rfc822_time(); + if (downloadtime) + downloadtime = g_strdup(downloadtime); + else + downloadtime = get_rfc822_time(); - g_hash_table_insert(c->downloaded_enclosures, - (gpointer)libxmlutil_attr_as_string(node, "url"), - (gpointer)downloadtime); + g_hash_table_insert(c->downloaded_enclosures, + (gpointer)libxmlutil_attr_as_string(node, "url"), + (gpointer)downloadtime); } channel *channel_new(const char *url, const char *channel_file, const char *spool_directory, const char *filename_pattern, int resume) { - channel *c; - xmlDocPtr doc; - xmlNode *root_element = NULL; - const char *s; - - c = (channel *)malloc(sizeof(struct _channel)); - c->url = g_strdup(url); - c->channel_filename = g_strdup(channel_file); - c->spool_directory = g_strdup(spool_directory); - c->filename_pattern = g_strdup(filename_pattern); - // c->resume = resume; - c->rss_last_fetched = NULL; - c->downloaded_enclosures = - g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); - - if (g_file_test(c->channel_filename, G_FILE_TEST_EXISTS)) { - doc = xmlReadFile(c->channel_filename, NULL, 0); - - if (!doc) { - g_fprintf(stderr, "Error parsing channel file %s.\n", - c->channel_filename); - return NULL; - } + channel *c; + xmlDocPtr doc; + xmlNode *root_element = NULL; + const char *s; + + c = (channel *)malloc(sizeof(struct _channel)); + c->url = g_strdup(url); + c->channel_filename = g_strdup(channel_file); + c->spool_directory = g_strdup(spool_directory); + c->filename_pattern = g_strdup(filename_pattern); + // c->resume = resume; + c->rss_last_fetched = NULL; + c->downloaded_enclosures = + g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); + + if (g_file_test(c->channel_filename, G_FILE_TEST_EXISTS)) { + doc = xmlReadFile(c->channel_filename, NULL, 0); + + if (!doc) { + g_fprintf(stderr, "Error parsing channel file %s.\n", + c->channel_filename); + return NULL; + } - root_element = xmlDocGetRootElement(doc); + root_element = xmlDocGetRootElement(doc); - if (!root_element) { - xmlFreeDoc(doc); + if (!root_element) { + xmlFreeDoc(doc); - g_fprintf(stderr, "Error parsing channel file %s.\n", - c->channel_filename); - return NULL; - } + g_fprintf(stderr, "Error parsing channel file %s.\n", + c->channel_filename); + return NULL; + } - /* Fetch channel attributes. */ - s = libxmlutil_attr_as_string(root_element, "rsslastfetched"); + /* Fetch channel attributes. */ + s = libxmlutil_attr_as_string(root_element, "rsslastfetched"); - if (s) - c->rss_last_fetched = g_strdup(s); + if (s) + c->rss_last_fetched = g_strdup(s); - /* Iterate encolsure elements. */ - libxmlutil_iterate_by_tag_name(root_element, "enclosure", c, - _enclosure_iterator); + /* Iterate encolsure elements. */ + libxmlutil_iterate_by_tag_name(root_element, "enclosure", c, + _enclosure_iterator); - xmlFreeDoc(doc); - } + xmlFreeDoc(doc); + } - return c; + return c; } static void _cast_channel_save_downloaded_enclosure(gpointer key, - gpointer value, - gpointer user_data) + gpointer value, + gpointer user_data) { - FILE *f = (FILE *)user_data; - gchar *escaped_key = g_markup_escape_text(key, -1); + FILE *f = (FILE *)user_data; + gchar *escaped_key = g_markup_escape_text(key, -1); - if (value) - g_fprintf(f, " \n", escaped_key, - (gchar *)value); - else - g_fprintf(f, " \n", escaped_key); + if (value) + g_fprintf(f, " \n", escaped_key, + (gchar *)value); + else + g_fprintf(f, " \n", escaped_key); - g_free(escaped_key); + g_free(escaped_key); } static int _cast_channel_save_channel(FILE *f, gpointer user_data, int debug) { - channel *c = (channel *)user_data; + channel *c = (channel *)user_data; - g_fprintf(f, "\n"); + g_fprintf(f, "\n"); - if (c->rss_last_fetched) - g_fprintf(f, "\n", - c->rss_last_fetched); - else - g_fprintf(f, "\n"); + if (c->rss_last_fetched) + g_fprintf(f, "\n", + c->rss_last_fetched); + else + g_fprintf(f, "\n"); - g_hash_table_foreach(c->downloaded_enclosures, - _cast_channel_save_downloaded_enclosure, f); + g_hash_table_foreach(c->downloaded_enclosures, + _cast_channel_save_downloaded_enclosure, f); - g_fprintf(f, "\n"); + g_fprintf(f, "\n"); - return 0; + return 0; } static void _cast_channel_save(channel *c, int debug) { - write_by_temporary_file(c->channel_filename, _cast_channel_save_channel, c, - NULL, debug); + write_by_temporary_file(c->channel_filename, _cast_channel_save_channel, c, + NULL, debug); } void channel_free(channel *c) { - g_hash_table_destroy(c->downloaded_enclosures); - g_free(c->spool_directory); - g_free(c->channel_filename); - g_free(c->url); - g_free(c->filename_pattern); - free(c); + g_hash_table_destroy(c->downloaded_enclosures); + g_free(c->spool_directory); + g_free(c->channel_filename); + g_free(c->url); + g_free(c->filename_pattern); + free(c); } static size_t _enclosure_urlget_cb(void *buffer, size_t size, size_t nmemb, void *user_data) { - FILE *f = (FILE *)user_data; + FILE *f = (FILE *)user_data; - return fwrite(buffer, size, nmemb, f); + return fwrite(buffer, size, nmemb, f); } static rss_file *_get_rss(channel *c, void *user_data, channel_callback cb, int debug) { - rss_file *f; + rss_file *f; - if (cb) - cb(user_data, CCA_RSS_DOWNLOAD_START, NULL, NULL, NULL); + if (cb) + cb(user_data, CCA_RSS_DOWNLOAD_START, NULL, NULL, NULL); - if (!strncmp("http://", c->url, strlen("http://")) || - !strncmp("https://", c->url, strlen("https://"))) - f = rss_open_url(c->url, debug); - else - f = rss_open_file(c->url); + if (!strncmp("http://", c->url, strlen("http://")) || + !strncmp("https://", c->url, strlen("https://"))) + f = rss_open_url(c->url, debug); + else + f = rss_open_file(c->url); - if (cb) - cb(user_data, CCA_RSS_DOWNLOAD_END, &(f->channel_info), NULL, NULL); + if (cb) + cb(user_data, CCA_RSS_DOWNLOAD_END, &(f->channel_info), NULL, NULL); - return f; + return f; } static int _do_download(channel *c, channel_info *channel_info, rss_item *item, void *user_data, channel_callback cb, int resume, int debug, int show_progress_bar) { - int download_failed; - long resume_from = 0; - gchar *enclosure_full_filename; - FILE *enclosure_file; - struct stat fileinfo; - progress_bar *pb; - - /* Check that the spool directory exists. */ - if (!g_file_test(c->spool_directory, G_FILE_TEST_IS_DIR)) { - g_fprintf(stderr, "Spool directory %s not found.\n", c->spool_directory); - return 1; - } - - /* Build enclosure filename. */ - enclosure_full_filename = build_enclosure_filename( - c->spool_directory, c->filename_pattern, channel_info, item); - - if (g_file_test(enclosure_full_filename, G_FILE_TEST_EXISTS)) { - /* A file with the same filename already exists. If the user has asked us - to resume downloads, we should append to the file. Otherwise we should - refuse to continue. If the feed uses the same filename for each - enclosure, running in append mode will corrupt existing files. There is - probably no practical way to avoid this, and the issue is documented in - castget(1) and castgetrc(5). */ - if (resume) { - /* Set resume offset to the size of the file as it is now (and use - non-append mode if the size is zero or stat() fails). */ - if (0 == stat(enclosure_full_filename, &fileinfo)) - resume_from = fileinfo.st_size; - else - resume_from = 0; - } else { - /* File exists but user does not allow us to append so we have to - abort. */ - g_fprintf(stderr, "Enclosure file %s already exists.\n", - enclosure_full_filename); - g_free(enclosure_full_filename); - return 1; + int download_failed; + long resume_from = 0; + gchar *enclosure_full_filename; + FILE *enclosure_file; + struct stat fileinfo; + progress_bar *pb; + + /* Check that the spool directory exists. */ + if (!g_file_test(c->spool_directory, G_FILE_TEST_IS_DIR)) { + g_fprintf(stderr, "Spool directory %s not found.\n", c->spool_directory); + return 1; } - } else - /* By letting the offset be 0 we will write in non-append mode. */ - resume_from = 0; - enclosure_file = fopen(enclosure_full_filename, resume_from ? "ab" : "wb"); + /* Build enclosure filename. */ + enclosure_full_filename = build_enclosure_filename( + c->spool_directory, c->filename_pattern, channel_info, item); + + if (g_file_test(enclosure_full_filename, G_FILE_TEST_EXISTS)) { + /* A file with the same filename already exists. If the user has asked us + to resume downloads, we should append to the file. Otherwise we should + refuse to continue. If the feed uses the same filename for each + enclosure, running in append mode will corrupt existing files. There is + probably no practical way to avoid this, and the issue is documented in + castget(1) and castgetrc(5). */ + if (resume) { + /* Set resume offset to the size of the file as it is now (and use + non-append mode if the size is zero or stat() fails). */ + if (0 == stat(enclosure_full_filename, &fileinfo)) + resume_from = fileinfo.st_size; + else + resume_from = 0; + } else { + /* File exists but user does not allow us to append so we have to + abort. */ + g_fprintf(stderr, "Enclosure file %s already exists.\n", + enclosure_full_filename); + g_free(enclosure_full_filename); + return 1; + } + } else + /* By letting the offset be 0 we will write in non-append mode. */ + resume_from = 0; + + enclosure_file = fopen(enclosure_full_filename, resume_from ? "ab" : "wb"); - if (!enclosure_file) { - g_fprintf(stderr, "Error opening enclosure file %s.\n", - enclosure_full_filename); - g_free(enclosure_full_filename); - return 1; - } + if (!enclosure_file) { + g_fprintf(stderr, "Error opening enclosure file %s.\n", + enclosure_full_filename); + g_free(enclosure_full_filename); + return 1; + } - if (cb) - cb(user_data, CCA_ENCLOSURE_DOWNLOAD_START, channel_info, item->enclosure, - enclosure_full_filename); + if (cb) + cb(user_data, CCA_ENCLOSURE_DOWNLOAD_START, channel_info, item->enclosure, + enclosure_full_filename); - if (show_progress_bar) - pb = progress_bar_new(resume_from); - else - pb = NULL; + if (show_progress_bar) + pb = progress_bar_new(resume_from); + else + pb = NULL; - if (urlget_buffer(item->enclosure->url, enclosure_file, _enclosure_urlget_cb, - resume_from, debug, pb)) { - g_fprintf(stderr, "Error downloading enclosure from %s.\n", - item->enclosure->url); + if (urlget_buffer(item->enclosure->url, enclosure_file, _enclosure_urlget_cb, + resume_from, debug, pb)) { + g_fprintf(stderr, "Error downloading enclosure from %s.\n", + item->enclosure->url); - download_failed = 1; - } else - download_failed = 0; + download_failed = 1; + } else + download_failed = 0; - if (pb) - progress_bar_free(pb); + if (pb) + progress_bar_free(pb); - fclose(enclosure_file); + fclose(enclosure_file); - if (cb) - cb(user_data, CCA_ENCLOSURE_DOWNLOAD_END, channel_info, item->enclosure, - enclosure_full_filename); + if (cb) + cb(user_data, CCA_ENCLOSURE_DOWNLOAD_END, channel_info, item->enclosure, + enclosure_full_filename); - g_free(enclosure_full_filename); + g_free(enclosure_full_filename); - return download_failed; + return download_failed; } void *_do_download_thread(void *arg) { - download_data *data = (download_data *)arg; - // Resume and progress bars are disabled, because - // those will be tricky with threading. - if (data->show_progress_bar) - printf("Downloading: %s\n", data->item->title); - data->result = _do_download(data->c, data->channel_info, data->item, - data->user_data, data->cb, 0, data->debug, 0); - if (data->show_progress_bar) - printf("Download Complete: %s\n", data->item->title); - pthread_exit(NULL); + download_data *data = (download_data *)arg; + // Resume and progress bars are disabled, because + // those will be tricky with threading. + if (data->show_progress_bar) + printf("Downloading: %s\n", data->item->title); + data->result = _do_download(data->c, data->channel_info, data->item, + data->user_data, data->cb, 0, data->debug, 0); + if (data->show_progress_bar) + printf("Download Complete: %s\n", data->item->title); + pthread_exit(NULL); } static int _do_catchup(channel *c, channel_info *channel_info, rss_item *item, void *user_data, channel_callback cb) { - if (cb) { - cb(user_data, CCA_ENCLOSURE_DOWNLOAD_START, channel_info, item->enclosure, - NULL); + if (cb) { + cb(user_data, CCA_ENCLOSURE_DOWNLOAD_START, channel_info, item->enclosure, + NULL); - cb(user_data, CCA_ENCLOSURE_DOWNLOAD_END, channel_info, item->enclosure, - NULL); - } + cb(user_data, CCA_ENCLOSURE_DOWNLOAD_END, channel_info, item->enclosure, + NULL); + } - return 0; + return 0; } void *_do_catchup_thread(void *arg) { - catchup_data *data = (catchup_data *)arg; - data->result = _do_catchup(data->c, data->channel_info, data->item, - data->user_data, data->cb); - pthread_exit(NULL); + catchup_data *data = (catchup_data *)arg; + data->result = _do_catchup(data->c, data->channel_info, data->item, + data->user_data, data->cb); + pthread_exit(NULL); } int channel_update(channel *c, void *user_data, channel_callback cb, @@ -322,129 +322,133 @@ int channel_update(channel *c, void *user_data, channel_callback cb, int resume, enclosure_filter *filter, int debug, int show_progress_bar) { - int i, download_failed; - rss_file *f; - int num_catchup = 0; - int num_download = 0; - void *status; - int t_result; - - /* Retrieve the RSS file. */ - f = _get_rss(c, user_data, cb, debug); - - catchup_data catchup_items[f->num_items]; - download_data download_items[f->num_items]; - - if (!f) - return 1; - - /* Check enclosures in RSS file. */ - for (i = 0; i < f->num_items; i++) - if (f->items[i]->enclosure) { - if (!g_hash_table_lookup_extended(c->downloaded_enclosures, - f->items[i]->enclosure->url, NULL, - NULL)) { - rss_item *item; - - item = f->items[i]; - - if (!filter || _enclosure_pattern_match(filter, item->enclosure)) { - if (no_download) { - // download_failed = - //_do_catchup(c, &(f->channel_info), item, user_data, cb); - catchup_items[num_catchup] = - (catchup_data){ .c = c, - .channel_info = &(f->channel_info), - .item = item, - .user_data = user_data, - .cb = cb }; - num_catchup++; - } else { - // download_failed = - //_do_download(c, &(f->channel_info), item, user_data, cb, resume, - // debug, show_progress_bar); - download_items[num_download] = - (download_data){ .c = c, - .channel_info = &(f->channel_info), - .item = item, - .user_data = user_data, - .cb = cb, - .resume = resume, - .debug = debug, - .show_progress_bar = show_progress_bar }; - num_download++; - } + int i, download_failed; + rss_file *f; + int num_catchup = 0; + int num_download = 0; + void *status; + int t_result; + + /* Retrieve the RSS file. */ + f = _get_rss(c, user_data, cb, debug); + + catchup_data catchup_items[f->num_items]; + download_data download_items[f->num_items]; + + if (!f) + return 1; + + /* Check enclosures in RSS file. */ + for (i = 0; i < f->num_items; i++) + if (f->items[i]->enclosure) { + if (!g_hash_table_lookup_extended(c->downloaded_enclosures, + f->items[i]->enclosure->url, NULL, + NULL)) { + rss_item *item; + + item = f->items[i]; + + if (!filter || _enclosure_pattern_match(filter, item->enclosure)) { + if (no_download) { + // download_failed = + //_do_catchup(c, &(f->channel_info), item, user_data, cb); + catchup_items[num_catchup] = + (catchup_data) { + .c = c, + .channel_info = &(f->channel_info), + .item = item, + .user_data = user_data, + .cb = cb + }; + num_catchup++; + } else { + // download_failed = + //_do_download(c, &(f->channel_info), item, user_data, cb, resume, + // debug, show_progress_bar); + download_items[num_download] = + (download_data) { + .c = c, + .channel_info = &(f->channel_info), + .item = item, + .user_data = user_data, + .cb = cb, + .resume = resume, + .debug = debug, + .show_progress_bar = show_progress_bar + }; + num_download++; + } + } + + /* If we have been instructed to deal only with the first + available enclosure, it is time to break out of the loop. */ + if (first_only) + break; + } } - /* If we have been instructed to deal only with the first - available enclosure, it is time to break out of the loop. */ - if (first_only) - break; - } - } + pthread_t catchup_threads[num_catchup]; - pthread_t catchup_threads[num_catchup]; - - for (i = 0; i < num_catchup; i++) { - pthread_create(&catchup_threads[i], NULL, _do_catchup_thread, - (void *)&catchup_items[i]); - } - - pthread_t download_threads[num_download]; - for (i = 0; i < num_download; i++) { - pthread_create(&download_threads[i], NULL, _do_download_thread, - (void *)&download_items[i]); - } - - for (i = 0; i < num_catchup; i++) { - t_result = pthread_join(catchup_threads[i], NULL); - if (t_result != 0) - printf(strerror(t_result)); - if (catchup_items[i].result != 0) { - download_failed = 1; - break; + for (i = 0; i < num_catchup; i++) { + pthread_create(&catchup_threads[i], NULL, _do_catchup_thread, + (void *)&catchup_items[i]); } - if (!no_mark_read) { - /* Mark enclosure as downloaded and immediately save channel - file to ensure that it reflects the change. */ - g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, - (gpointer)get_rfc822_time()); - _cast_channel_save(c, debug); + pthread_t download_threads[num_download]; + for (i = 0; i < num_download; i++) { + pthread_create(&download_threads[i], NULL, _do_download_thread, + (void *)&download_items[i]); } - } - - for (i = 0; i < num_download; i++) { - t_result = pthread_join(download_threads[i], NULL); - if (t_result != 0) - printf(strerror(t_result)); - if (download_items[i].result != 0 || download_failed) { - download_failed = 1; - printf("Download failed"); - break; + + for (i = 0; i < num_catchup; i++) { + t_result = pthread_join(catchup_threads[i], NULL); + if (t_result != 0) + printf(strerror(t_result)); + if (catchup_items[i].result != 0) { + download_failed = 1; + break; + } + if (!no_mark_read) { + /* Mark enclosure as downloaded and immediately save channel + file to ensure that it reflects the change. */ + g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, + (gpointer)get_rfc822_time()); + + _cast_channel_save(c, debug); + } } - /* Mark enclosure as downloaded and immediately save channel - file to ensure that it reflects the change. */ - g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, - (gpointer)get_rfc822_time()); - _cast_channel_save(c, debug); - } + for (i = 0; i < num_download; i++) { + t_result = pthread_join(download_threads[i], NULL); + if (t_result != 0) + printf(strerror(t_result)); + if (download_items[i].result != 0 || download_failed) { + download_failed = 1; + printf("Download failed"); + break; + } + /* Mark enclosure as downloaded and immediately save channel + file to ensure that it reflects the change. */ + g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, + (gpointer)get_rfc822_time()); - if (!no_mark_read) { - /* Update the RSS last fetched time and save the channel file again. */ + _cast_channel_save(c, debug); + } - if (c->rss_last_fetched) - g_free(c->rss_last_fetched); + if (!no_mark_read) { + /* Update the RSS last fetched time and save the channel file again. */ - c->rss_last_fetched = g_strdup(f->fetched_time); + if (c->rss_last_fetched) + g_free(c->rss_last_fetched); - _cast_channel_save(c, debug); - } + c->rss_last_fetched = g_strdup(f->fetched_time); - rss_close(f); + _cast_channel_save(c, debug); + } + + rss_close(f); - return 0; + return 0; } /* Match the (file) name of an enclosure against a regexp. Letters @@ -452,51 +456,51 @@ int channel_update(channel *c, void *user_data, channel_callback cb, 'caseless' is TRUE. Returns TRUE if the pattern matches, FALSE otherwise. */ static gboolean _enclosure_pattern_match(enclosure_filter *filter, - const enclosure *enclosure) + const enclosure *enclosure) { - GError *error = NULL; - GRegexCompileFlags compile_options = 0; - GRegexMatchFlags match_options = 0; - GRegex *regex; - gboolean match; - - g_assert(filter); - g_assert(filter->pattern); - g_assert(enclosure); - - if (filter->caseless) - compile_options |= G_REGEX_CASELESS; - - regex = g_regex_new(filter->pattern, compile_options, match_options, &error); - - if (error) { - fprintf(stderr, "Error compiling regular expression %s: %s\n", - filter->pattern, error->message); - g_error_free(error); - return FALSE; - } + GError *error = NULL; + GRegexCompileFlags compile_options = 0; + GRegexMatchFlags match_options = 0; + GRegex *regex; + gboolean match; + + g_assert(filter); + g_assert(filter->pattern); + g_assert(enclosure); + + if (filter->caseless) + compile_options |= G_REGEX_CASELESS; + + regex = g_regex_new(filter->pattern, compile_options, match_options, &error); + + if (error) { + fprintf(stderr, "Error compiling regular expression %s: %s\n", + filter->pattern, error->message); + g_error_free(error); + return FALSE; + } - match = g_regex_match(regex, enclosure->url, match_options, NULL); + match = g_regex_match(regex, enclosure->url, match_options, NULL); - g_regex_unref(regex); + g_regex_unref(regex); - return match; + return match; } enclosure_filter *enclosure_filter_new(const gchar *pattern, gboolean caseless) { - enclosure_filter *e = g_malloc(sizeof(struct _enclosure_filter)); + enclosure_filter *e = g_malloc(sizeof(struct _enclosure_filter)); - g_assert(pattern); + g_assert(pattern); - e->pattern = g_strdup(pattern); - e->caseless = caseless; + e->pattern = g_strdup(pattern); + e->caseless = caseless; - return e; + return e; } void enclosure_filter_free(enclosure_filter *e) { - g_free(e->pattern); - g_free(e); + g_free(e->pattern); + g_free(e); } diff --git a/src/channel.h b/src/channel.h index 919315e..c9a69d1 100644 --- a/src/channel.h +++ b/src/channel.h @@ -23,37 +23,37 @@ #include typedef enum { - CCA_RSS_DOWNLOAD_START, - CCA_RSS_DOWNLOAD_END, - CCA_ENCLOSURE_DOWNLOAD_START, - CCA_ENCLOSURE_DOWNLOAD_END + CCA_RSS_DOWNLOAD_START, + CCA_RSS_DOWNLOAD_END, + CCA_ENCLOSURE_DOWNLOAD_START, + CCA_ENCLOSURE_DOWNLOAD_END } channel_action; typedef struct _channel { - gchar *url; - gchar *channel_filename; - gchar *spool_directory; - gchar *filename_pattern; - GHashTable *downloaded_enclosures; - gchar *rss_last_fetched; + gchar *url; + gchar *channel_filename; + gchar *spool_directory; + gchar *filename_pattern; + GHashTable *downloaded_enclosures; + gchar *rss_last_fetched; } channel; typedef struct _channel_info { - char *title; - char *link; - char *description; - char *language; + char *title; + char *link; + char *description; + char *language; } channel_info; typedef struct _enclosure { - char *url; - long length; - char *type; + char *url; + long length; + char *type; } enclosure; typedef struct _enclosure_filter { - gchar *pattern; - gboolean caseless; + gchar *pattern; + gboolean caseless; } enclosure_filter; typedef void (*channel_callback)(void *user_data, channel_action action, @@ -75,24 +75,24 @@ void enclosure_filter_free(enclosure_filter *e); typedef struct _rss_item rss_item; typedef struct _download_data { - channel *c; - channel_info *channel_info; - rss_item *item; - void *user_data; - channel_callback cb; - int resume; - int debug; - int show_progress_bar; - int result; + channel *c; + channel_info *channel_info; + rss_item *item; + void *user_data; + channel_callback cb; + int resume; + int debug; + int show_progress_bar; + int result; } download_data; typedef struct _catchup_data { - channel *c; - channel_info *channel_info; - rss_item *item; - void *user_data; - channel_callback cb; - int result; + channel *c; + channel_info *channel_info; + rss_item *item; + void *user_data; + channel_callback cb; + int result; } catchup_data; #endif /* CHANNEL_H */ From 84da65924b6e06e0ebbd030794cb507eb677dccf Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Sat, 17 Apr 2021 15:28:32 +0000 Subject: [PATCH 4/5] Restyled by clang-format --- src/channel.c | 652 +++++++++++++++++++++++++------------------------- src/channel.h | 68 +++--- 2 files changed, 358 insertions(+), 362 deletions(-) diff --git a/src/channel.c b/src/channel.c index 8858c9f..2427b39 100644 --- a/src/channel.c +++ b/src/channel.c @@ -43,278 +43,278 @@ static int _enclosure_pattern_match(enclosure_filter *filter, static void _enclosure_iterator(const void *user_data, int i, const xmlNode *node) { - const char *downloadtime; + const char *downloadtime; - channel *c = (channel *)user_data; + channel *c = (channel *)user_data; - downloadtime = libxmlutil_attr_as_string(node, "downloadtime"); + downloadtime = libxmlutil_attr_as_string(node, "downloadtime"); - if (downloadtime) - downloadtime = g_strdup(downloadtime); - else - downloadtime = get_rfc822_time(); + if (downloadtime) + downloadtime = g_strdup(downloadtime); + else + downloadtime = get_rfc822_time(); - g_hash_table_insert(c->downloaded_enclosures, - (gpointer)libxmlutil_attr_as_string(node, "url"), - (gpointer)downloadtime); + g_hash_table_insert(c->downloaded_enclosures, + (gpointer)libxmlutil_attr_as_string(node, "url"), + (gpointer)downloadtime); } channel *channel_new(const char *url, const char *channel_file, const char *spool_directory, const char *filename_pattern, int resume) { - channel *c; - xmlDocPtr doc; - xmlNode *root_element = NULL; - const char *s; - - c = (channel *)malloc(sizeof(struct _channel)); - c->url = g_strdup(url); - c->channel_filename = g_strdup(channel_file); - c->spool_directory = g_strdup(spool_directory); - c->filename_pattern = g_strdup(filename_pattern); - // c->resume = resume; - c->rss_last_fetched = NULL; - c->downloaded_enclosures = - g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); - - if (g_file_test(c->channel_filename, G_FILE_TEST_EXISTS)) { - doc = xmlReadFile(c->channel_filename, NULL, 0); - - if (!doc) { - g_fprintf(stderr, "Error parsing channel file %s.\n", - c->channel_filename); - return NULL; - } + channel *c; + xmlDocPtr doc; + xmlNode *root_element = NULL; + const char *s; + + c = (channel *)malloc(sizeof(struct _channel)); + c->url = g_strdup(url); + c->channel_filename = g_strdup(channel_file); + c->spool_directory = g_strdup(spool_directory); + c->filename_pattern = g_strdup(filename_pattern); + // c->resume = resume; + c->rss_last_fetched = NULL; + c->downloaded_enclosures = + g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); + + if (g_file_test(c->channel_filename, G_FILE_TEST_EXISTS)) { + doc = xmlReadFile(c->channel_filename, NULL, 0); + + if (!doc) { + g_fprintf(stderr, "Error parsing channel file %s.\n", + c->channel_filename); + return NULL; + } - root_element = xmlDocGetRootElement(doc); + root_element = xmlDocGetRootElement(doc); - if (!root_element) { - xmlFreeDoc(doc); + if (!root_element) { + xmlFreeDoc(doc); - g_fprintf(stderr, "Error parsing channel file %s.\n", - c->channel_filename); - return NULL; - } + g_fprintf(stderr, "Error parsing channel file %s.\n", + c->channel_filename); + return NULL; + } - /* Fetch channel attributes. */ - s = libxmlutil_attr_as_string(root_element, "rsslastfetched"); + /* Fetch channel attributes. */ + s = libxmlutil_attr_as_string(root_element, "rsslastfetched"); - if (s) - c->rss_last_fetched = g_strdup(s); + if (s) + c->rss_last_fetched = g_strdup(s); - /* Iterate encolsure elements. */ - libxmlutil_iterate_by_tag_name(root_element, "enclosure", c, - _enclosure_iterator); + /* Iterate encolsure elements. */ + libxmlutil_iterate_by_tag_name(root_element, "enclosure", c, + _enclosure_iterator); - xmlFreeDoc(doc); - } + xmlFreeDoc(doc); + } - return c; + return c; } static void _cast_channel_save_downloaded_enclosure(gpointer key, - gpointer value, - gpointer user_data) + gpointer value, + gpointer user_data) { - FILE *f = (FILE *)user_data; - gchar *escaped_key = g_markup_escape_text(key, -1); + FILE *f = (FILE *)user_data; + gchar *escaped_key = g_markup_escape_text(key, -1); - if (value) - g_fprintf(f, " \n", escaped_key, - (gchar *)value); - else - g_fprintf(f, " \n", escaped_key); + if (value) + g_fprintf(f, " \n", escaped_key, + (gchar *)value); + else + g_fprintf(f, " \n", escaped_key); - g_free(escaped_key); + g_free(escaped_key); } static int _cast_channel_save_channel(FILE *f, gpointer user_data, int debug) { - channel *c = (channel *)user_data; + channel *c = (channel *)user_data; - g_fprintf(f, "\n"); + g_fprintf(f, "\n"); - if (c->rss_last_fetched) - g_fprintf(f, "\n", - c->rss_last_fetched); - else - g_fprintf(f, "\n"); + if (c->rss_last_fetched) + g_fprintf(f, "\n", + c->rss_last_fetched); + else + g_fprintf(f, "\n"); - g_hash_table_foreach(c->downloaded_enclosures, - _cast_channel_save_downloaded_enclosure, f); + g_hash_table_foreach(c->downloaded_enclosures, + _cast_channel_save_downloaded_enclosure, f); - g_fprintf(f, "\n"); + g_fprintf(f, "\n"); - return 0; + return 0; } static void _cast_channel_save(channel *c, int debug) { - write_by_temporary_file(c->channel_filename, _cast_channel_save_channel, c, - NULL, debug); + write_by_temporary_file(c->channel_filename, _cast_channel_save_channel, c, + NULL, debug); } void channel_free(channel *c) { - g_hash_table_destroy(c->downloaded_enclosures); - g_free(c->spool_directory); - g_free(c->channel_filename); - g_free(c->url); - g_free(c->filename_pattern); - free(c); + g_hash_table_destroy(c->downloaded_enclosures); + g_free(c->spool_directory); + g_free(c->channel_filename); + g_free(c->url); + g_free(c->filename_pattern); + free(c); } static size_t _enclosure_urlget_cb(void *buffer, size_t size, size_t nmemb, void *user_data) { - FILE *f = (FILE *)user_data; + FILE *f = (FILE *)user_data; - return fwrite(buffer, size, nmemb, f); + return fwrite(buffer, size, nmemb, f); } static rss_file *_get_rss(channel *c, void *user_data, channel_callback cb, int debug) { - rss_file *f; + rss_file *f; - if (cb) - cb(user_data, CCA_RSS_DOWNLOAD_START, NULL, NULL, NULL); + if (cb) + cb(user_data, CCA_RSS_DOWNLOAD_START, NULL, NULL, NULL); - if (!strncmp("http://", c->url, strlen("http://")) || - !strncmp("https://", c->url, strlen("https://"))) - f = rss_open_url(c->url, debug); - else - f = rss_open_file(c->url); + if (!strncmp("http://", c->url, strlen("http://")) || + !strncmp("https://", c->url, strlen("https://"))) + f = rss_open_url(c->url, debug); + else + f = rss_open_file(c->url); - if (cb) - cb(user_data, CCA_RSS_DOWNLOAD_END, &(f->channel_info), NULL, NULL); + if (cb) + cb(user_data, CCA_RSS_DOWNLOAD_END, &(f->channel_info), NULL, NULL); - return f; + return f; } static int _do_download(channel *c, channel_info *channel_info, rss_item *item, void *user_data, channel_callback cb, int resume, int debug, int show_progress_bar) { - int download_failed; - long resume_from = 0; - gchar *enclosure_full_filename; - FILE *enclosure_file; - struct stat fileinfo; - progress_bar *pb; - - /* Check that the spool directory exists. */ - if (!g_file_test(c->spool_directory, G_FILE_TEST_IS_DIR)) { - g_fprintf(stderr, "Spool directory %s not found.\n", c->spool_directory); - return 1; - } - - /* Build enclosure filename. */ - enclosure_full_filename = build_enclosure_filename( - c->spool_directory, c->filename_pattern, channel_info, item); - - if (g_file_test(enclosure_full_filename, G_FILE_TEST_EXISTS)) { - /* A file with the same filename already exists. If the user has asked us - to resume downloads, we should append to the file. Otherwise we should - refuse to continue. If the feed uses the same filename for each - enclosure, running in append mode will corrupt existing files. There is - probably no practical way to avoid this, and the issue is documented in - castget(1) and castgetrc(5). */ - if (resume) { - /* Set resume offset to the size of the file as it is now (and use - non-append mode if the size is zero or stat() fails). */ - if (0 == stat(enclosure_full_filename, &fileinfo)) - resume_from = fileinfo.st_size; - else - resume_from = 0; - } else { - /* File exists but user does not allow us to append so we have to - abort. */ - g_fprintf(stderr, "Enclosure file %s already exists.\n", - enclosure_full_filename); - g_free(enclosure_full_filename); - return 1; - } - } else - /* By letting the offset be 0 we will write in non-append mode. */ + int download_failed; + long resume_from = 0; + gchar *enclosure_full_filename; + FILE *enclosure_file; + struct stat fileinfo; + progress_bar *pb; + + /* Check that the spool directory exists. */ + if (!g_file_test(c->spool_directory, G_FILE_TEST_IS_DIR)) { + g_fprintf(stderr, "Spool directory %s not found.\n", c->spool_directory); + return 1; + } + + /* Build enclosure filename. */ + enclosure_full_filename = build_enclosure_filename( + c->spool_directory, c->filename_pattern, channel_info, item); + + if (g_file_test(enclosure_full_filename, G_FILE_TEST_EXISTS)) { + /* A file with the same filename already exists. If the user has asked us + to resume downloads, we should append to the file. Otherwise we should + refuse to continue. If the feed uses the same filename for each + enclosure, running in append mode will corrupt existing files. There is + probably no practical way to avoid this, and the issue is documented in + castget(1) and castgetrc(5). */ + if (resume) { + /* Set resume offset to the size of the file as it is now (and use + non-append mode if the size is zero or stat() fails). */ + if (0 == stat(enclosure_full_filename, &fileinfo)) + resume_from = fileinfo.st_size; + else resume_from = 0; + } else { + /* File exists but user does not allow us to append so we have to + abort. */ + g_fprintf(stderr, "Enclosure file %s already exists.\n", + enclosure_full_filename); + g_free(enclosure_full_filename); + return 1; + } + } else + /* By letting the offset be 0 we will write in non-append mode. */ + resume_from = 0; - enclosure_file = fopen(enclosure_full_filename, resume_from ? "ab" : "wb"); + enclosure_file = fopen(enclosure_full_filename, resume_from ? "ab" : "wb"); - if (!enclosure_file) { - g_fprintf(stderr, "Error opening enclosure file %s.\n", - enclosure_full_filename); - g_free(enclosure_full_filename); - return 1; - } + if (!enclosure_file) { + g_fprintf(stderr, "Error opening enclosure file %s.\n", + enclosure_full_filename); + g_free(enclosure_full_filename); + return 1; + } - if (cb) - cb(user_data, CCA_ENCLOSURE_DOWNLOAD_START, channel_info, item->enclosure, - enclosure_full_filename); + if (cb) + cb(user_data, CCA_ENCLOSURE_DOWNLOAD_START, channel_info, item->enclosure, + enclosure_full_filename); - if (show_progress_bar) - pb = progress_bar_new(resume_from); - else - pb = NULL; + if (show_progress_bar) + pb = progress_bar_new(resume_from); + else + pb = NULL; - if (urlget_buffer(item->enclosure->url, enclosure_file, _enclosure_urlget_cb, - resume_from, debug, pb)) { - g_fprintf(stderr, "Error downloading enclosure from %s.\n", - item->enclosure->url); + if (urlget_buffer(item->enclosure->url, enclosure_file, _enclosure_urlget_cb, + resume_from, debug, pb)) { + g_fprintf(stderr, "Error downloading enclosure from %s.\n", + item->enclosure->url); - download_failed = 1; - } else - download_failed = 0; + download_failed = 1; + } else + download_failed = 0; - if (pb) - progress_bar_free(pb); + if (pb) + progress_bar_free(pb); - fclose(enclosure_file); + fclose(enclosure_file); - if (cb) - cb(user_data, CCA_ENCLOSURE_DOWNLOAD_END, channel_info, item->enclosure, - enclosure_full_filename); + if (cb) + cb(user_data, CCA_ENCLOSURE_DOWNLOAD_END, channel_info, item->enclosure, + enclosure_full_filename); - g_free(enclosure_full_filename); + g_free(enclosure_full_filename); - return download_failed; + return download_failed; } void *_do_download_thread(void *arg) { - download_data *data = (download_data *)arg; - // Resume and progress bars are disabled, because - // those will be tricky with threading. - if (data->show_progress_bar) - printf("Downloading: %s\n", data->item->title); - data->result = _do_download(data->c, data->channel_info, data->item, - data->user_data, data->cb, 0, data->debug, 0); - if (data->show_progress_bar) - printf("Download Complete: %s\n", data->item->title); - pthread_exit(NULL); + download_data *data = (download_data *)arg; + // Resume and progress bars are disabled, because + // those will be tricky with threading. + if (data->show_progress_bar) + printf("Downloading: %s\n", data->item->title); + data->result = _do_download(data->c, data->channel_info, data->item, + data->user_data, data->cb, 0, data->debug, 0); + if (data->show_progress_bar) + printf("Download Complete: %s\n", data->item->title); + pthread_exit(NULL); } static int _do_catchup(channel *c, channel_info *channel_info, rss_item *item, void *user_data, channel_callback cb) { - if (cb) { - cb(user_data, CCA_ENCLOSURE_DOWNLOAD_START, channel_info, item->enclosure, - NULL); + if (cb) { + cb(user_data, CCA_ENCLOSURE_DOWNLOAD_START, channel_info, item->enclosure, + NULL); - cb(user_data, CCA_ENCLOSURE_DOWNLOAD_END, channel_info, item->enclosure, - NULL); - } + cb(user_data, CCA_ENCLOSURE_DOWNLOAD_END, channel_info, item->enclosure, + NULL); + } - return 0; + return 0; } void *_do_catchup_thread(void *arg) { - catchup_data *data = (catchup_data *)arg; - data->result = _do_catchup(data->c, data->channel_info, data->item, - data->user_data, data->cb); - pthread_exit(NULL); + catchup_data *data = (catchup_data *)arg; + data->result = _do_catchup(data->c, data->channel_info, data->item, + data->user_data, data->cb); + pthread_exit(NULL); } int channel_update(channel *c, void *user_data, channel_callback cb, @@ -322,133 +322,129 @@ int channel_update(channel *c, void *user_data, channel_callback cb, int resume, enclosure_filter *filter, int debug, int show_progress_bar) { - int i, download_failed; - rss_file *f; - int num_catchup = 0; - int num_download = 0; - void *status; - int t_result; - - /* Retrieve the RSS file. */ - f = _get_rss(c, user_data, cb, debug); - - catchup_data catchup_items[f->num_items]; - download_data download_items[f->num_items]; - - if (!f) - return 1; - - /* Check enclosures in RSS file. */ - for (i = 0; i < f->num_items; i++) - if (f->items[i]->enclosure) { - if (!g_hash_table_lookup_extended(c->downloaded_enclosures, - f->items[i]->enclosure->url, NULL, - NULL)) { - rss_item *item; - - item = f->items[i]; - - if (!filter || _enclosure_pattern_match(filter, item->enclosure)) { - if (no_download) { - // download_failed = - //_do_catchup(c, &(f->channel_info), item, user_data, cb); - catchup_items[num_catchup] = - (catchup_data) { - .c = c, - .channel_info = &(f->channel_info), - .item = item, - .user_data = user_data, - .cb = cb - }; - num_catchup++; - } else { - // download_failed = - //_do_download(c, &(f->channel_info), item, user_data, cb, resume, - // debug, show_progress_bar); - download_items[num_download] = - (download_data) { - .c = c, - .channel_info = &(f->channel_info), - .item = item, - .user_data = user_data, - .cb = cb, - .resume = resume, - .debug = debug, - .show_progress_bar = show_progress_bar - }; - num_download++; - } - } - - /* If we have been instructed to deal only with the first - available enclosure, it is time to break out of the loop. */ - if (first_only) - break; - } + int i, download_failed; + rss_file *f; + int num_catchup = 0; + int num_download = 0; + void *status; + int t_result; + + /* Retrieve the RSS file. */ + f = _get_rss(c, user_data, cb, debug); + + catchup_data catchup_items[f->num_items]; + download_data download_items[f->num_items]; + + if (!f) + return 1; + + /* Check enclosures in RSS file. */ + for (i = 0; i < f->num_items; i++) + if (f->items[i]->enclosure) { + if (!g_hash_table_lookup_extended(c->downloaded_enclosures, + f->items[i]->enclosure->url, NULL, + NULL)) { + rss_item *item; + + item = f->items[i]; + + if (!filter || _enclosure_pattern_match(filter, item->enclosure)) { + if (no_download) { + // download_failed = + //_do_catchup(c, &(f->channel_info), item, user_data, cb); + catchup_items[num_catchup] = + (catchup_data){ .c = c, + .channel_info = &(f->channel_info), + .item = item, + .user_data = user_data, + .cb = cb }; + num_catchup++; + } else { + // download_failed = + //_do_download(c, &(f->channel_info), item, user_data, cb, resume, + // debug, show_progress_bar); + download_items[num_download] = + (download_data){ .c = c, + .channel_info = &(f->channel_info), + .item = item, + .user_data = user_data, + .cb = cb, + .resume = resume, + .debug = debug, + .show_progress_bar = show_progress_bar }; + num_download++; + } } - pthread_t catchup_threads[num_catchup]; - - for (i = 0; i < num_catchup; i++) { - pthread_create(&catchup_threads[i], NULL, _do_catchup_thread, - (void *)&catchup_items[i]); + /* If we have been instructed to deal only with the first + available enclosure, it is time to break out of the loop. */ + if (first_only) + break; + } } - pthread_t download_threads[num_download]; - for (i = 0; i < num_download; i++) { - pthread_create(&download_threads[i], NULL, _do_download_thread, - (void *)&download_items[i]); + pthread_t catchup_threads[num_catchup]; + + for (i = 0; i < num_catchup; i++) { + pthread_create(&catchup_threads[i], NULL, _do_catchup_thread, + (void *)&catchup_items[i]); + } + + pthread_t download_threads[num_download]; + for (i = 0; i < num_download; i++) { + pthread_create(&download_threads[i], NULL, _do_download_thread, + (void *)&download_items[i]); + } + + for (i = 0; i < num_catchup; i++) { + t_result = pthread_join(catchup_threads[i], NULL); + if (t_result != 0) + printf(strerror(t_result)); + if (catchup_items[i].result != 0) { + download_failed = 1; + break; } + if (!no_mark_read) { + /* Mark enclosure as downloaded and immediately save channel + file to ensure that it reflects the change. */ + g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, + (gpointer)get_rfc822_time()); - for (i = 0; i < num_catchup; i++) { - t_result = pthread_join(catchup_threads[i], NULL); - if (t_result != 0) - printf(strerror(t_result)); - if (catchup_items[i].result != 0) { - download_failed = 1; - break; - } - if (!no_mark_read) { - /* Mark enclosure as downloaded and immediately save channel - file to ensure that it reflects the change. */ - g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, - (gpointer)get_rfc822_time()); - - _cast_channel_save(c, debug); - } + _cast_channel_save(c, debug); } - - for (i = 0; i < num_download; i++) { - t_result = pthread_join(download_threads[i], NULL); - if (t_result != 0) - printf(strerror(t_result)); - if (download_items[i].result != 0 || download_failed) { - download_failed = 1; - printf("Download failed"); - break; - } - /* Mark enclosure as downloaded and immediately save channel - file to ensure that it reflects the change. */ - g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, - (gpointer)get_rfc822_time()); - - _cast_channel_save(c, debug); + } + + for (i = 0; i < num_download; i++) { + t_result = pthread_join(download_threads[i], NULL); + if (t_result != 0) + printf(strerror(t_result)); + if (download_items[i].result != 0 || download_failed) { + download_failed = 1; + printf("Download failed"); + break; } + /* Mark enclosure as downloaded and immediately save channel + file to ensure that it reflects the change. */ + g_hash_table_insert(c->downloaded_enclosures, f->items[i]->enclosure->url, + (gpointer)get_rfc822_time()); - if (!no_mark_read) { - /* Update the RSS last fetched time and save the channel file again. */ + _cast_channel_save(c, debug); + } - if (c->rss_last_fetched) - g_free(c->rss_last_fetched); + if (!no_mark_read) { + /* Update the RSS last fetched time and save the channel file again. */ - c->rss_last_fetched = g_strdup(f->fetched_time); + if (c->rss_last_fetched) + g_free(c->rss_last_fetched); - _cast_channel_save(c, debug); - } + c->rss_last_fetched = g_strdup(f->fetched_time); + + _cast_channel_save(c, debug); + } - rss_close(f); + rss_close(f); - return 0; + return 0; } /* Match the (file) name of an enclosure against a regexp. Letters @@ -456,51 +452,51 @@ int channel_update(channel *c, void *user_data, channel_callback cb, 'caseless' is TRUE. Returns TRUE if the pattern matches, FALSE otherwise. */ static gboolean _enclosure_pattern_match(enclosure_filter *filter, - const enclosure *enclosure) + const enclosure *enclosure) { - GError *error = NULL; - GRegexCompileFlags compile_options = 0; - GRegexMatchFlags match_options = 0; - GRegex *regex; - gboolean match; - - g_assert(filter); - g_assert(filter->pattern); - g_assert(enclosure); - - if (filter->caseless) - compile_options |= G_REGEX_CASELESS; - - regex = g_regex_new(filter->pattern, compile_options, match_options, &error); - - if (error) { - fprintf(stderr, "Error compiling regular expression %s: %s\n", - filter->pattern, error->message); - g_error_free(error); - return FALSE; - } + GError *error = NULL; + GRegexCompileFlags compile_options = 0; + GRegexMatchFlags match_options = 0; + GRegex *regex; + gboolean match; + + g_assert(filter); + g_assert(filter->pattern); + g_assert(enclosure); + + if (filter->caseless) + compile_options |= G_REGEX_CASELESS; + + regex = g_regex_new(filter->pattern, compile_options, match_options, &error); + + if (error) { + fprintf(stderr, "Error compiling regular expression %s: %s\n", + filter->pattern, error->message); + g_error_free(error); + return FALSE; + } - match = g_regex_match(regex, enclosure->url, match_options, NULL); + match = g_regex_match(regex, enclosure->url, match_options, NULL); - g_regex_unref(regex); + g_regex_unref(regex); - return match; + return match; } enclosure_filter *enclosure_filter_new(const gchar *pattern, gboolean caseless) { - enclosure_filter *e = g_malloc(sizeof(struct _enclosure_filter)); + enclosure_filter *e = g_malloc(sizeof(struct _enclosure_filter)); - g_assert(pattern); + g_assert(pattern); - e->pattern = g_strdup(pattern); - e->caseless = caseless; + e->pattern = g_strdup(pattern); + e->caseless = caseless; - return e; + return e; } void enclosure_filter_free(enclosure_filter *e) { - g_free(e->pattern); - g_free(e); + g_free(e->pattern); + g_free(e); } diff --git a/src/channel.h b/src/channel.h index c9a69d1..919315e 100644 --- a/src/channel.h +++ b/src/channel.h @@ -23,37 +23,37 @@ #include typedef enum { - CCA_RSS_DOWNLOAD_START, - CCA_RSS_DOWNLOAD_END, - CCA_ENCLOSURE_DOWNLOAD_START, - CCA_ENCLOSURE_DOWNLOAD_END + CCA_RSS_DOWNLOAD_START, + CCA_RSS_DOWNLOAD_END, + CCA_ENCLOSURE_DOWNLOAD_START, + CCA_ENCLOSURE_DOWNLOAD_END } channel_action; typedef struct _channel { - gchar *url; - gchar *channel_filename; - gchar *spool_directory; - gchar *filename_pattern; - GHashTable *downloaded_enclosures; - gchar *rss_last_fetched; + gchar *url; + gchar *channel_filename; + gchar *spool_directory; + gchar *filename_pattern; + GHashTable *downloaded_enclosures; + gchar *rss_last_fetched; } channel; typedef struct _channel_info { - char *title; - char *link; - char *description; - char *language; + char *title; + char *link; + char *description; + char *language; } channel_info; typedef struct _enclosure { - char *url; - long length; - char *type; + char *url; + long length; + char *type; } enclosure; typedef struct _enclosure_filter { - gchar *pattern; - gboolean caseless; + gchar *pattern; + gboolean caseless; } enclosure_filter; typedef void (*channel_callback)(void *user_data, channel_action action, @@ -75,24 +75,24 @@ void enclosure_filter_free(enclosure_filter *e); typedef struct _rss_item rss_item; typedef struct _download_data { - channel *c; - channel_info *channel_info; - rss_item *item; - void *user_data; - channel_callback cb; - int resume; - int debug; - int show_progress_bar; - int result; + channel *c; + channel_info *channel_info; + rss_item *item; + void *user_data; + channel_callback cb; + int resume; + int debug; + int show_progress_bar; + int result; } download_data; typedef struct _catchup_data { - channel *c; - channel_info *channel_info; - rss_item *item; - void *user_data; - channel_callback cb; - int result; + channel *c; + channel_info *channel_info; + rss_item *item; + void *user_data; + channel_callback cb; + int result; } catchup_data; #endif /* CHANNEL_H */ From 8a95a6f77ebe6f7bac5e7bdfff83c99dec03efee Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Sat, 17 Apr 2021 15:28:32 +0000 Subject: [PATCH 5/5] Restyled by whitespace --- src/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4e45ce9..01ff54f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,4 +49,3 @@ castget_LDADD = \ $(GLIBS_LIBS) \ $(TAGLIB_LIBS) \ $(PTHREAD_LIBS) \ -