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 #ifdef _WIN32
19 #include <direct.h>
20 #include <io.h>
21 #else
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <dirent.h>
26 #endif
27
28 #include <cstdlib>
29 #include "securec/include/securec.h"
30
31 #if defined(_WIN32) && defined(SUPPORT_MSVC)
32 #define PATH_MAX 1024
33 #define F_OK 0
34 #endif
35
36 namespace mindspore {
37 namespace lite {
38 namespace {
39 const int MAXIMUM_NUMBERS_OF_FOLDER = 1000;
40
AccessFile(const std::string & file_path,int access_mode)41 inline int AccessFile(const std::string &file_path, int access_mode) {
42 #ifdef _WIN32
43 return _access(file_path.c_str(), access_mode);
44 #else
45 // android access interface always return true
46 struct stat st;
47 if (stat(file_path.c_str(), &st) == 0) {
48 mode_t perm = st.st_mode;
49 auto can_read = perm & S_IRUSR;
50 return (can_read && access(file_path.c_str(), access_mode) == 0) ? 0 : -1;
51 }
52 return -1;
53 #endif
54 }
55
Mkdir(const std::string & file_path)56 inline int Mkdir(const std::string &file_path) {
57 #ifdef _WIN32
58 return _mkdir(file_path.c_str());
59 #else
60 return mkdir(file_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
61 #endif
62 }
63 } // namespace
64
ReadFile(const char * file,size_t * size)65 char *ReadFile(const char *file, size_t *size) {
66 if (file == nullptr) {
67 MS_LOG(ERROR) << "file is nullptr";
68 return nullptr;
69 }
70 MS_ASSERT(size != nullptr);
71 std::string real_path = RealPath(file);
72 if (AccessFile(real_path, R_OK) != 0) {
73 MS_LOG(ERROR) << "cannot access file:" << real_path << ".please check file if exists and file mod";
74 return nullptr;
75 }
76 std::ifstream ifs(real_path, std::ifstream::in | std::ifstream::binary);
77 if (!ifs.good()) {
78 MS_LOG(ERROR) << "file: " << real_path << " is not exist";
79 return nullptr;
80 }
81
82 if (!ifs.is_open()) {
83 MS_LOG(ERROR) << "file: " << real_path << " open failed";
84 return nullptr;
85 }
86
87 ifs.seekg(0, std::ios::end);
88 *size = ifs.tellg();
89 auto buf = std::make_unique<char[]>(*size);
90 if (buf == nullptr) {
91 MS_LOG(ERROR) << "malloc buf failed, file: " << real_path;
92 ifs.close();
93 return nullptr;
94 }
95
96 ifs.seekg(0, std::ios::beg);
97 ifs.read(buf.get(), *size);
98 ifs.close();
99
100 return buf.release();
101 }
102
RealPath(const char * path)103 std::string RealPath(const char *path) {
104 if (path == nullptr) {
105 MS_LOG(ERROR) << "path is nullptr";
106 return "";
107 }
108 if ((strlen(path)) >= PATH_MAX) {
109 MS_LOG(ERROR) << "path is too long";
110 return "";
111 }
112 auto resolved_path = std::make_unique<char[]>(PATH_MAX);
113 if (resolved_path == nullptr) {
114 MS_LOG(ERROR) << "new resolved_path failed";
115 return "";
116 }
117 #ifdef _WIN32
118 char *real_path = _fullpath(resolved_path.get(), path, PATH_MAX);
119 #else
120 char *real_path = realpath(path, resolved_path.get());
121 #endif
122 if (real_path == nullptr || strlen(real_path) == 0) {
123 MS_LOG(ERROR) << "file path is not valid : " << path;
124 return "";
125 }
126 std::string res = resolved_path.get();
127 return res;
128 }
129
CreateOutputDir(std::string * file_path)130 int CreateOutputDir(std::string *file_path) {
131 if (file_path->empty()) {
132 MS_LOG(ERROR) << "input file path is empty.";
133 return RET_ERROR;
134 } else if (file_path->size() >= PATH_MAX) {
135 MS_LOG(ERROR) << "input file path is too long";
136 return RET_ERROR;
137 }
138
139 for (size_t i = 0; i < file_path->size(); i++) {
140 if ((*file_path).at(i) == '\\' || (*file_path).at(i) == '/') {
141 if (AccessFile(file_path->substr(0, i + 1), F_OK) != 0) {
142 int ret = Mkdir(file_path->substr(0, i + 1));
143 if (ret != RET_OK) {
144 MS_LOG(ERROR) << "mkdir failed. " << file_path->substr(0, i + 1);
145 return RET_ERROR;
146 }
147 }
148 }
149 }
150
151 if (file_path->back() != '\\' && file_path->back() != '/') {
152 if (AccessFile(*file_path, F_OK) != 0) {
153 int ret = Mkdir(*file_path);
154 if (ret != RET_OK) {
155 MS_LOG(ERROR) << "mkdir failed. " << file_path;
156 return RET_ERROR;
157 }
158 }
159 }
160
161 int count = 0;
162 while (AccessFile((*file_path + "/" + std::to_string(count)), F_OK) == 0) {
163 MS_LOG(INFO) << "current file_path has existed, file_path cnt plus 1."; // such as: /xxx/0 ==> /xxx/1
164 count++;
165 if (count >= MAXIMUM_NUMBERS_OF_FOLDER) {
166 MS_LOG(ERROR) << "the number of file folders exceeds the upper limit.";
167 return RET_ERROR;
168 }
169 }
170 #ifdef _WIN32
171 *file_path += "\\" + std::to_string(count);
172 #else
173 *file_path += "/" + std::to_string(count);
174 #endif
175 int ret = Mkdir(*file_path);
176 if (ret != RET_OK) {
177 MS_LOG(ERROR) << "mkdir failed. " << file_path->c_str();
178 return RET_ERROR;
179 }
180 return RET_OK;
181 }
182 } // namespace lite
183 } // namespace mindspore
184