diff --git a/core/collection.c b/core/collection.c index 192c692c..758a114e 100644 --- a/core/collection.c +++ b/core/collection.c @@ -5,8 +5,10 @@ #include #include +#include #include #include +#include static struct file c_file = FILE_INIT("library.q", 0); @@ -20,6 +22,29 @@ struct scan_data { static void __scan_dir(void *); +#ifdef CONFIG_TESTING +bool test_collection_eio = false; +static inline int __g_access(const gchar *path, int mode) +{ + if (test_collection_eio) { + errno = EIO; + return -1; + } + return g_access(path, F_OK); +} +#else +#define __g_access g_access +#endif /* CONFIG_TESTING */ + + +static inline int __check_access(const gchar *path) +{ + int ret = __g_access(path, F_OK); + if (ret == -1) + return -errno; + return ret; +} + static void __scan_dir_later(struct library *library, const gchar *dir) { struct scan_data *data = g_malloc(sizeof(struct scan_data)); @@ -77,6 +102,7 @@ static void __validate_library(void *data) struct library *library = data; struct db_entry *dbe, *next; struct track *track; + int access; gchar *path; db_for_each(dbe, next, track_db_get()) { @@ -84,12 +110,18 @@ static void __validate_library(void *data) if (track->tr_library != library) continue; - path = track_path(track); - if (g_file_test(path, G_FILE_TEST_EXISTS) == false) { + path = track_path(track); + access = __check_access(path); + g_free(path); + + if (access == -EIO) { + if (collection_check_library(library) == -EIO) + return; + } + if (access < 0) { queue_remove_all(&c_queue, track); track_remove(track); } - g_free(path); } } @@ -223,6 +255,8 @@ void collection_set_enabled(struct library *library, bool enabled) if (!library || (library->li_enabled == enabled)) return; + if (enabled && (collection_check_library(library) == -EIO)) + return; library_set_enabled(library, enabled); queue_set_flag(&c_queue, Q_ADD_FRONT); @@ -242,6 +276,16 @@ void collection_set_enabled(struct library *library, bool enabled) queue_resort(&c_queue); } +int collection_check_library(struct library *library) +{ + int ret = __check_access(library->li_path); + if (ret == -EIO) { + g_warning("Can't access library at %s/\n", library->li_path); + collection_set_enabled(library, false); + } + return ret; +} + struct queue *collection_get_queue() { return &c_queue; diff --git a/gui/gst.cpp b/gui/gst.cpp index 5d9e359b..10ddf959 100644 --- a/gui/gst.cpp +++ b/gui/gst.cpp @@ -7,6 +7,7 @@ */ #include extern "C" { +#include #include } #include @@ -154,6 +155,7 @@ static void parse_gst_error(GstMessage *error) if (track) { path = track_path(track); g_print("Error playing file: %s\n", path); + collection_check_library(track->tr_library); g_free(path); } g_print("Error: %s\n", err->message); diff --git a/include/core/collection.h b/include/core/collection.h index 61862983..f42af95c 100644 --- a/include/core/collection.h +++ b/include/core/collection.h @@ -48,7 +48,15 @@ bool collection_unban(struct track *); /* Called to enable or disable a library directory. */ void collection_set_enabled(struct library *, bool); +/* Called to check if the library path is good. */ +int collection_check_library(struct library *); + /* Called to access the collection queue. */ struct queue *collection_get_queue(); + +#ifdef CONFIG_TESTING +extern bool test_collection_eio; +#endif /* CONFIG_TESTING */ + #endif /* OCARINA_CORE_COLLECTION_H */ diff --git a/tests/core/collection.c b/tests/core/collection.c index 8eec2fa7..c5d8ed57 100644 --- a/tests/core/collection.c +++ b/tests/core/collection.c @@ -7,6 +7,7 @@ #include #include #include +#include static void test_init() { @@ -225,6 +226,42 @@ static void test_save_load() test_equal(GPOINTER_TO_INT(list->data), COMPARE_GENRE); } +static void test_eio() +{ + struct queue *q = collection_get_queue(); + struct library *lib = library_get(0); + + test_equal(queue_size(q), 48); + test_equal(collection_check_library(lib), 0); + test_equal(lib->li_enabled, (bool)true); + test_equal(queue_size(q), 48); + + test_collection_eio = true; + test_equal(collection_check_library(lib), -EIO); + test_equal(lib->li_enabled, (bool)false); + test_equal(queue_size(q), 0); + + collection_set_enabled(lib, true); + test_equal(lib->li_enabled, (bool)false); + test_equal(queue_size(q), 0); + + test_collection_eio = false; + collection_set_enabled(lib, true); + test_equal(lib->li_enabled, (bool)true); + test_equal(queue_size(q), 48); + + test_collection_eio = true; + collection_update_all(); + test_equal(idle_run_task(), (bool)true); + test_equal(lib->li_enabled, (bool)false); + test_equal(queue_size(q), 0); + + test_collection_eio = false; + collection_set_enabled(lib, true); + test_equal(lib->li_enabled, (bool)true); + test_equal(queue_size(q), 48); +} + static void test_remove() { struct queue *q = collection_get_queue(); @@ -250,5 +287,6 @@ DECLARE_UNIT_TESTS( UNIT_TEST("Collection Ban and Unban", test_ban), UNIT_TEST("Collection Enable and Disable", test_enable), UNIT_TEST("Collection Save and Load", test_save_load), + UNIT_TEST("Colleciton -EIO Handling", test_eio), UNIT_TEST("Collection Remove Path", test_remove), );