mirror of
https://github.com/curl/curl.git
synced 2026-05-18 10:46:20 +03:00
tool_dirhie: create dir hierarchy without strtok
And use dynbuf Closes #16566
This commit is contained in:
parent
86ac471dc6
commit
787ee935ac
1 changed files with 35 additions and 56 deletions
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "tool_dirhie.h"
|
||||
#include "tool_msgs.h"
|
||||
#include "dynbuf.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
|
|
@ -93,73 +94,51 @@ static void show_dir_errno(struct GlobalConfig *global, const char *name)
|
|||
#define PATH_DELIMITERS DIR_CHAR
|
||||
#endif
|
||||
|
||||
|
||||
CURLcode create_dir_hierarchy(const char *outfile, struct GlobalConfig *global)
|
||||
{
|
||||
char *tempdir;
|
||||
char *tempdir2;
|
||||
char *outdup;
|
||||
char *dirbuildup;
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t outlen;
|
||||
size_t outlen = strlen(outfile);
|
||||
struct curlx_dynbuf dirbuf;
|
||||
|
||||
outlen = strlen(outfile);
|
||||
outdup = strdup(outfile);
|
||||
if(!outdup)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
curlx_dyn_init(&dirbuf, outlen + 1);
|
||||
|
||||
dirbuildup = malloc(outlen + 1);
|
||||
if(!dirbuildup) {
|
||||
Curl_safefree(outdup);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
dirbuildup[0] = '\0';
|
||||
while(*outfile) {
|
||||
bool skip = FALSE;
|
||||
size_t seplen = strspn(outfile, PATH_DELIMITERS);
|
||||
size_t len = strcspn(&outfile[seplen], PATH_DELIMITERS);
|
||||
|
||||
/* Allow strtok() here since this is not used threaded */
|
||||
/* !checksrc! disable BANNEDFUNC 2 */
|
||||
tempdir = strtok(outdup, PATH_DELIMITERS);
|
||||
/* the last path component is the file and it ends with a null byte */
|
||||
if(!outfile[len + seplen])
|
||||
break;
|
||||
|
||||
while(tempdir) {
|
||||
bool skip = false;
|
||||
tempdir2 = strtok(NULL, PATH_DELIMITERS);
|
||||
/* since strtok returns a token for the last word even
|
||||
if not ending with DIR_CHAR, we need to prune it */
|
||||
if(tempdir2) {
|
||||
size_t dlen = strlen(dirbuildup);
|
||||
if(dlen)
|
||||
msnprintf(&dirbuildup[dlen], outlen - dlen, "%s%s", DIR_CHAR, tempdir);
|
||||
else {
|
||||
if(outdup == tempdir) {
|
||||
#if defined(_WIN32) || defined(MSDOS)
|
||||
/* Skip creating a drive's current directory.
|
||||
It may seem as though that would harmlessly fail but it could be
|
||||
a corner case if X: did not exist, since we would be creating it
|
||||
erroneously.
|
||||
eg if outfile is X:\foo\bar\filename then do not mkdir X:
|
||||
This logic takes into account unsupported drives !:, 1:, etc. */
|
||||
char *p = strchr(tempdir, ':');
|
||||
if(p && !p[1])
|
||||
skip = true;
|
||||
#endif
|
||||
/* the output string does not start with a separator */
|
||||
strcpy(dirbuildup, tempdir);
|
||||
}
|
||||
else
|
||||
msnprintf(dirbuildup, outlen, "%s%s", DIR_CHAR, tempdir);
|
||||
}
|
||||
/* Create directory. Ignore access denied error to allow traversal. */
|
||||
if(!skip && (-1 == mkdir(dirbuildup, (mode_t)0000750)) &&
|
||||
(errno != EACCES) && (errno != EEXIST)) {
|
||||
show_dir_errno(global, dirbuildup);
|
||||
result = CURLE_WRITE_ERROR;
|
||||
break; /* get out of loop */
|
||||
}
|
||||
if(!curlx_dyn_len(&dirbuf)) {
|
||||
/* Skip creating a drive's current directory. It may seem as though that
|
||||
would harmlessly fail but it could be a corner case if X: did not
|
||||
exist, since we would be creating it erroneously. eg if outfile is
|
||||
X:\foo\bar\filename then do not mkdir X: This logic takes into
|
||||
account unsupported drives !:, 1:, etc. */
|
||||
if(len > 1 && (outfile[1]==':'))
|
||||
skip = TRUE;
|
||||
}
|
||||
tempdir = tempdir2;
|
||||
#endif
|
||||
/* insert the leading separators (possibly plural) plus the following
|
||||
directory name */
|
||||
result = curlx_dyn_addn(&dirbuf, outfile, seplen + len);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Create directory. Ignore access denied error to allow traversal. */
|
||||
if(!skip && (-1 == mkdir(curlx_dyn_ptr(&dirbuf), (mode_t)0000750)) &&
|
||||
(errno != EACCES) && (errno != EEXIST)) {
|
||||
show_dir_errno(global, curlx_dyn_ptr(&dirbuf));
|
||||
result = CURLE_WRITE_ERROR;
|
||||
break; /* get out of loop */
|
||||
}
|
||||
outfile += len + seplen;
|
||||
}
|
||||
|
||||
Curl_safefree(dirbuildup);
|
||||
Curl_safefree(outdup);
|
||||
curlx_dyn_free(&dirbuf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue