• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "file_ex.h"
17 #include <fstream>
18 #include <iostream>
19 #include <algorithm>
20 #include <iterator>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <cstdio>
25 #include <securec.h>
26 #include <cstring>
27 #include "directory_ex.h"
28 #include "utils_log.h"
29 
30 using namespace std;
31 
32 const int MAX_FILE_LENGTH = 32 * 1024 * 1024;
33 
34 namespace OHOS {
35 
LoadStringFromFile(const string & filePath,string & content)36 bool LoadStringFromFile(const string& filePath, string& content)
37 {
38     ifstream file(filePath.c_str());
39     if (!file.is_open()) {
40         UTILS_LOGE("open file failed! filePath:%{public}s", filePath.c_str());
41         return false;
42     }
43 
44     file.seekg(0, ios::end);
45     const long fileLength = file.tellg();
46     if (fileLength > MAX_FILE_LENGTH) {
47         UTILS_LOGE("invalid file length(%{public}ld)!", fileLength);
48         return false;
49     }
50 
51     content.clear();
52     file.seekg(0, ios::beg);
53     copy(istreambuf_iterator<char>(file), istreambuf_iterator<char>(), back_inserter(content));
54     return true;
55 }
56 
GetFileNameByFd(const int fd)57 string GetFileNameByFd(const int fd)
58 {
59     if (fd <= 0) {
60         return string();
61     }
62 
63     string fdPath = "/proc/self/fd/" + std::to_string(fd);
64     char fileName[PATH_MAX + 1] = {0};
65 
66     int ret = readlink(fdPath.c_str(), fileName, PATH_MAX);
67     if (ret < 0 || ret > PATH_MAX) {
68         UTILS_LOGE("Get fileName failed, ret is: %{public}d!", ret);
69         return string();
70     }
71     fileName[ret] = '\0';
72     return string(fileName);
73 }
74 
LoadStringFromFdToFile(int fd,string & content)75 bool LoadStringFromFdToFile(int fd, string& content)
76 {
77     string fileName = GetFileNameByFd(fd);
78     if (fileName.empty()) {
79         UTILS_LOGE("LoadStringFromFd get file name by fd failed!");
80         return false;
81     }
82 
83     if (!LoadStringFromFile(fileName, content)) {
84         UTILS_LOGE("LoadStringFromFd get string from file failed!");
85         return false;
86     }
87     return true;
88 }
89 
LoadStringFromFd(int fd,string & content)90 bool LoadStringFromFd(int fd, string& content)
91 {
92     if (fd <= 0) {
93         UTILS_LOGE("invalid fd:%{public}d", fd);
94         return false;
95     }
96 
97     const long fileLength = lseek(fd, 0, SEEK_END);
98     if (fileLength > MAX_FILE_LENGTH) {
99         UTILS_LOGE("invalid file length(%{public}ld)!", fileLength);
100         return false;
101     }
102 
103     // lseek is not support the linux file node
104     if (fileLength < 0) {
105         return LoadStringFromFdToFile(fd, content);
106     }
107 
108     if (fileLength == 0) {
109         return true;
110     }
111 
112     content.resize(fileLength);
113     int loc = lseek(fd, 0, SEEK_SET);
114     if (loc == -1) {
115         UTILS_LOGE("lseek file to begin failed!");
116         return false;
117     }
118 
119     const long len = read(fd, content.data(), fileLength);
120     if (len != fileLength) {
121         UTILS_LOGE("the length read from file is not equal to fileLength!len:%{public}ld,fileLen:%{public}ld",
122             len, fileLength);
123         return false;
124     }
125 
126     return true;
127 }
128 
SaveStringToFile(const std::string & filePath,const std::string & content,bool truncated)129 bool SaveStringToFile(const std::string& filePath, const std::string& content, bool truncated /*= true*/)
130 {
131     if (content.empty()) {
132         UTILS_LOGI("content is empty, no need to save!");
133         return true;
134     }
135 
136     ofstream file;
137     if (truncated) {
138         file.open(filePath.c_str(), ios::out | ios::trunc);
139     } else {
140         file.open(filePath.c_str(), ios::out | ios::app);
141     }
142 
143     if (!file.is_open()) {
144         UTILS_LOGE("open file failed! filePath:%{private}s", filePath.c_str());
145         return false;
146     }
147 
148     file.write(content.c_str(), content.length());
149     if (file.fail()) {
150         UTILS_LOGE("write content to file failed!file:%{private}s, content:%{private}s",
151             filePath.c_str(), content.c_str());
152         return false;
153     }
154     return true;
155 }
156 
SaveStringToFd(int fd,const std::string & content)157 bool SaveStringToFd(int fd, const std::string& content)
158 {
159     if (fd <= 0) {
160         UTILS_LOGE("invalid fd:%{public}d", fd);
161         return false;
162     }
163 
164     if (content.empty()) {
165         UTILS_LOGI("content is empty, no need to save!");
166         return true;
167     }
168 
169     const long len = write(fd, content.c_str(), content.length());
170     if (len < 0) {
171         UTILS_LOGE("write file failed!errno:%{public}d, err:%{public}s", errno, strerror(errno));
172         return false;
173     }
174 
175     if ((unsigned long)len != content.length()) {
176         UTILS_LOGE("the length write to file is not equal to fileLength!len:%{public}ld, fileLen:%{public}zu",
177             len, content.length());
178         return false;
179     }
180 
181     return true;
182 }
183 
LoadBufferFromNodeFile(const string & filePath,vector<char> & content)184 bool LoadBufferFromNodeFile(const string& filePath, vector<char>& content)
185 {
186     string realPath;
187     if (!PathToRealPath(filePath, realPath)) {
188         UTILS_LOGE("filePath to realPath failed! filePath:%{private}s", filePath.c_str());
189         return false;
190     }
191 
192     FILE *fp = fopen(realPath.c_str(), "r");
193     if (fp == nullptr) {
194         UTILS_LOGE("open file failed! filePath:%{private}s", realPath.c_str());
195         return false;
196     }
197 
198     char ch = fgetc(fp);
199     int byteCount = 1;
200     while (!feof(fp)) {
201         if (byteCount > MAX_FILE_LENGTH) {
202             UTILS_LOGE("LoadBufferFromNodeFile invalid file length(%{public}d)!", byteCount);
203             fclose(fp);
204             fp = nullptr;
205             content.clear();
206             return false;
207         }
208 
209         content.push_back(ch);
210         ch = fgetc(fp);
211         byteCount++;
212     }
213 
214     fclose(fp);
215     fp = nullptr;
216     return true;
217 }
218 
219 /* load file to buffer. If the buffer is not empty,then overwrite */
LoadBufferFromFile(const string & filePath,vector<char> & content)220 bool LoadBufferFromFile(const string& filePath, vector<char>& content)
221 {
222     ifstream file;
223     file.open(filePath.c_str(), ios::in | ios::binary);
224     if (!file.is_open()) {
225         UTILS_LOGE("open file failed! filePath:%{private}s", filePath.c_str());
226         return false;
227     }
228 
229     file.seekg(0, std::ios::end);
230     const long fileLength = file.tellg();
231     if (fileLength > MAX_FILE_LENGTH) {
232         UTILS_LOGE("invalid file length(%{public}ld)!", fileLength);
233         return false;
234     }
235 
236     // lseek is not support the linux file node
237     if (fileLength < 0) {
238         return LoadBufferFromNodeFile(filePath, content);
239     }
240 
241     if (fileLength == 0) {
242         content.clear();
243         return true;
244     }
245 
246     file.seekg(0, std::ios::beg);
247     if (file.fail()) {
248         UTILS_LOGE("seekg file to begin failed!filePath:%{private}s", filePath.c_str());
249         return false;
250     }
251 
252     content.resize(fileLength);
253     file.read(&content[0], fileLength);
254     return true;
255 }
256 
SaveBufferToFile(const string & filePath,const vector<char> & content,bool truncated)257 bool SaveBufferToFile(const string& filePath, const vector<char>& content, bool truncated /*= true*/)
258 {
259     if (content.empty()) {
260         UTILS_LOGI("content is empty, no need to save!");
261         return true;
262     }
263 
264     // if the file is not exist,create it first!
265     uint32_t mode = truncated ? (ios::out | ios::binary | ios::trunc) : (ios::out | ios::binary | ios::app);
266     ofstream file;
267     file.open(filePath.c_str(), mode);
268     if (!file.is_open()) {
269         UTILS_LOGE("open file failed! filePath:%{private}s, mode:%{private}d", filePath.c_str(), mode);
270         return false;
271     }
272 
273     file.write(&content[0], content.size());
274     return true;
275 }
276 
FileExists(const string & fileName)277 bool FileExists(const string& fileName)
278 {
279     return (access(fileName.c_str(), F_OK) == 0);
280 }
281 
StringExistsInFile(const string & fileName,const string & subStr,bool caseSensitive)282 bool StringExistsInFile(const string& fileName, const string& subStr, bool caseSensitive /*= true*/)
283 {
284     if (subStr.empty()) {
285         UTILS_LOGE("String is empty");
286         return false;
287     }
288 
289     string str;
290     if (!LoadStringFromFile(fileName, str)) {
291         UTILS_LOGE("File load fail, filePath:%{private}s", fileName.c_str());
292         return false;
293     }
294 
295     if (caseSensitive) {
296         return (str.find(subStr) != string::npos);
297     }
298 
299     string strlower(str);
300     string sublower(subStr);
301     transform(str.begin(), str.end(), strlower.begin(), ::tolower);
302     transform(subStr.begin(), subStr.end(), sublower.begin(), ::tolower);
303     return (strlower.find(sublower) != string::npos);
304 }
305 
CountStrInStr(const string & str,const string & subStr)306 int CountStrInStr(const string& str, const string& subStr)
307 {
308     if (subStr.empty()) {
309         UTILS_LOGE("subStr is empty");
310         return 0;
311     }
312 
313     size_t position = 0;
314     int count = 0;
315     size_t length = subStr.length();
316     while ((position = str.find(subStr, position)) != string::npos) {
317         position += length;
318         count++;
319     }
320 
321     return count;
322 }
323 
CountStrInFile(const string & fileName,const string & subStr,bool caseSensitive)324 int CountStrInFile(const string& fileName, const string& subStr, bool caseSensitive /*= true*/)
325 {
326     if (subStr.empty()) {
327         UTILS_LOGE("String is empty");
328         return -1;
329     }
330 
331     string str;
332     if (!LoadStringFromFile(fileName, str)) {
333         UTILS_LOGE("File load fail, filePath:%{private}s", fileName.c_str());
334         return -1;
335     }
336 
337     // If case-insensitive, strings are converted to lowercase.
338     if (caseSensitive) {
339         return CountStrInStr(str, subStr);
340     }
341 
342     string strlower(str);
343     string sublower(subStr);
344     transform(str.begin(), str.end(), strlower.begin(), ::tolower);
345     transform(subStr.begin(), subStr.end(), sublower.begin(), ::tolower);
346     return CountStrInStr(strlower, sublower);
347 }
348 }
349