1
0
mirror of https://github.com/moparisthebest/curl synced 2024-08-13 17:03:50 -04:00

altsvc: make saving the cache an atomic operation

... by writing the file to temp name then rename to the final when done.

Assisted-by: Jay Satiro
Fixes #4936
Closes #4942
This commit is contained in:
Daniel Stenberg 2020-02-17 23:01:48 +01:00
parent 330f133224
commit 14916a82e2
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
4 changed files with 41 additions and 19 deletions

View File

@ -34,6 +34,8 @@
#include "parsedate.h" #include "parsedate.h"
#include "sendf.h" #include "sendf.h"
#include "warnless.h" #include "warnless.h"
#include "rand.h"
#include "rename.h"
/* The last 3 #include files should be in this order */ /* The last 3 #include files should be in this order */
#include "curl_printf.h" #include "curl_printf.h"
@ -317,12 +319,15 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
/* /*
* Curl_altsvc_save() writes the altsvc cache to a file. * Curl_altsvc_save() writes the altsvc cache to a file.
*/ */
CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file) CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct altsvcinfo *altsvc, const char *file)
{ {
struct curl_llist_element *e; struct curl_llist_element *e;
struct curl_llist_element *n; struct curl_llist_element *n;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
FILE *out; FILE *out;
char *tempstore;
unsigned char randsuffix[9];
if(!altsvc) if(!altsvc)
/* no cache activated */ /* no cache activated */
@ -335,20 +340,36 @@ CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file)
if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file || !file[0]) if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file || !file[0])
/* marked as read-only, no file or zero length file name */ /* marked as read-only, no file or zero length file name */
return CURLE_OK; return CURLE_OK;
out = fopen(file, FOPEN_WRITETEXT);
if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
return CURLE_FAILED_INIT;
tempstore = aprintf("%s.%s.tmp", file, randsuffix);
if(!tempstore)
return CURLE_OUT_OF_MEMORY;
out = fopen(tempstore, FOPEN_WRITETEXT);
if(!out) if(!out)
return CURLE_WRITE_ERROR; result = CURLE_WRITE_ERROR;
fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n" else {
"# This file was generated by libcurl! Edit at your own risk.\n", fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n"
out); "# This file was generated by libcurl! Edit at your own risk.\n",
for(e = altsvc->list.head; e; e = n) { out);
struct altsvc *as = e->ptr; for(e = altsvc->list.head; e; e = n) {
n = e->next; struct altsvc *as = e->ptr;
result = altsvc_out(as, out); n = e->next;
result = altsvc_out(as, out);
if(result)
break;
}
fclose(out);
if(!result && Curl_rename(tempstore, file))
result = CURLE_WRITE_ERROR;
if(result) if(result)
break; unlink(tempstore);
} }
fclose(out); free(tempstore);
return result; return result;
} }

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -59,7 +59,8 @@ struct altsvcinfo {
const char *Curl_alpnid2str(enum alpnid id); const char *Curl_alpnid2str(enum alpnid id);
struct altsvcinfo *Curl_altsvc_init(void); struct altsvcinfo *Curl_altsvc_init(void);
CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file); CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file);
CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file); CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct altsvcinfo *asi, const char *file);
CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl); CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
void Curl_altsvc_cleanup(struct altsvcinfo *altsvc); void Curl_altsvc_cleanup(struct altsvcinfo *altsvc);
CURLcode Curl_altsvc_parse(struct Curl_easy *data, CURLcode Curl_altsvc_parse(struct Curl_easy *data,
@ -70,9 +71,9 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
enum alpnid srcalpnid, const char *srchost, enum alpnid srcalpnid, const char *srchost,
int srcport, int srcport,
struct altsvc **dstentry, struct altsvc **dstentry,
int versions); /* one or more CURLALTSVC_H* bits */ const int versions); /* CURLALTSVC_H* bits */
#else #else
/* disabled */ /* disabled */
#define Curl_altsvc_save(a,b) #define Curl_altsvc_save(a,b,c)
#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ #endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
#endif /* HEADER_CURL_ALTSVC_H */ #endif /* HEADER_CURL_ALTSVC_H */

View File

@ -380,7 +380,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->state.ulbuf); Curl_safefree(data->state.ulbuf);
Curl_flush_cookies(data, TRUE); Curl_flush_cookies(data, TRUE);
#ifdef USE_ALTSVC #ifdef USE_ALTSVC
Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]); Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
Curl_altsvc_cleanup(data->asi); Curl_altsvc_cleanup(data->asi);
data->asi = NULL; data->asi = NULL;
#endif #endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -124,7 +124,7 @@ UNITTEST_START
} }
fail_unless(asi->num == 10, "wrong number of entries"); fail_unless(asi->num == 10, "wrong number of entries");
Curl_altsvc_save(asi, outname); Curl_altsvc_save(curl, asi, outname);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
fail: fail: