1 /*
2  * Copyright (c) 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 
16 #include "napi/native_api.h"
17 #include <cstdio>
18 #include <cstring>
19 #include <fcntl.h>
20 #include <js_native_api.h>
21 #include <js_native_api_types.h>
22 #include <node_api.h>
23 #include <sys/stat.h>
24 #include <sys/uio.h>
25 #include <unistd.h>
26 
27 #define PARAM_0 0
28 #define PARAM_1 1
29 #define PARAM_2 2
30 #define PARAM_256 256
31 #define PARAM_0777 0777
32 #define PARAM_UNNORMAL (-1)
33 #define RETURN_0 0
34 #define FAILD (-1)
35 #define ERRON_0 0
36 #define SIZE_10 10
37 #define SIZE_100 100
38 #define SIZE_4096 4096
39 #define SIZE_8192 8192
40 #define TEST_AT_FDCWD (-100)
41 #define TEST_ERROR_AT_FDCWD 100
42 
43 #define NO_ERR 0
44 #define SUCCESS 1
45 #define FAIL (-1)
46 #define TEN 10
47 #define TEST_MODE 0666
Readv(napi_env env, napi_callback_info info)48 static napi_value Readv(napi_env env, napi_callback_info info)
49 {
50     size_t argc = 1;
51     napi_value args[1] = {nullptr};
52     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
53 
54     int param;
55     napi_get_value_int32(env, args[0], &param);
56 
57     int ret;
58     if (param == PARAM_UNNORMAL) {
59         ret = readv(PARAM_UNNORMAL, nullptr, PARAM_UNNORMAL);
60     } else {
61         int fd = open("/data/storage/el2/base/files/testReadv.txt", O_RDWR | O_CREAT, PARAM_0777);
62 
63         char buf1[] = "testreadv1";
64         char buf2[] = "testreadv2";
65         struct iovec ios[] = {{buf1, strlen(buf1)}, {buf2, strlen(buf2)}};
66         ssize_t value = writev(fd, ios, sizeof(ios) / sizeof(struct iovec));
67         lseek(fd, PARAM_0, SEEK_SET);
68         memset(buf1, PARAM_0, sizeof(buf1));
69         memset(buf2, PARAM_0, sizeof(buf2));
70         value = readv(fd, ios, sizeof(ios) / sizeof(struct iovec));
71         if (value == strlen(buf1) + strlen(buf2)) {
72             ret = RETURN_0;
73         } else {
74             ret = FAIL;
75         }
76         close(fd);
77     }
78 
79     napi_value result = nullptr;
80     napi_create_int32(env, ret, &result);
81     return result;
82 }
83 
Writev(napi_env env, napi_callback_info info)84 static napi_value Writev(napi_env env, napi_callback_info info)
85 {
86     size_t argc = 1;
87     napi_value args[1] = {nullptr};
88     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
89     int param;
90     napi_get_value_int32(env, args[0], &param);
91     ssize_t resultValue = FAILD;
92     if (param == PARAM_UNNORMAL) {
93         resultValue = writev(PARAM_UNNORMAL, nullptr, PARAM_UNNORMAL);
94     } else {
95         char str0[] = "test ";
96         char str1[] = "writev\n";
97         struct iovec iov[PARAM_2];
98 
99         iov[PARAM_0].iov_base = str0;
100         iov[PARAM_0].iov_len = strlen(str0) + PARAM_1;
101         iov[PARAM_1].iov_base = str1;
102         iov[PARAM_1].iov_len = strlen(str1) + PARAM_1;
103 
104         ssize_t result = writev(PARAM_1, iov, PARAM_2);
105         if (result == (iov[PARAM_0].iov_len + iov[PARAM_1].iov_len)) {
106             resultValue = RETURN_0;
107         }
108     }
109 
110     napi_value result = nullptr;
111     napi_create_int32(env, resultValue, &result);
112 
113     return result;
114 }
115 
PReadV(napi_env env, napi_callback_info info)116 static napi_value PReadV(napi_env env, napi_callback_info info)
117 {
118     off_t offset = PARAM_0;
119     int ret;
120     int fd = open("/data/storage/el2/base/files/testReadv.txt", O_RDWR | O_CREAT, PARAM_0777);
121     char buf1[] = "testreadv1";
122     char buf2[] = "testreadv2";
123     struct iovec ios[] = {{buf1, strlen(buf1)}, {buf2, strlen(buf2)}};
124     ssize_t value = writev(fd, ios, sizeof(ios) / sizeof(struct iovec));
125     lseek(fd, PARAM_0, SEEK_SET);
126     memset(buf1, PARAM_0, sizeof(buf1));
127     memset(buf2, PARAM_0, sizeof(buf2));
128     value = preadv(fd, ios, sizeof(ios) / sizeof(struct iovec), offset);
129     if (value == strlen(buf1) + strlen(buf2)) {
130         ret = RETURN_0;
131     } else {
132         ret = FAIL;
133     }
134     close(fd);
135     napi_value result = nullptr;
136     napi_create_int32(env, ret, &result);
137     return result;
138 }
139 
PReadV64(napi_env env, napi_callback_info info)140 static napi_value PReadV64(napi_env env, napi_callback_info info)
141 {
142     off_t offset = PARAM_0;
143     int ret;
144     int fd = open("/data/storage/el2/base/files/testReadv.txt", O_RDWR | O_CREAT, PARAM_0777);
145     char buf1[] = "testreadv1";
146     char buf2[] = "testreadv2";
147     struct iovec ios[] = {{buf1, strlen(buf1)}, {buf2, strlen(buf2)}};
148     ssize_t value = writev(fd, ios, sizeof(ios) / sizeof(struct iovec));
149     lseek(fd, PARAM_0, SEEK_SET);
150     memset(buf1, PARAM_0, sizeof(buf1));
151     memset(buf2, PARAM_0, sizeof(buf2));
152     value = preadv64(fd, ios, sizeof(ios) / sizeof(struct iovec), offset);
153     if (value == strlen(buf1) + strlen(buf2)) {
154         ret = RETURN_0;
155     } else {
156         ret = FAIL;
157     }
158     close(fd);
159     napi_value result = nullptr;
160     napi_create_int32(env, ret, &result);
161     return result;
162 }
163 
PWriteV(napi_env env, napi_callback_info info)164 static napi_value PWriteV(napi_env env, napi_callback_info info)
165 {
166     char tmpfile[] = "/data/storage/el2/base/files/memfd_cr02100.txt";
167     char buf1[] = "preadv";
168     char buf2[] = "and pwritev";
169     struct iovec iov[2];
170 
171     iov[0].iov_base = buf1;
172     iov[0].iov_len = sizeof(buf1) / sizeof(char);
173     iov[1].iov_base = buf2;
174     iov[1].iov_len = sizeof(buf2) / sizeof(char);
175 
176     int fd = open(tmpfile, O_RDWR | O_CREAT, TEST_MODE);
177     int count = sizeof(iov) / sizeof(struct iovec);
178     int ret = pwritev(fd, iov, count, PARAM_0);
179     if (ret != PARAM_UNNORMAL) {
180         ret = SUCCESS;
181     } else {
182         ret = FAIL;
183     }
184     close(fd);
185     ret = access(tmpfile, F_OK);
186     if (ret == PARAM_0) {
187         ret = remove(tmpfile);
188     }
189     napi_value result = nullptr;
190     napi_create_int32(env, ret, &result);
191     return result;
192 }
PWriteV64(napi_env env, napi_callback_info info)193 static napi_value PWriteV64(napi_env env, napi_callback_info info)
194 {
195     char tmpfile[] = "/data/storage/el2/base/files/memfd_cr02100.txt";
196     char buf1[] = "preadv";
197     char buf2[] = "and pwritev";
198     struct iovec iov[2];
199 
200     iov[0].iov_base = buf1;
201     iov[0].iov_len = sizeof(buf1) / sizeof(char);
202     iov[1].iov_base = buf2;
203     iov[1].iov_len = sizeof(buf2) / sizeof(char);
204 
205     int fd = open(tmpfile, O_RDWR | O_CREAT, TEST_MODE);
206     int count = sizeof(iov) / sizeof(struct iovec);
207     int ret = pwritev64(fd, iov, count, PARAM_0);
208     if (ret != PARAM_UNNORMAL) {
209         ret = SUCCESS;
210     } else {
211         ret = FAIL;
212     }
213     close(fd);
214     ret = access(tmpfile, F_OK);
215     if (ret == PARAM_0) {
216         ret = remove(tmpfile);
217     }
218     napi_value result = nullptr;
219     napi_create_int32(env, ret, &result);
220     return result;
221 }
ProcessVmReadV(napi_env env, napi_callback_info info)222 static napi_value ProcessVmReadV(napi_env env, napi_callback_info info)
223 {
224     int ret = PARAM_UNNORMAL;
225     int bufferSize = PARAM_256;
226     char src[256] = "This is process_vm_readv_0100.";
227     char dst[256] = "";
228     struct iovec remote, local;
229     remote.iov_base = src;
230     remote.iov_len = bufferSize;
231 
232     local.iov_base = dst;
233     local.iov_len = bufferSize;
234 
235     int rev = process_vm_readv(getpid(), &local, PARAM_1, &remote, PARAM_1, PARAM_0);
236     if (rev == sizeof(src)) {
237         ret = RETURN_0;
238     } else {
239         ret = FAIL;
240     }
241     napi_value result = nullptr;
242     napi_create_int32(env, ret, &result);
243     return result;
244 }
ProcessVmWriteV(napi_env env, napi_callback_info info)245 static napi_value ProcessVmWriteV(napi_env env, napi_callback_info info)
246 {
247     int ret = PARAM_UNNORMAL;
248     char src[256] = "This is process_vm_readv_0100.";
249     char dst[256] = "";
250     struct iovec local = {.iov_base = src, .iov_len = sizeof(src)};
251     struct iovec remote = {.iov_base = dst, .iov_len = sizeof(dst)};
252 
253     ssize_t rev = process_vm_writev(getpid(), &local, PARAM_1, &remote, PARAM_1, PARAM_0);
254     if (rev == sizeof(src)) {
255         ret = RETURN_0;
256     } else {
257         ret = FAIL;
258     }
259     napi_value result = nullptr;
260     napi_create_int32(env, ret, &result);
261     return result;
262 }
263 EXTERN_C_START
Init(napi_env env, napi_value exports)264 static napi_value Init(napi_env env, napi_value exports)
265 {
266     napi_property_descriptor desc[] = {
267         {"readv", nullptr, Readv, nullptr, nullptr, nullptr, napi_default, nullptr},
268         {"writev", nullptr, Writev, nullptr, nullptr, nullptr, napi_default, nullptr},
269         {"processVmReadV", nullptr, ProcessVmReadV, nullptr, nullptr, nullptr, napi_default, nullptr},
270         {"processVmWriteV", nullptr, ProcessVmWriteV, nullptr, nullptr, nullptr, napi_default, nullptr},
271         {"pReadV", nullptr, PReadV, nullptr, nullptr, nullptr, napi_default, nullptr},
272         {"pReadV64", nullptr, PReadV64, nullptr, nullptr, nullptr, napi_default, nullptr},
273         {"pWriteV", nullptr, PWriteV, nullptr, nullptr, nullptr, napi_default, nullptr},
274         {"pWriteV64", nullptr, PWriteV64, nullptr, nullptr, nullptr, napi_default, nullptr},
275 
276     };
277     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
278     return exports;
279 }
280 EXTERN_C_END
281 
282 static napi_module demoModule = {
283     .nm_version = 1,
284     .nm_flags = 0,
285     .nm_filename = nullptr,
286     .nm_register_func = Init,
287     .nm_modname = "uio",
288     .nm_priv = ((void *)0),
289     .reserved = {0},
290 };
291 
RegisterModule(void)292 extern "C" __attribute__((constructor)) void RegisterModule(void) { napi_module_register(&demoModule); }
293