forked from huawei/mindspore2022
341 lines
8.3 KiB
C++
341 lines
8.3 KiB
C++
/**
|
|
* 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 <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <new>
|
|
#include <sstream>
|
|
#include <utility>
|
|
|
|
#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> Path::DirIterator::OpenDirectory(Path *f) {
|
|
auto it = new (std::nothrow) DirIterator(f);
|
|
|
|
if (it == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (it->dp_) {
|
|
return std::shared_ptr<DirIterator>(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
|