• 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/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 
ConvertJsFlags(int & flags)85 int CommonFunc::ConvertJsFlags(int &flags)
86 {
87     static constexpr int USR_O_RDONLY = 00;
88     static constexpr int USR_O_WRONLY = 01;
89     static constexpr int USR_O_RDWR = 02;
90     static constexpr int USR_O_CREAT = 0100;
91     static constexpr int USR_O_EXCL = 0200;
92     static constexpr int USR_O_TRUNC = 01000;
93     static constexpr int USR_O_APPEND = 02000;
94     static constexpr int USR_O_NONBLOCK = 04000;
95     static constexpr int USR_O_DIRECTORY = 0200000;
96     static constexpr int USR_O_NOFOLLOW = 0400000;
97     static constexpr int USR_O_SYNC = 04010000;
98 
99     int flagsABI = 0;
100     flagsABI |= ((flags & USR_O_RDONLY) == USR_O_RDONLY) ? O_RDONLY : 0;
101     flagsABI |= ((flags & USR_O_WRONLY) == USR_O_WRONLY) ? O_WRONLY : 0;
102     flagsABI |= ((flags & USR_O_RDWR) == USR_O_RDWR) ? O_RDWR : 0;
103     flagsABI |= ((flags & USR_O_CREAT) == USR_O_CREAT) ? O_CREAT : 0;
104     flagsABI |= ((flags & USR_O_EXCL) == USR_O_EXCL) ? O_EXCL : 0;
105     flagsABI |= ((flags & USR_O_TRUNC) == USR_O_TRUNC) ? O_TRUNC : 0;
106     flagsABI |= ((flags & USR_O_APPEND) == USR_O_APPEND) ? O_APPEND : 0;
107     flagsABI |= ((flags & USR_O_NONBLOCK) == USR_O_NONBLOCK) ? O_NONBLOCK : 0;
108     flagsABI |= ((flags & USR_O_DIRECTORY) == USR_O_DIRECTORY) ? O_DIRECTORY : 0;
109     flagsABI |= ((flags & USR_O_NOFOLLOW) == USR_O_NOFOLLOW) ? O_NOFOLLOW : 0;
110     flagsABI |= ((flags & USR_O_SYNC) == USR_O_SYNC) ? O_SYNC : 0;
111     flags = flagsABI;
112     return flagsABI;
113 }
114 
GetCopyPathArg(napi_env env,napi_value srcPath,napi_value dstPath)115 tuple<bool, unique_ptr<char[]>, unique_ptr<char[]>> CommonFunc::GetCopyPathArg(napi_env env,
116     napi_value srcPath,
117     napi_value dstPath)
118 {
119     bool succ = false;
120     unique_ptr<char[]> src;
121     tie(succ, src, ignore) = NVal(env, srcPath).ToUTF8String();
122     if (!succ) {
123         return { false, nullptr, nullptr };
124     }
125 
126     unique_ptr<char[]> dest;
127     tie(succ, dest, ignore) = NVal(env, dstPath).ToUTF8String();
128     if (!succ) {
129         return { false, nullptr, nullptr };
130     }
131     return make_tuple(succ, move(src), move(dest));
132 }
133 
GetReadArg(napi_env env,napi_value readBuf,napi_value option)134 tuple<bool, void *, int64_t, bool, int64_t, int> CommonFunc::GetReadArg(napi_env env,
135                                                                         napi_value readBuf,
136                                                                         napi_value option)
137 {
138     bool succ = false;
139     void *retBuf = nullptr;
140     int64_t retLen;
141     bool posAssigned = false;
142     int64_t position;
143 
144     NVal txt(env, readBuf);
145     void *buf = nullptr;
146     int64_t bufLen;
147     int offset = 0;
148     tie(succ, buf, bufLen) = txt.ToArraybuffer();
149     if (!succ) {
150         UniError(EINVAL).ThrowErr(env, "Invalid read buffer, expect arraybuffer");
151         return { false, nullptr, 0, posAssigned, position, offset };
152     }
153 
154     NVal op = NVal(env, option);
155     tie(succ, retBuf, offset) = GetActualBuf(env, buf, bufLen, op);
156     if (!succ) {
157         return { false, nullptr, 0, posAssigned, position, offset };
158     }
159 
160     int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
161     tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
162     if (!succ) {
163         return { false, nullptr, 0, posAssigned, position, offset };
164     }
165 
166     if (op.HasProp("position")) {
167         tie(succ, position) = op.GetProp("position").ToInt64();
168         if (succ && position >= 0) {
169             posAssigned = true;
170         } else {
171             UniError(EINVAL).ThrowErr(env, "option.position shall be positive number");
172             return { false, nullptr, 0, posAssigned, position, offset };
173         }
174     }
175 
176     return { true, retBuf, retLen, posAssigned, position, offset };
177 }
178 
DecodeString(napi_env env,NVal jsStr,NVal encoding)179 static tuple<bool, unique_ptr<char[]>, int64_t> DecodeString(napi_env env, NVal jsStr, NVal encoding)
180 {
181     unique_ptr<char[]> buf;
182     if (!jsStr.TypeIs(napi_string)) {
183         return { false, nullptr, 0 };
184     }
185 
186     bool succ = false;
187     if (!encoding) {
188         return jsStr.ToUTF8String();
189     }
190 
191     unique_ptr<char[]> encodingBuf;
192     tie(succ, encodingBuf, ignore) = encoding.ToUTF8String();
193     if (!succ) {
194         return { false, nullptr, 0 };
195     }
196     string encodingStr(encodingBuf.release());
197     if (encodingStr == "utf-8") {
198         return jsStr.ToUTF8String();
199     } else if (encodingStr == "utf-16") {
200         return jsStr.ToUTF16String();
201     } else {
202         return { false, nullptr, 0 };
203     }
204 }
205 
206 // Is everything 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)207 tuple<bool, unique_ptr<char[]>, void *, int64_t, bool, int64_t> CommonFunc::GetWriteArg(napi_env env,
208                                                                                         napi_value argWBuf,
209                                                                                         napi_value argOption)
210 {
211     void *retBuf = nullptr;
212     int64_t retLen;
213     bool hasPos = false;
214     int64_t retPos;
215 
216     /* To get write buffer */
217     bool succ = false;
218     void *buf = nullptr;
219     int64_t bufLen;
220     NVal op(env, argOption);
221     NVal jsBuffer(env, argWBuf);
222     unique_ptr<char[]> bufferGuard;
223     tie(succ, bufferGuard, bufLen) = DecodeString(env, jsBuffer, op.GetProp("encoding"));
224     if (!succ) {
225         tie(succ, buf, bufLen) = NVal(env, argWBuf).ToArraybuffer();
226         if (!succ) {
227             UniError(EINVAL).ThrowErr(env, "Illegal write buffer or encoding");
228             return { false, nullptr, nullptr, 0, hasPos, retPos };
229         }
230     } else {
231         buf = bufferGuard.get();
232     }
233 
234     tie(succ, retBuf, ignore) = GetActualBuf(env, buf, bufLen, op);
235     if (!succ) {
236         return { false, nullptr, nullptr, 0, hasPos, retPos };
237     }
238 
239     int64_t bufOff = static_cast<uint8_t *>(retBuf) - static_cast<uint8_t *>(buf);
240     tie(succ, retLen) = GetActualLen(env, bufLen, bufOff, op);
241     if (!succ) {
242         return { false, nullptr, nullptr, 0, hasPos, retPos };
243     }
244 
245     /* To parse options - Where to begin writing */
246     if (op.HasProp("position")) {
247         int32_t position = 0;
248         tie(succ, position) = op.GetProp("position").ToInt32();
249         if (!succ || position < 0) {
250             UniError(EINVAL).ThrowErr(env, "option.position shall be positive number");
251             return { false, nullptr, nullptr, 0, hasPos, retPos };
252         }
253         hasPos = true;
254         retPos = position;
255     } else {
256         retPos = INVALID_POSITION;
257     }
258     return { true, move(bufferGuard), retBuf, retLen, hasPos, retPos };
259 }
260 } // namespace ModuleFileIO
261 } // namespace DistributedFS
262 } // namespace OHOS
263