1 /*
2 * Copyright (c) 2025 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 "softbus_file_adapter.h"
16 #include "dtbcollabmgr_log.h"
17 #include "inner_transport.h"
18 #include "trans_type_enhanced.h"
19 #include "softbus_error_code.h"
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <cstdio>
23 #include <sys/stat.h>
24 #include <cstdlib>
25 #include <string>
26 #include <climits>
27
28 namespace OHOS {
29 namespace DistributedCollab {
30
31 IMPLEMENT_SINGLE_INSTANCE(SoftbusFileAdpater);
32
33 namespace {
34 static const std::string TAG = "SoftbusFileAdpaterInner";
35 static constexpr int32_t SUCCESS_CODE = 0;
36 static constexpr int32_t TEMP_DIR_PERMISSION = 0700;
37 }
38
OpenFile(const char * filename,int32_t flag,int32_t mode)39 static int OpenFile(const char* filename, int32_t flag, int32_t mode)
40 {
41 return SoftbusFileAdpater::GetInstance().Open(filename, flag, mode);
42 }
43
CloseFile(int32_t fd)44 static int CloseFile(int32_t fd)
45 {
46 return SoftbusFileAdpater::GetInstance().Close(fd);
47 }
48
RemoveFile(const char * filename)49 static int RemoveFile(const char* filename)
50 {
51 return SoftbusFileAdpater::GetInstance().Remove(filename);
52 }
53
SetFileSchema(int32_t socketId)54 int32_t SoftbusFileAdpater::SetFileSchema(int32_t socketId)
55 {
56 HILOGI("start to set file schema");
57 SocketFileSchema schema;
58 schema.OpenFd = OpenFile;
59 schema.CloseFd = CloseFile;
60 schema.RemoveFd = RemoveFile;
61
62 int32_t ret = RegisterFileSchema(socketId, &schema);
63 if (ret != SOFTBUS_OK) {
64 return -REGISTER_FILE_SCHEMA_FAILED;
65 }
66 return ERR_OK;
67 }
68
Open(const char * filename,int32_t flag,int32_t mode)69 int32_t SoftbusFileAdpater::Open(const char* filename, int32_t flag, int32_t mode)
70 {
71 HILOGI("dfile open file callback enter");
72 if (filename == nullptr) {
73 HILOGE("null file name");
74 return -INVALID_FILE_NAME;
75 }
76 // stack, no need delete
77 char realPath[PATH_MAX] = {0};
78 if (realpath(filename, realPath) == nullptr) {
79 if (errno != ENOENT) {
80 HILOGE("get real path failed, %{public}s, err=%{public}d", filename, errno);
81 return -INVALID_FILE_NAME;
82 }
83 // not exist dir, create
84 int32_t ret = CreateParentDirs(filename);
85 if (ret != ERR_OK) {
86 return ret;
87 }
88 return open(filename, flag, mode);
89 }
90 return open(realPath, flag, mode);
91 }
92
CreateParentDirs(const char * filename)93 int32_t SoftbusFileAdpater::CreateParentDirs(const char* filename)
94 {
95 HILOGI("create all parent dirs");
96 std::string path(filename);
97 size_t pos = 0;
98 // forbid contain relative
99 while ((pos = path.find("../", pos)) != std::string::npos) {
100 HILOGE("contain invalid relative path %{public}s", path.c_str());
101 return -CREATE_DIR_FAILED;
102 }
103 int32_t ret = ERR_OK;
104 pos = 0;
105 while ((pos = path.find_first_of('/', pos + 1)) != std::string::npos) {
106 std::string dir = path.substr(0, pos);
107 ret = CreateDir(dir);
108 if (ret != ERR_OK) {
109 return ret;
110 }
111 }
112 return ERR_OK;
113 }
114
CreateDir(const std::string & path)115 int32_t SoftbusFileAdpater::CreateDir(const std::string& path)
116 {
117 HILOGI("create dir");
118 char realPath[PATH_MAX] = {0};
119 if (realpath(path.c_str(), realPath) == nullptr) {
120 if (errno != ENOENT) {
121 HILOGE("get real path failed, %{public}s, err=%{public}d", path.c_str(), errno);
122 return -INVALID_FILE_NAME;
123 }
124 // valid path and not exist
125 int32_t ret = mkdir(path.c_str(), TEMP_DIR_PERMISSION);
126 if (ret != SUCCESS_CODE) {
127 HILOGE("create %{public}s failed, error=%{public}d", path.c_str(), ret);
128 return -CREATE_DIR_FAILED;
129 }
130 }
131 return ERR_OK;
132 }
133
Close(int32_t fd)134 int32_t SoftbusFileAdpater::Close(int32_t fd)
135 {
136 HILOGI("dfile close file callback enter");
137 if (fd < 0) {
138 HILOGE("Invalid file descriptor");
139 return -INVALID_PARAMETERS_ERR;
140 }
141 return close(fd);
142 }
143
Remove(const char * filename)144 int32_t SoftbusFileAdpater::Remove(const char* filename)
145 {
146 HILOGI("dfile remove file callback enter");
147 if (filename == nullptr) {
148 HILOGE("null file name");
149 return -INVALID_FILE_NAME;
150 }
151 char realPath[PATH_MAX] = {0};
152 if (realpath(filename, realPath) == nullptr) {
153 if (errno != ENOENT) {
154 HILOGE("get real path failed, %{public}s, err=%{public}d", filename, errno);
155 return -INVALID_FILE_NAME;
156 }
157 // file not exist
158 return ERR_OK;
159 }
160 return remove(filename);
161 }
162 }
163 }