1 /*
2  * Copyright (c) 2023 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_operator.h"
17 #include <cerrno>
18 #include <climits>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <fstream>
22 #include <sstream>
23 #include <string>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include "directory_ex.h"
28 #include "dlp_permission.h"
29 #include "dlp_permission_log.h"
30 
31 namespace OHOS {
32 namespace Security {
33 namespace DlpPermission {
34 namespace {
35 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "FileOperator" };
36 }
FileOperator()37 FileOperator::FileOperator() {}
38 
~FileOperator()39 FileOperator::~FileOperator() {}
40 
InputFileByPathAndContent(const std::string & path,const std::string & content)41 int32_t FileOperator::InputFileByPathAndContent(const std::string& path, const std::string& content)
42 {
43     std::string str = path;
44     str.erase(str.rfind('/'));
45     if (!IsExistDir(str)) {
46         DLP_LOG_INFO(LABEL, "dir not exist, str = %{public}s errCode %{public}d.", str.c_str(), errno);
47         return DLP_RETENTION_COMMON_FILE_OPEN_FAILED;
48     }
49 
50     char realPath[PATH_MAX] = {0};
51     (void)realpath(str.c_str(), realPath);
52 
53     if (str.compare(realPath) != 0) {
54         DLP_LOG_INFO(LABEL, "path need to be canonical, str %{public}s realPath %{public}s.", str.c_str(), realPath);
55         return DLP_RETENTION_COMMON_FILE_OPEN_FAILED;
56     }
57 
58     FILE* fp = fopen(path.c_str(), "wb");
59     if (fp == nullptr) {
60         DLP_LOG_INFO(LABEL, "failed to open %{public}s, errno %{public}d.", path.c_str(), errno);
61         return DLP_RETENTION_COMMON_FILE_OPEN_FAILED;
62     }
63     size_t num = fwrite(content.c_str(), sizeof(char), content.length(), fp);
64     if (num != content.length()) {
65         DLP_LOG_INFO(LABEL, "failed to fwrite %{public}s, errno %{public}d.", path.c_str(), errno);
66         fclose(fp);
67         return DLP_RETENTION_COMMON_FILE_OPEN_FAILED;
68     }
69     if (fflush(fp) != 0) {
70         DLP_LOG_INFO(LABEL, "failed to fflush %{public}s, errno %{public}d.", path.c_str(), errno);
71         fclose(fp);
72         return DLP_RETENTION_COMMON_FILE_OPEN_FAILED;
73     }
74     if (fsync(fileno(fp)) != 0) {
75         DLP_LOG_INFO(LABEL, "failed to fsync %{public}s, errno %{public}d.", path.c_str(), errno);
76         fclose(fp);
77         return DLP_RETENTION_COMMON_FILE_OPEN_FAILED;
78     }
79     fclose(fp);
80     fp = nullptr;
81     // change mode
82     if (!ChangeModeFile(path, S_IRUSR | S_IWUSR)) {
83         DLP_LOG_INFO(LABEL, "failed to change mode for file %{public}s, errno %{public}d.", path.c_str(), errno);
84     }
85 
86     return DLP_OK;
87 }
88 
GetFileContentByPath(const std::string & path,std::string & content)89 int32_t FileOperator::GetFileContentByPath(const std::string& path, std::string& content)
90 {
91     char realPath[PATH_MAX] = {0};
92     if ((realpath(path.c_str(), realPath) == nullptr) && (errno != ENOENT)) {
93         DLP_LOG_ERROR(LABEL, "Realpath %{private}s failed, %{public}s.", path.c_str(), strerror(errno));
94         return DLP_RETENTION_FILE_FIND_FILE_ERROR;
95     }
96     if (!IsExistFile(realPath)) {
97         DLP_LOG_INFO(LABEL, "cannot find file, path = %{public}s", realPath);
98         return DLP_RETENTION_FILE_FIND_FILE_ERROR;
99     }
100     std::stringstream buffer;
101     std::ifstream i(realPath);
102     if (!i.is_open()) {
103         DLP_LOG_INFO(LABEL, "cannot open file %{public}s, errno %{public}d.", realPath, errno);
104         return DLP_RETENTION_COMMON_FILE_OPEN_FAILED;
105     }
106     buffer << i.rdbuf();
107     content = buffer.str();
108     i.close();
109     return DLP_OK;
110 }
111 
IsExistFile(const std::string & path)112 bool FileOperator::IsExistFile(const std::string& path)
113 {
114     if (path.empty()) {
115         DLP_LOG_ERROR(LABEL, "path is empty");
116         return false;
117     }
118 
119     struct stat buf = {};
120     if (stat(path.c_str(), &buf) != 0) {
121         DLP_LOG_ERROR(LABEL, "stat path: %{public}s, errno %{public}d.", path.c_str(), errno);
122         return false;
123     }
124 
125     return S_ISREG(buf.st_mode);
126 }
127 
IsExistDir(const std::string & path)128 bool FileOperator::IsExistDir(const std::string& path)
129 {
130     if (path.empty()) {
131         DLP_LOG_ERROR(LABEL, "path is empty");
132         return false;
133     }
134 
135     struct stat buf = {};
136     if (stat(path.c_str(), &buf) != 0) {
137         DLP_LOG_ERROR(LABEL, "stat path: %{public}s, errno %{public}d.", path.c_str(), errno);
138         return false;
139     }
140 
141     return S_ISDIR(buf.st_mode);
142 }
143 } // namespace DlpPermission
144 } // namespace Security
145 } // namespace OHOS
146