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