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 "napi/native_api.h"
17 #include <cerrno>
18 #include <cstdio>
19 #include <cstring>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <js_native_api_types.h>
23 #include <malloc.h>
24 #include <unistd.h>
25 
26 #define SUCCESS 1
27 #define STRLENGTH 64
28 #define DEFAULT_VALUE 0
29 #define FAIL (-1)
30 #define ONE 1
31 #define TWO 2
32 #define THREE 3
33 #define BUFF_SIZE (20)
34 #define FILEFLAG (0640)
35 #define PARAM_0 0
36 #define PARAM_1 1
37 #define PARAM_2 2
38 #define PARAM_0777 0777
39 #define PARAM_UNNORMAL (-1)
40 #define RETURN_0 0
41 #define FAILD (-1)
42 #define ERRON_0 0
43 #define SIZE_6 6
44 #define SIZE_8 8
45 #define SIZE_10 10
46 #define SIZE_100 100
47 #define SIZE_123 123
48 #define SIZE_256 256
49 #define SIZE_1024 1024
50 #define SIZE_4096 4096
51 #define SIZE_8192 8192
52 #define SIZE_32768 32768
53 
Tee(napi_env env, napi_callback_info info)54 static napi_value Tee(napi_env env, napi_callback_info info)
55 {
56     size_t argc = PARAM_1;
57     napi_value args[1] = {nullptr};
58     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
59     int param;
60     napi_get_value_int32(env, args[0], &param);
61 
62     int ret;
63     errno = ERRON_0;
64     if (param == PARAM_0) {
65         char buf[BUFF_SIZE];
66         char text[] = "Hello";
67         memset(buf, PARAM_0, sizeof(buf));
68         int pipefd1[PARAM_2];
69         pipe(pipefd1);
70         write(pipefd1[PARAM_1], text, strlen(text));
71         int pipefd2[PARAM_2];
72         pipe(pipefd2);
73         ret = tee(pipefd1[PARAM_0], pipefd2[PARAM_1], SIZE_32768, SPLICE_F_NONBLOCK);
74         close(pipefd1[PARAM_0]);
75         close(pipefd1[PARAM_1]);
76         close(pipefd2[PARAM_0]);
77         close(pipefd2[PARAM_1]);
78     } else {
79         ret = tee(PARAM_UNNORMAL, PARAM_UNNORMAL, SIZE_32768, SPLICE_F_NONBLOCK);
80     }
81     if (ret > PARAM_0) {
82         ret = PARAM_0;
83     }
84 
85     napi_value result = nullptr;
86     napi_create_int32(env, ret, &result);
87     return result;
88 }
89 
Vmsplice(napi_env env, napi_callback_info info)90 static napi_value Vmsplice(napi_env env, napi_callback_info info)
91 {
92     size_t argc = PARAM_1;
93     napi_value args[1] = {nullptr};
94     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
95     int param;
96     napi_get_value_int32(env, args[0], &param);
97 
98     int pipe_size = PARAM_2;
99     int iov_length = SIZE_6;
100     int pipe_fds[pipe_size];
101     pipe(pipe_fds);
102     struct iovec v[pipe_size];
103     char strHello[] = "hello ";
104     char str_world[] = "world\n";
105     v[0].iov_base = strHello;
106     v[0].iov_len = iov_length;
107     v[1].iov_base = str_world;
108     v[1].iov_len = iov_length;
109     size_t result;
110     errno = ERRON_0;
111     if (param == PARAM_0) {
112         result = vmsplice(pipe_fds[PARAM_1], v, sizeof(v) / sizeof(struct iovec), PARAM_0);
113     } else {
114         result = vmsplice(pipe_fds[PARAM_1], v, PARAM_0, PARAM_0);
115     }
116     close(pipe_fds[1]);
117     if (result > PARAM_0) {
118         result = PARAM_0;
119     } else {
120         result = PARAM_UNNORMAL;
121     }
122 
123     napi_value resultS = nullptr;
124     napi_create_int32(env, result, &resultS);
125     return resultS;
126 }
127 
Readahead(napi_env env, napi_callback_info info)128 static napi_value Readahead(napi_env env, napi_callback_info info)
129 {
130     char path[] = "/data/storage/el2/base/files/testreadahead.txt";
131     char text[] = "test readahead";
132     size_t argc = PARAM_1;
133     napi_value args[1] = {nullptr};
134     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
135     int param;
136     napi_get_value_int32(env, args[0], &param);
137 
138     int ret;
139     if (param == PARAM_0) {
140         int fd = open(path, O_CREAT | O_RDWR, PARAM_0777);
141         write(fd, text, strlen(text));
142         ret = readahead(fd, PARAM_0, strlen(text));
143         close(fd);
144         remove(path);
145     } else {
146         ret = readahead(PARAM_UNNORMAL, PARAM_0, SIZE_123);
147     }
148 
149     napi_value result = nullptr;
150     napi_create_int32(env, ret, &result);
151     return result;
152 }
153 
PosixFallocate(napi_env env, napi_callback_info info)154 static napi_value PosixFallocate(napi_env env, napi_callback_info info)
155 {
156     char path[] = "/data/storage/el2/base/files/test.txt";
157     size_t argc = PARAM_1;
158     napi_value args[1] = {nullptr};
159     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
160     int param;
161     napi_get_value_int32(env, args[0], &param);
162 
163     int ret;
164     if (param == PARAM_0) {
165         int fd = open(path, O_CREAT | O_RDWR, PARAM_0777);
166         ret = posix_fallocate(fd, SIZE_8, SIZE_1024);
167         close(fd);
168         remove(path);
169     } else {
170         ret = posix_fallocate(PARAM_UNNORMAL, SIZE_8, SIZE_1024);
171         if (ret != PARAM_0) {
172             ret = PARAM_UNNORMAL;
173         }
174     }
175 
176     napi_value result = nullptr;
177     napi_create_int32(env, ret, &result);
178     return result;
179 }
180 
NameToHandleAt(napi_env env, napi_callback_info info)181 static napi_value NameToHandleAt(napi_env env, napi_callback_info info)
182 {
183     char dir[] = "/data/storage/el2/base/files/";
184     size_t argc = PARAM_1;
185     napi_value args[1] = {nullptr};
186     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
187     int param;
188     napi_get_value_int32(env, args[0], &param);
189 
190     struct file_handle tempHandle;
191     tempHandle.handle_bytes = PARAM_0;
192     int mountId = 0;
193     int fd = 0;
194     DIR *dirfp = opendir(dir);
195     fd = dirfd(dirfp);
196 
197     name_to_handle_at(fd, dir, &tempHandle, &mountId, PARAM_0);
198     struct file_handle *handle = (struct file_handle *)malloc(tempHandle.handle_bytes);
199     handle->handle_bytes = tempHandle.handle_bytes;
200 
201     int ret = PARAM_0;
202     ret = name_to_handle_at(fd, dir, handle, &mountId, PARAM_0);
203 
204     closedir(dirfp);
205     free(handle);
206 
207     napi_value result = nullptr;
208     napi_create_int32(env, ret, &result);
209     return result;
210 }
211 
Open(napi_env env, napi_callback_info info)212 static napi_value Open(napi_env env, napi_callback_info info)
213 {
214     char path[] = "/data/storage/el2/base/files/testopen.txt";
215     size_t argc = PARAM_1;
216     napi_value args[1] = {nullptr};
217     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
218     int param;
219     napi_get_value_int32(env, args[0], &param);
220 
221     int fd;
222     if (param == PARAM_0) {
223         fd = open(path, O_CREAT | O_RDWR, PARAM_0777);
224     } else {
225         fd = open("/", O_CREAT | O_RDWR, PARAM_0777);
226     }
227     int ret;
228     if (fd != FAILD) {
229         close(fd);
230         remove(path);
231         ret = PARAM_0;
232     } else {
233         ret = PARAM_UNNORMAL;
234     }
235 
236     napi_value result = nullptr;
237     napi_create_int32(env, ret, &result);
238     return result;
239 }
240 
Open64(napi_env env, napi_callback_info info)241 static napi_value Open64(napi_env env, napi_callback_info info)
242 {
243     char path[] = "/data/storage/el2/base/files/testopen64.txt";
244     size_t argc = PARAM_1;
245     napi_value args[1] = {nullptr};
246     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
247     int param;
248     napi_get_value_int32(env, args[0], &param);
249 
250     int fd;
251     if (param == PARAM_0) {
252         fd = open64(path, O_CREAT | O_RDWR, PARAM_0777);
253     } else {
254         fd = open64("/", O_CREAT | O_RDWR, PARAM_0777);
255     }
256     int ret;
257     if (fd != FAILD) {
258         close(fd);
259         remove(path);
260         ret = PARAM_0;
261     } else {
262         ret = PARAM_UNNORMAL;
263     }
264 
265     napi_value result = nullptr;
266     napi_create_int32(env, ret, &result);
267     return result;
268 }
269 
OpenByHandleAt(napi_env env, napi_callback_info info)270 static napi_value OpenByHandleAt(napi_env env, napi_callback_info info)
271 {
272     char dir[] = "/data/storage/el2/base/files/";
273     size_t argc = PARAM_1;
274     napi_value args[1] = {nullptr};
275     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
276     int param;
277     napi_get_value_int32(env, args[0], &param);
278 
279     struct file_handle tempHandle;
280     tempHandle.handle_bytes = PARAM_0;
281     int mountId = 0;
282     int fd = 0;
283     DIR *dirfp = opendir(dir);
284     fd = dirfd(dirfp);
285 
286     name_to_handle_at(fd, dir, &tempHandle, &mountId, PARAM_0);
287     struct file_handle *handle = (struct file_handle *)malloc(tempHandle.handle_bytes);
288     handle->handle_bytes = tempHandle.handle_bytes;
289 
290     int ret = PARAM_0;
291     ret = name_to_handle_at(fd, dir, handle, &mountId, PARAM_0);
292     ret = open_by_handle_at(mountId, handle, PARAM_0);
293 
294     closedir(dirfp);
295     free(handle);
296 
297     napi_value result = nullptr;
298     napi_create_int32(env, ret, &result);
299     return result;
300 }
301 
PosixFadvise(napi_env env, napi_callback_info info)302 static napi_value PosixFadvise(napi_env env, napi_callback_info info)
303 {
304     char path[] = "/data/storage/el2/base/files/test.txt";
305     size_t argc = PARAM_1;
306     napi_value args[1] = {nullptr};
307     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
308     int param;
309     napi_get_value_int32(env, args[0], &param);
310 
311     int ret;
312     if (param == PARAM_0) {
313         int fd = open(path, O_CREAT | O_RDWR, PARAM_0777);
314         ret = posix_fadvise(fd, SIZE_8, SIZE_1024, POSIX_FADV_NORMAL);
315         close(fd);
316         remove(path);
317     } else {
318         ret = posix_fadvise(PARAM_UNNORMAL, SIZE_8, SIZE_1024, POSIX_FADV_NORMAL);
319     }
320     if (ret != PARAM_0) {
321         ret = PARAM_UNNORMAL;
322     }
323 
324     napi_value result = nullptr;
325     napi_create_int32(env, ret, &result);
326     return result;
327 }
328 
FalLocate(napi_env env, napi_callback_info info)329 static napi_value FalLocate(napi_env env, napi_callback_info info)
330 {
331     char path[] = "/data/storage/el2/base/files/testfallocate.txt";
332     char text[] = "test fallocate";
333     size_t argc = PARAM_1;
334     napi_value args[1] = {nullptr};
335     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
336     int param;
337     napi_get_value_int32(env, args[0], &param);
338 
339     int ret;
340     if (param == PARAM_0) {
341         int fd = open(path, O_CREAT | O_RDWR, PARAM_0777);
342         write(fd, text, sizeof(text));
343         ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, SIZE_4096, SIZE_4096 * THREE);
344         close(fd);
345         remove(path);
346     } else {
347         ret = fallocate(PARAM_UNNORMAL, PARAM_0, PARAM_0, PARAM_0);
348     }
349 
350     napi_value result = nullptr;
351     napi_create_int32(env, ret, &result);
352     return result;
353 }
354 
FalLocate64(napi_env env, napi_callback_info info)355 static napi_value FalLocate64(napi_env env, napi_callback_info info)
356 {
357     char path[] = "/data/storage/el2/base/files/test.txt";
358     size_t argc = PARAM_1;
359     napi_value args[1] = {nullptr};
360     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
361     int param;
362     napi_get_value_int32(env, args[0], &param);
363 
364     int ret;
365     if (param == PARAM_0) {
366         int fd = open(path, O_CREAT | O_RDWR, PARAM_0777);
367         ret = fallocate64(fd, FALLOC_FL_KEEP_SIZE, SIZE_4096, SIZE_4096 * THREE);
368         close(fd);
369         remove(path);
370     } else {
371         ret = fallocate64(PARAM_UNNORMAL, PARAM_0, PARAM_0, PARAM_0);
372     }
373 
374     napi_value result = nullptr;
375     napi_create_int32(env, ret, &result);
376     return result;
377 }
378 
FcnTl(napi_env env, napi_callback_info info)379 static napi_value FcnTl(napi_env env, napi_callback_info info)
380 {
381     char path[] = "/data/storage/el2/base/files/test.txt";
382     size_t argc = PARAM_1;
383     napi_value args[1] = {nullptr};
384     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
385     int param;
386     napi_get_value_int32(env, args[0], &param);
387 
388     int ret;
389     if (param == PARAM_0) {
390         int fd = open(path, O_CREAT, PARAM_0777);
391         ret = fcntl(fd, F_GETFL);
392         if (ret != FAILD) {
393             ret = PARAM_0;
394         } else {
395             ret = PARAM_UNNORMAL;
396         }
397         close(fd);
398         remove(path);
399     } else {
400         ret = fcntl(PARAM_UNNORMAL, F_GETFL);
401     }
402 
403     napi_value result = nullptr;
404     napi_create_int32(env, ret, &result);
405     return result;
406 }
407 
408 extern "C" size_t __fwrite_chk(const void *buf, size_t size, size_t count, FILE *stream, size_t buf_size);
FwriteChk(napi_env env, napi_callback_info info)409 static napi_value FwriteChk(napi_env env, napi_callback_info info)
410 {
411     const char *TEMP_FILE = "/data/storage/el2/base/files/test.txt";
412     const char *gTempFileContent = "This is a test";
413     int len = strlen(gTempFileContent);
414     int ret = FAILD;
415     size_t writeCount = PARAM_0;
416     FILE *fp = nullptr;
417     do {
418         int fileDescribe = open(TEMP_FILE, O_CREAT | O_WRONLY);
419         fp = fdopen(fileDescribe, "w");
420         if (fp == nullptr) {
421             break;
422         }
423         writeCount = __fwrite_chk(gTempFileContent, len, 1, fp, len);
424         ret = writeCount == PARAM_1;
425     } while (PARAM_0);
426     if (fp != nullptr) {
427         fclose(fp);
428     }
429     remove(TEMP_FILE);
430     napi_value result = nullptr;
431     napi_create_int32(env, ret, &result);
432     return result;
433 }
434 
435 EXTERN_C_START
Init(napi_env env, napi_value exports)436 static napi_value Init(napi_env env, napi_value exports)
437 {
438     napi_property_descriptor desc[] = {
439         {"nameToHandleAt", nullptr, NameToHandleAt, nullptr, nullptr, nullptr, napi_default, nullptr},
440         {"open", nullptr, Open, nullptr, nullptr, nullptr, napi_default, nullptr},
441         {"openByHandleAt", nullptr, OpenByHandleAt, nullptr, nullptr, nullptr, napi_default, nullptr},
442         {"open64", nullptr, Open64, nullptr, nullptr, nullptr, napi_default, nullptr},
443         {"tee", nullptr, Tee, nullptr, nullptr, nullptr, napi_default, nullptr},
444         {"vmsplice", nullptr, Vmsplice, nullptr, nullptr, nullptr, napi_default, nullptr},
445         {"readahead", nullptr, Readahead, nullptr, nullptr, nullptr, napi_default, nullptr},
446         {"posixfallocate", nullptr, PosixFallocate, nullptr, nullptr, nullptr, napi_default, nullptr},
447         {"posixfadvise", nullptr, PosixFadvise, nullptr, nullptr, nullptr, napi_default, nullptr},
448         {"fcntl", nullptr, FcnTl, nullptr, nullptr, nullptr, napi_default, nullptr},
449         {"fallocate64", nullptr, FalLocate64, nullptr, nullptr, nullptr, napi_default, nullptr},
450         {"fallocate", nullptr, FalLocate, nullptr, nullptr, nullptr, napi_default, nullptr},
451         {"fwritechk", nullptr, FwriteChk, nullptr, nullptr, nullptr, napi_default, nullptr},
452     };
453     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
454     return exports;
455 }
456 EXTERN_C_END
457 
458 static napi_module demoModule = {
459     .nm_version = 1,
460     .nm_flags = 0,
461     .nm_filename = "fcntl1ndk",
462     .nm_register_func = Init,
463     .nm_modname = "libfcntl1ndk",
464     .nm_priv = ((void *)0),
465     .reserved = {0},
466 };
467 
RegisterModule(void)468 extern "C" __attribute__((constructor)) void RegisterModule(void) { napi_module_register(&demoModule); }
469