Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/src/tool_dirhie.c
2649 views
1
/***************************************************************************
2
* _ _ ____ _
3
* Project ___| | | | _ \| |
4
* / __| | | | |_) | |
5
* | (__| |_| | _ <| |___
6
* \___|\___/|_| \_\_____|
7
*
8
* Copyright (C) Daniel Stenberg, <[email protected]>, 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.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
* SPDX-License-Identifier: curl
22
*
23
***************************************************************************/
24
#include "tool_setup.h"
25
26
#if defined(_WIN32) && !defined(UNDER_CE)
27
# include <direct.h>
28
#endif
29
30
#include "tool_dirhie.h"
31
#include "tool_msgs.h"
32
33
#include "memdebug.h" /* keep this as LAST include */
34
35
#if defined(_WIN32) || (defined(MSDOS) && !defined(__DJGPP__))
36
# define mkdir(x,y) (mkdir)((x))
37
# ifndef F_OK
38
# define F_OK 0
39
# endif
40
#endif
41
42
static void show_dir_errno(const char *name)
43
{
44
switch(errno) {
45
#ifdef EACCES
46
/* !checksrc! disable ERRNOVAR 1 */
47
case EACCES:
48
errorf("You do not have permission to create %s", name);
49
break;
50
#endif
51
#ifdef ENAMETOOLONG
52
case ENAMETOOLONG:
53
errorf("The directory name %s is too long", name);
54
break;
55
#endif
56
#ifdef EROFS
57
case EROFS:
58
errorf("%s resides on a read-only file system", name);
59
break;
60
#endif
61
#ifdef ENOSPC
62
case ENOSPC:
63
errorf("No space left on the file system that will "
64
"contain the directory %s", name);
65
break;
66
#endif
67
#ifdef EDQUOT
68
case EDQUOT:
69
errorf("Cannot create directory %s because you "
70
"exceeded your quota", name);
71
break;
72
#endif
73
default:
74
errorf("Error creating directory %s", name);
75
break;
76
}
77
}
78
79
/*
80
* Create the needed directory hierarchy recursively in order to save
81
* multi-GETs in file output, ie:
82
* curl "http://example.org/dir[1-5]/file[1-5].txt" -o "dir#1/file#2.txt"
83
* should create all the dir* automagically
84
*/
85
86
#if defined(_WIN32) || defined(__DJGPP__)
87
/* systems that may use either or when specifying a path */
88
#define PATH_DELIMITERS "\\/"
89
#else
90
#define PATH_DELIMITERS DIR_CHAR
91
#endif
92
93
CURLcode create_dir_hierarchy(const char *outfile)
94
{
95
CURLcode result = CURLE_OK;
96
size_t outlen = strlen(outfile);
97
struct dynbuf dirbuf;
98
99
curlx_dyn_init(&dirbuf, outlen + 1);
100
101
while(*outfile) {
102
bool skip = FALSE;
103
size_t seplen = strspn(outfile, PATH_DELIMITERS);
104
size_t len = strcspn(&outfile[seplen], PATH_DELIMITERS);
105
106
/* the last path component is the file and it ends with a null byte */
107
if(!outfile[len + seplen])
108
break;
109
110
#if defined(_WIN32) || defined(MSDOS)
111
if(!curlx_dyn_len(&dirbuf)) {
112
/* Skip creating a drive's current directory. It may seem as though that
113
would harmlessly fail but it could be a corner case if X: did not
114
exist, since we would be creating it erroneously. eg if outfile is
115
X:\foo\bar\filename then do not mkdir X: This logic takes into
116
account unsupported drives !:, 1:, etc. */
117
if(len > 1 && (outfile[1]==':'))
118
skip = TRUE;
119
}
120
#endif
121
/* insert the leading separators (possibly plural) plus the following
122
directory name */
123
result = curlx_dyn_addn(&dirbuf, outfile, seplen + len);
124
if(result)
125
return result;
126
127
/* Create directory. Ignore access denied error to allow traversal. */
128
/* !checksrc! disable ERRNOVAR 1 */
129
if(!skip && (mkdir(curlx_dyn_ptr(&dirbuf), (mode_t)0000750) == -1) &&
130
(errno != EACCES) && (errno != EEXIST)) {
131
show_dir_errno(curlx_dyn_ptr(&dirbuf));
132
result = CURLE_WRITE_ERROR;
133
break; /* get out of loop */
134
}
135
outfile += len + seplen;
136
}
137
138
curlx_dyn_free(&dirbuf);
139
140
return result;
141
}
142
143