1
0
mirror of https://github.com/moparisthebest/curl synced 2024-08-13 17:03:50 -04:00
curl/src/tool_dirhie.c
Daniel Stenberg dcd6f81025
snprintf: renamed and we now only use msnprintf()
The function does not return the same value as snprintf() normally does,
so readers may be mislead into thinking the code works differently than
it actually does. A different function name makes this easier to detect.

Reported-by: Tomas Hoger
Assisted-by: Daniel Gustafsson
Fixes #3296
Closes #3297
2018-11-23 08:26:51 +01:00

156 lines
4.1 KiB
C

/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "tool_setup.h"
#include <sys/stat.h>
#ifdef WIN32
# include <direct.h>
#endif
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
#include "tool_dirhie.h"
#include "memdebug.h" /* keep this as LAST include */
#ifdef NETWARE
# ifndef __NOVELL_LIBC__
# define mkdir mkdir_510
# endif
#endif
#if defined(WIN32) || (defined(MSDOS) && !defined(__DJGPP__))
# define mkdir(x,y) (mkdir)((x))
# ifndef F_OK
# define F_OK 0
# endif
#endif
static void show_dir_errno(FILE *errors, const char *name)
{
switch(errno) {
#ifdef EACCES
case EACCES:
fprintf(errors, "You don't have permission to create %s.\n", name);
break;
#endif
#ifdef ENAMETOOLONG
case ENAMETOOLONG:
fprintf(errors, "The directory name %s is too long.\n", name);
break;
#endif
#ifdef EROFS
case EROFS:
fprintf(errors, "%s resides on a read-only file system.\n", name);
break;
#endif
#ifdef ENOSPC
case ENOSPC:
fprintf(errors, "No space left on the file system that will "
"contain the directory %s.\n", name);
break;
#endif
#ifdef EDQUOT
case EDQUOT:
fprintf(errors, "Cannot create directory %s because you "
"exceeded your quota.\n", name);
break;
#endif
default :
fprintf(errors, "Error creating directory %s.\n", name);
break;
}
}
/*
* Create the needed directory hierarchy recursively in order to save
* multi-GETs in file output, ie:
* curl "http://my.site/dir[1-5]/file[1-5].txt" -o "dir#1/file#2.txt"
* should create all the dir* automagically
*/
#if defined(WIN32) || defined(__DJGPP__)
/* systems that may use either or when specifying a path */
#define PATH_DELIMITERS "\\/"
#else
#define PATH_DELIMITERS DIR_CHAR
#endif
CURLcode create_dir_hierarchy(const char *outfile, FILE *errors)
{
char *tempdir;
char *tempdir2;
char *outdup;
char *dirbuildup;
CURLcode result = CURLE_OK;
size_t outlen;
outlen = strlen(outfile);
outdup = strdup(outfile);
if(!outdup)
return CURLE_OUT_OF_MEMORY;
dirbuildup = malloc(outlen + 1);
if(!dirbuildup) {
Curl_safefree(outdup);
return CURLE_OUT_OF_MEMORY;
}
dirbuildup[0] = '\0';
/* Allow strtok() here since this isn't used threaded */
/* !checksrc! disable BANNEDFUNC 2 */
tempdir = strtok(outdup, PATH_DELIMITERS);
while(tempdir != NULL) {
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 != NULL) {
size_t dlen = strlen(dirbuildup);
if(dlen)
msnprintf(&dirbuildup[dlen], outlen - dlen, "%s%s", DIR_CHAR, tempdir);
else {
if(outdup == tempdir)
/* the output string doesn't start with a separator */
strcpy(dirbuildup, tempdir);
else
msnprintf(dirbuildup, outlen, "%s%s", DIR_CHAR, tempdir);
}
if((-1 == mkdir(dirbuildup, (mode_t)0000750)) && (errno != EEXIST)) {
show_dir_errno(errors, dirbuildup);
result = CURLE_WRITE_ERROR;
break; /* get out of loop */
}
}
tempdir = tempdir2;
}
Curl_safefree(dirbuildup);
Curl_safefree(outdup);
return result;
}