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