• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "truncate.h"
17 
18 #include <cstring>
19 #include <tuple>
20 #include <unistd.h>
21 
22 #include "common_func.h"
23 #include "file_utils.h"
24 #include "filemgmt_libhilog.h"
25 
26 namespace OHOS::FileManagement::ModuleFileIO {
27 using namespace std;
28 using namespace OHOS::FileManagement::LibN;
29 using namespace OHOS::DistributedFS;
30 
ParseJsFile(napi_env env,napi_value pathOrFdFromJsArg)31 static tuple<bool, FileInfo> ParseJsFile(napi_env env, napi_value pathOrFdFromJsArg)
32 {
33     auto [isPath, path, ignore] = NVal(env, pathOrFdFromJsArg).ToUTF8StringPath();
34     if (isPath) {
35         return { true, FileInfo { true, move(path), {} } };
36     }
37     auto [isFd, fd] = NVal(env, pathOrFdFromJsArg).ToInt32();
38     if (!isFd || fd < 0) {
39         HILOGE("Invalid fd");
40         NError(EINVAL).ThrowErr(env);
41         return { false, FileInfo { false, {}, {} } };
42     }
43     auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(fd, false);
44     if (fdg == nullptr) {
45         HILOGE("Failed to request heap memory.");
46         NError(ENOMEM).ThrowErr(env);
47         return { false, FileInfo { false, {}, {} } };
48     }
49     return { true, FileInfo { false, {}, move(fdg) } };
50 };
51 
TruncateCore(napi_env env,FileInfo & fileInfo,int64_t truncateLen)52 static NError TruncateCore(napi_env env, FileInfo &fileInfo, int64_t truncateLen)
53 {
54     if (fileInfo.isPath) {
55         std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> open_req = {
56             new uv_fs_t, CommonFunc::fs_req_cleanup };
57         if (!open_req) {
58             HILOGE("Failed to request heap memory.");
59             return NError(ENOMEM);
60         }
61         int ret = uv_fs_open(nullptr, open_req.get(), fileInfo.path.get(), O_RDWR,
62                              S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, nullptr);
63         if (ret < 0) {
64             HILOGE("Failed to open by libuv ret %{public}d", ret);
65             return NError(ret);
66         }
67         FDGuard fd(ret);
68         std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> ftruncate_req = {
69             new uv_fs_t, CommonFunc::fs_req_cleanup };
70         if (!ftruncate_req) {
71             HILOGE("Failed to request heap memory.");
72             return NError(ENOMEM);
73         }
74         ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), fd.GetFD(), truncateLen, nullptr);
75         if (ret < 0) {
76             HILOGE("Failed to truncate file by path ret %{public}d", ret);
77             return NError(ret);
78         }
79     } else {
80         std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> ftruncate_req = {
81             new uv_fs_t, CommonFunc::fs_req_cleanup };
82         if (!ftruncate_req) {
83             HILOGE("Failed to request heap memory.");
84             return NError(ENOMEM);
85         }
86         int ret = uv_fs_ftruncate(nullptr, ftruncate_req.get(), fileInfo.fdg->GetFD(), truncateLen, nullptr);
87         if (ret < 0) {
88             HILOGE("Failed to truncate file by fd for libuv error %{public}d", ret);
89             return NError(ret);
90         }
91     }
92     return NError(ERRNO_NOERR);
93 }
94 
Sync(napi_env env,napi_callback_info info)95 napi_value Truncate::Sync(napi_env env, napi_callback_info info)
96 {
97     NFuncArg funcArg(env, info);
98     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
99         HILOGE("Number of arguments unmatched");
100         NError(EINVAL).ThrowErr(env);
101         return nullptr;
102     }
103     auto [succ, fileInfo] = ParseJsFile(env, funcArg[NARG_POS::FIRST]);
104     if (!succ) {
105         NError(EINVAL).ThrowErr(env);
106         return nullptr;
107     }
108     int64_t truncateLen = 0;
109     if (funcArg.GetArgc() == NARG_CNT::TWO) {
110         tie(succ, truncateLen) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt64(truncateLen);
111         if (!succ || truncateLen < 0) {
112             HILOGE("Invalid truncate length");
113             NError(EINVAL).ThrowErr(env);
114             return nullptr;
115         }
116     }
117     auto err = TruncateCore(env, fileInfo, truncateLen);
118     if (err) {
119         err.ThrowErr(env);
120         return nullptr;
121     }
122 
123     return NVal::CreateUndefined(env).val_;
124 }
125 
Async(napi_env env,napi_callback_info info)126 napi_value Truncate::Async(napi_env env, napi_callback_info info)
127 {
128     NFuncArg funcArg(env, info);
129     if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) {
130         HILOGE("Number of arguments unmatched");
131         NError(EINVAL).ThrowErr(env);
132         return nullptr;
133     }
134     auto [succ, fileInfo] = ParseJsFile(env, funcArg[NARG_POS::FIRST]);
135     if (!succ) {
136         return nullptr;
137     }
138     int64_t truncateLen = 0;
139     if (funcArg.GetArgc() >= NARG_CNT::TWO) {
140         tie(succ, truncateLen) = NVal(env, funcArg[NARG_POS::SECOND]).ToInt64(truncateLen);
141         if (!succ || truncateLen < 0) {
142             HILOGE("Invalid truncate length");
143             NError(EINVAL).ThrowErr(env);
144             return nullptr;
145         }
146     }
147     auto cbExec = [fileInfo = make_shared<FileInfo>(move(fileInfo)), truncateLen, env = env]() -> NError {
148         return TruncateCore(env, *fileInfo, truncateLen);
149     };
150     auto cbCompl = [](napi_env env, NError err) -> NVal {
151         if (err) {
152             return { env, err.GetNapiErr(env) };
153         } else {
154             return NVal::CreateUndefined(env);
155         }
156     };
157     NVal thisVar(env, funcArg.GetThisVar());
158     if (funcArg.GetArgc() == NARG_CNT::ONE || (funcArg.GetArgc() == NARG_CNT::TWO &&
159         !NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function))) {
160         return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_TRUNCATE_NAME, cbExec, cbCompl).val_;
161     } else {
162         NVal cb(env, funcArg[((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD)]);
163         return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_TRUNCATE_NAME, cbExec, cbCompl).val_;
164     }
165 }
166 } // namespace OHOS::FileManagement::ModuleFileIO