diff options
author | Werner Koch <wk@gnupg.org> | 2016-01-14 16:50:15 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2016-01-14 16:50:24 +0100 |
commit | 8241ed59d05e06252647b26477ed5c2f84895a26 (patch) | |
tree | 915ecd413d70c3896bb2d8dc1979aa6825b664c8 /kbx | |
parent | kbx: Add function keybox_tmp_names to avoid code duplication. (diff) | |
download | gnupg2-8241ed59d05e06252647b26477ed5c2f84895a26.tar.xz gnupg2-8241ed59d05e06252647b26477ed5c2f84895a26.zip |
kbx: New function keybox_file_rename to replace rename.
* kbx/keybox-util.c: Include windows.h.
(keybox_file_rename): New.
* kbx/keybox-update.c (rename_tmp_file): Replace remove+rename by
keybox_file_rename.
* g10/keyring.c (rename_tmp_file): Ditto.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'kbx')
-rw-r--r-- | kbx/keybox-update.c | 17 | ||||
-rw-r--r-- | kbx/keybox-util.c | 65 | ||||
-rw-r--r-- | kbx/keybox.h | 1 |
3 files changed, 71 insertions, 12 deletions
diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c index eebcfcad4..ff6590436 100644 --- a/kbx/keybox-update.c +++ b/kbx/keybox-update.c @@ -119,22 +119,15 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, /* First make a backup file except for secret keyboxes. */ if (!secret) { -#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - gnupg_remove (bakfname); -#endif - if (rename (fname, bakfname) ) - { - return gpg_error_from_syserror (); - } + rc = keybox_file_rename (fname, bakfname); + if (rc) + return rc; } /* Then rename the file. */ -#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - gnupg_remove (fname); -#endif - if (rename (tmpfname, fname) ) + rc = keybox_file_rename (tmpfname, fname); + if (rc) { - rc = gpg_error_from_syserror (); if (secret) { /* log_info ("WARNING: 2 files with confidential" */ diff --git a/kbx/keybox-util.c b/kbx/keybox-util.c index f7efd1a29..740ea73b4 100644 --- a/kbx/keybox-util.c +++ b/kbx/keybox-util.c @@ -21,6 +21,10 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#ifdef HAVE_DOSISH_SYSTEM +# define WIN32_LEAN_AND_MEAN /* We only need the OS core stuff. */ +# include <windows.h> +#endif #include "keybox-defs.h" @@ -141,3 +145,64 @@ keybox_tmp_names (const char *filename, int for_keyring, *r_tmpname = tmp_name; return 0; } + + +/* Wrapper for rename(2) to handle Windows peculiarities. */ +gpg_error_t +keybox_file_rename (const char *oldname, const char *newname) +{ + gpg_error_t err = 0; + +#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. We use the + * same retry intervals as used by dotlock.c, namely 50ms, + * 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s. */ + if (!wtime) + wtime = 50; + else if (wtime < 800) + wtime *= 2; + else if (wtime == 800) + wtime = 2000; + else if (wtime < 8000) + wtime *= 2; + + if (wtime >= 800) + log_info ("waiting for file '%s' to become accessible ...\n", + oldname); + + Sleep (wtime); + goto again; + } + err = gpg_error_from_syserror (); + } + +#else /* Unix */ + +#ifdef __riscos__ + gnupg_remove (newname); +#endif + if (rename (oldname, newname) ) + err = gpg_error_from_syserror (); + +#endif /* Unix */ + + if (err) + log_error ("renaming '%s' to '%s' failed: %s\n", + oldname, newname, gpg_strerror (err)); + return err; +} diff --git a/kbx/keybox.h b/kbx/keybox.h index 4d556c571..bfc358620 100644 --- a/kbx/keybox.h +++ b/kbx/keybox.h @@ -134,6 +134,7 @@ void keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), gpg_error_t keybox_tmp_names (const char *filename, int for_keyring, char **r_bakname, char **r_tmpname); +gpg_error_t keybox_file_rename (const char *oldname, const char *newname); #ifdef __cplusplus |