1 /**
2 * Copyright 2021 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "distributed/persistent/storage/file_io_utils.h"
18 #include <fstream>
19
20 #ifdef _MSC_VER
21 #include <direct.h> // for _mkdir on windows
22 #endif
23 #include "mindspore/core/utils/file_utils.h"
24 #include "utils/convert_utils_base.h"
25 #include "utils/log_adapter.h"
26 #include "utils/os.h"
27
28 namespace mindspore {
29 namespace distributed {
30 namespace storage {
31 namespace {
CheckFStreamLength(const std::string & file_name,std::fstream & fs,size_t size)32 bool CheckFStreamLength(const std::string &file_name, std::fstream &fs, size_t size) {
33 size_t cur_pos = LongToSize(fs.tellp());
34 (void)fs.seekp(0, std::ios::end);
35 if (!fs.good() || fs.fail() || fs.bad()) {
36 MS_LOG(ERROR) << "Failed to seedp file pos, file name: " << file_name;
37 return false;
38 }
39 size_t end_pos = LongToSize(fs.tellp());
40 if (end_pos - cur_pos < size) {
41 MS_LOG(ERROR) << "The content length of file:" << file_name << " is less than expected size: " << size;
42 return false;
43 }
44 (void)fs.seekp(cur_pos);
45 if (!fs.good() || fs.fail() || fs.bad()) {
46 MS_LOG(ERROR) << "Failed to seedp file pos, file name: " << file_name;
47 return false;
48 }
49
50 return true;
51 }
52 } // namespace
53
Write(const std::string & file_name,const std::vector<std::pair<const void *,size_t>> & inputs)54 bool FileIOUtils::Write(const std::string &file_name, const std::vector<std::pair<const void *, size_t>> &inputs) {
55 if (file_name.empty()) {
56 MS_LOG(ERROR) << "The file name is empty";
57 return false;
58 }
59
60 std::fstream fs;
61 fs.open(file_name, std::ios::out | std::ios::binary);
62 if (!fs.is_open() || !fs.good()) {
63 MS_LOG(ERROR) << "Open file failed, file name: " << file_name;
64 return false;
65 }
66
67 for (const auto &item : inputs) {
68 const void *data = item.first;
69 MS_ERROR_IF_NULL(data);
70 size_t size = item.second;
71 (void)fs.write(reinterpret_cast<const char *>(data), SizeToLong(size));
72 if (!fs.good() || fs.fail() || fs.bad()) {
73 fs.close();
74 MS_LOG(ERROR) << "Insert data to fstream failed.";
75 return false;
76 }
77 (void)fs.flush();
78 if (!fs.good() || fs.fail() || fs.bad()) {
79 fs.close();
80 MS_LOG(ERROR) << "Insert data to fstream failed.";
81 return false;
82 }
83 }
84
85 fs.close();
86 return true;
87 }
88
Read(const std::string & file_name,const std::vector<std::pair<void *,size_t>> & outputs)89 bool FileIOUtils::Read(const std::string &file_name, const std::vector<std::pair<void *, size_t>> &outputs) {
90 if (file_name.empty()) {
91 MS_LOG(ERROR) << "The file name is empty";
92 return false;
93 }
94
95 std::fstream fs;
96 fs.open(file_name, std::ios::in | std::ios::binary);
97 if (!fs.is_open() || !fs.good()) {
98 MS_LOG(ERROR) << "Open file failed, file name: " << file_name;
99 return false;
100 }
101
102 for (const auto &item : outputs) {
103 void *data = item.first;
104 MS_ERROR_IF_NULL(data);
105 size_t size = item.second;
106
107 if (!CheckFStreamLength(file_name, fs, size)) {
108 return false;
109 }
110
111 (void)fs.read(reinterpret_cast<char *>(data), SizeToLong(size));
112 if (!fs.good() || fs.fail() || fs.bad()) {
113 fs.close();
114 MS_LOG(ERROR) << "Read data from fstream failed.";
115 return false;
116 }
117 }
118 fs.close();
119 return true;
120 }
121
IsFileOrDirExist(const std::string & path)122 bool FileIOUtils::IsFileOrDirExist(const std::string &path) {
123 if (path.empty()) {
124 MS_LOG(EXCEPTION) << "The path name is empty";
125 }
126
127 return access(path.c_str(), F_OK) == 0;
128 }
129
CreateFile(const std::string & file_path,mode_t mode)130 void FileIOUtils::CreateFile(const std::string &file_path, mode_t mode) {
131 (void)mode;
132 if (IsFileOrDirExist(file_path)) {
133 return;
134 }
135
136 std::ofstream output_file(file_path);
137 output_file.close();
138 #ifndef _MSC_VER
139 ChangeFileMode(file_path, mode);
140 #endif
141 }
142
CreateDir(const std::string & dir_path,mode_t mode)143 void FileIOUtils::CreateDir(const std::string &dir_path, mode_t mode) {
144 if (IsFileOrDirExist(dir_path)) {
145 return;
146 }
147
148 #if defined(_WIN32) || defined(_WIN64)
149 #ifndef _MSC_VER
150 int ret = mkdir(dir_path.c_str());
151 #else
152 int ret = _mkdir(dir_path.c_str());
153 #endif
154 #else
155 int ret = mkdir(dir_path.c_str(), mode);
156 if (ret == 0) {
157 ChangeFileMode(dir_path, mode);
158 }
159 #endif
160 if (ret != 0) {
161 MS_LOG(EXCEPTION) << "Failed to create directory " << dir_path << ". Errno = " << errno;
162 }
163 }
164
CreateDirRecursive(const std::string & dir_path,mode_t mode)165 void FileIOUtils::CreateDirRecursive(const std::string &dir_path, mode_t mode) {
166 if (dir_path.empty()) {
167 MS_LOG(EXCEPTION) << "The directory path need to be create is empty";
168 }
169 size_t dir_path_len = dir_path.length();
170 if (dir_path_len > PATH_MAX) {
171 MS_LOG(EXCEPTION) << "Directory path is too long to exceed max length limit: " << PATH_MAX
172 << ", the path: " << dir_path;
173 }
174
175 char tmp_dir_path[PATH_MAX] = {0};
176 for (size_t i = 0; i < dir_path_len; ++i) {
177 tmp_dir_path[i] = dir_path[i];
178 if (tmp_dir_path[i] == '/' || dir_path == tmp_dir_path) {
179 if (access(tmp_dir_path, F_OK) == 0) {
180 continue;
181 }
182
183 #if defined(_WIN32) || defined(_WIN64)
184 #ifndef _MSC_VER
185 int32_t ret = mkdir(tmp_dir_path);
186 #else
187 int32_t ret = _mkdir(tmp_dir_path);
188 #endif
189 if (ret != 0) {
190 MS_LOG(EXCEPTION) << "Failed to create directory recursion: " << dir_path << ". Errno = " << errno;
191 }
192 #else
193 int32_t ret = mkdir(tmp_dir_path, mode);
194 if (ret == 0) {
195 ChangeFileMode(tmp_dir_path, mode);
196 } else if (errno != EEXIST) {
197 MS_LOG(EXCEPTION) << "Failed to create directory recursion: " << dir_path << ". Errno = " << errno;
198 }
199 #endif
200 }
201 }
202 }
203 } // namespace storage
204 } // namespace distributed
205 } // namespace mindspore
206