• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "common_func.h"
17 
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 
25 #include "log.h"
26 #include "n_class.h"
27 #include "n_func_arg.h"
28 #include "n_val.h"
29 #include "uni_error.h"
30 
31 namespace OHOS {
32 namespace DistributedFS {
33 namespace ModuleFileIO {
34 using namespace std;
35 
InitOpenMode(napi_env env,napi_value exports)36 void InitOpenMode(napi_env env, napi_value exports)
37 {
38     char propertyName[] = "OpenMode";
39     napi_property_descriptor desc[] = {
40         DECLARE_NAPI_STATIC_PROPERTY("READ_ONLY", NVal::CreateInt32(env, RDONLY).val_),
41         DECLARE_NAPI_STATIC_PROPERTY("WRITE_ONLY", NVal::CreateInt32(env, WRONLY).val_),
42         DECLARE_NAPI_STATIC_PROPERTY("READ_WRITE", NVal::CreateInt32(env, RDWR).val_),
43         DECLARE_NAPI_STATIC_PROPERTY("CREATE", NVal::CreateInt32(env, CREATE).val_),
44         DECLARE_NAPI_STATIC_PROPERTY("TRUNC", NVal::CreateInt32(env, TRUNC).val_),
45         DECLARE_NAPI_STATIC_PROPERTY("APPEND", NVal::CreateInt32(env, APPEND).val_),
46         DECLARE_NAPI_STATIC_PROPERTY("NONBLOCK", NVal::CreateInt32(env, NONBLOCK).val_),
47         DECLARE_NAPI_STATIC_PROPERTY("DIR", NVal::CreateInt32(env, DIRECTORY).val_),
48         DECLARE_NAPI_STATIC_PROPERTY("NOFOLLOW", NVal::CreateInt32(env, NOFOLLOW).val_),
49         DECLARE_NAPI_STATIC_PROPERTY("SYNC", NVal::CreateInt32(env, SYNC).val_),
50     };
51     napi_value obj = nullptr;
52     napi_create_object(env, &obj);
53     napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc);
54     napi_set_named_property(env, exports, propertyName, obj);
55 }
56 
GetActualBuf(napi_env env,void * rawBuf,size_t bufLen,NVal op)57 static tuple<bool, void *, int64_t> GetActualBuf(napi_env env, void *rawBuf, size_t bufLen, NVal op)
58 {
59     bool succ = false;
60     void *realBuf = nullptr;
61     int64_t opOffset = 0;
62     if (op.HasProp("offset")) {
63         tie(succ, opOffset) = op.GetProp("offset").ToInt64(opOffset);
64         if (!succ || opOffset < 0) {
65             UniError(EINVAL).ThrowErr(env, "Invalid option.offset, positive integer is desired");
66             return { false, nullptr, opOffset };
67         } else if (opOffset > static_cast<int64_t>(bufLen)) {
68             UniError(EINVAL).ThrowErr(env, "Invalid option.offset, buffer limit exceeded");
69             return { false, nullptr, opOffset };
70         } else {
71             realBuf = static_cast<uint8_t *>(rawBuf) + opOffset;
72         }
73     } else {
74         realBuf = rawBuf;
75     }
76 
77     return { true, realBuf, opOffset };
78 }
79 
GetActualLen(napi_env env,size_t bufLen,size_t bufOff,NVal op)80 static tuple<bool, size_t> GetActualLen(napi_env env, size_t bufLen, size_t bufOff, NVal op)
81 {
82     bool succ = false;
83     size_t retLen = bufLen - bufOff;
84 
85     if (op.HasProp("length")) {
86         int64_t opLength = 0;
87         tie(succ, opLength) = op.GetProp("length").ToInt64(static_cast<int64_t>(retLen));
88         if (!succ || opLength < 0 || static_cast<size_t>(opLength) > retLen) {
89             UniError(EINVAL).ThrowErr(env, "Invalid option.length");
90             return { false, 0 };
91         }
92         retLen = static_cast<size_t>(opLength);
93     }
94     return { true, retLen };
95 }
96 
GetActualLenV9(napi_env env,int64_t bufLen,int64_t bufOff,NVal op)97 static tuple<bool, size_t> GetActualLenV9(napi_env env, int64_t bufLen, int64_t bufOff, NVal op)
98 {
99     bool succ = false;
100     int64_t retLen;
101 
102     if (op.HasProp("length")) {
103         int64_t opLength;
104         tie(succ, opLength) = op.GetProp("length").ToInt64();
105         if (!succ) {
106             HILOGE("Invalid option.length, expect integer");
107             UniError(EINVAL).ThrowErr(env);
108             return { false, 0 };
109         }
110         if (opLength < 0) {
111             retLen = bufLen - bufOff;
112         } else if (opLength > bufLen - bufOff) {
113             HILOGE("Invalid option.length, buffer limit exceeded");
114             UniError(EINVAL).ThrowErr(env);
115             return { false, 0 };
116         } else {
117             retLen = opLength;
118         }
119     } else {
120         retLen = bufLen - bufOff;
121     }
122 
123     return { true, retLen };
124 }
125 
ConvertJsFlags(unsigned int & flags)126 unsigned int CommonFunc::ConvertJsFlags(unsigned int &flags)
127 {
128     static constexpr unsigned int usrWriteOnly = 01;
129     static constexpr unsigned int usrReadWrite = 02;
130     static constexpr unsigned int usrCreate = 0100;
131     static constexpr unsigned int usrExecuteLock = 0200;
132     static constexpr unsigned int usrTruncate = 01000;
133     static constexpr unsigned int usrAppend = 02000;
134     static constexpr unsigned int usrNoneBlock = 04000;
135     static constexpr unsigned int usrDirectory = 0200000;
136     static constexpr unsigned int usrNoFollowed = 0400000;
137     static constexpr unsigned int usrSynchronous = 04010000;
138 
139     // default value is usrReadOnly 00
140     unsigned int flagsABI = 0;
141     flagsABI |= ((flags & usrWriteOnly) == usrWriteOnly) ? O_WRONLY : 0;
142     flagsABI |= ((flags & usrReadWrite) == usrReadWrite) ? O_RDWR : 0;
143     flagsABI |= ((flags & usrCreate) == usrCreate) ? O_CREAT : 0;
144     flagsABI |= ((flags & usrExecuteLock) == usrExecuteLock) ? O_EXCL : 0;
145     flagsABI |= ((flags & usrTruncate) == usrTruncate) ? O_TRUNC : 0;
146     flagsABI |= ((flags & usrAppend) == usrAppend) ? O_APPEND : 0;
147     flagsABI |= ((flags & usrNoneBlock) == usrNoneBlock) ? O_NONBLOCK : 0;
148     flagsABI |= ((flags & usrDirectory) == usrDirectory) ? O_DIRECTORY : 0;
149     flagsABI |= ((flags & usrNoFollowed) == usrNoFollowed) ? O_NOFOLLOW : 0;
150     flagsABI |= ((flags & usrSynchronous) == usrSynchronous) ? O_SYNC : 0;
151     flags = flagsABI;
152     return flagsABI;
153 }
154 
GetCopyPathArg(napi_env env,napi_value srcPath,napi_value dstPath)155 tuple<bool, unique_ptr<char[]>, unique_ptr<char[]>> CommonFunc::GetCopyPathArg(napi_env env,
156                                                                                napi_value srcPath,
157                                                                                napi_value dstPath)
158 {
159     bool succ = false;
160     unique_ptr<char[]> src;
161     tie(succ, src, ignore) = NVal(env, srcPath).ToUTF8StringPath();
162     if (!succ) {
163         return { false, nullptr, nullptr };
164     }
165 
166     unique_ptr<char[]> dest;
167     tie(succ, dest, ignore) = NVal(env, dstPath).ToUTF8StringPath();
168     if (!succ) {
169         return { false, nullptr, nullptr };
170     }
171     return make_tuple(true, move(src), move(dest));
172 }
173 
GetReadArg(napi_env env,napi_value readBuf,napi_value option)174 tuple<bool, void *, size_t, int64_t, int64_t> CommonFunc::GetReadArg(napi_env env,
175                                                                      napi_value readBuf,
176                                                                      napi_value option)
177 {
178     bool succ = false;
179     void *retBuf = nullptr;
180     size_t retLen = 0;
181     int64_t position = -1;
182 
183     NVal txt(env, readBuf);
184     void *buf = nullptr;
185     size_t bufLen = 0;
186     int64_t offset = 0;
187     tie(succ, buf, bufLen) = txt.ToArraybuffer();
188     if (!succ) {
189         UniError(EINVAL).ThrowErr(env, "Invalid read buffer, expect arraybuffer");
190         return { false, nullptr, 0, position, offset };
191     }
192 
193     NVal op(env, option);
194     tie(succ, retBuf, offset) = GetActualBuf(env, buf, bufLen, op);
195     if (!succ) {
196         return { false, nullptr, 0, position, offset };
197     }
198 
199     int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
200     tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
201     if (!succ) {
202         return { false, nullptr, 0, position, offset };
203     }
204 
205     if (op.HasProp("position") && !op.GetProp("position").TypeIs(napi_undefined)) {
206         tie(succ, position) = op.GetProp("position").ToInt64();
207         if (!succ || position < 0) {
208             UniError(EINVAL).ThrowErr(env, "option.position shall be positive number");
209             return { false, nullptr, 0, position, offset };
210         }
211     }
212 
213     return { true, retBuf, retLen, position, offset };
214 }
215 
DecodeString(napi_env env,NVal jsStr,NVal encoding)216 static tuple<bool, unique_ptr<char[]>, size_t> DecodeString(napi_env env, NVal jsStr, NVal encoding)
217 {
218     unique_ptr<char[]> buf = nullptr;
219     if (!jsStr.TypeIs(napi_string)) {
220         return { false, nullptr, 0 };
221     }
222     if (!encoding) {
223         return jsStr.ToUTF8String();
224     }
225 
226     auto [succ, encodingBuf, ignore] = encoding.ToUTF8String("utf-8");
227     if (!succ) {
228         return { false, nullptr, 0 };
229     }
230     string_view encodingStr(encodingBuf.get());
231     if (encodingStr == "utf-8") {
232         return jsStr.ToUTF8String();
233     } else if (encodingStr == "utf-16") {
234         return jsStr.ToUTF16String();
235     } else {
236         return { false, nullptr, 0 };
237     }
238 }
239 
GetWriteArg(napi_env env,napi_value argWBuf,napi_value argOption)240 tuple<bool, unique_ptr<char[]>, void *, size_t, int64_t> CommonFunc::GetWriteArg(napi_env env,
241                                                                                  napi_value argWBuf,
242                                                                                  napi_value argOption)
243 {
244     void *retBuf = nullptr;
245     size_t retLen = 0;
246     int64_t position = -1;
247     bool succ = false;
248     void *buf = nullptr;
249     size_t bufLen = 0;
250     NVal op(env, argOption);
251     NVal jsBuffer(env, argWBuf);
252     unique_ptr<char[]> bufferGuard = nullptr;
253     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
254     if (!succ) {
255         tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
256         if (!succ) {
257             UniError(EINVAL).ThrowErr(env, "Illegal write buffer or encoding");
258             return { false, nullptr, nullptr, 0, position };
259         }
260     } else {
261         buf = bufferGuard.get();
262     }
263 
264     tie(succ, retBuf, ignore) = GetActualBuf(env, buf, bufLen, op);
265     if (!succ) {
266         return { false, nullptr, nullptr, 0, position };
267     }
268 
269     int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
270     tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
271     if (!succ) {
272         return { false, nullptr, nullptr, 0, position };
273     }
274 
275     if (op.HasProp("position") && !op.GetProp("position").TypeIs(napi_undefined)) {
276         tie(succ, position) = op.GetProp("position").ToInt64();
277         if (!succ || position < 0) {
278             UniError(EINVAL).ThrowErr(env, "option.position shall be positive number");
279             return { false, nullptr, nullptr, 0, position };
280         }
281     }
282     return { true, move(bufferGuard), retBuf, retLen, position };
283 }
284 
GetReadArgV9(napi_env env,napi_value readBuf,napi_value option)285 tuple<bool, void *, int64_t, bool, int64_t> CommonFunc::GetReadArgV9(napi_env env,
286     napi_value readBuf, napi_value option)
287 {
288     bool succ = false;
289     int64_t retLen;
290     bool posAssigned = false;
291     int64_t position;
292 
293     NVal txt(env, readBuf);
294     void *buf = nullptr;
295     int64_t bufLen;
296     tie(succ, buf, bufLen) = txt.ToArraybuffer();
297     if (!succ) {
298         HILOGE("Invalid read buffer, expect arraybuffer");
299         UniError(EINVAL).ThrowErr(env);
300         return { false, nullptr, 0, posAssigned, position };
301     }
302     NVal op = NVal(env, option);
303     tie(succ, retLen) = GetActualLenV9(env, bufLen, 0, op);
304     if (!succ) {
305         return { false, nullptr, 0, posAssigned, position };
306     }
307 
308     if (op.HasProp("offset")) {
309         tie(succ, position) = op.GetProp("offset").ToInt64();
310         if (succ && position >= 0) {
311             posAssigned = true;
312         } else {
313             HILOGE("option.offset shall be positive number");
314             UniError(EINVAL).ThrowErr(env);
315             return { false, nullptr, 0, posAssigned, position };
316         }
317     }
318 
319     return { true, buf, retLen, posAssigned, position };
320 }
321 
GetWriteArgV9(napi_env env,napi_value argWBuf,napi_value argOption)322 tuple<bool, unique_ptr<char[]>, void *, int64_t, bool, int64_t> CommonFunc::GetWriteArgV9(napi_env env,
323     napi_value argWBuf, napi_value argOption)
324 {
325     int64_t retLen;
326     bool hasPos = false;
327     int64_t retPos;
328 
329     bool succ = false;
330     void *buf = nullptr;
331     int64_t bufLen;
332     NVal op(env, argOption);
333     NVal jsBuffer(env, argWBuf);
334     unique_ptr<char[]> bufferGuard;
335     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
336     if (!succ) {
337         tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
338         if (!succ) {
339             HILOGE("Illegal write buffer or encoding");
340             UniError(EINVAL).ThrowErr(env);
341             return { false, nullptr, nullptr, 0, hasPos, retPos };
342         }
343     } else {
344         buf = bufferGuard.get();
345     }
346     tie(succ, retLen) = GetActualLenV9(env, bufLen, 0, op);
347     if (!succ) {
348         return { false, nullptr, nullptr, 0, hasPos, retPos };
349     }
350 
351     if (op.HasProp("offset")) {
352         int32_t position = 0;
353         tie(succ, position) = op.GetProp("offset").ToInt32();
354         if (!succ || position < 0) {
355             HILOGE("option.offset shall be positive number");
356             UniError(EINVAL).ThrowErr(env);
357             return { false, nullptr, nullptr, 0, hasPos, retPos };
358         }
359         hasPos = true;
360         retPos = position;
361     } else {
362         retPos = INVALID_POSITION;
363     }
364     return { true, move(bufferGuard), buf, retLen, hasPos, retPos };
365 }
366 
367 } // namespace ModuleFileIO
368 } // namespace DistributedFS
369 } // namespace OHOS
370