core/file: Create a single file_open() function

This function currently only supports opening files for reading, but it
will soon be expanded to supporting writes as well.  To support binary
reads, I add a new OPEN_READ_BINARY open mode.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2018-02-20 14:26:47 -05:00
parent 0aaafcb5f7
commit a848d5d03c
17 changed files with 85 additions and 58 deletions

View File

@ -131,7 +131,7 @@ static bool __audio_init_idle(void *data)
if (settings_has(SETTINGS_TRACK)) {
track = settings_get(SETTINGS_TRACK);
__audio_load(track_get(track), LOAD_HISTORY);
} else if (data_file_open(&audio_file, OPEN_READ)) {
} else if (file_open(&audio_file, OPEN_READ)) {
data_file_readf(&audio_file, "%u", &track);
file_close(&audio_file);
file_remove(&audio_file);

View File

@ -115,7 +115,7 @@ void db_load(struct database *db)
unsigned int size;
bool save;
if (data_file_open(&db->db_file, OPEN_READ) == false)
if (file_open(&db->db_file, OPEN_READ) == false)
return;
data_file_readf(&db->db_file, "%u", &size);

View File

@ -32,14 +32,23 @@ static gchar *__file_path(const gchar *base, const gchar *dir,
return g_build_filename(base, OCARINA_NAME, dir ? dir : "", name, NULL);
}
static FILE *__file_open(gchar *path, const gchar *mode)
static bool __file_open(struct file *file, enum open_mode mode)
{
FILE *ret = g_fopen(path, mode);
gchar *cmode, *path;
if (!ret)
if (mode == OPEN_READ || mode == OPEN_READ_BINARY) {
cmode = "r";
path = file_path(file);
} else {
cmode = "w";
path = file_write_path(file);
}
file->f_file = g_fopen(path, cmode);
if (!file->f_file)
REPORT_ERRNO(path);
g_free(path);
return ret;
return file->f_file != NULL;
}
static bool __file_mkdir(const gchar *basedir, const gchar *subdir)
@ -115,26 +124,27 @@ bool file_exists(struct file *file)
return ret;
}
static bool __file_open_read(struct file *data)
static bool __file_open_read(struct file *file, enum open_mode mode)
{
if (!file_exists(data))
if (!file_exists(file))
return false;
if (!__file_open(file, mode))
return false;
data->f_file = __file_open(file_path(data), "r");
if (!data->f_file)
return false;
file->f_mode = mode;
if (mode == OPEN_READ_BINARY)
return true;
data->f_mode = OPEN_READ;
if (data_file_readf(data, "%u\n", &data->f_prev) != 1)
if (data_file_readf(file, "%u\n", &file->f_prev) != 1)
return false;
if (data->f_prev < data->f_min) {
REPORT_ERROR(data->f_name, "File too old to be upgraded.");
file_close(data);
if (file->f_prev < file->f_min) {
REPORT_ERROR(file->f_name, "File too old to be upgraded.");
file_close(file);
exit(1);
}
if (data->f_prev > data->f_version) {
REPORT_ERROR(data->f_name, "File too new to be opened.");
file_close(data);
if (file->f_prev > file->f_version) {
REPORT_ERROR(file->f_name, "File too new to be opened.");
file_close(file);
exit(1);
}
return true;
@ -146,9 +156,7 @@ static bool __file_open_write(struct file *data)
return false;
if (!__file_can_write(data))
return false;
data->f_file = __file_open(file_write_path(data), "w");
if (!data->f_file)
if (!__file_open(data, OPEN_WRITE))
return false;
data->f_mode = OPEN_WRITE;
@ -159,11 +167,8 @@ bool data_file_open(struct file *data, enum open_mode mode)
{
if ((string_length(data->f_name) == 0) || (data->f_file != NULL))
return false;
if (mode == CLOSED)
if (mode == CLOSED || mode == OPEN_READ)
return false;
else if (mode == OPEN_READ)
return __file_open_read(data);
return __file_open_write(data);
}
@ -175,12 +180,25 @@ bool cache_file_open(struct file *cache, enum open_mode mode)
return false;
if (!__file_mkdir(g_get_user_cache_dir(), cache->f_subdir))
return false;
if (!__file_open(cache, OPEN_WRITE))
return false;
cache->f_file = __file_open(file_write_path(cache), "wb");
cache->f_mode = mode;
return cache->f_file != NULL;
}
bool file_open(struct file *file, enum open_mode mode)
{
if ((string_length(file->f_name) == 0) || (file->f_file != NULL))
return false;
if (mode == CLOSED)
return false;
if (mode == OPEN_READ || mode == OPEN_READ_BINARY)
return __file_open_read(file, mode);
return false;
}
void file_close(struct file *file)
{
gchar *path = file_path(file);

View File

@ -47,7 +47,7 @@ static bool __artist_pl_load(void *data)
unsigned int i, n;
gchar *name;
if (!data_file_open(&artist_file, OPEN_READ))
if (!file_open(&artist_file, OPEN_READ))
return true;
data_file_readf(&artist_file, "%u\n", &n);

View File

@ -52,7 +52,7 @@ static bool __lib_pl_load(void *data)
unsigned int i, n;
gchar *name;
if (!data_file_open(&lib_file, OPEN_READ))
if (!file_open(&lib_file, OPEN_READ))
return true;
data_file_readf(&lib_file, "%u\n", &n);

View File

@ -143,7 +143,7 @@ static bool sys_pl_queued_load()
struct playlist *playlist = pl_system_get(SYS_PL_QUEUED);
unsigned int num, i, flags = 0;
if (!data_file_open(&sys_deck_f, OPEN_READ))
if (!file_open(&sys_deck_f, OPEN_READ))
return true;
data_file_readf(&sys_deck_f, "%u", &num);
@ -193,7 +193,7 @@ static bool sys_pl_collection_load()
{
struct playlist *playlist = pl_system_get(SYS_PL_COLLECTION);
if (data_file_open(&sys_collection_f, OPEN_READ)) {
if (file_open(&sys_collection_f, OPEN_READ)) {
playlist_generic_load(playlist, &sys_collection_f, PL_SAVE_FLAGS);
file_close(&sys_collection_f);
file_remove(&sys_collection_f);
@ -261,7 +261,7 @@ static bool __sys_pl_load()
unsigned int i, n;
gchar *name;
if (!data_file_open(&sys_file, OPEN_READ))
if (!file_open(&sys_file, OPEN_READ))
return true;
data_file_readf(&sys_file, "%u\n", &n);
@ -289,7 +289,7 @@ static bool __sys_pl_load_new()
unsigned int i, n, load;
gchar *name;
if (!data_file_open(&sys_pl_file, OPEN_READ)) {
if (!file_open(&sys_pl_file, OPEN_READ)) {
__sys_pl_load();
sys_pl_collection_load();
sys_pl_queued_load();

View File

@ -42,7 +42,7 @@ void settings_init()
gui_settings = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, NULL);
if (data_file_open(&gui_settings_file, OPEN_READ))
if (file_open(&gui_settings_file, OPEN_READ))
__settings_read();
file_close(&gui_settings_file);
}

View File

@ -30,9 +30,10 @@
enum open_mode {
CLOSED, /* File is not open. */
OPEN_READ, /* File is open for reading text. */
OPEN_WRITE, /* File is open for writing text. */
CLOSED, /* File is not open. */
OPEN_READ, /* File is open for reading text. */
OPEN_READ_BINARY, /* File is open for reading binary data. */
OPEN_WRITE, /* File is open for writing text. */
};
struct file {
@ -86,9 +87,10 @@ bool file_exists(struct file *);
* Call to open a file for either reading or writing. Callers
* are expected to call file_close() when IO is completed.
*
* When opening a file for reading (OPEN_READ):
* - Check if the file exists.
* - Read in file->_prev_version from the start of the file.
* When opening a file for reading (OPEN_READ / OPEN_READ_BINARY):
* - Check if the file exists
* - If open for reading text (OPEN_READ):
* - Read in file->_prev_version from the start of the file.
*
* When opening a file for writing (OPEN_WRITE):
* - Create missing directories as needed.
@ -96,10 +98,10 @@ bool file_exists(struct file *);
* - Write file->_version to the start of the file (data files only).
*
* Returns true if the open was successful and false otherwise.
* Oening a cache file with OPEN_READ is currently unsupported.
*/
bool data_file_open(struct file *, enum open_mode);
bool cache_file_open(struct file *, enum open_mode);
bool file_open(struct file *, enum open_mode);
/*
* Closes an open file, setting file->f_file to NULL and file->f_mode

View File

@ -83,7 +83,7 @@ static void test_db_entry()
int_ops.dbe_free(&ent->ie_dbe);
g_assert_cmpuint(test_free_count, ==, 1);
data_file_open(&f, OPEN_READ);
file_open(&f, OPEN_READ);
ent = INT_ENTRY(int_ops.dbe_read(&f, 0));
file_close(&f);

View File

@ -42,7 +42,7 @@ void test_date()
date_write_stamp(&f, &date);
file_close(&f);
data_file_open(&f, OPEN_READ);
file_open(&f, OPEN_READ);
date_read(&f, &date);
g_assert_cmpuint(date.d_year, ==, 1988);

View File

@ -23,7 +23,7 @@ static void test_invalid_file(gconstpointer path)
file_init_data(&file, "", (gchar *)path, 0);
test_verify_constructor(&file, "", "");
g_assert_false(data_file_open(&file, OPEN_READ));
g_assert_false(file_open(&file, OPEN_READ));
g_assert_null(file.f_file);
g_assert_false(data_file_open(&file, OPEN_WRITE));
g_assert_null(file.f_file);
@ -44,8 +44,8 @@ static void __test_file_subprocess()
test_verify_constructor(&file, filepath, realpath);
g_assert_false(file_exists(&file));
g_assert_false(data_file_open(&file, OPEN_READ));
g_assert_false(data_file_open(&file, CLOSED));
g_assert_false(file_open(&file, OPEN_READ));
g_assert_false(file_open(&file, CLOSED));
g_assert_true(data_file_open(&file, OPEN_WRITE));
g_assert_nonnull(file.f_file);
g_assert_cmpuint(file.f_mode, ==, OPEN_WRITE);
@ -60,14 +60,14 @@ static void __test_file_subprocess()
g_chmod(filepath, 0444);
g_assert_false(data_file_open(&file, OPEN_WRITE));
g_chmod(filepath, 0200);
g_assert_false(data_file_open(&file, OPEN_READ));
g_assert_false(file_open(&file, OPEN_READ));
g_chmod(filepath, 0644);
g_assert_false(data_file_open(&file, CLOSED));
g_assert_false(file_open(&file, CLOSED));
g_assert_true(data_file_open(&file, OPEN_READ));
g_assert_true(file_open(&file, OPEN_READ));
g_assert_nonnull(file.f_file);
g_assert_cmpuint(file.f_mode, ==, OPEN_READ);
g_assert_false(data_file_open(&file, OPEN_READ));
g_assert_false(file_open(&file, OPEN_READ));
g_assert_false(file_remove(&file));
g_assert_true(file_exists(&file));
@ -107,7 +107,7 @@ static void test_io()
file_close(&fout);
g_assert_true(file_exists(&fout));
g_assert_true(data_file_open(&fin, OPEN_READ));
g_assert_true(file_open(&fin, OPEN_READ));
g_assert_cmpuint(data_file_version(&fin), ==, 1);
g_assert_cmpuint(data_file_readf(&fin, "%u %ms\n", &i, &res), ==, 2);
@ -144,7 +144,7 @@ static void __test_versioning_subprocess(unsigned int out, unsigned int in)
file_close(&fout);
g_assert_true(file_exists(&fout));
g_assert_false(data_file_open(&fin, OPEN_READ));
g_assert_false(file_open(&fin, OPEN_READ));
g_assert_null(fin.f_file);
}
@ -194,6 +194,7 @@ static void test_cache()
/* Test writing data to a cache file. */
g_assert_false(file_exists(&file));
g_assert_false(file_open(&file, OPEN_READ_BINARY));
g_assert_false(cache_file_open(&file, OPEN_READ));
g_assert_false(cache_file_open(&file, CLOSED));
g_assert_true(cache_file_open(&file, OPEN_WRITE));
@ -209,6 +210,12 @@ static void test_cache()
g_assert_true(file_exists(&file));
g_assert_false(cache_file_open(&file, OPEN_READ));
g_assert_true(file_open(&file, OPEN_READ_BINARY));
g_assert_cmpuint(file.f_mode, ==, OPEN_READ_BINARY);
g_assert_cmpuint(file.f_version, ==, OCARINA_MINOR_VERSION);
g_assert_cmpuint(file.f_prev, ==, 0);
file_close(&file);
/* Test importing a file into the cache. */
g_assert_false(file_exists(&copy));
g_assert_false(cache_file_import(&copy, filepath));

View File

@ -349,7 +349,7 @@ static void test_save_load()
playlist_generic_save(&q, &f, PL_SAVE_ALL);
file_close(&f);
g_assert_true(data_file_open(&f, OPEN_READ));
g_assert_true(file_open(&f, OPEN_READ));
playlist_generic_load(&r, &f, PL_SAVE_METADATA);
playlist_generic_load(&s, &f, PL_SAVE_ALL);
file_close(&f);

View File

@ -64,7 +64,7 @@ static void test_album()
file_close(&f);
album_ops->dbe_free(&album->al_dbe);
data_file_open(&f, OPEN_READ);
file_open(&f, OPEN_READ);
album = ALBUM(album_ops->dbe_read(&f, 0));
test_verify_empty(album);
album_ops->dbe_free(&album->al_dbe);

View File

@ -47,7 +47,7 @@ static void test_artist()
g_free(artist->ar_name);
artist_ops->dbe_free(&artist->ar_dbe);
data_file_open(&f, OPEN_READ);
file_open(&f, OPEN_READ);
data_file_readf(&f, "%u", &i);
artist = ARTIST(artist_ops->dbe_read(&f, 0));
test_verify_empty(artist);

View File

@ -45,7 +45,7 @@ static void test_genre()
g_free(genre->ge_name);
genre_ops->dbe_free(&genre->ge_dbe);
data_file_open(&f, OPEN_READ);
file_open(&f, OPEN_READ);
data_file_readf(&f, "%u", &i);
genre = GENRE(genre_ops->dbe_read(&f, 0));
test_verify_empty(genre);

View File

@ -36,7 +36,7 @@ static void test_library()
library_ops->dbe_write(&f, &zelda->li_dbe);
file_close(&f);
data_file_open(&f, OPEN_READ);
file_open(&f, OPEN_READ);
library = LIBRARY(library_ops->dbe_read(&f, 0));
test_verify_link(library);
g_assert_cmpstr_free(library_file(library, "navi.mp3"), ==,

View File

@ -107,7 +107,7 @@ static void test_track()
g_free(track->tr_path);
track_ops->dbe_free(&track->tr_dbe);
data_file_open(&f, OPEN_READ);
file_open(&f, OPEN_READ);
track = TRACK(track_ops->dbe_read(&f, 0));
track->tr_dbe.dbe_index = 0;
test_verify_notrack(track);