1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, 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 http://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 "setup.h" 23 24#include <curl/curl.h> 25 26#include <sys/stat.h> 27 28#ifdef HAVE_UNISTD_H 29# include <unistd.h> 30#endif 31 32#ifdef WIN32 33# include <direct.h> 34#endif 35 36#define ENABLE_CURLX_PRINTF 37/* use our own printf() functions */ 38#include "curlx.h" 39 40#include "tool_dirhie.h" 41 42#include "memdebug.h" /* keep this as LAST include */ 43 44#ifdef NETWARE 45# ifndef __NOVELL_LIBC__ 46# define mkdir mkdir_510 47# endif 48#endif 49 50#ifdef WIN32 51# define mkdir(x,y) (mkdir)((x)) 52# ifndef __POCC__ 53# define F_OK 0 54# endif 55#endif 56 57static void show_dir_errno(FILE *errors, const char *name) 58{ 59 switch(ERRNO) { 60#ifdef EACCES 61 case EACCES: 62 fprintf(errors, "You don't have permission to create %s.\n", name); 63 break; 64#endif 65#ifdef ENAMETOOLONG 66 case ENAMETOOLONG: 67 fprintf(errors, "The directory name %s is too long.\n", name); 68 break; 69#endif 70#ifdef EROFS 71 case EROFS: 72 fprintf(errors, "%s resides on a read-only file system.\n", name); 73 break; 74#endif 75#ifdef ENOSPC 76 case ENOSPC: 77 fprintf(errors, "No space left on the file system that will " 78 "contain the directory %s.\n", name); 79 break; 80#endif 81#ifdef EDQUOT 82 case EDQUOT: 83 fprintf(errors, "Cannot create directory %s because you " 84 "exceeded your quota.\n", name); 85 break; 86#endif 87 default : 88 fprintf(errors, "Error creating directory %s.\n", name); 89 break; 90 } 91} 92 93/* 94 * Create the needed directory hierarchy recursively in order to save 95 * multi-GETs in file output, ie: 96 * curl "http://my.site/dir[1-5]/file[1-5].txt" -o "dir#1/file#2.txt" 97 * should create all the dir* automagically 98 */ 99 100CURLcode create_dir_hierarchy(const char *outfile, FILE *errors) 101{ 102 char *tempdir; 103 char *tempdir2; 104 char *outdup; 105 char *dirbuildup; 106 CURLcode result = CURLE_OK; 107 108 outdup = strdup(outfile); 109 if(!outdup) 110 return CURLE_OUT_OF_MEMORY; 111 112 dirbuildup = malloc(strlen(outfile) + 1); 113 if(!dirbuildup) { 114 Curl_safefree(outdup); 115 return CURLE_OUT_OF_MEMORY; 116 } 117 dirbuildup[0] = '\0'; 118 119 tempdir = strtok(outdup, DIR_CHAR); 120 121 while(tempdir != NULL) { 122 tempdir2 = strtok(NULL, DIR_CHAR); 123 /* since strtok returns a token for the last word even 124 if not ending with DIR_CHAR, we need to prune it */ 125 if(tempdir2 != NULL) { 126 size_t dlen = strlen(dirbuildup); 127 if(dlen) 128 sprintf(&dirbuildup[dlen], "%s%s", DIR_CHAR, tempdir); 129 else { 130 if(0 != strncmp(outdup, DIR_CHAR, 1)) 131 strcpy(dirbuildup, tempdir); 132 else 133 sprintf(dirbuildup, "%s%s", DIR_CHAR, tempdir); 134 } 135 if(access(dirbuildup, F_OK) == -1) { 136 if(-1 == mkdir(dirbuildup,(mode_t)0000750)) { 137 show_dir_errno(errors, dirbuildup); 138 result = CURLE_WRITE_ERROR; 139 break; /* get out of loop */ 140 } 141 } 142 } 143 tempdir = tempdir2; 144 } 145 146 Curl_safefree(dirbuildup); 147 Curl_safefree(outdup); 148 149 return result; 150} 151 152