1 /*
2 * Copyright (c) 2021-2022 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 "account_file_operator.h"
16 #include <cerrno>
17 #include <cstdio>
18 #include <fstream>
19 #include <nlohmann/json.hpp>
20 #include <sstream>
21 #include <string>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 #ifdef WITH_SELINUX
26 #include <policycoreutils.h>
27 #endif // WITH_SELINUX
28 #include "account_log_wrapper.h"
29 #include "directory_ex.h"
30 #include "hisysevent_adapter.h"
31 namespace OHOS {
32 namespace AccountSA {
AccountFileOperator()33 AccountFileOperator::AccountFileOperator()
34 {}
35
~AccountFileOperator()36 AccountFileOperator::~AccountFileOperator()
37 {}
38
CreateDir(const std::string & path)39 ErrCode AccountFileOperator::CreateDir(const std::string &path)
40 {
41 ACCOUNT_LOGD("enter");
42
43 if (!OHOS::ForceCreateDirectory(path)) {
44 ACCOUNT_LOGE("failed to create %{public}s, errno %{public}d.", path.c_str(), errno);
45 return ERR_OSACCOUNT_SERVICE_FILE_CREATE_DIR_ERROR;
46 }
47 mode_t mode = S_IRWXU;
48 bool createFlag = OHOS::ChangeModeDirectory(path, mode);
49 if (!createFlag) {
50 ACCOUNT_LOGE("failed to change mode for %{public}s, errno %{public}d.", path.c_str(), errno);
51 return ERR_OSACCOUNT_SERVICE_FILE_CHANGE_DIR_MODE_ERROR;
52 }
53
54 return ERR_OK;
55 }
56
DeleteDirOrFile(const std::string & path)57 ErrCode AccountFileOperator::DeleteDirOrFile(const std::string &path)
58 {
59 bool delFlag = false;
60 if (IsExistFile(path)) {
61 delFlag = OHOS::RemoveFile(path);
62 }
63 if (IsExistDir(path)) {
64 delFlag = OHOS::ForceRemoveDirectory(path);
65 }
66 if (!delFlag) {
67 ACCOUNT_LOGE("DeleteDirOrFile failed, path %{public}s errno %{public}d.", path.c_str(), errno);
68 return ERR_OSACCOUNT_SERVICE_FILE_DELE_ERROR;
69 }
70
71 return ERR_OK;
72 }
73
InputFileByPathAndContent(const std::string & path,const std::string & content)74 ErrCode AccountFileOperator::InputFileByPathAndContent(const std::string &path, const std::string &content)
75 {
76 std::string str = path;
77 str.erase(str.rfind('/'));
78 if (!IsExistDir(str)) {
79 ErrCode errCode = CreateDir(str);
80 if (errCode != ERR_OK) {
81 ACCOUNT_LOGE("failed to create dir, str = %{public}s errCode %{public}d.", str.c_str(), errCode);
82 return errCode;
83 }
84 }
85 FILE *fp = fopen(path.c_str(), "wb");
86 if (fp == nullptr) {
87 ACCOUNT_LOGE("failed to open %{public}s, errno %{public}d.", path.c_str(), errno);
88 return ERR_ACCOUNT_COMMON_FILE_OPEN_FAILED;
89 }
90 size_t num = fwrite(content.c_str(), sizeof(char), content.length(), fp);
91 if (num != content.length()) {
92 ACCOUNT_LOGE("failed to fwrite %{public}s, errno %{public}d.", path.c_str(), errno);
93 fclose(fp);
94 return ERR_ACCOUNT_COMMON_FILE_WRITE_FAILED;
95 }
96 if (fflush(fp) != 0) {
97 ACCOUNT_LOGE("failed to fflush %{public}s, errno %{public}d.", path.c_str(), errno);
98 fclose(fp);
99 return ERR_ACCOUNT_COMMON_FILE_WRITE_FAILED;
100 }
101 if (fsync(fileno(fp)) != 0) {
102 ACCOUNT_LOGE("failed to fsync %{public}s, errno %{public}d.", path.c_str(), errno);
103 fclose(fp);
104 return ERR_ACCOUNT_COMMON_FILE_WRITE_FAILED;
105 }
106 fclose(fp);
107 #ifdef WITH_SELINUX
108 Restorecon(path.c_str());
109 #endif // WITH_SELINUX
110 // change mode
111 if (!ChangeModeFile(path, S_IRUSR | S_IWUSR)) {
112 ACCOUNT_LOGW("failed to change mode for file %{public}s, errno %{public}d.", path.c_str(), errno);
113 }
114
115 return ERR_OK;
116 }
117
GetFileContentByPath(const std::string & path,std::string & content)118 ErrCode AccountFileOperator::GetFileContentByPath(const std::string &path, std::string &content)
119 {
120 if (!IsExistFile(path)) {
121 ACCOUNT_LOGE("cannot find file, path = %{public}s", path.c_str());
122 return ERR_OSACCOUNT_SERVICE_FILE_FIND_FILE_ERROR;
123 }
124 std::stringstream buffer;
125 std::ifstream i(path);
126 if (!i.is_open()) {
127 ACCOUNT_LOGE("cannot open file %{public}s, errno %{public}d.", path.c_str(), errno);
128 return ERR_ACCOUNT_COMMON_FILE_OPEN_FAILED;
129 }
130 buffer << i.rdbuf();
131 content = buffer.str();
132 i.close();
133 return ERR_OK;
134 }
135
IsExistFile(const std::string & path)136 bool AccountFileOperator::IsExistFile(const std::string &path)
137 {
138 if (path.empty()) {
139 return false;
140 }
141
142 struct stat buf = {};
143 if (stat(path.c_str(), &buf) != 0) {
144 return false;
145 }
146
147 return S_ISREG(buf.st_mode);
148 }
149
IsJsonFormat(const std::string & path)150 bool AccountFileOperator::IsJsonFormat(const std::string &path)
151 {
152 std::ifstream fin(path);
153 if (!fin) {
154 return false;
155 }
156
157 nlohmann::json jsonData = nlohmann::json::parse(fin, nullptr, false);
158 fin.close();
159 if (!jsonData.is_structured()) {
160 return false;
161 }
162 return true;
163 }
164
IsJsonFileReady(const std::string & path)165 bool AccountFileOperator::IsJsonFileReady(const std::string &path)
166 {
167 return IsExistFile(path) && IsJsonFormat(path);
168 }
169
IsExistDir(const std::string & path)170 bool AccountFileOperator::IsExistDir(const std::string &path)
171 {
172 if (path.empty()) {
173 return false;
174 }
175
176 struct stat buf = {};
177 if (stat(path.c_str(), &buf) != 0) {
178 return false;
179 }
180
181 return S_ISDIR(buf.st_mode);
182 }
183 } // namespace AccountSA
184 } // namespace OHOS
185