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/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
GetActualBuf(napi_env env,void * rawBuf,int64_t bufLen,NVal op)35 static tuple<bool, void *, int> GetActualBuf(napi_env env, void *rawBuf, int64_t bufLen, NVal op)
36 {
37 bool succ = false;
38 void *realBuf = nullptr;
39 int64_t opOffset = 0;
40 if (op.HasProp("offset")) {
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, opOffset };
45 } else if (opOffset > bufLen) {
46 UniError(EINVAL).ThrowErr(env, "Invalid option.offset, buffer limit exceeded");
47 return { false, nullptr, opOffset };
48 } else {
49 realBuf = static_cast<uint8_t *>(rawBuf) + opOffset;
50 }
51 } else {
52 realBuf = rawBuf;
53 }
54
55 return { true, realBuf, opOffset };
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
GetCopyPathArg(napi_env env,napi_value srcPath,napi_value dstPath)85 tuple<bool, unique_ptr<char[]>, unique_ptr<char[]>> CommonFunc::GetCopyPathArg(napi_env env,
86 napi_value srcPath,
87 napi_value dstPath)
88 {
89 bool succ = false;
90 unique_ptr<char[]> src;
91 tie(succ, src, ignore) = NVal(env, srcPath).ToUTF8String();
92 if (!succ) {
93 return { false, nullptr, nullptr };
94 }
95
96 unique_ptr<char[]> dest;
97 tie(succ, dest, ignore) = NVal(env, dstPath).ToUTF8String();
98 if (!succ) {
99 return { false, nullptr, nullptr };
100 }
101 return make_tuple(succ, move(src), move(dest));
102 }
103
GetReadArg(napi_env env,napi_value readBuf,napi_value option)104 tuple<bool, void *, int64_t, bool, int64_t, int> CommonFunc::GetReadArg(napi_env env,
105 napi_value readBuf,
106 napi_value option)
107 {
108 bool succ = false;
109 void *retBuf = nullptr;
110 int64_t retLen;
111 bool posAssigned = false;
112 int64_t position;
113
114 NVal txt(env, readBuf);
115 void *buf = nullptr;
116 int64_t bufLen;
117 int offset = 0;
118 tie(succ, buf, bufLen) = txt.ToArraybuffer();
119 if (!succ) {
120 UniError(EINVAL).ThrowErr(env, "Invalid read buffer, expect arraybuffer");
121 return { false, nullptr, 0, posAssigned, position, offset };
122 }
123
124 NVal op = NVal(env, option);
125 tie(succ, retBuf, offset) = GetActualBuf(env, buf, bufLen, op);
126 if (!succ) {
127 return { false, nullptr, 0, posAssigned, position, offset };
128 }
129
130 int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
131 tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
132 if (!succ) {
133 return { false, nullptr, 0, posAssigned, position, offset };
134 }
135
136 tie(succ, position) = op.GetProp("position").ToInt64();
137 if (succ && position >= 0) {
138 posAssigned = true;
139 }
140 return { true, retBuf, retLen, posAssigned, position, offset };
141 }
142
DecodeString(napi_env env,NVal jsStr,NVal encoding)143 static tuple<bool, unique_ptr<char[]>, int64_t> DecodeString(napi_env env, NVal jsStr, NVal encoding)
144 {
145 unique_ptr<char[]> buf;
146 if (!jsStr.TypeIs(napi_string)) {
147 return { false, nullptr, 0 };
148 }
149
150 bool succ = false;
151 if (!encoding) {
152 return jsStr.ToUTF8String();
153 }
154
155 unique_ptr<char[]> encodingBuf;
156 tie(succ, encodingBuf, ignore) = encoding.ToUTF8String();
157 if (!succ) {
158 return { false, nullptr, 0 };
159 }
160 string encodingStr(encodingBuf.release());
161 if (encodingStr == "utf-8") {
162 return jsStr.ToUTF8String();
163 } else if (encodingStr == "utf-16") {
164 return jsStr.ToUTF16String();
165 } else {
166 return { false, nullptr, 0 };
167 }
168 }
169
170 // 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)171 tuple<bool, unique_ptr<char[]>, void *, int64_t, bool, int64_t> CommonFunc::GetWriteArg(napi_env env,
172 napi_value argWBuf,
173 napi_value argOption)
174 {
175 void *retBuf = nullptr;
176 int64_t retLen;
177 bool hasPos = false;
178 int64_t retPos;
179
180 /* To get write buffer */
181 bool succ = false;
182 void *buf = nullptr;
183 int64_t bufLen;
184 NVal op(env, argOption);
185 NVal jsBuffer(env, argWBuf);
186 unique_ptr<char[]> bufferGuard;
187 tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
188 if (!succ) {
189 tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
190 if (!succ) {
191 UniError(EINVAL).ThrowErr(env, "Illegal write buffer or encoding");
192 return { false, nullptr, nullptr, 0, hasPos, retPos };
193 }
194 } else {
195 buf = bufferGuard.get();
196 }
197
198 tie(succ, retBuf, ignore) = GetActualBuf(env, buf, bufLen, op);
199 if (!succ) {
200 return { false, nullptr, nullptr, 0, hasPos, retPos };
201 }
202
203 int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
204 tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
205 if (!succ) {
206 return { false, nullptr, nullptr, 0, hasPos, retPos };
207 }
208
209 /* To parse options - Where to begin writing */
210 if (op.HasProp("position")) {
211 int32_t position = 0;
212 tie(succ, position) = op.GetProp("position").ToInt32();
213 if (!succ || position < 0) {
214 UniError(EINVAL).ThrowErr(env, "option.position shall be positive number");
215 return { false, nullptr, nullptr, 0, hasPos, retPos };
216 }
217 hasPos = true;
218 retPos = position;
219 } else {
220 retPos = INVALID_POSITION;
221 }
222 return { true, move(bufferGuard), retBuf, retLen, hasPos, retPos };
223 }
224 } // namespace ModuleFileIO
225 } // namespace DistributedFS
226 } // namespace OHOS
227