summaryrefslogtreecommitdiff
path: root/src/support/filename.c
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2016-03-27 12:47:02 -0400
committerKeith Bostic <keith@wiredtiger.com>2016-03-27 12:47:02 -0400
commit45aa4385e43957970bfb8f768c63bf05afb5d5f8 (patch)
treed66a42e6b7cb812f0ac4f8a2c9662ea73152c6a0 /src/support/filename.c
parent69b26f1f8338eee18fe0abdba43264e4cbfd443f (diff)
downloadmongo-45aa4385e43957970bfb8f768c63bf05afb5d5f8.tar.gz
WT-2330: in-memory configurations should not create on-disk collection files
The wt utility isn't syncing the enclosing directory on a backup file which leaves us potentially vulnerable on a crash on Linux. WiredTiger knows how to do the magic, so use a WiredTiger function to do the backup file copy. This also gets rid of some Windows-specific code in the wt utility.
Diffstat (limited to 'src/support/filename.c')
-rw-r--r--src/support/filename.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/support/filename.c b/src/support/filename.c
index ac0aee5686e..b4858d2e982 100644
--- a/src/support/filename.c
+++ b/src/support/filename.c
@@ -123,3 +123,69 @@ __wt_sync_handle_and_rename(
return (__wt_rename_and_sync_directory(session, from, to));
}
+
+/*
+ * __wt_copy_and_sync --
+ * Copy a file safely; here to support the wt utility.
+ */
+int
+__wt_copy_and_sync(WT_SESSION *wt_session, const char *from, const char *to)
+{
+ WT_DECL_ITEM(tmp);
+ WT_DECL_RET;
+ WT_FH *ffh, *tfh;
+ WT_SESSION_IMPL *session;
+ size_t n;
+ wt_off_t offset, size;
+ char *buf;
+
+ session = (WT_SESSION_IMPL *)wt_session;
+ ffh = tfh = NULL;
+ buf = NULL;
+
+ /*
+ * Remove the target file if it exists, then create a temporary file,
+ * copy the original into it and rename it into place. I don't think
+ * its necessary to remove the file, or create a copy and do a rename,
+ * it's likely safe to overwrite the backup file directly. I'm doing
+ * the remove and rename to insulate us from errors in other programs
+ * that might not detect a corrupted backup file; it's cheap insurance
+ * in a path where undetected failure is very bad.
+ */
+ WT_RET(__wt_remove_if_exists(session, to));
+
+ WT_ERR(__wt_scr_alloc(session, 0, &tmp));
+ WT_ERR(__wt_buf_fmt(session, tmp, "%s.copy", to));
+
+ /* Open the from and temporary file handles. */
+ WT_ERR(__wt_open(session, from,
+ WT_FILE_TYPE_REGULAR, WT_OPEN_READONLY, &ffh));
+ WT_ERR(__wt_open(session, tmp->data,
+ WT_FILE_TYPE_REGULAR, WT_OPEN_CREATE | WT_OPEN_EXCLUSIVE, &tfh));
+
+ /*
+ * Allocate a copy buffer. Don't use a scratch buffer, this thing is
+ * big, and we don't want it hanging around.
+ */
+#define WT_BACKUP_COPY_SIZE (128 * 1024)
+ WT_ERR(__wt_malloc(session, WT_BACKUP_COPY_SIZE, &buf));
+
+ /* Get the file's size, then copy the bytes. */
+ WT_ERR(__wt_filesize(session, ffh, &size));
+ for (offset = 0; size > 0; size -= n, offset += n) {
+ n = (size_t)WT_MIN(size, WT_BACKUP_COPY_SIZE);
+ WT_ERR(__wt_read(session, ffh, offset, n, buf));
+ WT_ERR(__wt_write(session, tfh, offset, n, buf));
+ }
+
+ /* Close the from handle, then swap the temporary file into place. */
+ WT_ERR(__wt_close(session, &ffh));
+ ret = __wt_sync_handle_and_rename(session, &tfh, tmp->data, to);
+
+err: WT_TRET(__wt_close(session, &ffh));
+ WT_TRET(__wt_close(session, &tfh));
+
+ __wt_free(session, buf);
+ __wt_scr_free(session, &tmp);
+ return (ret);
+}