• 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 #include "read_text.h"
16 
17 #include <fcntl.h>
18 #include <securec.h>
19 #include <sys/stat.h>
20 #include <tuple>
21 #include <unistd.h>
22 #include "../../common/file_helper/fd_guard.h"
23 #include "../../common/napi/n_async/n_async_work_callback.h"
24 #include "../../common/napi/n_async/n_async_work_promise.h"
25 #include "../../common/napi/n_func_arg.h"
26 #include "../common_func.h"
27 
28 namespace OHOS {
29 namespace DistributedFS {
30 namespace ModuleFileIO {
31 using namespace std;
32 
GetReadTextArg(napi_env env,napi_value argOption)33 static tuple<bool, ssize_t, bool, ssize_t, unique_ptr<char[]>, bool> GetReadTextArg(napi_env env, napi_value argOption)
34 {
35     NVal op(env, argOption);
36     ssize_t position = 0;
37     ssize_t len = 0;
38     bool succ = false;
39     bool hasOp = false;
40     bool hasLen = false;
41     unique_ptr<char[]> encoding;
42     if (op.HasProp("position")) {
43         tie(succ, position) = op.GetProp("position").ToInt32();
44         if (!succ) {
45             return { false, position, hasLen, len, nullptr, hasOp };
46         }
47         hasOp = true;
48     }
49     if (op.HasProp("length")) {
50         tie(succ, len) = op.GetProp("length").ToInt32();
51         if (!succ) {
52             return { false, position, hasLen, len, nullptr, hasOp };
53         }
54         hasOp = true;
55         hasLen = true;
56     }
57     if (op.HasProp("encoding")) {
58         tie(succ, encoding, ignore) = op.GetProp("encoding").ToUTF8String();
59         if (!succ) {
60             return { false, position, hasLen, len, nullptr, hasOp };
61         }
62         hasOp = true;
63     }
64     return { true, position, hasLen, len, move(encoding), hasOp };
65 }
66 
Sync(napi_env env,napi_callback_info info)67 napi_value ReadText::Sync(napi_env env, napi_callback_info info)
68 {
69     NFuncArg funcArg(env, info);
70     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
71         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
72         return nullptr;
73     }
74     unique_ptr<char[]> path;
75     bool succ = false;
76     FDGuard sfd;
77     tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
78     if (!succ) {
79         UniError(EINVAL).ThrowErr(env, "Invalid path");
80         return nullptr;
81     }
82     ssize_t position = 0;
83     ssize_t len = 0;
84     unique_ptr<char[]> encoding;
85     bool hasLen = false;
86     tie(succ, position, hasLen, len, encoding, ignore) = GetReadTextArg(env, funcArg[NARG_POS::SECOND]);
87     if (!succ) {
88         UniError(EINVAL).ThrowErr(env, "Invalid option");
89         return nullptr;
90     }
91     struct stat statbf;
92     int ret;
93     sfd.SetFD(open(path.get(), O_RDONLY));
94     if ((!sfd) || (fstat(sfd.GetFD(), &statbf) == -1)) {
95         UniError(errno).ThrowErr(env);
96         return nullptr;
97     }
98     if (position > statbf.st_size) {
99         UniError(EINVAL).ThrowErr(env, "Invalid position");
100         return nullptr;
101     }
102     len = !hasLen ? statbf.st_size : len;
103     len = ((len  < statbf.st_size) ? len : statbf.st_size);
104     std::unique_ptr<char[]> readbuf = std::make_unique<char[]>(len + 1);
105     if (readbuf == nullptr) {
106         UniError(EINVAL).ThrowErr(env, "file is too large");
107         return nullptr;
108     }
109     if (memset_s(readbuf.get(), len + 1, 0, len + 1) != EOK) {
110         UniError(errno).ThrowErr(env, "dfs mem error");
111         return nullptr;
112     }
113     ret = position > 0 ? pread(sfd.GetFD(), readbuf.get(), len, position) : read(sfd.GetFD(), readbuf.get(), len);
114     if (ret == -1) {
115         UniError(EINVAL).ThrowErr(env, "Invalid read file");
116         return nullptr;
117     }
118     return NVal::CreateUTF8String(env, readbuf.get(), ret).val_;
119 }
120 
AsyncExec(const std::string & path,std::shared_ptr<AsyncReadTextArg> arg,ssize_t position,bool hasLen,ssize_t len)121 UniError ReadText::AsyncExec(const std::string &path, std::shared_ptr<AsyncReadTextArg> arg, ssize_t position,
122     bool hasLen, ssize_t len)
123 {
124     if (arg == nullptr) {
125         return UniError(ENOMEM);
126     }
127 
128     FDGuard sfd;
129     struct stat statbf;
130     arg->len = len;
131     sfd.SetFD(open(path.c_str(), O_RDONLY));
132     if (sfd.GetFD() == -1) {
133         return UniError(EINVAL);
134     }
135     if (fstat(sfd.GetFD(), &statbf) == -1) {
136         return UniError(EINVAL);
137     }
138     if (position > statbf.st_size) {
139         return UniError(EINVAL);
140     }
141     if (!hasLen) {
142         arg->len = statbf.st_size;
143     }
144     arg->len = ((arg->len < statbf.st_size) ? arg->len : statbf.st_size);
145     arg->buf = std::make_unique<char[]>(arg->len);
146     if (arg->buf == nullptr) {
147         return UniError(ENOMEM);
148     }
149     if (position > 0) {
150         arg->len = pread(sfd.GetFD(), arg->buf.get(), arg->len, position);
151     } else {
152         arg->len = read(sfd.GetFD(), arg->buf.get(), arg->len);
153     }
154     if (arg->len == -1) {
155         return UniError(EINVAL);
156     }
157 
158     return UniError(ERRNO_NOERR);
159 }
160 
Async(napi_env env,napi_callback_info info)161 napi_value ReadText::Async(napi_env env, napi_callback_info info)
162 {
163     NFuncArg funcArg(env, info);
164     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
165         UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
166         return nullptr;
167     }
168     unique_ptr<char[]> path;
169     bool succ = false;
170     tie(succ, path, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String();
171     if (!succ) {
172         UniError(EINVAL).ThrowErr(env, "Invalid path");
173         return nullptr;
174     }
175     ssize_t position;
176     ssize_t len;
177     unique_ptr<char[]> encoding;
178     bool hasOp = false;
179     bool hasLen = false;
180     tie(succ, position, hasLen, len, encoding, hasOp) = GetReadTextArg(env, funcArg[NARG_POS::SECOND]);
181     if (!succ) {
182         UniError(EINVAL).ThrowErr(env, "Invalid option");
183         return nullptr;
184     }
185     auto arg = make_shared<AsyncReadTextArg>(NVal(env, funcArg.GetThisVar()));
186     if (arg == nullptr) {
187         return nullptr;
188     }
189     auto cbExec = [path = string(path.get()), arg, position, hasLen, len](napi_env env) -> UniError {
190         return AsyncExec(path, arg, position, hasLen, len);
191     };
192     auto cbComplete = [arg](napi_env env, UniError err) -> NVal {
193         if (err) {
194             return { env, err.GetNapiErr(env) };
195         } else {
196             return NVal::CreateUTF8String(env, arg->buf.get(), arg->len);
197         }
198     };
199     size_t argc = funcArg.GetArgc();
200     NVal thisVar(env, funcArg.GetThisVar());
201     if (argc == NARG_CNT::ONE || (argc == NARG_CNT::TWO && hasOp)) {
202         return NAsyncWorkPromise(env, thisVar).Schedule("FileIOReadText", cbExec, cbComplete).val_;
203     } else {
204         int cbIdx = !hasOp ? NARG_POS::SECOND : NARG_POS::THIRD;
205         NVal cb(env, funcArg[cbIdx]);
206         return NAsyncWorkCallback(env, thisVar, cb).Schedule("FileIOReadText", cbExec, cbComplete).val_;
207     }
208 }
209 } // namespace ModuleFileIO
210 } // namespace DistributedFS
211 } // namespace OHOS