aboutsummaryrefslogtreecommitdiffstats
path: root/common/sysutils.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2016-11-16 16:43:59 +0000
committerWerner Koch <[email protected]>2016-11-16 16:43:59 +0000
commitc4506a3f15bba5d257cb4c6738800c5e00ecc9a2 (patch)
treef2f6356a33ca8b64d0a565ffb17c52b80013f479 /common/sysutils.c
parentwks: Always build gpg-wks-client. (diff)
downloadgnupg-c4506a3f15bba5d257cb4c6738800c5e00ecc9a2.tar.gz
gnupg-c4506a3f15bba5d257cb4c6738800c5e00ecc9a2.zip
common: Rename keybox_file_rename to gnupg_rename_file.
* kbx/keybox-util.c (keybox_file_rename): Rename to ... * common/sysutils.c (gnupg_rename_file): this. Change all callers. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'common/sysutils.c')
-rw-r--r--common/sysutils.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/common/sysutils.c b/common/sysutils.c
index a0addd11d..c7df8722a 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -618,6 +618,76 @@ gnupg_remove (const char *fname)
}
+/* Wrapper for rename(2) to handle Windows peculiarities. If
+ * BLOCK_SIGNALS is not NULL and points to a variable set to true, all
+ * signals will be blocked by calling gnupg_block_all_signals; the
+ * caller needs to call gnupg_unblock_all_signals if that variable is
+ * still set to true on return. */
+gpg_error_t
+gnupg_rename_file (const char *oldname, const char *newname, int *block_signals)
+{
+ gpg_error_t err = 0;
+
+ if (block_signals && *block_signals)
+ gnupg_block_all_signals ();
+
+#ifdef HAVE_DOSISH_SYSTEM
+ {
+ int wtime = 0;
+
+ gnupg_remove (newname);
+ again:
+ if (rename (oldname, newname))
+ {
+ if (GetLastError () == ERROR_SHARING_VIOLATION)
+ {
+ /* Another process has the file open. We do not use a
+ * lock for read but instead we wait until the other
+ * process has closed the file. This may take long but
+ * that would also be the case with a dotlock approach for
+ * read and write. Note that we don't need this on Unix
+ * due to the inode concept.
+ *
+ * So let's wait until the rename has worked. The retry
+ * intervals are 50, 100, 200, 400, 800, 50ms, ... */
+ if (!wtime || wtime >= 800)
+ wtime = 50;
+ else
+ wtime *= 2;
+
+ if (wtime >= 800)
+ log_info (_("waiting for file '%s' to become accessible ...\n"),
+ oldname);
+
+ Sleep (wtime);
+ goto again;
+ }
+ err = my_error_from_syserror ();
+ }
+ }
+#else /* Unix */
+ {
+#ifdef __riscos__
+ gnupg_remove (newname);
+#endif
+ if (rename (oldname, newname) )
+ err = my_error_from_syserror ();
+ }
+#endif /* Unix */
+
+ if (block_signals && *block_signals && err)
+ {
+ gnupg_unblock_all_signals ();
+ *block_signals = 0;
+ }
+
+ if (err)
+ log_error (_("renaming '%s' to '%s' failed: %s\n"),
+ oldname, newname, gpg_strerror (err));
+ return err;
+}
+
+
#ifndef HAVE_W32_SYSTEM
static mode_t
modestr_to_mode (const char *modestr)