• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/uni_error.h"
28 
29 namespace OHOS {
30 namespace DistributedFS {
31 namespace ModuleFileIO {
32 using namespace std;
33 
GetActualBuf(napi_env env,void * rawBuf,int64_t bufLen,NVal op)34 static tuple<bool, void *> GetActualBuf(napi_env env, void *rawBuf, int64_t bufLen, NVal op)
35 {
36     bool succ = false;
37     void *realBuf = nullptr;
38 
39     if (op.HasProp("offset")) {
40         int64_t opOffset;
41         tie(succ, opOffset) = op.GetProp("offset").ToInt64();
42         if (!succ || opOffset < 0) {
43             UniError(EINVAL).ThrowErr(env, "Invalid option.offset, positive integer is desired");
44             return { false, nullptr };
45         } else if (opOffset > bufLen) {
46             UniError(EINVAL).ThrowErr(env, "Invalid option.offset, buffer limit exceeded");
47             return { false, nullptr };
48         } else {
49             realBuf = static_cast<uint8_t *>(rawBuf) + opOffset;
50         }
51     } else {
52         realBuf = rawBuf;
53     }
54 
55     return { true, realBuf };
56 }
57 
GetActualLen(napi_env env,int64_t bufLen,int64_t bufOff,NVal op)58 static tuple<bool, size_t> GetActualLen(napi_env env, int64_t bufLen, int64_t bufOff, NVal op)
59 {
60     bool succ = false;
61     int64_t retLen;
62 
63     if (op.HasProp("length")) {
64         int64_t opLength;
65         tie(succ, opLength) = op.GetProp("length").ToInt64();
66         if (!succ) {
67             UniError(EINVAL).ThrowErr(env, "Invalid option.length, expect integer");
68             return { false, 0 };
69         }
70         if (opLength < 0) {
71             retLen = bufLen - bufOff;
72         } else if (opLength + bufOff > bufLen) {
73             UniError(EINVAL).ThrowErr(env, "Invalid option.length, buffer limit exceeded");
74             return { false, 0 };
75         } else {
76             retLen = opLength;
77         }
78     } else {
79         retLen = bufLen - bufOff;
80     }
81 
82     return { true, retLen };
83 }
84 
GetReadArg(napi_env env,napi_value readBuf,napi_value option)85 tuple<bool, void *, int64_t, bool, int64_t> CommonFunc::GetReadArg(napi_env env, napi_value readBuf, napi_value option)
86 {
87     bool succ = false;
88     void *retBuf = nullptr;
89     int64_t retLen;
90     bool posAssigned = false;
91     int64_t position;
92 
93     NVal txt(env, readBuf);
94     void *buf = nullptr;
95     int64_t bufLen;
96     tie(succ, buf, bufLen) = txt.ToArraybuffer();
97     if (!succ) {
98         UniError(EINVAL).ThrowErr(env, "Invalid read buffer, expect arraybuffer");
99         return { false, nullptr, 0, posAssigned, position };
100     }
101 
102     NVal op = NVal(env, option);
103     tie(succ, retBuf) = GetActualBuf(env, buf, bufLen, op);
104     if (!succ) {
105         return { false, nullptr, 0, posAssigned, position };
106     }
107 
108     int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
109     tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
110     if (!succ) {
111         return { false, nullptr, 0, posAssigned, position };
112     }
113 
114     tie(succ, position) = op.GetProp("position").ToInt64();
115     if (succ && position >= 0) {
116         posAssigned = true;
117     }
118     return { true, retBuf, retLen, posAssigned, position };
119 }
120 
DecodeString(napi_env env,NVal jsStr,NVal encoding)121 static tuple<bool, unique_ptr<char[]>, int64_t> DecodeString(napi_env env, NVal jsStr, NVal encoding)
122 {
123     unique_ptr<char[]> buf;
124     if (!jsStr.TypeIs(napi_string)) {
125         return { false, nullptr, 0 };
126     }
127 
128     bool succ = false;
129     if (!encoding) {
130         return jsStr.ToUTF8String();
131     }
132 
133     unique_ptr<char[]> encodingBuf;
134     tie(succ, encodingBuf, ignore) = encoding.ToUTF8String();
135     if (!succ) {
136         return { false, nullptr, 0 };
137     }
138     string encodingStr(encodingBuf.release());
139     if (encodingStr == "utf-8") {
140         return jsStr.ToUTF8String();
141     } else if (encodingStr == "utf-16") {
142         return jsStr.ToUTF16String();
143     } else {
144         return { false, nullptr, 0 };
145     }
146 }
147 
148 // Is everthing ok? Do we need to free memory? What's the three args required by fwrite? Where to start writing?
GetWriteArg(napi_env env,napi_value argWBuf,napi_value argOption)149 tuple<bool, unique_ptr<char[]>, void *, int64_t, bool, int64_t> CommonFunc::GetWriteArg(napi_env env,
150                                                                                         napi_value argWBuf,
151                                                                                         napi_value argOption)
152 {
153     void *retBuf = nullptr;
154     int64_t retLen;
155     bool hasPos = false;
156     int64_t retPos;
157 
158     /* To get write buffer */
159     bool succ = false;
160     void *buf = nullptr;
161     int64_t bufLen;
162     NVal op(env, argOption);
163     NVal jsBuffer(env, argWBuf);
164     unique_ptr<char[]> bufferGuard;
165     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
166     if (!succ) {
167         tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
168         if (!succ) {
169             UniError(EINVAL).ThrowErr(env, "Illegal write buffer or encoding");
170             return { false, nullptr, nullptr, 0, hasPos, retPos };
171         }
172     } else {
173         buf = bufferGuard.get();
174     }
175 
176     tie(succ, retBuf) = GetActualBuf(env, buf, bufLen, op);
177     if (!succ) {
178         return { false, nullptr, nullptr, 0, hasPos, retPos };
179     }
180 
181     int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
182     tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
183     if (!succ) {
184         return { false, nullptr, nullptr, 0, hasPos, retPos };
185     }
186 
187     /* To parse options - Where to begin writing */
188     if (op.HasProp("position")) {
189         int32_t position = 0;
190         tie(succ, position) = op.GetProp("position").ToInt32();
191         if (!succ || position < 0) {
192             UniError(EINVAL).ThrowErr(env, "option.position shall be positive number");
193             return { false, nullptr, nullptr, 0, hasPos, retPos };
194         }
195         hasPos = true;
196         retPos = position;
197     } else {
198         retPos = INVALID_POSITION;
199     }
200     return { true, move(bufferGuard), retBuf, retLen, hasPos, retPos };
201 }
202 } // namespace ModuleFileIO
203 } // namespace DistributedFS
204 } // namespace OHOS
205