fopen: create short(er) temporary file name
Only using random letters in the name plus a ".tmp" extension. Not by appending characters to the final file name. Reported-by: Maksymilian Arciemowicz Closes #12388
This commit is contained in:
parent
2692d41c23
commit
73b65e94f3
65
lib/fopen.c
65
lib/fopen.c
@ -39,6 +39,51 @@
|
|||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
The dirslash() function breaks a null-terminated pathname string into
|
||||||
|
directory and filename components then returns the directory component up
|
||||||
|
to, *AND INCLUDING*, a final '/'. If there is no directory in the path,
|
||||||
|
this instead returns a "" string.
|
||||||
|
|
||||||
|
This function returns a pointer to malloc'ed memory.
|
||||||
|
|
||||||
|
The input path to this function is expected to have a file name part.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define PATHSEP "\\"
|
||||||
|
#define IS_SEP(x) (((x) == '/') || ((x) == '\\'))
|
||||||
|
#elif defined(MSDOS) || defined(__EMX__) || defined(OS2)
|
||||||
|
#define PATHSEP "\\"
|
||||||
|
#define IS_SEP(x) ((x) == '\\')
|
||||||
|
#else
|
||||||
|
#define PATHSEP "/"
|
||||||
|
#define IS_SEP(x) ((x) == '/')
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static char *dirslash(const char *path)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
struct dynbuf out;
|
||||||
|
DEBUGASSERT(path);
|
||||||
|
Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH);
|
||||||
|
n = strlen(path);
|
||||||
|
if(n) {
|
||||||
|
/* find the rightmost path separator, if any */
|
||||||
|
while(n && !IS_SEP(path[n-1]))
|
||||||
|
--n;
|
||||||
|
/* skip over all the path separators, if any */
|
||||||
|
while(n && IS_SEP(path[n-1]))
|
||||||
|
--n;
|
||||||
|
}
|
||||||
|
if(Curl_dyn_addn(&out, path, n))
|
||||||
|
return NULL;
|
||||||
|
/* if there was a directory, append a single trailing slash */
|
||||||
|
if(n && Curl_dyn_addn(&out, PATHSEP, 1))
|
||||||
|
return NULL;
|
||||||
|
return Curl_dyn_ptr(&out);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_fopen() opens a file for writing with a temp name, to be renamed
|
* Curl_fopen() opens a file for writing with a temp name, to be renamed
|
||||||
* to the final name when completed. If there is an existing file using this
|
* to the final name when completed. If there is an existing file using this
|
||||||
@ -50,25 +95,34 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
|
|||||||
FILE **fh, char **tempname)
|
FILE **fh, char **tempname)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_WRITE_ERROR;
|
CURLcode result = CURLE_WRITE_ERROR;
|
||||||
unsigned char randsuffix[9];
|
unsigned char randbuf[41];
|
||||||
char *tempstore = NULL;
|
char *tempstore = NULL;
|
||||||
struct_stat sb;
|
struct_stat sb;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
char *dir;
|
||||||
*tempname = NULL;
|
*tempname = NULL;
|
||||||
|
|
||||||
|
dir = dirslash(filename);
|
||||||
|
if(!dir)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
*fh = fopen(filename, FOPEN_WRITETEXT);
|
*fh = fopen(filename, FOPEN_WRITETEXT);
|
||||||
if(!*fh)
|
if(!*fh)
|
||||||
goto fail;
|
goto fail;
|
||||||
if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode))
|
if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) {
|
||||||
|
free(dir);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
}
|
||||||
fclose(*fh);
|
fclose(*fh);
|
||||||
*fh = NULL;
|
*fh = NULL;
|
||||||
|
|
||||||
result = Curl_rand_alnum(data, randsuffix, sizeof(randsuffix));
|
result = Curl_rand_alnum(data, randbuf, sizeof(randbuf));
|
||||||
if(result)
|
if(result)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
|
/* The temp file name should not end up too long for the target file
|
||||||
|
system */
|
||||||
|
tempstore = aprintf("%s%s.tmp", dir, randbuf);
|
||||||
if(!tempstore) {
|
if(!tempstore) {
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -95,6 +149,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
|
|||||||
if(!*fh)
|
if(!*fh)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
free(dir);
|
||||||
*tempname = tempstore;
|
*tempname = tempstore;
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
@ -105,7 +160,7 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(tempstore);
|
free(tempstore);
|
||||||
|
free(dir);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user