| 3227 | } |
| 3228 | |
| 3229 | Status S3FileSystem::CreateDir(const std::string& s, bool recursive) { |
| 3230 | ARROW_ASSIGN_OR_RAISE(auto path, S3Path::FromString(s)); |
| 3231 | |
| 3232 | if (path.key.empty()) { |
| 3233 | // Create bucket |
| 3234 | return impl_->CreateBucket(path.bucket); |
| 3235 | } |
| 3236 | |
| 3237 | ARROW_ASSIGN_OR_RAISE(auto backend, impl_->GetBackend()); |
| 3238 | |
| 3239 | FileInfo file_info; |
| 3240 | if (recursive) { |
| 3241 | // Ensure bucket exists |
| 3242 | ARROW_ASSIGN_OR_RAISE(bool bucket_exists, impl_->BucketExists(path.bucket)); |
| 3243 | if (!bucket_exists) { |
| 3244 | RETURN_NOT_OK(impl_->CreateBucket(path.bucket)); |
| 3245 | } |
| 3246 | |
| 3247 | auto key_i = path.key_parts.begin(); |
| 3248 | std::string parent_key{}; |
| 3249 | if (options().check_directory_existence_before_creation || |
| 3250 | backend == S3Backend::Minio) { |
| 3251 | // Walk up the directory first to find the first existing parent |
| 3252 | for (const auto& part : path.key_parts) { |
| 3253 | parent_key += part; |
| 3254 | parent_key += kSep; |
| 3255 | } |
| 3256 | for (key_i = path.key_parts.end(); key_i-- != path.key_parts.begin();) { |
| 3257 | ARROW_ASSIGN_OR_RAISE(file_info, |
| 3258 | this->GetFileInfo(path.bucket + kSep + parent_key)); |
| 3259 | if (file_info.type() != FileType::NotFound) { |
| 3260 | // Found! |
| 3261 | if (file_info.type() != FileType::Directory) { |
| 3262 | return Status::IOError("Cannot create directory '", file_info.path(), |
| 3263 | "': a non-directory entry already exists"); |
| 3264 | } |
| 3265 | break; |
| 3266 | } else { |
| 3267 | // remove the kSep and the part |
| 3268 | parent_key.pop_back(); |
| 3269 | parent_key.erase(parent_key.end() - key_i->size(), parent_key.end()); |
| 3270 | } |
| 3271 | } |
| 3272 | key_i++; // Above for loop moves one extra iterator at the end |
| 3273 | } |
| 3274 | // Ensure that all parents exist, then the directory itself |
| 3275 | // Create all missing directories |
| 3276 | for (; key_i < path.key_parts.end(); ++key_i) { |
| 3277 | parent_key += *key_i; |
| 3278 | parent_key += kSep; |
| 3279 | RETURN_NOT_OK(impl_->CreateEmptyDir(path.bucket, parent_key)); |
| 3280 | } |
| 3281 | return Status::OK(); |
| 3282 | } else { |
| 3283 | // Check parent dir exists |
| 3284 | if (path.has_parent()) { |
| 3285 | S3Path parent_path = path.parent(); |
| 3286 | ARROW_ASSIGN_OR_RAISE(bool exists, impl_->IsNonEmptyDirectory(parent_path)); |