Annotation of embedaddon/curl/src/tool_dirhie.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
                      9:  *
                     10:  * This software is licensed as described in the file COPYING, which
                     11:  * you should have received as part of this distribution. The terms
                     12:  * are also available at https://curl.haxx.se/docs/copyright.html.
                     13:  *
                     14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
                     15:  * copies of the Software, and permit persons to whom the Software is
                     16:  * furnished to do so, under the terms of the COPYING file.
                     17:  *
                     18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
                     19:  * KIND, either express or implied.
                     20:  *
                     21:  ***************************************************************************/
                     22: #include "tool_setup.h"
                     23: 
                     24: #include <sys/stat.h>
                     25: 
                     26: #ifdef WIN32
                     27: #  include <direct.h>
                     28: #endif
                     29: 
                     30: #define ENABLE_CURLX_PRINTF
                     31: /* use our own printf() functions */
                     32: #include "curlx.h"
                     33: 
                     34: #include "tool_dirhie.h"
                     35: 
                     36: #include "memdebug.h" /* keep this as LAST include */
                     37: 
                     38: #ifdef NETWARE
                     39: #  ifndef __NOVELL_LIBC__
                     40: #    define mkdir mkdir_510
                     41: #  endif
                     42: #endif
                     43: 
                     44: #if defined(WIN32) || (defined(MSDOS) && !defined(__DJGPP__))
                     45: #  define mkdir(x,y) (mkdir)((x))
                     46: #  ifndef F_OK
                     47: #    define F_OK 0
                     48: #  endif
                     49: #endif
                     50: 
                     51: static void show_dir_errno(FILE *errors, const char *name)
                     52: {
                     53:   switch(errno) {
                     54: #ifdef EACCES
                     55:   case EACCES:
                     56:     fprintf(errors, "You don't have permission to create %s.\n", name);
                     57:     break;
                     58: #endif
                     59: #ifdef ENAMETOOLONG
                     60:   case ENAMETOOLONG:
                     61:     fprintf(errors, "The directory name %s is too long.\n", name);
                     62:     break;
                     63: #endif
                     64: #ifdef EROFS
                     65:   case EROFS:
                     66:     fprintf(errors, "%s resides on a read-only file system.\n", name);
                     67:     break;
                     68: #endif
                     69: #ifdef ENOSPC
                     70:   case ENOSPC:
                     71:     fprintf(errors, "No space left on the file system that will "
                     72:             "contain the directory %s.\n", name);
                     73:     break;
                     74: #endif
                     75: #ifdef EDQUOT
                     76:   case EDQUOT:
                     77:     fprintf(errors, "Cannot create directory %s because you "
                     78:             "exceeded your quota.\n", name);
                     79:     break;
                     80: #endif
                     81:   default :
                     82:     fprintf(errors, "Error creating directory %s.\n", name);
                     83:     break;
                     84:   }
                     85: }
                     86: 
                     87: /*
                     88:  * Create the needed directory hierarchy recursively in order to save
                     89:  *  multi-GETs in file output, ie:
                     90:  *  curl "http://my.site/dir[1-5]/file[1-5].txt" -o "dir#1/file#2.txt"
                     91:  *  should create all the dir* automagically
                     92:  */
                     93: 
                     94: #if defined(WIN32) || defined(__DJGPP__)
                     95: /* systems that may use either or when specifying a path */
                     96: #define PATH_DELIMITERS "\\/"
                     97: #else
                     98: #define PATH_DELIMITERS DIR_CHAR
                     99: #endif
                    100: 
                    101: 
                    102: CURLcode create_dir_hierarchy(const char *outfile, FILE *errors)
                    103: {
                    104:   char *tempdir;
                    105:   char *tempdir2;
                    106:   char *outdup;
                    107:   char *dirbuildup;
                    108:   CURLcode result = CURLE_OK;
                    109:   size_t outlen;
                    110: 
                    111:   outlen = strlen(outfile);
                    112:   outdup = strdup(outfile);
                    113:   if(!outdup)
                    114:     return CURLE_OUT_OF_MEMORY;
                    115: 
                    116:   dirbuildup = malloc(outlen + 1);
                    117:   if(!dirbuildup) {
                    118:     Curl_safefree(outdup);
                    119:     return CURLE_OUT_OF_MEMORY;
                    120:   }
                    121:   dirbuildup[0] = '\0';
                    122: 
                    123:   /* Allow strtok() here since this isn't used threaded */
                    124:   /* !checksrc! disable BANNEDFUNC 2 */
                    125:   tempdir = strtok(outdup, PATH_DELIMITERS);
                    126: 
                    127:   while(tempdir != NULL) {
                    128:     bool skip = false;
                    129:     tempdir2 = strtok(NULL, PATH_DELIMITERS);
                    130:     /* since strtok returns a token for the last word even
                    131:        if not ending with DIR_CHAR, we need to prune it */
                    132:     if(tempdir2 != NULL) {
                    133:       size_t dlen = strlen(dirbuildup);
                    134:       if(dlen)
                    135:         msnprintf(&dirbuildup[dlen], outlen - dlen, "%s%s", DIR_CHAR, tempdir);
                    136:       else {
                    137:         if(outdup == tempdir) {
                    138: #if defined(MSDOS) || defined(WIN32)
                    139:           /* Skip creating a drive's current directory.
                    140:              It may seem as though that would harmlessly fail but it could be
                    141:              a corner case if X: did not exist, since we would be creating it
                    142:              erroneously.
                    143:              eg if outfile is X:\foo\bar\filename then don't mkdir X:
                    144:              This logic takes into account unsupported drives !:, 1:, etc. */
                    145:           char *p = strchr(tempdir, ':');
                    146:           if(p && !p[1])
                    147:             skip = true;
                    148: #endif
                    149:           /* the output string doesn't start with a separator */
                    150:           strcpy(dirbuildup, tempdir);
                    151:         }
                    152:         else
                    153:           msnprintf(dirbuildup, outlen, "%s%s", DIR_CHAR, tempdir);
                    154:       }
                    155:       /* Create directory. Ignore access denied error to allow traversal. */
                    156:       if(!skip && (-1 == mkdir(dirbuildup, (mode_t)0000750)) &&
                    157:          (errno != EACCES) && (errno != EEXIST)) {
                    158:         show_dir_errno(errors, dirbuildup);
                    159:         result = CURLE_WRITE_ERROR;
                    160:         break; /* get out of loop */
                    161:       }
                    162:     }
                    163:     tempdir = tempdir2;
                    164:   }
                    165: 
                    166:   Curl_safefree(dirbuildup);
                    167:   Curl_safefree(outdup);
                    168: 
                    169:   return result;
                    170: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>