summaryrefslogtreecommitdiff
path: root/content/fs_backing_store.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2014-11-19 11:26:27 +0000
committerVincent Sanders <vince@kyllikki.org>2014-11-19 11:26:27 +0000
commita79b30bd6ffff03a2246d6e1d40548a77a1d14b4 (patch)
tree7b24866ca2226acda1e41515325f4cd624f90d7a /content/fs_backing_store.c
parent1ddf8215cfde443a48043274cef17e45c68f0c91 (diff)
downloadnetsurf-a79b30bd6ffff03a2246d6e1d40548a77a1d14b4.tar.gz
netsurf-a79b30bd6ffff03a2246d6e1d40548a77a1d14b4.tar.bz2
make backing store use rename to atomicly replace entries file
Diffstat (limited to 'content/fs_backing_store.c')
-rw-r--r--content/fs_backing_store.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/content/fs_backing_store.c b/content/fs_backing_store.c
index 33f559671..012422048 100644
--- a/content/fs_backing_store.c
+++ b/content/fs_backing_store.c
@@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Low-level resource cache persistent storage implementation.
*
* file based backing store.
@@ -64,6 +65,9 @@
/** Get store entry from ident. */
#define BS_ENTRY(ident, state) state->entries[state->addrmap[(ident) & ((1 << state->ident_bits) - 1)]]
+/** Filename of serialised entries */
+#define ENTRIES_FNAME "entries"
+
enum store_entry_flags {
STORE_ENTRY_FLAG_NONE = 0,
};
@@ -699,16 +703,18 @@ build_entrymap(struct store_state *state)
/**
* Write filesystem entries to file.
*
- * @todo consider atomic replace using rename.
+ * Serialise entry index out to storage.
*
- * @param state The backing store state to read the entries from.
+ * @param state The backing store state to serialise.
* @return NSERROR_OK on sucess or error code on faliure.
*/
static nserror write_entries(struct store_state *state)
{
int fd;
- char *fname = NULL;
- ssize_t written;
+ char *tname = NULL; /* temporary file name for atomic replace */
+ char *fname = NULL; /* target filename */
+ size_t entries_size;
+ size_t written;
nserror ret;
if (state->entries_dirty == false) {
@@ -716,22 +722,41 @@ static nserror write_entries(struct store_state *state)
return NSERROR_OK;
}
- ret = netsurf_mkpath(&fname, NULL, 2, state->path, "entries");
+ ret = netsurf_mkpath(&tname, NULL, 2, state->path, "t"ENTRIES_FNAME);
if (ret != NSERROR_OK) {
return ret;
}
- fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
- free(fname);
+ fd = open(tname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1) {
+ free(tname);
return NSERROR_SAVE_FAILED;
}
- written = write(fd, state->entries,
- state->last_entry * sizeof(struct store_entry));
+ entries_size = state->last_entry * sizeof(struct store_entry);
+
+ written = (size_t)write(fd, state->entries, entries_size);
+
close(fd);
- if (written < 0) {
- /** @todo Delete the file? */
+
+ /* check all data was written */
+ if (written != entries_size) {
+ unlink(tname);
+ free(tname);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ ret = netsurf_mkpath(&fname, NULL, 2, state->path, ENTRIES_FNAME);
+ if (ret != NSERROR_OK) {
+ unlink(tname);
+ free(tname);
+ return ret;
+ }
+
+ if (rename(tname, fname) != 0) {
+ unlink(tname);
+ free(tname);
+ free(fname);
return NSERROR_SAVE_FAILED;
}
@@ -753,7 +778,7 @@ read_entries(struct store_state *state)
char *fname = NULL;
nserror ret;
- ret = netsurf_mkpath(&fname, NULL, 2, state->path, "entries");
+ ret = netsurf_mkpath(&fname, NULL, 2, state->path, ENTRIES_FNAME);
if (ret != NSERROR_OK) {
return ret;
}