16 #include "auth/davixx509cred.hpp"
17 #include "auth/davixauth.hpp"
23 std::vector<std::string> SplitString(
const std::string& input,
24 const std::string& delimiter) {
29 auto result = std::vector<std::string>{};
32 end = input.find(delimiter, start);
34 if (end != std::string::npos)
37 length = input.length() - start;
39 if (length) result.push_back(input.substr(start, length));
41 start = end + delimiter.size();
42 }
while (end != std::string::npos);
47 void SetTimeout(Davix::RequestParams& params, uint16_t timeout) {
57 struct timespec ts = {0, 0};
59 params.setConnectionTimeout(&ts);
61 params.setOperationRetry(0);
62 params.setOperationRetryDelay(2);
66 std::ostringstream data;
67 if (S_ISDIR(stats.st_mode)) {
68 data << stats.st_dev <<
" " << stats.st_size <<
" "
69 << (XrdCl::StatInfo::Flags::IsDir | XrdCl::StatInfo::Flags::IsReadable |
70 XrdCl::StatInfo::Flags::IsWritable | XrdCl::StatInfo::Flags::XBitSet)
71 <<
" " << stats.st_mtime;
74 if (getenv(
"AWS_ACCESS_KEY_ID")) {
75 data << stats.st_dev <<
" " << stats.st_size <<
" "
76 << XrdCl::StatInfo::Flags::IsReadable <<
" " << stats.st_mtime;
79 data << stats.st_dev <<
" " << stats.st_size <<
" "
80 << stats.st_mode <<
" " << stats.st_mtime;
110 int LoadX509UserCredentialCallBack(
void *userdata,
111 const Davix::SessionInfo &info,
112 Davix::X509Credential *cert,
113 Davix::DavixError **err) {
114 std::string myX509proxyFile;
115 if (getenv(
"X509_USER_PROXY") != NULL)
116 myX509proxyFile = getenv(
"X509_USER_PROXY");
118 myX509proxyFile =
"/tmp/x509up_u" + std::to_string(geteuid());
120 struct stat myX509proxyStat;
121 if (
stat(myX509proxyFile.c_str(), &myX509proxyStat) == 0)
122 return cert->loadFromFilePEM(myX509proxyFile.c_str(), myX509proxyFile.c_str(),
"", err);
127 void SetX509(Davix::RequestParams& params) {
128 params.setClientCertCallbackX509(&LoadX509UserCredentialCallBack, NULL);
136 if (getenv(
"X509_CERT_DIR") != NULL)
137 params.addCertificateAuthorityPath(getenv(
"X509_CERT_DIR"));
139 params.addCertificateAuthorityPath(
"/etc/grid-security/certificates");
142 void SetAuthS3(Davix::RequestParams& params) {
146 params.setProtocol(Davix::RequestProtocol::AwsS3);
147 params.setAwsAuthorizationKeys(getenv(
"AWS_SECRET_ACCESS_KEY"),
148 getenv(
"AWS_ACCESS_KEY_ID"));
149 params.setAwsAlternate(
true);
151 if (getenv(
"AWS_REGION"))
152 params.setAwsRegion(getenv(
"AWS_REGION"));
153 else if (! getenv(
"AWS_SIGNATURE_V2"))
154 params.setAwsRegion(
"mars");
157 void SetAuthz(Davix::RequestParams& params) {
158 if (getenv(
"AWS_ACCESS_KEY_ID") && getenv(
"AWS_SECRET_ACCESS_KEY"))
164 std::string SanitizedURL(
const std::string& url) {
166 std::string path = xurl.GetPath();
167 if (path.find(
"/") != 0) path =
"/" + path;
168 std::string returl = xurl.GetProtocol() +
"://"
169 + xurl.GetHostName() +
":"
170 + std::to_string(xurl.GetPort())
175 if (! getenv(
"AWS_ACCESS_KEY_ID") && ! xurl.GetParamsAsString().empty()) {
176 returl = returl + xurl.GetParamsAsString();
183 std::pair<uint16_t, XErrorCode> ErrCodeConvert(Davix::StatusCode::Code code) {
184 if (code == Davix::StatusCode::FileNotFound)
186 else if (code == Davix::StatusCode::FileExist)
188 else if (code == Davix::StatusCode::PermissionRefused)
198 using namespace XrdCl;
200 std::pair<DAVIX_FD*, XRootDStatus>
Open(Davix::DavPosix& davix_client,
201 const std::string& url,
int flags,
203 Davix::RequestParams params;
204 SetTimeout(params, timeout);
206 Davix::DavixError* err =
nullptr;
207 DAVIX_FD* fd = davix_client.open(¶ms, SanitizedURL(url), flags, &err);
210 auto res = ErrCodeConvert(err->getStatus());
217 return std::make_pair(fd, status);
221 Davix::DavixError* err =
nullptr;
222 if (davix_client.close(fd, &err)) {
238 Davix::RequestParams params;
239 SetTimeout(params, timeout);
242 auto DoMkDir = [&davix_client, ¶ms](
const std::string& path) {
243 Davix::DavixError* err =
nullptr;
244 if (davix_client.mkdir(¶ms, SanitizedURL(path), S_IRWXU, &err) &&
245 (err->getStatus() != Davix::StatusCode::FileExist)) {
260 auto dirs = SplitString(url.GetPath(),
"/");
262 std::string dirs_cumul;
263 for (
const auto& d : dirs) {
264 dirs_cumul +=
"/" + d;
265 url.SetPath(dirs_cumul);
266 auto status =
DoMkDir(url.GetLocation());
267 if (status.IsError()) {
273 auto status =
DoMkDir(url.GetURL());
274 if (status.IsError()) {
284 Davix::RequestParams params;
285 SetTimeout(params, timeout);
288 Davix::DavixError* err =
nullptr;
289 if (davix_client.rmdir(¶ms, path, &err)) {
299 std::pair<XrdCl::DirectoryList*, XrdCl::XRootDStatus>
DirList(
300 Davix::DavPosix& davix_client,
const std::string& path,
bool details,
301 bool , uint16_t timeout) {
302 Davix::RequestParams params;
303 SetTimeout(params, timeout);
308 Davix::DavixError* err =
nullptr;
310 auto dir_fd = davix_client.opendirpp(¶ms, SanitizedURL(path), &err);
315 return std::make_pair(
nullptr, errStatus);
319 while (
auto entry = davix_client.readdirpp(dir_fd, &info, &err)) {
324 return std::make_pair(
nullptr, errStatus);
330 auto res = FillStatInfo(info, stat_info);
334 return std::make_pair(
nullptr, res);
339 dir_list->Add(list_entry);
346 if (davix_client.closedirpp(dir_fd, &err)) {
350 return std::make_pair(
nullptr, errStatus);
357 const std::string& dest, uint16_t timeout) {
363 if (getenv(
"AWS_ACCESS_KEY_ID"))
366 Davix::RequestParams params;
367 SetTimeout(params, timeout);
370 Davix::DavixError* err =
nullptr;
371 if (davix_client.rename(¶ms, SanitizedURL(source), SanitizedURL(dest), &err)) {
382 uint16_t timeout,
StatInfo* stat_info) {
383 Davix::RequestParams params;
384 SetTimeout(params, timeout);
388 Davix::DavixError* err =
nullptr;
389 if (davix_client.stat(¶ms, SanitizedURL(url), &stats, &err)) {
390 auto res = ErrCodeConvert(err->getStatus());
397 auto res = FillStatInfo(stats, stat_info);
407 Davix::RequestParams params;
408 SetTimeout(params, timeout);
411 Davix::DavixError* err =
nullptr;
412 if (davix_client.unlink(¶ms, SanitizedURL(url), &err)) {
422 std::pair<int, XRootDStatus>
_PRead(Davix::DavPosix& davix_client, DAVIX_FD* fd,
423 void* buffer, uint32_t size,
424 uint64_t offset,
bool no_pread =
false) {
425 Davix::DavixError* err =
nullptr;
428 num_bytes_read = davix_client.read(fd, buffer, size, &err);
431 num_bytes_read = davix_client.pread(fd, buffer, size, offset, &err);
433 if (num_bytes_read < 0) {
437 return std::make_pair(num_bytes_read, errStatus);
443 std::pair<int, XRootDStatus>
Read(Davix::DavPosix& davix_client, DAVIX_FD* fd,
444 void* buffer, uint32_t size) {
445 return _PRead(davix_client, fd, buffer, size, 0,
true);
448 std::pair<int, XRootDStatus>
PRead(Davix::DavPosix& davix_client, DAVIX_FD* fd,
449 void* buffer, uint32_t size, uint64_t offset) {
450 return _PRead(davix_client, fd, buffer, size, offset,
false);
453 std::pair<int, XrdCl::XRootDStatus>
PReadVec(Davix::DavPosix& davix_client,
457 const auto num_chunks = chunks.size();
458 std::vector<Davix::DavIOVecInput> input_vector(num_chunks);
459 std::vector<Davix::DavIOVecOuput> output_vector(num_chunks);
461 for (
size_t i = 0; i < num_chunks; ++i) {
462 input_vector[i].diov_offset = chunks[i].offset;
463 input_vector[i].diov_size = chunks[i].length;
464 input_vector[i].diov_buffer = chunks[i].buffer;
467 Davix::DavixError* err =
nullptr;
468 int num_bytes_read = davix_client.preadVec(
469 fd, input_vector.data(), output_vector.data(), num_chunks, &err);
470 if (num_bytes_read < 0) {
480 std::pair<int, XrdCl::XRootDStatus>
PWrite(Davix::DavPosix& davix_client,
481 DAVIX_FD* fd, uint64_t offset,
482 uint32_t size,
const void* buffer,
484 Davix::DavixError* err =
nullptr;
485 off_t new_offset = davix_client.lseek(fd, offset, SEEK_SET, &err);
486 if (uint64_t(new_offset) != offset) {
490 return std::make_pair(new_offset, errStatus);
492 int num_bytes_written = davix_client.write(fd, buffer, size, &err);
493 if (num_bytes_written < 0) {
497 return std::make_pair(num_bytes_written, errStatus);
500 return std::make_pair(num_bytes_written,
XRootDStatus());
XRootDStatus DoMkDir(FileSystem *fs, Env *env, const FSExecutor::CommandParams &args)
int stat(const char *path, struct stat *buf)
bool ParseServerResponse(const char *data)
Parse server response and fill up the object.
std::pair< int, XrdCl::XRootDStatus > PReadVec(Davix::DavPosix &davix_client, DAVIX_FD *fd, const XrdCl::ChunkList &chunks, void *buffer)
std::pair< int, XRootDStatus > Read(Davix::DavPosix &davix_client, DAVIX_FD *fd, void *buffer, uint32_t size)
std::pair< int, XrdCl::XRootDStatus > PWrite(Davix::DavPosix &davix_client, DAVIX_FD *fd, uint64_t offset, uint32_t size, const void *buffer, uint16_t timeout)
std::pair< DAVIX_FD *, XRootDStatus > Open(Davix::DavPosix &davix_client, const std::string &url, int flags, uint16_t timeout)
std::pair< int, XRootDStatus > PRead(Davix::DavPosix &davix_client, DAVIX_FD *fd, void *buffer, uint32_t size, uint64_t offset)
XRootDStatus Close(Davix::DavPosix &davix_client, DAVIX_FD *fd)
XRootDStatus Unlink(Davix::DavPosix &davix_client, const std::string &url, uint16_t timeout)
XRootDStatus RmDir(Davix::DavPosix &davix_client, const std::string &path, uint16_t timeout)
std::pair< XrdCl::DirectoryList *, XrdCl::XRootDStatus > DirList(Davix::DavPosix &davix_client, const std::string &path, bool details, bool, uint16_t timeout)
XRootDStatus MkDir(Davix::DavPosix &davix_client, const std::string &path, XrdCl::MkDirFlags::Flags flags, XrdCl::Access::Mode, uint16_t timeout)
std::pair< int, XRootDStatus > _PRead(Davix::DavPosix &davix_client, DAVIX_FD *fd, void *buffer, uint32_t size, uint64_t offset, bool no_pread=false)
XRootDStatus Rename(Davix::DavPosix &davix_client, const std::string &source, const std::string &dest, uint16_t timeout)
XRootDStatus Stat(Davix::DavPosix &davix_client, const std::string &url, uint16_t timeout, StatInfo *stat_info)
const uint16_t errUnknown
Unknown error.
const uint16_t errErrorResponse
const uint16_t stError
An error occurred that could potentially be retried.
const uint16_t errDataError
data is corrupted
const uint16_t errInternal
Internal error.
std::vector< ChunkInfo > ChunkList
List of chunks.
@ MakePath
create the entire directory tree if it doesn't exist