diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2021-06-27 12:38:10 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2021-07-17 22:56:25 +0300 |
commit | a563f9c8e5269195f217e4c50694a67dd44d3e75 (patch) | |
tree | 870cc28c9d6272c2abc057baa2094641b0fef186 | |
parent | 4ae4541e80a6e6b43c3b6b58fa582a382722205d (diff) | |
download | gdbm-a563f9c8e5269195f217e4c50694a67dd44d3e75.tar.gz gdbm-a563f9c8e5269195f217e4c50694a67dd44d3e75.tar.bz2 |
Improve fsync_to_root. Other minor fixes.
* src/gdbm.h.in (gdbm_latest_status): Rename to
gdbm_latest_snapshot_status.
* src/gdbmsync.c (fsync_to_root): Start synching from the snapshot
itself. Take care to open it write-only.
(gdbm_latest_snapshot): Reorganize to improve readability.
[!GDBM_FAILURE_ATOMIC] gdbm_latest_snapshot: Fix signature.
-rw-r--r-- | src/gdbm.h.in | 2 | ||||
-rw-r--r-- | src/gdbmsync.c | 82 |
2 files changed, 45 insertions, 39 deletions
diff --git a/src/gdbm.h.in b/src/gdbm.h.in index 6feddd1..1bff4a7 100644 --- a/src/gdbm.h.in +++ b/src/gdbm.h.in @@ -127,7 +127,7 @@ extern int gdbm_reorganize (GDBM_FILE); extern int gdbm_sync (GDBM_FILE); extern int gdbm_failure_atomic (GDBM_FILE, const char *, const char *); -enum gdbm_latest_status +enum gdbm_latest_snapshot_status { GDBM_SNAPSHOT_OK, GDBM_SNAPSHOT_BAD, diff --git a/src/gdbmsync.c b/src/gdbmsync.c index 266f249..80fdbf1 100644 --- a/src/gdbmsync.c +++ b/src/gdbmsync.c @@ -38,31 +38,34 @@ static int fsync_to_root (const char *f) { + int flags = O_WRONLY; char path[PATH_MAX], *end; + if (realpath (f, path) == NULL) return GDBM_ERR_REALPATH; end = path + strlen(path); while (path < end) { - if (end[-1] == '/') + int fd; + + *end = 0; + fd = open (path, flags); + flags = O_RDONLY; + if (fd == -1) + return GDBM_FILE_OPEN_ERROR; + if (fsync (fd)) { - int fd; - - *end = 0; - fd = open (path, O_RDONLY); - if (fd == -1) - return GDBM_FILE_OPEN_ERROR; - if (fsync (fd)) - { - int ec = errno; - close (fd); - errno = ec; - return GDBM_FILE_SYNC_ERROR; - } - if (close (fd)) - return GDBM_FILE_CLOSE_ERROR; + int ec = errno; + close (fd); + errno = ec; + return GDBM_FILE_SYNC_ERROR; } - end--; + if (close (fd)) + return GDBM_FILE_CLOSE_ERROR; + + do + --end; + while (path < end && end[-1] != '/'); } return GDBM_NO_ERROR; } @@ -258,7 +261,26 @@ gdbm_latest_snapshot (const char *even, const char *odd, const char **ret) *ret = even; return GDBM_SNAPSHOT_OK; } - /* Both readable: check mtime */ + + /* + * Both readable: check mtime. + * Select the newer snapshot, i.e. the one whose mtime + * is greater than the other's + */ + switch (timespec_cmp (&st_even.st_mtim, &st_odd.st_mtim)) + { + case -1: + *ret = odd; + break; + + case 1: + *ret = even; + break; + + case 0: + /* Shouldn't happen */ + return GDBM_SNAPSHOT_SAME; + } } else if (st_odd.st_mode & S_IRUSR) { @@ -266,28 +288,12 @@ gdbm_latest_snapshot (const char *even, const char *odd, const char **ret) return GDBM_SNAPSHOT_OK; } else - { - /* neither readable: error */ + { + /* neither readable: this means the crash occurred during + gdbm_failure_atomic() */ return GDBM_SNAPSHOT_BAD; } - /* Compare mtimes, select the newer snapshot, i.e. the one whose mtime - is greater than the other's */ - switch (timespec_cmp (&st_even.st_mtim, &st_odd.st_mtim)) - { - case -1: - *ret = odd; - break; - - case 1: - *ret = even; - break; - - case 0: - /* Shouldn't happen */ - return GDBM_SNAPSHOT_SAME; - } - return GDBM_SNAPSHOT_OK; } #else @@ -300,7 +306,7 @@ gdbm_failure_atomic (GDBM_FILE dbf, const char *even, const char *odd) } int -gdbm_latest_snapshot (const char *even, const char *odd, const char *ret) +gdbm_latest_snapshot (const char *even, const char *odd, const char **ret) { errno = ENOSYS; return GDBM_SNAPSHOT_ERR; |