[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnurl] 125/282: cookies: make saving atomic with a rename
From: |
gnunet |
Subject: |
[gnurl] 125/282: cookies: make saving atomic with a rename |
Date: |
Wed, 01 Apr 2020 14:29:50 +0200 |
This is an automated email from the git hooks/post-receive script.
ng0 pushed a commit to branch master
in repository gnurl.
commit b834890a3fa3f525cd8ef4e99554cdb4558d7e1b
Author: Daniel Stenberg <address@hidden>
AuthorDate: Fri Feb 14 14:36:50 2020 +0100
cookies: make saving atomic with a rename
Saves the file as "[filename].[8 random hex digits].tmp" and renames
away the extension when done.
Co-authored-by: Jay Satiro
Reported-by: Mike Frysinger
Fixes #4914
Closes #4926
---
lib/cookie.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 63 insertions(+), 16 deletions(-)
diff --git a/lib/cookie.c b/lib/cookie.c
index fa3337598..7ae90ea27 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -97,6 +97,7 @@ Example set of cookies:
#include "curl_memrchr.h"
#include "inet_pton.h"
#include "parsedate.h"
+#include "rand.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -1493,6 +1494,31 @@ static char *get_netscape_format(const struct Cookie *co)
co->value?co->value:"");
}
+/* return 0 on success, 1 on error */
+static int xrename(const char *oldpath, const char *newpath)
+{
+#ifdef WIN32
+ /* rename() on Windows doesn't overwrite, so we can't use it here.
+ MoveFileExA() will overwrite and is usually atomic, however it fails
+ when there are open handles to the file. */
+ const int max_wait_ms = 1000;
+ struct curltime start = Curl_now();
+ for(;;) {
+ timediff_t diff;
+ if(MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
+ break;
+ diff = Curl_timediff(Curl_now(), start);
+ if(diff < 0 || diff > max_wait_ms)
+ return 1;
+ Sleep(1);
+ }
+#else
+ if(rename(oldpath, newpath))
+ return 1;
+#endif
+ return 0;
+}
+
/*
* cookie_output()
*
@@ -1501,11 +1527,14 @@ static char *get_netscape_format(const struct Cookie
*co)
*
* The function returns non-zero on write failure.
*/
-static int cookie_output(struct CookieInfo *c, const char *dumphere)
+static int cookie_output(struct Curl_easy *data,
+ struct CookieInfo *c, const char *filename)
{
struct Cookie *co;
- FILE *out;
+ FILE *out = NULL;
bool use_stdout = FALSE;
+ char *tempstore = NULL;
+ bool error = false;
if(!c)
/* no cookie engine alive */
@@ -1514,16 +1543,24 @@ static int cookie_output(struct CookieInfo *c, const
char *dumphere)
/* at first, remove expired cookies */
remove_expired(c);
- if(!strcmp("-", dumphere)) {
+ if(!strcmp("-", filename)) {
/* use stdout */
out = stdout;
use_stdout = TRUE;
}
else {
- out = fopen(dumphere, FOPEN_WRITETEXT);
- if(!out) {
- return 1; /* failure */
- }
+ unsigned char randsuffix[9];
+
+ if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
+ return 2;
+
+ tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
+ if(!tempstore)
+ return 1;
+
+ out = fopen(tempstore, FOPEN_WRITETEXT);
+ if(!out)
+ goto error;
}
fputs("# Netscape HTTP Cookie File\n"
@@ -1538,9 +1575,7 @@ static int cookie_output(struct CookieInfo *c, const char
*dumphere)
array = calloc(1, sizeof(struct Cookie *) * c->numcookies);
if(!array) {
- if(!use_stdout)
- fclose(out);
- return 1;
+ goto error;
}
/* only sort the cookies with a domain property */
@@ -1559,9 +1594,7 @@ static int cookie_output(struct CookieInfo *c, const char
*dumphere)
if(format_ptr == NULL) {
fprintf(out, "#\n# Fatal libcurl error\n");
free(array);
- if(!use_stdout)
- fclose(out);
- return 1;
+ goto error;
}
fprintf(out, "%s\n", format_ptr);
free(format_ptr);
@@ -1569,10 +1602,24 @@ static int cookie_output(struct CookieInfo *c, const
char *dumphere)
free(array);
}
- if(!use_stdout)
+
+ if(out && !use_stdout) {
fclose(out);
+ out = NULL;
+ if(xrename(tempstore, filename)) {
+ unlink(tempstore);
+ goto error;
+ }
+ }
- return 0;
+ goto cleanup;
+error:
+ error = true;
+cleanup:
+ if(out && !use_stdout)
+ fclose(out);
+ free(tempstore);
+ return error ? 1 : 0;
}
static struct curl_slist *cookie_list(struct Curl_easy *data)
@@ -1631,7 +1678,7 @@ void Curl_flush_cookies(struct Curl_easy *data, bool
cleanup)
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
/* if we have a destination file for all the cookies to get dumped to */
- if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
+ if(cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]))
infof(data, "WARNING: failed to save cookies in %s\n",
data->set.str[STRING_COOKIEJAR]);
}
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [gnurl] 121/282: ftp: convert 'sock_accepted' to a plain boolean, (continued)
- [gnurl] 121/282: ftp: convert 'sock_accepted' to a plain boolean, gnunet, 2020/04/01
- [gnurl] 116/282: tool_home: Fix the copyright year being out of date, gnunet, 2020/04/01
- [gnurl] 114/282: strerror.h: Copyright year out of date, gnunet, 2020/04/01
- [gnurl] 115/282: tool_homedir: Change GetEnv() to use libcurl's curl_getenv(), gnunet, 2020/04/01
- [gnurl] 118/282: TODO: CURLOPT_SSL_CTX_FUNCTION for LDAPS, gnunet, 2020/04/01
- [gnurl] 126/282: rename: a new file for Curl_rename(), gnunet, 2020/04/01
- [gnurl] 124/282: RELEASE-NOTES: synced, gnunet, 2020/04/01
- [gnurl] 110/282: create-dirs.d: mention the mode, gnunet, 2020/04/01
- [gnurl] 109/282: CURLOPT_ALTSVC_CTRL.3: fix the DEFAULT wording, gnunet, 2020/04/01
- [gnurl] 117/282: azure: disable brotli on the macos debug-builds, gnunet, 2020/04/01
- [gnurl] 125/282: cookies: make saving atomic with a rename,
gnunet <=
- [gnurl] 122/282: multi: if Curl_readwrite sets 'comeback' use expire, not loop, gnunet, 2020/04/01
- [gnurl] 119/282: TODO: Paged searches on LDAP server, gnunet, 2020/04/01
- [gnurl] 133/282: HTTP-COOKIES: mention that a trailing newline is required, gnunet, 2020/04/01
- [gnurl] 130/282: SOCKS: fix typo in printf formatting, gnunet, 2020/04/01
- [gnurl] 127/282: altsvc: make saving the cache an atomic operation, gnunet, 2020/04/01
- [gnurl] 129/282: CURLOPT_REDIR_PROTOCOLS.3: update the DEFAULT section, gnunet, 2020/04/01
- [gnurl] 135/282: win32: USE_WIN32_CRYPTO to enable Win32 based MD4, MD5 and SHA256 functions, gnunet, 2020/04/01
- [gnurl] 142/282: md4: Fixed compilation issues when using GNU TLS gcrypt, gnunet, 2020/04/01
- [gnurl] 131/282: tool_util: Improve Windows version of tvnow(), gnunet, 2020/04/01
- [gnurl] 128/282: docs/GOVERNANCE: refreshed + added "donations" and "commercial support", gnunet, 2020/04/01