diff --git a/core/audio.c b/core/audio.c index b8cae084..8f6de007 100644 --- a/core/audio.c +++ b/core/audio.c @@ -7,7 +7,7 @@ #include #include -static struct file audio_file = FILE_INIT("cur_track", 0); +static struct file audio_file = FILE_INIT("cur_track", 0, 0); static struct track *audio_track = NULL; static GstElement *audio_player = NULL; static struct audio_ops *audio_ops = NULL; diff --git a/core/collection.c b/core/collection.c index b5cf2f2f..8c5ad2cf 100644 --- a/core/collection.c +++ b/core/collection.c @@ -10,7 +10,7 @@ #include -static struct file c_file = FILE_INIT("library.q", 0); +static struct file c_file = FILE_INIT("library.q", 0, 0); static struct queue c_queue; struct scan_data { diff --git a/core/containers/database.c b/core/containers/database.c index 9974e712..5df470aa 100644 --- a/core/containers/database.c +++ b/core/containers/database.c @@ -78,7 +78,7 @@ void db_init(struct database *db, const char *filepath, bool autosave, db->db_autosave = autosave; db->db_entries = g_ptr_array_new(); db->db_keys = g_hash_table_new(g_str_hash, g_str_equal); - file_init(&db->db_file, filepath, 0); + file_init(&db->db_file, filepath, 0, 0); } void db_deinit(struct database *db) diff --git a/core/file.c b/core/file.c index 76c8e3d0..3f272a0b 100644 --- a/core/file.c +++ b/core/file.c @@ -61,11 +61,13 @@ static void __file_rename_tmp(struct file *file) } -void file_init(struct file *file, const gchar *name, unsigned int version) +void file_init(struct file *file, const gchar *name, + unsigned int version, unsigned int min) { file->f_mode = OPEN_READ; file->f_version = version; file->f_prev = 0; + file->f_min = 0; file->f_file = NULL; file->f_name = name; } @@ -117,7 +119,14 @@ static bool __file_open_read(struct file *file) return false; file->f_mode = OPEN_READ; - return file_readf(file, "%u\n", &file->f_prev) == 1; + if (file_readf(file, "%u\n", &file->f_prev) != 1) + return false; + if (file->f_prev < file->f_min) { + REPORT_ERROR(file->f_name, "File too old to be upgraded."); + file_close(file); + return false; + } + return true; } static bool __file_open_write(struct file *file) diff --git a/core/tempq.c b/core/tempq.c index b4f7256d..c0a503d3 100644 --- a/core/tempq.c +++ b/core/tempq.c @@ -8,7 +8,7 @@ #include #include -static struct file tempq_file = FILE_INIT("deck", 1); +static struct file tempq_file = FILE_INIT("deck", 1, 1); static struct queue_ops *tempq_ops = NULL; static GSList *tempq_list; static struct file tempq_file; @@ -63,13 +63,10 @@ static void __tempq_init_idle(void *data) if (!file_open(&tempq_file, OPEN_READ)) return; - if (file_version(&tempq_file) < 1) - goto out; file_readf(&tempq_file, "%u", &num); for (i = 0; i < num; i++) __tempq_read_queue(); -out: file_close(&tempq_file); } diff --git a/gui/settings.c b/gui/settings.c index f9230dc1..01d1f259 100644 --- a/gui/settings.c +++ b/gui/settings.c @@ -5,7 +5,7 @@ #include static GHashTable *gui_settings = NULL; -static struct file gui_settings_file = FILE_INIT("settings", 0); +static struct file gui_settings_file = FILE_INIT("settings", 0, 0); static void __settings_save_item(gpointer key, gpointer value, gpointer data) diff --git a/include/core/containers/database.h b/include/core/containers/database.h index 8d668f86..545245b8 100644 --- a/include/core/containers/database.h +++ b/include/core/containers/database.h @@ -81,7 +81,7 @@ struct database { { \ .db_size = 0, \ .db_autosave = autosave, \ - .db_file = FILE_INIT(fname, 0), \ + .db_file = FILE_INIT(fname, 0, 0), \ .db_entries = g_ptr_array_new(), \ .db_keys = g_hash_table_new(g_str_hash, g_str_equal), \ .db_ops = ops, \ diff --git a/include/core/file.h b/include/core/file.h index 2d2a207c..053e8d85 100644 --- a/include/core/file.h +++ b/include/core/file.h @@ -37,21 +37,24 @@ struct file { enum open_mode f_mode; /* The file's current open mode. */ unsigned int f_version; /* The file's current data version. */ unsigned int f_prev; /* The file's on-disk data version. */ + unsigned int f_min; /* The file's minimum data version. */ FILE *f_file; /* The file's IO stream. */ const gchar *f_name; /* The file's basename. */ }; -#define FILE_INIT(fname, version) \ - { \ - .f_mode = OPEN_READ, \ - .f_version = version, \ - .f_prev = 0, .f_file = NULL, \ - .f_name = fname, \ +#define FILE_INIT(fname, version, min) \ + { \ + .f_mode = OPEN_READ, \ + .f_version = version, \ + .f_prev = 0, \ + .f_min = min, \ + .f_file = NULL, \ + .f_name = fname, \ } /* Initialize a new file object. */ -void file_init(struct file *, const gchar *, unsigned int); +void file_init(struct file *, const gchar *, unsigned int, unsigned int); /* * Returns the full path of the file or an empty string if filename is not set. diff --git a/tests/core/containers/database.c b/tests/core/containers/database.c index ee3cebb5..61499ab4 100644 --- a/tests/core/containers/database.c +++ b/tests/core/containers/database.c @@ -83,7 +83,7 @@ static void test_db_entry() test_equal(ent->ie_val, 1); test_str_equal(int_ops.dbe_key(&ent->ie_dbe), "1"); - file_init(&f, "test_db_entry", 0); + file_init(&f, "test_db_entry", 0, 0); file_open(&f, OPEN_WRITE); int_ops.dbe_write(&f, &ent->ie_dbe); file_close(&f); diff --git a/tests/core/containers/index.c b/tests/core/containers/index.c index 18eaa58a..66f474f9 100644 --- a/tests/core/containers/index.c +++ b/tests/core/containers/index.c @@ -26,7 +26,7 @@ static void test_entry() i++; } test_loop_passed(); - file_init(&f, "index_entry", 0); + file_init(&f, "index_entry", 0, 0); file_open(&f, OPEN_WRITE); file_writef(&f, "Zelda\n0 \n"); index_ops->dbe_write(&f, &ie->ie_dbe); diff --git a/tests/core/containers/set.c b/tests/core/containers/set.c index c909756b..ff9350d8 100644 --- a/tests/core/containers/set.c +++ b/tests/core/containers/set.c @@ -7,7 +7,7 @@ void test_set() { - struct file f = FILE_INIT("set", 0); + struct file f = FILE_INIT("set", 0, 0); struct set set = SET_INIT(); unsigned int i, N = 10; struct set_iter it; diff --git a/tests/core/date.c b/tests/core/date.c index 4697c7bb..d3b97c36 100644 --- a/tests/core/date.c +++ b/tests/core/date.c @@ -17,7 +17,7 @@ void test_date() .d_month = 0, .d_day = 0, }; - struct file f = FILE_INIT("date", 0); + struct file f = FILE_INIT("date", 0, 0); gchar *str; date_today(NULL); diff --git a/tests/core/file.c b/tests/core/file.c index ad7a6921..e013ca7d 100644 --- a/tests/core/file.c +++ b/tests/core/file.c @@ -33,20 +33,20 @@ static void test_invalid_file(struct file *file) static void test_null() { struct file fnull; - file_init(&fnull, NULL, 0); + file_init(&fnull, NULL, 0, 0); test_invalid_file(&fnull); } static void test_empty() { struct file fempty; - file_init(&fempty, "", 0); + file_init(&fempty, "", 0, 0); test_invalid_file(&fempty); } static void test_file() { - struct file file = FILE_INIT("file.txt", 0); + struct file file = FILE_INIT("file.txt", 0, 0); gchar *basepath, *filepath, *realpath; basepath = g_strjoin("/", g_get_user_data_dir(), OCARINA_NAME, NULL); @@ -88,8 +88,8 @@ static void test_file() static void test_io() { - struct file fout = FILE_INIT("file.txt", 1); - struct file fin = FILE_INIT("file.txt", 0); + struct file fout = FILE_INIT("file.txt", 1, 1); + struct file fin = FILE_INIT("file.txt", 0, 0); char *res = NULL; unsigned int i; @@ -129,9 +129,24 @@ static void test_io() test_equal(file_version(&fin), 0); } +static void test_versioning() +{ + struct file fout = FILE_INIT("file.txt", 0, 0); + struct file fin = FILE_INIT("file.txt", 2, 1); + + test_equal(file_open(&fout, OPEN_WRITE), (bool)true); + file_writef(&fout, "abcdefghijklmnopqrstuvwxyz"); + file_close(&fout); + test_equal(file_exists(&fout), (bool)true); + + test_equal(file_open(&fin, OPEN_READ), (bool)false); + test_equal((void *)fin.f_file, NULL); +} + DECLARE_UNIT_TESTS( UNIT_TEST("File (Path = NULL)", test_null), UNIT_TEST("File (Path = \"\")", test_empty), UNIT_TEST("File (Path = \"file.txt\")", test_file), UNIT_TEST("File I/O", test_io), + UNIT_TEST("File Versioning", test_versioning), ); diff --git a/tests/core/tags/album.c b/tests/core/tags/album.c index c864a66d..48a394ee 100644 --- a/tests/core/tags/album.c +++ b/tests/core/tags/album.c @@ -31,7 +31,7 @@ static void test_album() album = ALBUM(album_ops->dbe_alloc("1998/Hyrule Symphony")); test_verify_hyrule(album); - file_init(&f, "album_tag", 0); + file_init(&f, "album_tag", 0, 0); file_open(&f, OPEN_WRITE); file_writef(&f, "0 \n"); album_ops->dbe_write(&f, &album->al_dbe); diff --git a/tests/core/tags/artist.c b/tests/core/tags/artist.c index da64f1a0..bf251054 100644 --- a/tests/core/tags/artist.c +++ b/tests/core/tags/artist.c @@ -30,7 +30,7 @@ static void test_artist() artist = ARTIST(artist_ops->dbe_alloc("Koji Kondo")); test_verify_koji(artist); - file_init(&f, "artist_tag", 0); + file_init(&f, "artist_tag", 0, 0); file_open(&f, OPEN_WRITE); file_writef(&f, "1 \n2 "); artist_ops->dbe_write(&f, &artist->ar_dbe); diff --git a/tests/core/tags/genre.c b/tests/core/tags/genre.c index b1a2623c..22b86d17 100644 --- a/tests/core/tags/genre.c +++ b/tests/core/tags/genre.c @@ -30,7 +30,7 @@ static void test_genre() genre = GENRE(genre_ops->dbe_alloc("Video Game Music")); test_verify_vg(genre); - file_init(&f, "genre_tag", 0); + file_init(&f, "genre_tag", 0, 0); file_open(&f, OPEN_WRITE); file_writef(&f, "1 \n1 "); genre_ops->dbe_write(&f, &genre->ge_dbe); diff --git a/tests/core/tags/library.c b/tests/core/tags/library.c index 2329b035..3c16a9b4 100644 --- a/tests/core/tags/library.c +++ b/tests/core/tags/library.c @@ -36,7 +36,7 @@ static void test_library() link->li_size = 21; zelda->li_size = 42; - file_init(&f, "library_tag", 0); + file_init(&f, "library_tag", 0, 0); file_open(&f, OPEN_WRITE); library_ops->dbe_write(&f, &link->li_dbe); file_writef(&f, "\n"); diff --git a/tests/core/tags/track.c b/tests/core/tags/track.c index f179b1eb..e071ecbf 100644 --- a/tests/core/tags/track.c +++ b/tests/core/tags/track.c @@ -74,7 +74,7 @@ static void test_track() setlocale(LC_TIME, "C"); filter_init(); tags_init(); - file_init(&f, "track_tag", 0); + file_init(&f, "track_tag", 0, 0); while (idle_run_task()) {} date = string_tm2str(now); diff --git a/tests/gui/settings.c b/tests/gui/settings.c index da90f114..52479183 100644 --- a/tests/gui/settings.c +++ b/tests/gui/settings.c @@ -7,7 +7,7 @@ static void test_settings() { - struct file f = FILE_INIT("settings", 0); + struct file f = FILE_INIT("settings", 0, 0); test_equal((void *)test_get_gui_settings(), NULL); gui_settings_set("test.value1", 42);