Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: CPL - Common Portability Library
4 : * Purpose: Implement VSI large file api for Alibaba Object Storage Service
5 : * Author: Even Rouault, even.rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2017-2018, Even Rouault <even.rouault at spatialys.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "cpl_port.h"
30 : #include "cpl_http.h"
31 : #include "cpl_minixml.h"
32 : #include "cpl_vsil_curl_priv.h"
33 : #include "cpl_vsil_curl_class.h"
34 :
35 : #include <errno.h>
36 :
37 : #include <algorithm>
38 : #include <set>
39 : #include <map>
40 : #include <memory>
41 :
42 : #include "cpl_alibaba_oss.h"
43 :
44 : #ifndef HAVE_CURL
45 :
46 : void VSIInstallOSSFileHandler(void)
47 : {
48 : // Not supported
49 : }
50 :
51 : #else
52 :
53 : //! @cond Doxygen_Suppress
54 : #ifndef DOXYGEN_SKIP
55 :
56 : #define ENABLE_DEBUG 0
57 :
58 : namespace cpl
59 : {
60 :
61 : /************************************************************************/
62 : /* VSIOSSFSHandler */
63 : /************************************************************************/
64 :
65 : class VSIOSSFSHandler final : public IVSIS3LikeFSHandler
66 : {
67 : CPL_DISALLOW_COPY_ASSIGN(VSIOSSFSHandler)
68 :
69 : protected:
70 : VSICurlHandle *CreateFileHandle(const char *pszFilename) override;
71 : std::string GetURLFromFilename(const std::string &osFilename) override;
72 :
73 110 : const char *GetDebugKey() const override
74 : {
75 110 : return "OSS";
76 : }
77 :
78 : IVSIS3LikeHandleHelper *CreateHandleHelper(const char *pszURI,
79 : bool bAllowNoObject) override;
80 :
81 786 : std::string GetFSPrefix() const override
82 : {
83 786 : return "/vsioss/";
84 : }
85 :
86 : void ClearCache() override;
87 :
88 : VSIVirtualHandleUniquePtr
89 : CreateWriteHandle(const char *pszFilename,
90 : CSLConstList papszOptions) override;
91 :
92 : public:
93 1228 : VSIOSSFSHandler() = default;
94 : ~VSIOSSFSHandler() override;
95 :
96 : const char *GetOptions() override;
97 :
98 : char *GetSignedURL(const char *pszFilename,
99 : CSLConstList papszOptions) override;
100 :
101 : std::string
102 0 : GetStreamingFilename(const std::string &osFilename) const override
103 : {
104 0 : return osFilename;
105 : }
106 : };
107 :
108 : /************************************************************************/
109 : /* VSIOSSHandle */
110 : /************************************************************************/
111 :
112 : class VSIOSSHandle final : public IVSIS3LikeHandle
113 : {
114 : CPL_DISALLOW_COPY_ASSIGN(VSIOSSHandle)
115 :
116 : VSIOSSHandleHelper *m_poHandleHelper = nullptr;
117 :
118 : protected:
119 : struct curl_slist *
120 : GetCurlHeaders(const std::string &osVerb,
121 : const struct curl_slist *psExistingHeaders) override;
122 : bool CanRestartOnError(const char *, const char *, bool) override;
123 :
124 : public:
125 : VSIOSSHandle(VSIOSSFSHandler *poFS, const char *pszFilename,
126 : VSIOSSHandleHelper *poHandleHelper);
127 : ~VSIOSSHandle() override;
128 : };
129 :
130 : /************************************************************************/
131 : /* ~VSIOSSFSHandler() */
132 : /************************************************************************/
133 :
134 1704 : VSIOSSFSHandler::~VSIOSSFSHandler()
135 : {
136 852 : VSIOSSFSHandler::ClearCache();
137 1704 : }
138 :
139 : /************************************************************************/
140 : /* CreateWriteHandle() */
141 : /************************************************************************/
142 :
143 : VSIVirtualHandleUniquePtr
144 16 : VSIOSSFSHandler::CreateWriteHandle(const char *pszFilename,
145 : CSLConstList papszOptions)
146 : {
147 : auto poHandleHelper =
148 16 : CreateHandleHelper(pszFilename + GetFSPrefix().size(), false);
149 16 : if (poHandleHelper == nullptr)
150 1 : return nullptr;
151 : auto poHandle = std::make_unique<VSIS3WriteHandle>(
152 30 : this, pszFilename, poHandleHelper, false, papszOptions);
153 15 : if (!poHandle->IsOK())
154 : {
155 0 : return nullptr;
156 : }
157 15 : return VSIVirtualHandleUniquePtr(poHandle.release());
158 : }
159 :
160 : /************************************************************************/
161 : /* ClearCache() */
162 : /************************************************************************/
163 :
164 1098 : void VSIOSSFSHandler::ClearCache()
165 : {
166 1098 : VSICurlFilesystemHandlerBase::ClearCache();
167 :
168 1098 : VSIOSSUpdateParams::ClearCache();
169 1098 : }
170 :
171 : /************************************************************************/
172 : /* GetOptions() */
173 : /************************************************************************/
174 :
175 2 : const char *VSIOSSFSHandler::GetOptions()
176 : {
177 : static std::string osOptions(
178 2 : std::string("<Options>") +
179 : " <Option name='OSS_SECRET_ACCESS_KEY' type='string' "
180 : "description='Secret access key. To use with OSS_ACCESS_KEY_ID'/>"
181 : " <Option name='OSS_ACCESS_KEY_ID' type='string' "
182 : "description='Access key id'/>"
183 : " <Option name='OSS_ENDPOINT' type='string' "
184 : "description='Default endpoint' default='oss-us-east-1.aliyuncs.com'/>"
185 : " <Option name='VSIOSS_CHUNK_SIZE' type='int' "
186 : "description='Size in MB for chunks of files that are uploaded. The"
187 : "default value of 50 MB allows for files up to 500 GB each' "
188 3 : "default='50' min='1' max='1000'/>" +
189 3 : VSICurlFilesystemHandlerBase::GetOptionsStatic() + "</Options>");
190 2 : return osOptions.c_str();
191 : }
192 :
193 : /************************************************************************/
194 : /* GetSignedURL() */
195 : /************************************************************************/
196 :
197 2 : char *VSIOSSFSHandler::GetSignedURL(const char *pszFilename,
198 : CSLConstList papszOptions)
199 : {
200 2 : if (!STARTS_WITH_CI(pszFilename, GetFSPrefix().c_str()))
201 0 : return nullptr;
202 :
203 4 : VSIOSSHandleHelper *poHandleHelper = VSIOSSHandleHelper::BuildFromURI(
204 6 : pszFilename + GetFSPrefix().size(), GetFSPrefix().c_str(), false,
205 : papszOptions);
206 2 : if (poHandleHelper == nullptr)
207 : {
208 1 : return nullptr;
209 : }
210 :
211 2 : std::string osRet(poHandleHelper->GetSignedURL(papszOptions));
212 :
213 1 : delete poHandleHelper;
214 1 : return CPLStrdup(osRet.c_str());
215 : }
216 :
217 : /************************************************************************/
218 : /* CreateFileHandle() */
219 : /************************************************************************/
220 :
221 45 : VSICurlHandle *VSIOSSFSHandler::CreateFileHandle(const char *pszFilename)
222 : {
223 90 : VSIOSSHandleHelper *poHandleHelper = VSIOSSHandleHelper::BuildFromURI(
224 135 : pszFilename + GetFSPrefix().size(), GetFSPrefix().c_str(), false);
225 45 : if (poHandleHelper)
226 : {
227 43 : return new VSIOSSHandle(this, pszFilename, poHandleHelper);
228 : }
229 2 : return nullptr;
230 : }
231 :
232 : /************************************************************************/
233 : /* GetURLFromFilename() */
234 : /************************************************************************/
235 :
236 17 : std::string VSIOSSFSHandler::GetURLFromFilename(const std::string &osFilename)
237 : {
238 : std::string osFilenameWithoutPrefix =
239 34 : osFilename.substr(GetFSPrefix().size());
240 :
241 17 : VSIOSSHandleHelper *poHandleHelper = VSIOSSHandleHelper::BuildFromURI(
242 34 : osFilenameWithoutPrefix.c_str(), GetFSPrefix().c_str(), true);
243 17 : if (poHandleHelper == nullptr)
244 : {
245 0 : return "";
246 : }
247 :
248 34 : std::string osBaseURL(poHandleHelper->GetURL());
249 17 : if (!osBaseURL.empty() && osBaseURL.back() == '/')
250 7 : osBaseURL.resize(osBaseURL.size() - 1);
251 17 : delete poHandleHelper;
252 :
253 17 : return osBaseURL;
254 : }
255 :
256 : /************************************************************************/
257 : /* CreateHandleHelper() */
258 : /************************************************************************/
259 :
260 28 : IVSIS3LikeHandleHelper *VSIOSSFSHandler::CreateHandleHelper(const char *pszURI,
261 : bool bAllowNoObject)
262 : {
263 56 : return VSIOSSHandleHelper::BuildFromURI(pszURI, GetFSPrefix().c_str(),
264 56 : bAllowNoObject);
265 : }
266 :
267 : /************************************************************************/
268 : /* VSIOSSHandle() */
269 : /************************************************************************/
270 :
271 43 : VSIOSSHandle::VSIOSSHandle(VSIOSSFSHandler *poFSIn, const char *pszFilename,
272 43 : VSIOSSHandleHelper *poHandleHelper)
273 43 : : IVSIS3LikeHandle(poFSIn, pszFilename, poHandleHelper->GetURL().c_str()),
274 43 : m_poHandleHelper(poHandleHelper)
275 : {
276 43 : }
277 :
278 : /************************************************************************/
279 : /* ~VSIOSSHandle() */
280 : /************************************************************************/
281 :
282 86 : VSIOSSHandle::~VSIOSSHandle()
283 : {
284 43 : delete m_poHandleHelper;
285 86 : }
286 :
287 : /************************************************************************/
288 : /* GetCurlHeaders() */
289 : /************************************************************************/
290 :
291 : struct curl_slist *
292 43 : VSIOSSHandle::GetCurlHeaders(const std::string &osVerb,
293 : const struct curl_slist *psExistingHeaders)
294 : {
295 43 : return m_poHandleHelper->GetCurlHeaders(osVerb, psExistingHeaders);
296 : }
297 :
298 : /************************************************************************/
299 : /* CanRestartOnError() */
300 : /************************************************************************/
301 :
302 2 : bool VSIOSSHandle::CanRestartOnError(const char *pszErrorMsg,
303 : const char *pszHeaders, bool bSetError)
304 : {
305 2 : if (m_poHandleHelper->CanRestartOnError(pszErrorMsg, pszHeaders, bSetError))
306 : {
307 1 : SetURL(m_poHandleHelper->GetURL().c_str());
308 1 : return true;
309 : }
310 1 : return false;
311 : }
312 :
313 : } /* end of namespace cpl */
314 :
315 : #endif // DOXYGEN_SKIP
316 : //! @endcond
317 :
318 : /************************************************************************/
319 : /* VSIInstallOSSFileHandler() */
320 : /************************************************************************/
321 :
322 : /*!
323 : \brief Install /vsioss/ Alibaba Cloud Object Storage Service (OSS) file
324 : system handler (requires libcurl)
325 :
326 : \verbatim embed:rst
327 : See :ref:`/vsioss/ documentation <vsioss>`
328 : \endverbatim
329 :
330 : @since GDAL 2.3
331 : */
332 1228 : void VSIInstallOSSFileHandler(void)
333 : {
334 1228 : VSIFileManager::InstallHandler("/vsioss/", new cpl::VSIOSSFSHandler);
335 1228 : }
336 :
337 : #endif /* HAVE_CURL */
|