Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmcurl/lib/curl_fopen.c
5015 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 "curl_setup.h"
25
26
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
27
!defined(CURL_DISABLE_HSTS)
28
29
#include "urldata.h"
30
#include "rand.h"
31
#include "curl_fopen.h"
32
33
/*
34
The dirslash() function breaks a null-terminated pathname string into
35
directory and filename components then returns the directory component up
36
to, *AND INCLUDING*, a final '/'. If there is no directory in the path,
37
this instead returns a "" string.
38
39
This function returns a pointer to malloc'ed memory.
40
41
The input path to this function is expected to have a filename part.
42
*/
43
44
#ifdef _WIN32
45
#define PATHSEP "\\"
46
#define IS_SEP(x) (((x) == '/') || ((x) == '\\'))
47
#elif defined(MSDOS) || defined(OS2)
48
#define PATHSEP "\\"
49
#define IS_SEP(x) ((x) == '\\')
50
#else
51
#define PATHSEP "/"
52
#define IS_SEP(x) ((x) == '/')
53
#endif
54
55
static char *dirslash(const char *path)
56
{
57
size_t n;
58
struct dynbuf out;
59
DEBUGASSERT(path);
60
curlx_dyn_init(&out, CURL_MAX_INPUT_LENGTH);
61
n = strlen(path);
62
if(n) {
63
/* find the rightmost path separator, if any */
64
while(n && !IS_SEP(path[n - 1]))
65
--n;
66
/* skip over all the path separators, if any */
67
while(n && IS_SEP(path[n - 1]))
68
--n;
69
}
70
if(curlx_dyn_addn(&out, path, n))
71
return NULL;
72
/* if there was a directory, append a single trailing slash */
73
if(n && curlx_dyn_addn(&out, PATHSEP, 1))
74
return NULL;
75
return curlx_dyn_ptr(&out);
76
}
77
78
/*
79
* Curl_fopen() opens a file for writing with a temp name, to be renamed
80
* to the final name when completed. If there is an existing file using this
81
* name at the time of the open, this function will clone the mode from that
82
* file. if 'tempname' is non-NULL, it needs a rename after the file is
83
* written.
84
*/
85
CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
86
FILE **fh, char **tempname)
87
{
88
CURLcode result = CURLE_WRITE_ERROR;
89
unsigned char randbuf[41];
90
char *tempstore = NULL;
91
#ifndef _WIN32
92
struct_stat sb;
93
#endif
94
int fd = -1;
95
char *dir = NULL;
96
*tempname = NULL;
97
98
#ifndef _WIN32
99
*fh = curlx_fopen(filename, FOPEN_WRITETEXT);
100
if(!*fh)
101
goto fail;
102
if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) {
103
return CURLE_OK;
104
}
105
curlx_fclose(*fh);
106
#endif
107
*fh = NULL;
108
109
result = Curl_rand_alnum(data, randbuf, sizeof(randbuf));
110
if(result)
111
goto fail;
112
113
dir = dirslash(filename);
114
if(dir) {
115
/* The temp filename should not end up too long for the target file
116
system */
117
tempstore = curl_maprintf("%s%s.tmp", dir, randbuf);
118
curlx_free(dir);
119
}
120
121
if(!tempstore) {
122
result = CURLE_OUT_OF_MEMORY;
123
goto fail;
124
}
125
126
result = CURLE_WRITE_ERROR;
127
#ifdef _WIN32
128
fd = curlx_open(tempstore, O_WRONLY | O_CREAT | O_EXCL,
129
S_IREAD | S_IWRITE);
130
#elif (defined(ANDROID) || defined(__ANDROID__)) && \
131
(defined(__i386__) || defined(__arm__))
132
fd = curlx_open(tempstore, O_WRONLY | O_CREAT | O_EXCL,
133
(mode_t)(S_IRUSR | S_IWUSR | sb.st_mode));
134
#else
135
fd = curlx_open(tempstore, O_WRONLY | O_CREAT | O_EXCL,
136
S_IRUSR | S_IWUSR | sb.st_mode);
137
#endif
138
if(fd == -1)
139
goto fail;
140
141
*fh = curlx_fdopen(fd, FOPEN_WRITETEXT);
142
if(!*fh)
143
goto fail;
144
145
*tempname = tempstore;
146
return CURLE_OK;
147
148
fail:
149
if(fd != -1) {
150
close(fd);
151
unlink(tempstore);
152
}
153
154
curlx_free(tempstore);
155
return result;
156
}
157
158
#endif /* !disabled */
159
160