153 lines
4.8 KiB
C
153 lines
4.8 KiB
C
/*
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
*
|
|
* File data is store in the user's home directory according to the
|
|
* XDG / freedesktop.org specification, meaning all of our data will
|
|
* be stored in a subdirectory of $XDG_DATA_HOME. The actual subdirectory
|
|
* changes based on what configuration values the user has set when Ocarina
|
|
* is compiled.
|
|
*
|
|
* Config Value | Ocarina Directory
|
|
* ---------------|--------------------
|
|
* default | $XDG_DATA_HOME/ocarina/
|
|
* CONFIG_DEBUG | $XDG_DATA_HOME/ocarina-debug/
|
|
* CONFIG_TESTING | $XDG_DATA_HOME/ocarina-test/
|
|
*
|
|
* The beginning of every file is the current file version followed by a
|
|
* newline. For example:
|
|
*
|
|
* 42
|
|
* <data> <more data>
|
|
* <even more data>
|
|
*/
|
|
#ifndef OCARINA_CORE_FILE_H
|
|
#define OCARINA_CORE_FILE_H
|
|
|
|
#include <core/version.h>
|
|
#include <glib.h>
|
|
#include <glib/gstdio.h>
|
|
#include <stdbool.h>
|
|
|
|
|
|
enum open_mode {
|
|
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. */
|
|
OPEN_WRITE_BINARY, /* File is open for writing binary data. */
|
|
};
|
|
|
|
struct file {
|
|
FILE *f_file; /* The file's IO stream. */
|
|
const gchar *f_name; /* The file's basename. */
|
|
const gchar *f_subdir; /* The file's subdirectory. */
|
|
|
|
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. */
|
|
|
|
const gchar *(*f_user_dir)(void); /* The file's user directory. */
|
|
};
|
|
|
|
#define FILE_INIT_DATA(fdir, fname, min) \
|
|
{ \
|
|
.f_file = NULL, \
|
|
.f_name = fname, \
|
|
.f_subdir = fdir, \
|
|
.f_mode = CLOSED, \
|
|
.f_version = OCARINA_MINOR_VERSION, \
|
|
.f_prev = 0, \
|
|
.f_min = min, \
|
|
.f_user_dir = g_get_user_data_dir, \
|
|
}
|
|
|
|
/* Initialize a file object. */
|
|
void file_init_data(struct file *, const gchar *, const gchar *, unsigned int);
|
|
void file_init_cache(struct file *, const gchar *, const gchar *);
|
|
|
|
/*
|
|
* Returns the full path of the file or an empty string if filename is not set.
|
|
* NOTE: This function allocates a new string that MUST be freed with g_free().
|
|
*/
|
|
gchar *file_path(struct file *);
|
|
|
|
/*
|
|
* Returns the path to the temporary file used for writes.
|
|
* NOTE: This function allocates a new string that MUST be freed with g_free().
|
|
*/
|
|
gchar *file_write_path(struct file *);
|
|
|
|
/* Returns the version number of the file. */
|
|
const unsigned int file_version(struct file *);
|
|
|
|
/* Returns true if the file exists on disk and false otherwise. */
|
|
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 / 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 / OPEN_WRITE_BINARY):
|
|
* - Create missing directories as needed.
|
|
* - Open a temporary file to protect data if Ocarina crashes.
|
|
* - If open for writing text (OPEN_WRITE):
|
|
* - Write file->_version to the start of the file (data files only).
|
|
*
|
|
* Returns true if the open was successful and false otherwise.
|
|
*/
|
|
bool file_open(struct file *, enum open_mode);
|
|
|
|
/*
|
|
* Closes an open file, setting file->f_file to NULL and file->f_mode
|
|
* to CLOSED. If the file was opened for writing, then rename the
|
|
* temporary file to file_path().
|
|
*/
|
|
void file_close(struct file *);
|
|
|
|
/*
|
|
* Called to read an unsigned int, signed int, single word, or entire
|
|
* line from the file.
|
|
* NOTE: file_readw() and file_readl() both return a new string that
|
|
* MUST be freed with g_free()
|
|
*/
|
|
gchar *file_readw(struct file *);
|
|
gchar *file_readl(struct file *);
|
|
|
|
unsigned int file_readu(struct file *);
|
|
static inline int file_readd(struct file *file)
|
|
{ return (int)file_readu(file); }
|
|
static inline unsigned short int file_readhu(struct file *file)
|
|
{ return (unsigned short int)file_readu(file); }
|
|
|
|
/*
|
|
* Write to a file with an fprintf(3) style format string.
|
|
* Returns the number of bytes successfully written.
|
|
*/
|
|
int file_writef(struct file *, const char *, ...);
|
|
|
|
/*
|
|
* Reads the contents of a file as binary data.
|
|
* NOTE: This function returns a new string which MUST be freed with g_free().
|
|
*/
|
|
gchar *file_read(struct file *);
|
|
|
|
/*
|
|
* Write binary data a cache file, similar to fwrite(3).
|
|
* Returns the number of bytes successfully written.
|
|
*/
|
|
int file_write(struct file *, const void *, size_t);
|
|
|
|
/* Import a file into the cache. */
|
|
bool file_import(struct file *, const gchar *);
|
|
|
|
/* Removes a closed file from disk. */
|
|
bool file_remove(struct file *);
|
|
|
|
#endif /* OCARINA_CORE_FILE_H */
|