• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "close.h"
17 
18 #include <cstring>
19 #include <tuple>
20 #include <unistd.h>
21 
22 #include "common_func.h"
23 #include "filemgmt_libhilog.h"
24 
25 namespace OHOS {
26 namespace FileManagement {
27 namespace ModuleFileIO {
28 using namespace std;
29 using namespace OHOS::FileManagement::LibN;
30 
GetFileEntity(napi_env env,napi_value objFile)31 static FileEntity *GetFileEntity(napi_env env, napi_value objFile)
32 {
33     auto fileEntity = NClass::GetEntityOf<FileEntity>(env, objFile);
34     if (!fileEntity) {
35         HILOGE("Failed to get file entity");
36         return nullptr;
37     }
38     if (!fileEntity->fd_) {
39         HILOGE("The fd of rafEntity is not exist");
40         return nullptr;
41     }
42     return fileEntity;
43 }
44 
CloseFd(int fd)45 static NError CloseFd(int fd)
46 {
47     std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> close_req = {
48         new uv_fs_t, CommonFunc::fs_req_cleanup };
49     if (!close_req) {
50         HILOGE("Failed to request heap memory.");
51         return NError(ENOMEM);
52     }
53     int ret = uv_fs_close(nullptr, close_req.get(), fd, nullptr);
54     if (ret < 0) {
55         HILOGE("Failed to close file with ret: %{public}d", ret);
56         return NError(errno);
57     }
58     return NError(ERRNO_NOERR);
59 }
60 
ParseJsOperand(napi_env env,napi_value fdOrFileFromJsArg)61 static tuple<bool, FileStruct> ParseJsOperand(napi_env env, napi_value fdOrFileFromJsArg)
62 {
63     auto [isFd, fd] = NVal(env, fdOrFileFromJsArg).ToInt32();
64     if (isFd && fd >= 0) {
65         return { true, FileStruct { true, fd, nullptr } };
66     }
67     if (isFd && fd < 0) {
68         return { false, FileStruct { false, -1, nullptr } };
69     }
70     auto file = GetFileEntity(env, fdOrFileFromJsArg);
71     if (file) {
72         return { true, FileStruct { false, -1, file } };
73     }
74 
75     return { false, FileStruct { false, -1, nullptr } };
76 }
77 
Sync(napi_env env,napi_callback_info info)78 napi_value Close::Sync(napi_env env, napi_callback_info info)
79 {
80     NFuncArg funcArg(env, info);
81     if (!funcArg.InitArgs(NARG_CNT::ONE)) {
82         HILOGE("Number of arguments unmatched");
83         NError(EINVAL).ThrowErr(env);
84         return nullptr;
85     }
86 
87     auto [resGetFirstArg, fileStruct] = ParseJsOperand(env, funcArg[NARG_POS::FIRST]);
88     if (!resGetFirstArg) {
89         HILOGI("Failed to parse fd or FileEntity from JS parameter");
90         NError(EINVAL).ThrowErr(env);
91         return nullptr;
92     }
93 
94     if (fileStruct.isFd) {
95         auto err = CloseFd(fileStruct.fd);
96         if (err) {
97             err.ThrowErr(env);
98             return nullptr;
99         }
100     } else {
101         auto fp = NClass::RemoveEntityOfFinal<FileEntity>(env, funcArg[NARG_POS::FIRST]);
102         if (!fp) {
103             NError(EINVAL).ThrowErr(env);
104             return nullptr;
105         }
106     }
107 
108     return NVal::CreateUndefined(env).val_;
109 }
110 
Async(napi_env env,napi_callback_info info)111 napi_value Close::Async(napi_env env, napi_callback_info info)
112 {
113     NFuncArg funcArg(env, info);
114     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
115         HILOGE("Number of arguments unmatched");
116         NError(EINVAL).ThrowErr(env);
117         return nullptr;
118     }
119 
120     auto [resGetFirstArg, fileStruct] = ParseJsOperand(env, funcArg[NARG_POS::FIRST]);
121     if (!resGetFirstArg) {
122         HILOGI("Failed to parse JS operand");
123         NError(EINVAL).ThrowErr(env);
124         return nullptr;
125     }
126 
127     if (!fileStruct.isFd) {
128         auto fp = NClass::RemoveEntityOfFinal<FileEntity>(env, funcArg[NARG_POS::FIRST]);
129         if (!fp) {
130             NError(EINVAL).ThrowErr(env);
131             return nullptr;
132         }
133     }
134 
135     auto cbExec = [fileStruct = fileStruct]() -> NError {
136         if (fileStruct.isFd) {
137             return CloseFd(fileStruct.fd);
138         }
139         return NError(ERRNO_NOERR);
140     };
141 
142     auto cbComplete = [](napi_env env, NError err) -> NVal {
143         if (err) {
144             return { env, err.GetNapiErr(env) };
145         } else {
146             return NVal::CreateUndefined(env);
147         }
148     };
149 
150     size_t argc = funcArg.GetArgc();
151     NVal thisVar(env, funcArg.GetThisVar());
152     if (argc == NARG_CNT::ONE) {
153         return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_CLOSE_NAME, cbExec, cbComplete).val_;
154     } else {
155         NVal cb(env, funcArg[NARG_POS::SECOND]);
156         return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_CLOSE_NAME, cbExec, cbComplete).val_;
157     }
158 }
159 } // namespace ModuleFileIO
160 } // namespace FileManagement
161 } // namespace OHOS