/** * Copyright 2019 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "minddata/dataset/util/path.h" #include #include #include #include #include #include #include "utils/ms_utils.h" #include "utils/log_adapter.h" namespace mindspore { namespace dataset { #if defined(_WIN32) || defined(_WIN64) char Path::separator_ = '\\'; #else char Path::separator_ = '/'; #endif Path::Path(const std::string &s) : path_(s) {} Path::Path(const char *p) : path_(p) {} Path::Path(const Path &p) : path_(p.path_) {} Path &Path::operator=(const Path &p) { if (&p != this) { this->path_ = p.path_; } return *this; } Path &Path::operator=(Path &&p) noexcept { if (&p != this) { this->path_ = std::move(p.path_); } return *this; } Path::Path(Path &&p) noexcept { this->path_ = std::move(p.path_); } Path Path::operator+(const Path &p) { std::string q = path_ + p.toString(); return Path(q); } Path Path::operator+(const std::string &p) { std::string q = path_ + p; return Path(q); } Path Path::operator+(const char *p) { std::string q = path_ + p; return Path(q); } Path &Path::operator+=(const Path &rhs) { path_ += rhs.toString(); return *this; } Path &Path::operator+=(const std::string &p) { path_ += p; return *this; } Path &Path::operator+=(const char *p) { path_ += p; return *this; } Path Path::operator/(const Path &p) { std::string q = path_ + separator_ + p.toString(); return Path(q); } Path Path::operator/(const std::string &p) { std::string q = path_ + separator_ + p; return Path(q); } Path Path::operator/(const char *p) { std::string q = path_ + separator_ + p; return Path(q); } std::string Path::Extension() const { std::size_t found = path_.find_last_of('.'); if (found != std::string::npos) { return path_.substr(found); } else { return std::string(""); } } bool Path::Exists() { struct stat sb; int rc = stat(common::SafeCStr(path_), &sb); if (rc == -1 && errno != ENOENT) { MS_LOG(WARNING) << "Unable to query the status of " << path_ << ". Errno = " << errno << "."; } return (rc == 0); } bool Path::IsDirectory() { struct stat sb; int rc = stat(common::SafeCStr(path_), &sb); if (rc == 0) { return S_ISDIR(sb.st_mode); } else { return false; } } Status Path::CreateDirectory() { if (!Exists()) { #if defined(_WIN32) || defined(_WIN64) int rc = mkdir(common::SafeCStr(path_)); #else int rc = mkdir(common::SafeCStr(path_), S_IRUSR | S_IWUSR | S_IXUSR); #endif if (rc) { std::ostringstream oss; oss << "Unable to create directory " << path_ << ". Errno = " << errno; RETURN_STATUS_UNEXPECTED(oss.str()); } return Status::OK(); } else { if (IsDirectory()) { return Status::OK(); } else { std::ostringstream oss; oss << "Unable to create directory " << path_ << ". It exists but is not a directory"; RETURN_STATUS_UNEXPECTED(oss.str()); } } } std::string Path::ParentPath() { std::string r(""); std::size_t found = path_.find_last_of(separator_); if (found != std::string::npos) { if (found == 0) { r += separator_; } else { r = std::string(path_.substr(0, found)); } } return r; } Status Path::CreateDirectories() { if (IsDirectory()) { MS_LOG(DEBUG) << "Directory " << toString() << " already exists."; return Status::OK(); } else { MS_LOG(DEBUG) << "Creating directory " << toString() << "."; std::string parent = ParentPath(); if (!parent.empty()) { if (Path(parent).CreateDirectories()) { return CreateDirectory(); } } else { return CreateDirectory(); } } return Status::OK(); } Status Path::Remove() { if (Exists()) { if (IsDirectory()) { errno_t err = rmdir(common::SafeCStr(path_)); if (err == -1) { std::ostringstream oss; oss << "Unable to delete directory " << path_ << ". Errno = " << errno; RETURN_STATUS_UNEXPECTED(oss.str()); } } else { errno_t err = unlink(common::SafeCStr(path_)); if (err == -1) { std::ostringstream oss; oss << "Unable to delete file " << path_ << ". Errno = " << errno; RETURN_STATUS_UNEXPECTED(oss.str()); } } } return Status::OK(); } Status Path::CreateFile(int *file_descriptor) { return OpenFile(file_descriptor, true); } Status Path::OpenFile(int *file_descriptor, bool create) { int fd; if (file_descriptor == nullptr) { RETURN_STATUS_UNEXPECTED("null pointer"); } if (IsDirectory()) { std::ostringstream oss; oss << "Unable to create file " << path_ << " which is a directory."; RETURN_STATUS_UNEXPECTED(oss.str()); } // Convert to canonical form. if (strlen(common::SafeCStr(path_)) > PATH_MAX) { RETURN_STATUS_UNEXPECTED(strerror(errno)); } char canonical_path[PATH_MAX + 1] = {0x00}; #if defined(_WIN32) || defined(_WIN64) if (_fullpath(canonical_path, common::SafeCStr(path_), PATH_MAX) == nullptr) { #else if (realpath(common::SafeCStr(path_), canonical_path) == nullptr) { #endif if (errno == ENOENT && create) { // File doesn't exist and we are to create it. Let's break it down. auto file_part = Basename(); auto parent_part = ParentPath(); #if defined(_WIN32) || defined(_WIN64) if (_fullpath(canonical_path, common::SafeCStr(parent_part), PATH_MAX) == nullptr) { #else if (realpath(common::SafeCStr(parent_part), canonical_path) == nullptr) { #endif RETURN_STATUS_UNEXPECTED(strerror(errno)); } auto cur_inx = strlen(canonical_path); if ((cur_inx + file_part.length() + 1) > PATH_MAX) { RETURN_STATUS_UNEXPECTED(strerror(errno)); } canonical_path[cur_inx++] = separator_; if (strncpy_s(canonical_path + cur_inx, PATH_MAX - cur_inx, common::SafeCStr(file_part), file_part.length()) != EOK) { RETURN_STATUS_UNEXPECTED(strerror(errno)); } } else { RETURN_STATUS_UNEXPECTED(strerror(errno)); } } if (create) { fd = open(canonical_path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP); } else { fd = open(canonical_path, O_RDWR); } if (fd == -1) { RETURN_STATUS_UNEXPECTED(strerror(errno)); } *file_descriptor = fd; return Status::OK(); } Status Path::CloseFile(int fd) const { if (close(fd) < 0) { RETURN_STATUS_UNEXPECTED(strerror(errno)); } return Status::OK(); } Status Path::TruncateFile(int fd) const { int rc; rc = ftruncate(fd, 0); if (rc == 0) { return Status::OK(); } else { RETURN_STATUS_UNEXPECTED(strerror(errno)); } } std::string Path::Basename() { std::size_t found = path_.find_last_of(separator_); if (found != std::string::npos) { return path_.substr(found + 1); } else { return path_; } } std::shared_ptr Path::DirIterator::OpenDirectory(Path *f) { auto it = new (std::nothrow) DirIterator(f); if (it == nullptr) { return nullptr; } if (it->dp_) { return std::shared_ptr(it); } else { delete it; return nullptr; } } Path::DirIterator::~DirIterator() { if (dp_) { (void)closedir(dp_); } dp_ = nullptr; dir_ = nullptr; entry_ = nullptr; } Path::DirIterator::DirIterator(Path *f) : dir_(f), dp_(nullptr), entry_(nullptr) { MS_LOG(DEBUG) << "Open directory " << f->toString() << "."; dp_ = opendir(f->toString().c_str()); } bool Path::DirIterator::hasNext() { do { entry_ = readdir(dp_); if (entry_) { if (strcmp(entry_->d_name, ".") == 0 || strcmp(entry_->d_name, "..") == 0) { continue; } } break; } while (true); return (entry_ != nullptr); } Path Path::DirIterator::next() { return (*(this->dir_) / Path(entry_->d_name)); } std::ostream &operator<<(std::ostream &os, const Path &s) { os << s.path_; return os; } } // namespace dataset } // namespace mindspore