1 /*
2 * Copyright (c) 2025 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 "file_impl.h"
17 #include "file_fs_impl.h"
18 #include "file_ffi.h"
19 #include "macro.h"
20 #include "uni_error.h"
21 #include "js_native_api.h"
22 #include "js_native_api_types.h"
23 #include "file_n_exporter.h"
24 #include "file_entity.h"
25 #include "n_class.h"
26 #include "n_val.h"
27
28 using namespace OHOS::FFI;
29 using namespace OHOS::CJSystemapi;
30 namespace OHOS {
31 namespace CJSystemapi {
32 namespace FileFs {
33
34 extern "C" {
RegisterAndSaveClass(napi_env env)35 void RegisterAndSaveClass(napi_env env)
36 {
37 std::vector<napi_property_descriptor> props = {
38 FileManagement::LibN::NVal::DeclareNapiGetter("fd",
39 OHOS::FileManagement::ModuleFileIO::FileNExporter::GetFD),
40 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
41 FileManagement::LibN::NVal::DeclareNapiGetter("path",
42 OHOS::FileManagement::ModuleFileIO::FileNExporter::GetPath),
43 FileManagement::LibN::NVal::DeclareNapiGetter("name",
44 OHOS::FileManagement::ModuleFileIO::FileNExporter::GetName),
45 FileManagement::LibN::NVal::DeclareNapiFunction("lock",
46 OHOS::FileManagement::ModuleFileIO::FileNExporter::Lock),
47 FileManagement::LibN::NVal::DeclareNapiFunction("tryLock",
48 OHOS::FileManagement::ModuleFileIO::FileNExporter::TryLock),
49 FileManagement::LibN::NVal::DeclareNapiFunction("unlock",
50 OHOS::FileManagement::ModuleFileIO::FileNExporter::UnLock),
51 FileManagement::LibN::NVal::DeclareNapiFunction("getParent",
52 OHOS::FileManagement::ModuleFileIO::FileNExporter::GetParent),
53 #endif
54 };
55
56 bool succ = false;
57 napi_value classValue = nullptr;
58 std::tie(succ, classValue) = FileManagement::LibN::NClass::DefineClass(
59 env,
60 OHOS::FileManagement::ModuleFileIO::FileNExporter::className_,
61 OHOS::FileManagement::ModuleFileIO::FileNExporter::Constructor,
62 move(props));
63 FileManagement::LibN::NClass::SaveClass(
64 env,
65 OHOS::FileManagement::ModuleFileIO::FileNExporter::className_,
66 classValue);
67 }
68
FfiConvertFile2Napi(napi_env env,int64_t id)69 napi_value FfiConvertFile2Napi(napi_env env, int64_t id)
70 {
71 napi_value undefined = nullptr;
72 napi_get_undefined(env, &undefined);
73
74 auto instance = FFIData::GetData<FileEntity>(id);
75
76 if (instance == nullptr) {
77 LOGE("FfiConvertFile2Napi instance not exist %{public}" PRId64, id);
78 return undefined;
79 }
80 RegisterAndSaveClass(env);
81 napi_value objRAF = FileManagement::LibN::NClass::InstantiateClass(
82 env,
83 OHOS::FileManagement::ModuleFileIO::FileNExporter::className_,
84 {});
85 if (!env || !objRAF) {
86 LOGE("Empty input: env %d, obj %d", env == nullptr, objRAF == nullptr);
87 return undefined;
88 }
89
90 OHOS::FileManagement::ModuleFileIO::FileEntity *rafEntity = nullptr;
91 napi_status status = napi_unwrap(env, objRAF, reinterpret_cast<void **>(&rafEntity));
92 if (status != napi_ok) {
93 LOGE("Cannot unwrap for pointer: %d", status);
94 return undefined;
95 }
96 if (!rafEntity) {
97 LOGE("Cannot instantiate file because of void entity");
98 return undefined;
99 }
100
101 rafEntity->fd_.swap(instance->fd_);
102 rafEntity->path_ = instance->path_;
103 rafEntity->uri_ = instance->uri_;
104
105 napi_valuetype type;
106 status = napi_typeof(env, objRAF, &type);
107 if (status != napi_ok || type == napi_undefined) {
108 LOGE("[File]: create napiobj failed");
109 return undefined;
110 }
111
112 return objRAF;
113 }
114
FfiCreateFileFromNapi(napi_env env,napi_value objRAF)115 int64_t FfiCreateFileFromNapi(napi_env env, napi_value objRAF)
116 {
117 using ModuleFileIOFileEntity = OHOS::FileManagement::ModuleFileIO::FileEntity;
118 using CJFileEntity = OHOS::CJSystemapi::FileFs::FileEntity;
119
120 if (env == nullptr || objRAF == nullptr) {
121 LOGE("[File]: parameter is nullptr");
122 return ERR_INVALID_INSTANCE_CODE;
123 }
124
125 napi_valuetype type = napi_undefined;
126
127 if (napi_typeof(env, objRAF, &type) != napi_ok || type != napi_object) {
128 LOGE("[File]: parameter is not object");
129 return ERR_INVALID_INSTANCE_CODE;
130 }
131
132 auto fileEntity = FileManagement::LibN::NClass::GetEntityOf<ModuleFileIOFileEntity>(env, objRAF);
133 if (!fileEntity) {
134 LOGE("[File]: Cannot instantiate file because of void entity");
135 return ERR_INVALID_INSTANCE_CODE;
136 }
137
138 auto native = FFIData::Create<CJFileEntity>(std::move(fileEntity->fd_), fileEntity->path_, fileEntity->uri_);
139 if (native == nullptr) {
140 LOGE("[File]: Create ffidata failed");
141 return ERR_INVALID_INSTANCE_CODE;
142 }
143
144 return native->GetID();
145 }
146
FfiOHOSFileFsOpen(const char * path,int64_t mode)147 RetDataI64 FfiOHOSFileFsOpen(const char* path, int64_t mode)
148 {
149 LOGI("FS_TEST::FfiOHOSFILEOpen");
150 RetDataI64 ret = { .code = ERR_INVALID_INSTANCE_CODE, .data = 0 };
151 auto [state, nativeStream] = FileEntity::Open(path, mode);
152 if (state != SUCCESS_CODE) {
153 LOGE("FS_TEST::FfiOHOSFILEOpen error");
154 ret.code = GetErrorCode(state);
155 ret.data = 0;
156 return ret;
157 }
158 LOGI("FS_TEST::FfiOHOSFILEOpen success");
159 ret.code = state;
160 ret.data = nativeStream->GetID();
161 return ret;
162 }
163
FfiOHOSFileFsCloseByFd(int32_t file)164 int FfiOHOSFileFsCloseByFd(int32_t file)
165 {
166 LOGI("FS_TEST::FfiOHOSFileFsClose");
167 int err = FileFsImpl::Close(file);
168 LOGI("FS_TEST::FfiOHOSFileFsClose success");
169 return err;
170 }
171
FfiOHOSFileFsClose(int64_t file)172 int FfiOHOSFileFsClose(int64_t file)
173 {
174 LOGI("FS_TEST::FfiOHOSFileFsClose");
175 auto instance = FFIData::GetData<FileEntity>(file);
176 if (!instance) {
177 LOGE("Stream instance not exist %{public}" PRId64, file);
178 return ERR_INVALID_INSTANCE_CODE;
179 }
180 int err = FileFsImpl::Close(instance);
181 FFIData::Release(file);
182 LOGI("FS_TEST::FfiOHOSFileFsClose success");
183 return err;
184 }
185
FfiOHOSFileFsDup(int32_t fd)186 RetDataI64 FfiOHOSFileFsDup(int32_t fd)
187 {
188 LOGI("FS_TEST::FfiOHOSFileFsDup");
189 RetDataI64 ret = { .code = ERR_INVALID_INSTANCE_CODE, .data = 0 };
190 auto [state, nativeFile] = FileEntity::Dup(fd);
191 if (state != SUCCESS_CODE) {
192 LOGE("FS_TEST::FfiOHOSFileFsDup error");
193 ret.code = GetErrorCode(state);
194 return ret;
195 }
196 LOGI("FS_TEST::FfiOHOSFileFsDup success");
197 ret.code = state;
198 ret.data = nativeFile->GetID();
199 return ret;
200 }
201
FfiOHOSFILEFsGetFD(int64_t id)202 int FfiOHOSFILEFsGetFD(int64_t id)
203 {
204 LOGI("FS_TEST::FfiOHOSFILEGetFD");
205 auto instance = FFIData::GetData<FileEntity>(id);
206 if (!instance) {
207 LOGE("FileEntity instance not exist %{public}" PRId64, id);
208 return ERR_INVALID_INSTANCE_CODE;
209 }
210 return instance->GetFD(id);
211 }
212
FfiOHOSFILEFsGetPath(int64_t id)213 const char* FfiOHOSFILEFsGetPath(int64_t id)
214 {
215 LOGI("FS_TEST::FfiOHOSFILEGetPath");
216 auto instance = FFIData::GetData<FileEntity>(id);
217 if (!instance) {
218 LOGE("FileEntity instance not exist %{public}" PRId64, id);
219 return "error";
220 }
221 return instance->GetPath(id);
222 }
223
FfiOHOSFILEFsGetName(int64_t id)224 const char* FfiOHOSFILEFsGetName(int64_t id)
225 {
226 LOGI("FS_TEST::FfiOHOSFILEGetName");
227 auto instance = FFIData::GetData<FileEntity>(id);
228 if (!instance) {
229 LOGE("FileEntity instance not exist %{public}" PRId64, id);
230 return "error";
231 }
232 return instance->GetName(id);
233 }
234
FfiOHOSFILEFsTryLock(int64_t id,bool exclusive)235 RetCode FfiOHOSFILEFsTryLock(int64_t id, bool exclusive)
236 {
237 LOGI("FS_TEST::FfiOHOSFILEFsTryLock");
238 auto instance = FFIData::GetData<FileEntity>(id);
239 if (!instance) {
240 LOGE("FileEntity instance not exist %{public}" PRId64, id);
241 return ERR_INVALID_INSTANCE_CODE;
242 }
243 return instance->TryLock(id, exclusive);
244 }
245
FfiOHOSFILEFsUnLock(int64_t id)246 RetCode FfiOHOSFILEFsUnLock(int64_t id)
247 {
248 LOGI("FS_TEST::FfiOHOSFILEFsUnLock");
249 auto instance = FFIData::GetData<FileEntity>(id);
250 if (!instance) {
251 LOGE("FileEntity instance not exist %{public}" PRId64, id);
252 return ERR_INVALID_INSTANCE_CODE;
253 }
254 return instance->UnLock(id);
255 }
256
FfiOHOSFILEFsGetParent(int64_t id)257 RetDataCString FfiOHOSFILEFsGetParent(int64_t id)
258 {
259 LOGI("FS_TEST::FfiOHOSFILEFsGetParent");
260 auto instance = FFIData::GetData<FileEntity>(id);
261 RetDataCString ret = { .code = EINVAL, .data = nullptr };
262 if (!instance) {
263 LOGE("FS_TEST::FfiOHOSFILEFsGetParent instance not exist %{public}" PRId64, id);
264 return ret;
265 }
266 ret = instance->GetParent();
267 if (ret.code != SUCCESS_CODE) {
268 ret.code = GetErrorCode(ret.code);
269 }
270 LOGI("FS_TEST::FfiOHOSFILEFsGetParent end");
271 return ret;
272 }
273 }
274 } // namespace FileFs
275 } // namespace CJSystemapi
276 } // namespace OHOS