| 3144 | std::string S3FileSystem::region() const { return impl_->region(); } |
| 3145 | |
| 3146 | Result<FileInfo> S3FileSystem::GetFileInfo(const std::string& s) { |
| 3147 | ARROW_ASSIGN_OR_RAISE(auto client_lock, impl_->holder_->Lock()); |
| 3148 | |
| 3149 | ARROW_ASSIGN_OR_RAISE(auto path, S3Path::FromString(s)); |
| 3150 | FileInfo info; |
| 3151 | info.set_path(s); |
| 3152 | |
| 3153 | if (path.empty()) { |
| 3154 | // It's the root path "" |
| 3155 | info.set_type(FileType::Directory); |
| 3156 | return info; |
| 3157 | } else if (path.key.empty()) { |
| 3158 | // It's a bucket |
| 3159 | S3Model::HeadBucketRequest req; |
| 3160 | req.SetBucket(ToAwsString(path.bucket)); |
| 3161 | |
| 3162 | auto outcome = client_lock.Move()->HeadBucket(req); |
| 3163 | if (!outcome.IsSuccess()) { |
| 3164 | impl_->GetOrSetBackend(outcome.GetError()); |
| 3165 | if (!IsNotFound(outcome.GetError())) { |
| 3166 | const auto msg = "When getting information for bucket '" + path.bucket + "': "; |
| 3167 | return ErrorToStatus(msg, "HeadBucket", outcome.GetError(), |
| 3168 | impl_->options().region); |
| 3169 | } |
| 3170 | info.set_type(FileType::NotFound); |
| 3171 | return info; |
| 3172 | } |
| 3173 | // NOTE: S3 doesn't have a bucket modification time. Only a creation |
| 3174 | // time is available, and you have to list all buckets to get it. |
| 3175 | info.set_type(FileType::Directory); |
| 3176 | return info; |
| 3177 | } else { |
| 3178 | // It's an object |
| 3179 | S3Model::HeadObjectRequest req; |
| 3180 | req.SetBucket(ToAwsString(path.bucket)); |
| 3181 | req.SetKey(ToAwsString(path.key)); |
| 3182 | |
| 3183 | auto outcome = client_lock.Move()->HeadObject(req); |
| 3184 | if (outcome.IsSuccess()) { |
| 3185 | // "File" object found |
| 3186 | FileObjectToInfo(path.key, outcome.GetResult(), &info); |
| 3187 | return info; |
| 3188 | } |
| 3189 | impl_->GetOrSetBackend(outcome.GetError()); |
| 3190 | if (!IsNotFound(outcome.GetError())) { |
| 3191 | const auto msg = "When getting information for key '" + path.key + "' in bucket '" + |
| 3192 | path.bucket + "': "; |
| 3193 | return ErrorToStatus(msg, "HeadObject", outcome.GetError(), |
| 3194 | impl_->options().region); |
| 3195 | } |
| 3196 | // Not found => perhaps it's an empty "directory" |
| 3197 | ARROW_ASSIGN_OR_RAISE(bool is_dir, impl_->IsEmptyDirectory(path, &outcome)); |
| 3198 | if (is_dir) { |
| 3199 | info.set_type(FileType::Directory); |
| 3200 | return info; |
| 3201 | } |
| 3202 | // Not found => perhaps it's a non-empty "directory" |
| 3203 | ARROW_ASSIGN_OR_RAISE(is_dir, impl_->IsNonEmptyDirectory(path)); |