| 3077 | std::string S3FileSystem::region() const { return impl_->region(); } |
| 3078 | |
| 3079 | Result<FileInfo> S3FileSystem::GetFileInfo(const std::string& s) { |
| 3080 | ARROW_ASSIGN_OR_RAISE(auto client_lock, impl_->holder_->Lock()); |
| 3081 | |
| 3082 | ARROW_ASSIGN_OR_RAISE(auto path, S3Path::FromString(s)); |
| 3083 | FileInfo info; |
| 3084 | info.set_path(s); |
| 3085 | |
| 3086 | if (path.empty()) { |
| 3087 | // It's the root path "" |
| 3088 | info.set_type(FileType::Directory); |
| 3089 | return info; |
| 3090 | } else if (path.key.empty()) { |
| 3091 | // It's a bucket |
| 3092 | S3Model::HeadBucketRequest req; |
| 3093 | req.SetBucket(ToAwsString(path.bucket)); |
| 3094 | |
| 3095 | auto outcome = client_lock.Move()->HeadBucket(req); |
| 3096 | if (!outcome.IsSuccess()) { |
| 3097 | impl_->GetOrSetBackend(outcome.GetError()); |
| 3098 | if (!IsNotFound(outcome.GetError())) { |
| 3099 | const auto msg = "When getting information for bucket '" + path.bucket + "': "; |
| 3100 | return ErrorToStatus(msg, "HeadBucket", outcome.GetError(), |
| 3101 | impl_->options().region); |
| 3102 | } |
| 3103 | info.set_type(FileType::NotFound); |
| 3104 | return info; |
| 3105 | } |
| 3106 | // NOTE: S3 doesn't have a bucket modification time. Only a creation |
| 3107 | // time is available, and you have to list all buckets to get it. |
| 3108 | info.set_type(FileType::Directory); |
| 3109 | return info; |
| 3110 | } else { |
| 3111 | // It's an object |
| 3112 | S3Model::HeadObjectRequest req; |
| 3113 | req.SetBucket(ToAwsString(path.bucket)); |
| 3114 | req.SetKey(ToAwsString(path.key)); |
| 3115 | |
| 3116 | auto outcome = client_lock.Move()->HeadObject(req); |
| 3117 | if (outcome.IsSuccess()) { |
| 3118 | // "File" object found |
| 3119 | FileObjectToInfo(path.key, outcome.GetResult(), &info); |
| 3120 | return info; |
| 3121 | } |
| 3122 | impl_->GetOrSetBackend(outcome.GetError()); |
| 3123 | if (!IsNotFound(outcome.GetError())) { |
| 3124 | const auto msg = "When getting information for key '" + path.key + "' in bucket '" + |
| 3125 | path.bucket + "': "; |
| 3126 | return ErrorToStatus(msg, "HeadObject", outcome.GetError(), |
| 3127 | impl_->options().region); |
| 3128 | } |
| 3129 | // Not found => perhaps it's an empty "directory" |
| 3130 | ARROW_ASSIGN_OR_RAISE(bool is_dir, impl_->IsEmptyDirectory(path, &outcome)); |
| 3131 | if (is_dir) { |
| 3132 | info.set_type(FileType::Directory); |
| 3133 | return info; |
| 3134 | } |
| 3135 | // Not found => perhaps it's a non-empty "directory" |
| 3136 | ARROW_ASSIGN_OR_RAISE(is_dir, impl_->IsNonEmptyDirectory(path)); |