• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2020 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 "src/common/file_utils.h"
18 #include <sys/stat.h>
19 #ifdef _WIN32
20 #include <direct.h>
21 #include <io.h>
22 #else
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <dirent.h>
26 #endif
27 
28 #include <cstdlib>
29 #include "securec/include/securec.h"
30 
31 #ifdef _MSC_VER
32 #define PATH_MAX 1024
33 #define F_OK 0
34 #define R_OK 4
35 #endif
36 
37 namespace mindspore {
38 namespace lite {
39 namespace {
40 const int MAXIMUM_NUMBERS_OF_FOLDER = 1000;
41 
AccessFile(const std::string & file_path,int access_mode)42 inline int AccessFile(const std::string &file_path, int access_mode) {
43 #ifdef _WIN32
44   return _access(file_path.c_str(), access_mode);
45 #else
46   // android access interface always return true
47   struct stat st;
48   if (stat(file_path.c_str(), &st) == 0) {
49     mode_t perm = st.st_mode;
50     auto can_read = perm & S_IRUSR;
51     return (can_read && access(file_path.c_str(), access_mode) == 0) ? 0 : -1;
52   }
53   return -1;
54 #endif
55 }
56 
Mkdir(const std::string & file_path)57 inline int Mkdir(const std::string &file_path) {
58 #ifdef _WIN32
59   return _mkdir(file_path.c_str());
60 #else
61   return mkdir(file_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
62 #endif
63 }
64 }  // namespace
65 
IsCharEndWith(const char * src,const char * end)66 bool IsCharEndWith(const char *src, const char *end) {
67   if (strlen(src) > strlen(end)) {
68     const char *src_end = src + (strlen(src) - strlen(end));
69     if (strcmp(src_end, end) == 0) {
70       return true;
71     }
72   }
73   return false;
74 }
75 
76 // do not call RealPath function in OpenFile, because OpenFile may open a non-exist file
OpenFile(const std::string & file_path,std::ios_base::openmode open_mode)77 std::fstream *OpenFile(const std::string &file_path, std::ios_base::openmode open_mode) {
78   auto fs = new (std::nothrow) std::fstream();
79   if (fs == nullptr) {
80     MS_LOG(DEBUG) << "Create file stream failed";
81     return nullptr;
82   }
83   fs->open(file_path, open_mode);
84   if (!fs->good()) {
85     MS_LOG(DEBUG) << "File is not exist: " << file_path;
86     delete fs;
87     return nullptr;
88   }
89   if (!fs->is_open()) {
90     MS_LOG(DEBUG) << "Can not open file: " << file_path;
91     delete fs;
92     return nullptr;
93   }
94   return fs;
95 }
96 
97 // read file in [offset, offset + len)
ReadFileSegment(const std::string & file,int64_t offset,int64_t len)98 char *ReadFileSegment(const std::string &file, int64_t offset, int64_t len) {
99   if (len <= 0) {
100     return nullptr;
101   }
102   auto len_pos = static_cast<size_t>(len);
103   if (offset < 0) {
104     MS_LOG(DEBUG) << "offset is invalid, offset: " << offset;
105     return nullptr;
106   }
107   auto offset_pos = static_cast<size_t>(offset);
108   std::string real_path = lite::RealPath(file.c_str());
109   if (lite::AccessFile(real_path, R_OK) != 0) {
110     MS_LOG(DEBUG) << "cannot access file:" << real_path << ".please check file if exists and file mod";
111     return nullptr;
112   }
113   std::ifstream ifs(real_path, std::ifstream::in | std::ifstream::binary);
114   if (!ifs.good()) {
115     MS_LOG(DEBUG) << "file: " << real_path << " is not exist";
116     return nullptr;
117   }
118 
119   if (!ifs.is_open()) {
120     MS_LOG(DEBUG) << "file: " << real_path << " open failed";
121     return nullptr;
122   }
123 
124   ifs.seekg(0, std::ios::end);
125   auto goffset = ifs.tellg();
126   if (goffset < 0) {
127     MS_LOG(ERROR) << "read file range failed";
128     ifs.close();
129     return nullptr;
130   }
131   size_t total_size = static_cast<size_t>(goffset);
132   if (offset_pos + len_pos > total_size) {
133     MS_LOG(ERROR) << "file segment out of range";
134     ifs.close();
135     return nullptr;
136   }
137 
138   auto buf = reinterpret_cast<char *>(malloc(len));
139   if (buf == nullptr) {
140     MS_LOG(ERROR) << "malloc buf failed, file: " << real_path;
141     ifs.close();
142     return nullptr;
143   }
144 
145   ifs.seekg(offset, std::ios::beg);
146   ifs.read(buf, len);
147   ifs.close();
148 
149   return buf;
150 }
151 
ReadFile(const char * file,size_t * size,std::shared_ptr<Allocator> allocator)152 char *ReadFile(const char *file, size_t *size, std::shared_ptr<Allocator> allocator) {
153   if (file == nullptr) {
154     MS_LOG(ERROR) << "File path is nullptr";
155     return nullptr;
156   }
157   MS_ASSERT(size != nullptr);
158   std::string real_path = RealPath(file);
159   if (real_path.empty()) {
160     MS_LOG(DEBUG) << "File path not regular: " << file;
161     return nullptr;
162   }
163 #ifndef _MSC_VER
164   if (access(real_path.c_str(), F_OK) != 0) {
165     MS_LOG(ERROR) << "File is not exist: " << real_path;
166     return nullptr;
167   }
168   if (access(real_path.c_str(), R_OK) != 0) {
169     MS_LOG(ERROR) << "File " << real_path << " can't be read. Please change the file permission.";
170     return nullptr;
171   }
172 #endif
173   auto ifs = OpenFile(real_path, std::ifstream::in | std::ifstream::binary);
174   if (ifs == nullptr) {
175     MS_LOG(ERROR) << "Open file failed.";
176     return nullptr;
177   }
178 
179   ifs->seekg(0, std::ios::end);
180   auto goffset = ifs->tellg();
181   if (goffset < 0) {
182     MS_LOG(ERROR) << "read file range failed";
183     ifs->close();
184     delete ifs;
185     return nullptr;
186   }
187   *size = static_cast<size_t>(goffset);
188   char *model_buf = nullptr;
189   if (allocator != nullptr) {
190     MS_LOG(INFO) << "read ms model buf in numa 0.";
191     auto buf = allocator->Malloc(*size);
192     model_buf = static_cast<char *>(buf);
193   } else {
194     model_buf = new (std::nothrow) char[*size];
195   }
196   if (model_buf == nullptr) {
197     MS_LOG(ERROR) << "malloc buf failed, file: " << file;
198     ifs->close();
199     delete ifs;
200     return nullptr;
201   }
202 
203   ifs->seekg(0, std::ios::beg);
204   ifs->read(model_buf, *size);
205   ifs->close();
206   delete ifs;
207   return model_buf;
208 }
209 
RealPath(const char * path)210 std::string RealPath(const char *path) {
211   if (path == nullptr) {
212     MS_LOG(ERROR) << "path is nullptr";
213     return "";
214   }
215   if ((strlen(path)) >= PATH_MAX) {
216     MS_LOG(ERROR) << "path is too long";
217     return "";
218   }
219   auto resolved_path = std::make_unique<char[]>(PATH_MAX);
220   if (resolved_path == nullptr) {
221     MS_LOG(ERROR) << "new resolved_path failed";
222     return "";
223   }
224 #ifdef _WIN32
225   char *real_path = _fullpath(resolved_path.get(), path, PATH_MAX);
226 #else
227   char *real_path = realpath(path, resolved_path.get());
228 #endif
229   if (real_path == nullptr || strlen(real_path) == 0) {
230     MS_LOG(ERROR) << "file path not exists: " << path;
231     return "";
232   }
233   std::string res = resolved_path.get();
234   return res;
235 }
236 
CreateDir(const std::string & file_path)237 int CreateDir(const std::string &file_path) {
238   if (file_path.empty()) {
239     MS_LOG(ERROR) << "input file path is empty.";
240     return RET_ERROR;
241   } else if (file_path.size() >= PATH_MAX) {
242     MS_LOG(ERROR) << "input file path is too long";
243     return RET_ERROR;
244   }
245 
246   for (size_t i = 0; i < file_path.size(); i++) {
247     if (file_path.at(i) == '\\' || file_path.at(i) == '/') {
248       if (AccessFile(file_path.substr(0, i + 1), F_OK) != 0) {
249         int ret = Mkdir(file_path.substr(0, i + 1));
250         if (ret != RET_OK) {
251           MS_LOG(ERROR) << "mkdir failed. " << file_path.substr(0, i + 1);
252           return RET_ERROR;
253         }
254       }
255     }
256   }
257 
258   if (file_path.back() != '\\' && file_path.back() != '/') {
259     if (AccessFile(file_path, F_OK) != 0) {
260       int ret = Mkdir(file_path);
261       if (ret != RET_OK) {
262         MS_LOG(ERROR) << "mkdir failed. " << file_path;
263         return RET_ERROR;
264       }
265     }
266   }
267   return RET_OK;
268 }
269 
CreateOutputDir(std::string * file_path)270 int CreateOutputDir(std::string *file_path) {
271   if (CreateDir(*file_path) != RET_OK) {
272     MS_LOG(ERROR) << "Create file dir failed";
273     return RET_ERROR;
274   }
275 
276   int count = 0;
277   while (AccessFile((*file_path + "/" + std::to_string(count)), F_OK) == 0) {
278     MS_LOG(INFO) << "current file_path has existed, file_path cnt plus 1.";  // such as: /xxx/0 ==> /xxx/1
279     count++;
280     if (count >= MAXIMUM_NUMBERS_OF_FOLDER) {
281       MS_LOG(ERROR) << "the number of file folders exceeds the upper limit.";
282       return RET_ERROR;
283     }
284   }
285 #ifdef _WIN32
286   *file_path += "\\" + std::to_string(count);
287 #else
288   *file_path += "/" + std::to_string(count);
289 #endif
290   int ret = Mkdir(*file_path);
291   if (ret != RET_OK) {
292     MS_LOG(ERROR) << "mkdir failed. " << file_path->c_str();
293     return RET_ERROR;
294   }
295   return RET_OK;
296 }
297 
GetDirectory(const std::string & path)298 std::string GetDirectory(const std::string &path) {
299   auto pos = path.find_last_of('/');
300   if (pos == std::string::npos) {
301     pos = path.find_last_of('\\');
302   }
303   std::string dir;
304   if (pos != std::string::npos) {
305     dir = path.substr(0, pos + 1);
306   }
307   return dir;
308 }
309 
ParserPathAndModelName(const std::string & output_path,std::string * save_path,std::string * model_name)310 bool ParserPathAndModelName(const std::string &output_path, std::string *save_path, std::string *model_name) {
311   auto pos = output_path.find_last_of('/');
312   if (pos == std::string::npos) {
313     pos = output_path.find_last_of('\\');
314   }
315   std::string tmp_model_name;
316   if (pos == std::string::npos) {
317 #ifdef _WIN32
318     *save_path = ".\\";
319 #else
320     *save_path = "./";
321 #endif
322     tmp_model_name = output_path;
323   } else {
324     *save_path = output_path.substr(0, pos + 1);
325     tmp_model_name = output_path.substr(pos + 1);
326   }
327   *save_path = RealPath(save_path->c_str());
328   if (save_path->empty()) {
329     MS_LOG(DEBUG) << "File path not regular: " << save_path;
330     return false;
331   }
332   auto suffix_pos = tmp_model_name.find_last_of('.');
333   if (suffix_pos == std::string::npos) {
334     *model_name = tmp_model_name;
335   } else {
336     if (tmp_model_name.substr(suffix_pos + 1) == "ms") {
337       *model_name = tmp_model_name.substr(0, suffix_pos);
338     } else {
339       *model_name = tmp_model_name;
340     }
341   }
342   return true;
343 }
344 }  // namespace lite
345 }  // namespace mindspore
346