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 #include <unistd.h>
16 #include <sys/stat.h>
17 #include "hilog_wrapper.h"
18 #include "util/file_utils.h"
19 using namespace std;
20 namespace OHOS {
21 namespace HiviewDFX {
22 static const std::string UNKNOWN = "unknown";
23 constexpr int VALUES_MIN_LEN = 1;
FileUtils()24 FileUtils::FileUtils()
25 {
26 }
~FileUtils()27 FileUtils::~FileUtils()
28 {
29 }
30 
CreateFolder(const string & path)31 bool FileUtils::CreateFolder(const string &path)
32 {
33     if (!access(path.c_str(), F_OK) || path == "") {
34         return true;
35     }
36 
37     size_t pos = path.rfind("/");
38     if (pos == string::npos) {
39         return false;
40     }
41 
42     string upperPath = path.substr(0, pos);
43     if (CreateFolder(upperPath)) {
44         if (mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO)) {
45             if (errno != EEXIST) {
46                 return false;
47             }
48         }
49         return true;
50     }
51     return false;
52 }
53 
LoadStringFromProcCb(const std::string & path,bool oneLine,bool endWithoutN,const DataHandler & func)54 bool FileUtils::LoadStringFromProcCb(const std::string& path, bool oneLine, bool endWithoutN, const DataHandler& func)
55 {
56     char canonicalPath[PATH_MAX] = {0};
57     if (realpath(path.c_str(), canonicalPath) == nullptr) {
58         return false;
59     }
60     auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(canonicalPath, "re"), fclose};
61     if (fp == nullptr) {
62         return false;
63     }
64     char *lineBuf = nullptr;
65     ssize_t lineLen;
66     size_t lineAlloc = 0;
67     while ((lineLen = getline(&lineBuf, &lineAlloc, fp.get())) > 0) {
68         lineBuf[lineLen] = '\0';
69         if (endWithoutN && lineBuf[lineLen-1] == '\n') {
70             lineBuf[lineLen-1] = '\0';
71         }
72         const string content = lineBuf;
73         func(content);
74         if (oneLine) {
75             break;
76         }
77     }
78     if (lineBuf != nullptr) {
79         free(lineBuf);
80         lineBuf = nullptr;
81     }
82     return true;
83 }
84 
GetProcValue(const int32_t & pid,const string & path,const string & key)85 string FileUtils::GetProcValue(const int32_t &pid, const string& path, const string& key)
86 {
87     if (!DumpUtils::PathIsValid(path)) {
88         DUMPER_HILOGE(MODULE_COMMON, "path is valid");
89         return UNKNOWN;
90     }
91     auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "rd"), fclose};
92     if (fp == nullptr) {
93         DUMPER_HILOGE(MODULE_COMMON, "fopen failed");
94         return UNKNOWN;
95     }
96     char *lineBuf = nullptr;
97     ssize_t lineLen;
98     size_t lineAlloc = 0;
99     string content;
100     while ((lineLen = getline(&lineBuf, &lineAlloc, fp.get())) > 0) {
101         lineBuf[lineLen] = '\0';
102         if (lineBuf[lineLen - 1] == '\n') {
103             lineBuf[lineLen - 1] = '\0';
104         }
105         content = lineBuf;
106         if (content.find(key) != std::string::npos) {
107             break;
108         }
109         content = "";
110     }
111     if (lineBuf != nullptr) {
112         free(lineBuf);
113         lineBuf = nullptr;
114     }
115     if (!content.empty()) {
116         vector<string> values;
117         StringUtils::GetInstance().StringSplit(content, ":", values);
118         if (values.size() <= VALUES_MIN_LEN || values[VALUES_MIN_LEN].size() <= VALUES_MIN_LEN) {
119             DUMPER_HILOGE(MODULE_SERVICE, "values is invalid");
120             return UNKNOWN;
121         } else {
122             return values[VALUES_MIN_LEN].substr(VALUES_MIN_LEN);
123         }
124     } else {
125         DUMPER_HILOGE(MODULE_SERVICE, "content is empty");
126         return UNKNOWN;
127     }
128 }
129 } // namespace HiviewDFX
130 } // namespace OHOS