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 #include "c_mock_common.h"
16 
17 #include <dlfcn.h>
18 #include <fuse_lowlevel.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include "securec.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 static const std::string LIBFUSE_LIB_PATH = "libfuse.z.so";
29 
30 typedef int (*AddArgsT)(struct fuse_args *args, const char *arg);
31 typedef void (*FreeArgsT)(struct fuse_args *args);
32 typedef struct fuse_session *(*NewSessionT)(struct fuse_args *args,
33     const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata);
34 typedef int (*MountSessionT)(struct fuse_session *se, const char *mountpoint);
35 typedef void (*DestorySessionT)(struct fuse_session *se);
36 typedef int (*LoopSessionT)(struct fuse_session *se);
37 typedef int (*FuseReplyErrT)(fuse_req_t req, int err);
38 typedef int (*FuseReplyEntryT)(fuse_req_t req, const struct fuse_entry_param *e);
39 typedef int (*FuseReplyAttrT)(fuse_req_t req, const struct stat *attr, double attr_timeout);
40 typedef int (*FuseReplyOpenT)(fuse_req_t req, const struct fuse_file_info *f);
41 typedef int (*FuseReplyBufT)(fuse_req_t req, const char *buf, size_t size);
42 typedef int (*FuseReplyWriteT)(fuse_req_t req, size_t count);
43 typedef size_t (*FuseAddDirentryT)(fuse_req_t req, char *buf, size_t bufsize,
44     const char *name, const struct stat *stbuf, off_t off);
45 
46 static void *g_libfuseHandle = nullptr;
GetLibfuseLibFunc(const char * funcName)47 static void *GetLibfuseLibFunc(const char *funcName)
48 {
49     if (g_libfuseHandle == nullptr) {
50         g_libfuseHandle = dlopen(LIBFUSE_LIB_PATH.c_str(), RTLD_LAZY);
51         if (g_libfuseHandle == nullptr) {
52             return nullptr;
53         }
54     }
55 
56     void *func = dlsym(g_libfuseHandle, funcName);
57     return func;
58 }
59 
fuse_opt_add_arg(struct fuse_args * args,const char * arg)60 int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
61 {
62     if (IsFuncNeedMock(__func__)) {
63         CommonMockFuncT rawFunc = GetMockFunc(__func__);
64         if (rawFunc != nullptr) {
65             return (*reinterpret_cast<AddArgsT>(rawFunc))(args, arg);
66         }
67         return -1;
68     }
69 
70     AddArgsT func = reinterpret_cast<AddArgsT>(GetLibfuseLibFunc(__func__));
71     if (func == nullptr) {
72         return -1;
73     }
74     return (*func)(args, arg);
75 }
76 
fuse_opt_free_args(struct fuse_args * args)77 void fuse_opt_free_args(struct fuse_args *args)
78 {
79     if (IsFuncNeedMock(__func__)) {
80         CommonMockFuncT rawFunc = GetMockFunc(__func__);
81         if (rawFunc != nullptr) {
82             (*reinterpret_cast<FreeArgsT>(rawFunc))(args);
83         }
84         return;
85     }
86 
87     FreeArgsT func = reinterpret_cast<FreeArgsT>(GetLibfuseLibFunc(__func__));
88     if (func == nullptr) {
89         return;
90     }
91     (*func)(args);
92 }
93 
fuse_session_new(struct fuse_args * args,const struct fuse_lowlevel_ops * op,size_t op_size,void * userdata)94 struct fuse_session *fuse_session_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op,
95     size_t op_size, void *userdata)
96 {
97     if (IsFuncNeedMock(__func__)) {
98         CommonMockFuncT rawFunc = GetMockFunc(__func__);
99         if (rawFunc != nullptr) {
100             return (*reinterpret_cast<NewSessionT>(rawFunc))(args, op, op_size, userdata);
101         }
102         return nullptr;
103     }
104     NewSessionT func = reinterpret_cast<NewSessionT>(GetLibfuseLibFunc(__func__));
105     if (func == nullptr) {
106         return nullptr;
107     }
108     return (*func)(args, op, op_size, userdata);
109 }
110 
fuse_session_mount(struct fuse_session * se,const char * mountpoint)111 int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
112 {
113     if (IsFuncNeedMock(__func__)) {
114         CommonMockFuncT rawFunc = GetMockFunc(__func__);
115         if (rawFunc != nullptr) {
116             return (*reinterpret_cast<MountSessionT>(rawFunc))(se, mountpoint);
117         }
118         return -1;
119     }
120 
121     MountSessionT func = reinterpret_cast<MountSessionT>(GetLibfuseLibFunc(__func__));
122     if (func == nullptr) {
123         return -1;
124     }
125     return (*func)(se, mountpoint);
126 }
127 
fuse_session_destroy(struct fuse_session * se)128 void fuse_session_destroy(struct fuse_session *se)
129 {
130     if (IsFuncNeedMock(__func__)) {
131         CommonMockFuncT rawFunc = GetMockFunc(__func__);
132         if (rawFunc != nullptr) {
133             (*reinterpret_cast<DestorySessionT>(rawFunc))(se);
134         }
135         return;
136     }
137 
138     DestorySessionT func = reinterpret_cast<DestorySessionT>(GetLibfuseLibFunc(__func__));
139     if (func == nullptr) {
140         return;
141     }
142     (*func)(se);
143 }
144 
fuse_session_loop(struct fuse_session * se)145 int fuse_session_loop(struct fuse_session *se)
146 {
147     if (IsFuncNeedMock(__func__)) {
148         CommonMockFuncT rawFunc = GetMockFunc(__func__);
149         if (rawFunc != nullptr) {
150             return (*reinterpret_cast<LoopSessionT>(rawFunc))(se);
151         }
152         return -1;
153     }
154 
155     LoopSessionT func = reinterpret_cast<LoopSessionT>(GetLibfuseLibFunc(__func__));
156     if (func == nullptr) {
157         return -1;
158     }
159     return (*func)(se);
160 }
161 
fuse_reply_err(fuse_req_t req,int err)162 int fuse_reply_err(fuse_req_t req, int err)
163 {
164     if (IsFuncNeedMock(__func__)) {
165         CommonMockFuncT rawFunc = GetMockFunc(__func__);
166         if (rawFunc != nullptr) {
167             return (*reinterpret_cast<FuseReplyErrT>(rawFunc))(req, err);
168         }
169         return -1;
170     }
171 
172     FuseReplyErrT func = reinterpret_cast<FuseReplyErrT>(GetLibfuseLibFunc(__func__));
173     if (func == nullptr) {
174         return -1;
175     }
176     return (*func)(req, err);
177 }
178 
fuse_reply_entry(fuse_req_t req,const struct fuse_entry_param * e)179 int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
180 {
181     if (IsFuncNeedMock(__func__)) {
182         CommonMockFuncT rawFunc = GetMockFunc(__func__);
183         if (rawFunc != nullptr) {
184             return (*reinterpret_cast<FuseReplyEntryT>(rawFunc))(req, e);
185         }
186         return -1;
187     }
188 
189     FuseReplyEntryT func = reinterpret_cast<FuseReplyEntryT>(GetLibfuseLibFunc(__func__));
190     if (func == nullptr) {
191         return -1;
192     }
193     return (*func)(req, e);
194 }
195 
fuse_reply_attr(fuse_req_t req,const struct stat * attr,double attr_timeout)196 int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
197 {
198     if (IsFuncNeedMock(__func__)) {
199         CommonMockFuncT rawFunc = GetMockFunc(__func__);
200         if (rawFunc != nullptr) {
201             return (*reinterpret_cast<FuseReplyAttrT>(rawFunc))(req, attr, attr_timeout);
202         }
203         return -1;
204     }
205 
206     FuseReplyAttrT func = reinterpret_cast<FuseReplyAttrT>(GetLibfuseLibFunc(__func__));
207     if (func == nullptr) {
208         return -1;
209     }
210     return (*func)(req, attr, attr_timeout);
211 }
212 
fuse_reply_open(fuse_req_t req,const struct fuse_file_info * f)213 int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f)
214 {
215     if (IsFuncNeedMock(__func__)) {
216         CommonMockFuncT rawFunc = GetMockFunc(__func__);
217         if (rawFunc != nullptr) {
218             return (*reinterpret_cast<FuseReplyOpenT>(rawFunc))(req, f);
219         }
220         return -1;
221     }
222 
223     FuseReplyOpenT func = reinterpret_cast<FuseReplyOpenT>(GetLibfuseLibFunc(__func__));
224     if (func == nullptr) {
225         return -1;
226     }
227     return (*func)(req, f);
228 }
229 
fuse_reply_buf(fuse_req_t req,const char * buf,size_t size)230 int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
231 {
232     if (IsFuncNeedMock(__func__)) {
233         CommonMockFuncT rawFunc = GetMockFunc(__func__);
234         if (rawFunc != nullptr) {
235             return (*reinterpret_cast<FuseReplyBufT>(rawFunc))(req, buf, size);
236         }
237         return -1;
238     }
239 
240     FuseReplyBufT func = reinterpret_cast<FuseReplyBufT>(GetLibfuseLibFunc(__func__));
241     if (func == nullptr) {
242         return -1;
243     }
244     return (*func)(req, buf, size);
245 }
246 
fuse_reply_write(fuse_req_t req,size_t count)247 int fuse_reply_write(fuse_req_t req, size_t count)
248 {
249     if (IsFuncNeedMock(__func__)) {
250         CommonMockFuncT rawFunc = GetMockFunc(__func__);
251         if (rawFunc != nullptr) {
252             return (*reinterpret_cast<FuseReplyWriteT>(rawFunc))(req, count);
253         }
254         return -1;
255     }
256 
257     FuseReplyWriteT func = reinterpret_cast<FuseReplyWriteT>(GetLibfuseLibFunc(__func__));
258     if (func == nullptr) {
259         return -1;
260     }
261     return (*func)(req, count);
262 }
263 
fuse_add_direntry(fuse_req_t req,char * buf,size_t bufsize,const char * name,const struct stat * stbuf,off_t off)264 size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
265     const char *name, const struct stat *stbuf, off_t off)
266 {
267     if (IsFuncNeedMock(__func__)) {
268         CommonMockFuncT rawFunc = GetMockFunc(__func__);
269         if (rawFunc != nullptr) {
270             return (*reinterpret_cast<FuseAddDirentryT>(rawFunc))(req, buf, bufsize, name, stbuf, off);
271         }
272         return 0;
273     }
274 
275     FuseAddDirentryT func = reinterpret_cast<FuseAddDirentryT>(GetLibfuseLibFunc(__func__));
276     if (func == nullptr) {
277         return 0;
278     }
279     return (*func)(req, buf, bufsize, name, stbuf, off);
280 }
281 
282 #ifdef __cplusplus
283 }
284 #endif
285