• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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