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 "common/napi_helper.cpp"
17 #include "napi/native_api.h"
18 #include <cstdio>
19 #include <cstring>
20 #include <fcntl.h>
21 #include <ifaddrs.h>
22 #include <js_native_api_types.h>
23 #include <linux/quota.h>
24 #include <net/if.h>
25 #include <string>
26 #include <sys/inotify.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <utmp.h>
30 #include <uv.h>
31 #include <hilog/log.h>
32 
33 #define ONE 1
34 #define TWO 2
35 #define SIZE_2 2
36 #define PATH "/data/storage/el2/base/files"
37 #define PARAM_777 777
38 #define PARAM_0777 0777
39 #define PARAM_0 0
40 #define PARAM_1 1
41 #define PARAM_2 2
42 #define PARAM_UNNORMAL (-1)
43 #define ERRON_0 0
44 #define SUCCESS 1
45 #define SIZE_64 64
46 #define SEC_TIME 123840
47 #define TEST_MODE 0666
48 #define TEST_AT_FDCWD (-100)
49 #define TEST_ERROR_AT_FDCWD 100
50 #define NO_ERR 0
51 #define SUCCESS 1
52 #define FAIL (-1)
53 #define TEN 10
54 #define TEST_FIFO_MODE 0666
55 #define BUFSIZE 128
56 #define PARAM_3 3
57 #undef LOG_DOMAIN
58 #undef LOG_TAG
59 #define LOG_DOMAIN 0xFEFE
60 #define LOG_TAG "MUSL_STATNDK"
61 
Stat(napi_env env, napi_callback_info info)62 static napi_value Stat(napi_env env, napi_callback_info info)
63 {
64     size_t argc = PARAM_1;
65     napi_value args[PARAM_1] = {nullptr};
66     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
67 
68     int value;
69     napi_get_value_int32(env, args[PARAM_0], &value);
70     int intValue = PARAM_0;
71     struct stat sb = {PARAM_0};
72     if (value == ONE) {
73         intValue = stat(PATH, &sb);
74     } else if (value == TWO) {
75         intValue = stat(nullptr, &sb);
76     }
77     napi_value result = nullptr;
78     napi_create_int32(env, intValue, &result);
79     return result;
80 }
Stat64(napi_env env, napi_callback_info info)81 static napi_value Stat64(napi_env env, napi_callback_info info)
82 {
83     size_t argc = PARAM_1;
84     napi_value args[PARAM_1] = {nullptr};
85     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
86     int value;
87     napi_get_value_int32(env, args[PARAM_0], &value);
88     int intValue = PARAM_0;
89     struct stat64 sb = {PARAM_0};
90     if (value == ONE) {
91         intValue = stat64(PATH, &sb);
92     } else if (value == TWO) {
93         intValue = stat64(nullptr, &sb);
94     }
95     napi_value result = nullptr;
96     napi_create_int32(env, intValue, &result);
97     return result;
98 }
99 
Umask(napi_env env, napi_callback_info info)100 static napi_value Umask(napi_env env, napi_callback_info info)
101 {
102     size_t argc = PARAM_1;
103     napi_value args[PARAM_1] = {nullptr};
104     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
105     int valueFirst;
106     napi_get_value_int32(env, args[PARAM_0], &valueFirst);
107     mode_t mode = PARAM_0;
108     if (valueFirst == PARAM_777) {
109         mode = S_IRWXU | S_IRWXG | S_IRWXO;
110     }
111     mode_t umaskValue = umask(mode);
112     umaskValue = umask(umaskValue);
113 
114     int toJs = FAIL;
115     if (umaskValue == mode && valueFirst == PARAM_777) {
116         toJs = SUCCESS;
117     }
118     napi_value result = nullptr;
119     napi_create_int32(env, toJs, &result);
120     return result;
121 }
122 
Utimensat(napi_env env, napi_callback_info info)123 static napi_value Utimensat(napi_env env, napi_callback_info info)
124 {
125     int toCppResult = FAIL;
126     char path[] = "/data/storage/el2/base/files/Utimensat.txt";
127     int fd = open(path, O_CREAT);
128 
129     struct timespec times[] = {{.tv_nsec = UTIME_OMIT}, {.tv_nsec = UTIME_OMIT}};
130 
131     int utimensatValue = utimensat(fd, path, times, PARAM_0);
132     if (utimensatValue == PARAM_0) {
133         toCppResult = SUCCESS;
134     }
135     close(fd);
136     remove(path);
137     napi_value result = nullptr;
138     napi_create_int32(env, toCppResult, &result);
139     return result;
140 }
141 
FchModAt(napi_env env, napi_callback_info info)142 static napi_value FchModAt(napi_env env, napi_callback_info info)
143 {
144     char path[] = "/data/storage/el2/base/files/modAt.txt";
145     int df = open(path, O_CREAT, PARAM_0777);
146     int ret = fchmodat(df, path, S_IRUSR, PARAM_0);
147     close(df);
148     remove(path);
149     napi_value result = nullptr;
150     napi_create_int32(env, ret, &result);
151     return result;
152 }
153 
FchMod(napi_env env, napi_callback_info info)154 static napi_value FchMod(napi_env env, napi_callback_info info)
155 {
156     char path[] = "/data/storage/el2/base/files/mod.txt";
157     int df = open(path, O_CREAT, PARAM_0777);
158     int ret = fchmod(df, S_IRUSR);
159     close(df);
160     remove(path);
161     napi_value result = nullptr;
162     napi_create_int32(env, ret, &result);
163     return result;
164 }
165 
Creat(napi_env env, napi_callback_info info)166 static napi_value Creat(napi_env env, napi_callback_info info)
167 {
168     int backResult;
169     char path[] = "/data/storage/el2/base/files/Fzl.txt";
170     backResult = creat(path, O_CREAT);
171     napi_value result = nullptr;
172     if (backResult != FAIL) {
173         napi_create_int32(env, PARAM_0, &result);
174     } else {
175         napi_create_int32(env, PARAM_UNNORMAL, &result);
176     }
177     remove(path);
178     return result;
179 }
180 
Creat64(napi_env env, napi_callback_info info)181 static napi_value Creat64(napi_env env, napi_callback_info info)
182 {
183     int backResult;
184     char path[] = "/data/storage/el2/base/files/Fzl.txt";
185     backResult = creat64(path, O_CREAT);
186     napi_value result = nullptr;
187     if (backResult != FAIL) {
188         napi_create_int32(env, PARAM_0, &result);
189     } else {
190         napi_create_int32(env, PARAM_UNNORMAL, &result);
191     }
192     remove(path);
193     return result;
194 }
195 
Chmod(napi_env env, napi_callback_info info)196 static napi_value Chmod(napi_env env, napi_callback_info info)
197 {
198     int returnValue = chmod("/data/storage/el2/base/files", S_IRWXU | S_IRWXG | S_IRWXO);
199     napi_value result;
200     napi_create_int32(env, returnValue, &result);
201     return result;
202 }
203 
Fstat(napi_env env, napi_callback_info info)204 static napi_value Fstat(napi_env env, napi_callback_info info)
205 {
206     size_t argc = PARAM_1;
207     napi_value args[PARAM_1] = {nullptr};
208     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
209     size_t length = SIZE_64;
210     size_t stresult = PARAM_0;
211     char path[SIZE_64] = {PARAM_0};
212     napi_get_value_string_utf8(env, args[PARAM_0], path, length, &stresult);
213     struct stat sb = {PARAM_0};
214     int fd = open(path, O_CREAT, PARAM_0777);
215     int value = fstat(fd, &sb);
216     napi_value result;
217     napi_create_int32(env, value, &result);
218     close(fd);
219     return result;
220 }
221 
Fstat64(napi_env env, napi_callback_info info)222 static napi_value Fstat64(napi_env env, napi_callback_info info)
223 {
224     size_t argc = PARAM_1;
225     napi_value args[PARAM_1] = {nullptr};
226     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
227     size_t length = SIZE_64;
228     size_t stresult = PARAM_0;
229     char path[SIZE_64] = {PARAM_0};
230     napi_get_value_string_utf8(env, args[PARAM_0], path, length, &stresult);
231     struct stat sb = {PARAM_0};
232     int fd = open(path, O_CREAT, PARAM_0777);
233     int value = fstat64(fd, &sb);
234     napi_value result;
235     napi_create_int32(env, value, &result);
236     close(fd);
237     return result;
238 }
239 
Fstatat(napi_env env, napi_callback_info info)240 static napi_value Fstatat(napi_env env, napi_callback_info info)
241 {
242     size_t argc = PARAM_1;
243     napi_value args[PARAM_1] = {nullptr};
244     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
245     size_t length = SIZE_64;
246     size_t stresult = PARAM_0;
247     char path[SIZE_64] = {PARAM_0};
248     napi_get_value_string_utf8(env, args[PARAM_0], path, length, &stresult);
249     struct stat st = {PARAM_0};
250     int fd = open(path, O_CREAT, PARAM_0777);
251     int ret = fstatat(AT_FDCWD, path, &st, PARAM_0);
252     napi_value result;
253     napi_create_int32(env, ret, &result);
254     close(fd);
255     return result;
256 }
257 
Fstatat64(napi_env env, napi_callback_info info)258 static napi_value Fstatat64(napi_env env, napi_callback_info info)
259 {
260     size_t argc = PARAM_1;
261     napi_value args[PARAM_1] = {nullptr};
262     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
263     size_t length = SIZE_64;
264     size_t stresult = PARAM_0;
265     char path[SIZE_64] = {PARAM_0};
266     napi_get_value_string_utf8(env, args[PARAM_0], path, length, &stresult);
267     struct stat st = {PARAM_0};
268     int fd = open(path, O_CREAT, PARAM_0777);
269     int ret = fstatat64(AT_FDCWD, path, &st, PARAM_0);
270     napi_value result;
271     napi_create_int32(env, ret, &result);
272     close(fd);
273     return result;
274 }
275 
Futimens(napi_env env, napi_callback_info info)276 static napi_value Futimens(napi_env env, napi_callback_info info)
277 {
278     int fd = open("/data/storage/el2/base/files/utime.txt", O_CREAT, PARAM_0777);
279     int ret = futimens(fd, ((struct timespec[PARAM_2]){{.tv_nsec = UTIME_OMIT}, {.tv_nsec = UTIME_OMIT}}));
280     napi_value result;
281     napi_create_int32(env, ret, &result);
282     close(fd);
283     remove("/data/storage/el2/base/files/utime.txt");
284     return result;
285 }
MkFifoAt(napi_env env, napi_callback_info info)286 static napi_value MkFifoAt(napi_env env, napi_callback_info info)
287 {
288     napi_value result = nullptr;
289     size_t argc = PARAM_2;
290     napi_value args[PARAM_2] = {nullptr};
291     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
292     int ret, name;
293     napi_get_value_int32(env, args[PARAM_0], &name);
294     size_t length = SIZE_64;
295     size_t strResult = PARAM_0;
296     char path[length];
297     napi_get_value_string_utf8(env, args[PARAM_1], path, length, &strResult);
298     errno = 0;
299     ret = mkfifoat(name, path, S_IFIFO | TEST_FIFO_MODE);
300     if (ret != 0) {
301         OH_LOG_INFO(LOG_APP, "MUSL mkfifoat ret %{public}d errno : %{public}d", ret, errno);
302         if (ret == -1 && errno == EACCES) {
303             ret = 0;
304         }
305     }
306     unlink(path);
307     remove(path);
308     napi_create_int32(env, ret, &result);
309     return result;
310 }
311 
MkNodAt(napi_env env, napi_callback_info info)312 static napi_value MkNodAt(napi_env env, napi_callback_info info)
313 {
314     size_t argc = PARAM_3;
315     napi_value args[PARAM_3] = {nullptr};
316     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
317     int ret = 0;
318     int dirfd = 0;
319     int mode = 0;
320     napi_get_value_int32(env, args[PARAM_0], &dirfd);
321     size_t length = SIZE_64;
322     size_t strResult = PARAM_0;
323     char path[length];
324     napi_get_value_string_utf8(env, args[PARAM_1], path, length, &strResult);
325     napi_get_value_int32(env, args[PARAM_2], &mode);
326     dev_t st_dev = PARAM_0;
327     errno = 0;
328     ret = mknodat(dirfd, path, mode, st_dev);
329     int mkret = ret;
330     int mkerrno = errno;
331     if (ret != 0) {
332         OH_LOG_INFO(LOG_APP, "MUSL mknodat ret %{public}d errno : %{public}d", ret, errno);
333         if (ret == -1 && (errno == EACCES || errno == EPERM)) {
334             ret = 0;
335         }
336     }
337     struct stat newFifo = {PARAM_0};
338     errno = 0;
339     if (mkret == 0 || mkerrno == EEXIST) {
340         ret = stat(path, &newFifo);
341         if (ret != 0) {
342             OH_LOG_INFO(LOG_APP, "MUSL stat ret %{public}d errno : %{public}d", ret, errno);
343         }
344     }
345     napi_value result;
346     napi_create_int32(env, ret, &result);
347     unlink(path);
348     return result;
349 }
350 
MkNod(napi_env env, napi_callback_info info)351 static napi_value MkNod(napi_env env, napi_callback_info info)
352 {
353     size_t argc = PARAM_2;
354     napi_value args[PARAM_2] = {nullptr};
355     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
356     size_t length = SIZE_64;
357     size_t strResult = PARAM_0;
358     char pathname[PATH_MAX];
359     napi_get_value_string_utf8(env, args[PARAM_0], pathname, length, &strResult);
360     int mode = PARAM_0;
361     napi_get_value_int32(env, args[PARAM_1], &mode);
362     int ret = PARAM_0;
363     napi_value result;
364     napi_create_int32(env, ret, &result);
365     return result;
366 }
367 
MkDir(napi_env env, napi_callback_info info)368 static napi_value MkDir(napi_env env, napi_callback_info info)
369 {
370     int ret = PARAM_0;
371     char path[] = "/data/storage/el2/base/files/mkdir1";
372     if (access(path, F_OK) != PARAM_0) {
373         ret = mkdir(path, S_IRWXG);
374         remove(path);
375     } else {
376         remove(path);
377         ret = mkdir(path, S_IRWXG);
378         remove(path);
379     }
380     napi_value result = nullptr;
381     napi_create_int32(env, ret, &result);
382     return result;
383 }
384 
MkDirAt(napi_env env, napi_callback_info info)385 static napi_value MkDirAt(napi_env env, napi_callback_info info)
386 {
387     int ret = PARAM_0;
388     char path[] = "/data/storage/el2/base/files/mkdirat1";
389     ret = mkdirat(PARAM_0, path, S_IRWXG);
390     napi_value result = nullptr;
391     napi_create_int32(env, ret, &result);
392     return result;
393 }
394 
MkFiFo(napi_env env, napi_callback_info info)395 static napi_value MkFiFo(napi_env env, napi_callback_info info)
396 {
397     size_t argc = PARAM_1;
398     napi_value args[PARAM_1] = {nullptr};
399     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
400     size_t lenA;
401     size_t lenV = BUFSIZE;
402     char path[BUFSIZE] = {PARAM_0};
403     napi_get_value_string_utf8(env, args[PARAM_0], path, lenV, &lenA);
404     int ret = PARAM_0;
405     unlink(path);
406     remove(path);
407     napi_value result = nullptr;
408     napi_create_int32(env, ret, &result);
409     return result;
410 }
411 
Lstat(napi_env env, napi_callback_info info)412 static napi_value Lstat(napi_env env, napi_callback_info info)
413 {
414     struct stat statbuff;
415     int32_t ret = lstat("/etc/passwd", &statbuff);
416     napi_value result = nullptr;
417     if (ret == FAIL) {
418         napi_create_int32(env, PARAM_UNNORMAL, &result);
419     } else {
420         napi_create_int32(env, PARAM_0, &result);
421     }
422     return result;
423 }
424 
Lstat64(napi_env env, napi_callback_info info)425 static napi_value Lstat64(napi_env env, napi_callback_info info)
426 {
427     struct stat statbuff;
428     int32_t ret = lstat64("/etc/passwd", &statbuff);
429     napi_value result = nullptr;
430     if (ret == FAIL) {
431         napi_create_int32(env, PARAM_UNNORMAL, &result);
432     } else {
433         napi_create_int32(env, PARAM_0, &result);
434     }
435     return result;
436 }
437 
438 EXTERN_C_START
Init(napi_env env, napi_value exports)439 static napi_value Init(napi_env env, napi_value exports)
440 {
441     napi_property_descriptor desc[] = {
442         {"stat", nullptr, Stat, nullptr, nullptr, nullptr, napi_default, nullptr},
443         {"stat64", nullptr, Stat64, nullptr, nullptr, nullptr, napi_default, nullptr},
444         {"umask", nullptr, Umask, nullptr, nullptr, nullptr, napi_default, nullptr},
445         {"utimensat", nullptr, Utimensat, nullptr, nullptr, nullptr, napi_default, nullptr},
446         {"fchmodat", nullptr, FchModAt, nullptr, nullptr, nullptr, napi_default, nullptr},
447         {"fchmod", nullptr, FchMod, nullptr, nullptr, nullptr, napi_default, nullptr},
448         {"creat", nullptr, Creat, nullptr, nullptr, nullptr, napi_default, nullptr},
449         {"creat64", nullptr, Creat64, nullptr, nullptr, nullptr, napi_default, nullptr},
450         {"chmod", nullptr, Chmod, nullptr, nullptr, nullptr, napi_default, nullptr},
451         {"fstat", nullptr, Fstat, nullptr, nullptr, nullptr, napi_default, nullptr},
452         {"fstat64", nullptr, Fstat64, nullptr, nullptr, nullptr, napi_default, nullptr},
453         {"fstatat", nullptr, Fstatat, nullptr, nullptr, nullptr, napi_default, nullptr},
454         {"fstatat64", nullptr, Fstatat64, nullptr, nullptr, nullptr, napi_default, nullptr},
455         {"futimens", nullptr, Futimens, nullptr, nullptr, nullptr, napi_default, nullptr},
456         {"mkFifoAt", nullptr, MkFifoAt, nullptr, nullptr, nullptr, napi_default, nullptr},
457         {"mkNodAt", nullptr, MkNodAt, nullptr, nullptr, nullptr, napi_default, nullptr},
458         {"mkNod", nullptr, MkNod, nullptr, nullptr, nullptr, napi_default, nullptr},
459         {"mkDir", nullptr, MkDir, nullptr, nullptr, nullptr, napi_default, nullptr},
460         {"mkDirAt", nullptr, MkDirAt, nullptr, nullptr, nullptr, napi_default, nullptr},
461         {"lstat", nullptr, Lstat, nullptr, nullptr, nullptr, napi_default, nullptr},
462         {"lstat64", nullptr, Lstat64, nullptr, nullptr, nullptr, napi_default, nullptr},
463         {"mkFiFo", nullptr, MkFiFo, nullptr, nullptr, nullptr, napi_default, nullptr},
464 
465     };
466     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
467     return exports;
468 }
469 EXTERN_C_END
470 
471 static napi_module demoModule = {
472     .nm_version = 1,
473     .nm_flags = 0,
474     .nm_filename = nullptr,
475     .nm_register_func = Init,
476     .nm_modname = "stat",
477     .nm_priv = ((void *)0),
478     .reserved = {0},
479 };
480 
RegisterModule(void)481 extern "C" __attribute__((constructor)) void RegisterModule(void) { napi_module_register(&demoModule); }
482