• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "create_randomaccessfile_core.h"
16 
17 #include <securec.h>
18 
19 #include "file_entity.h"
20 #include "file_utils.h"
21 #include "filemgmt_libhilog.h"
22 #include "fs_randomaccessfile.h"
23 #include "fs_utils.h"
24 #include "randomaccessfile_entity.h"
25 
26 namespace OHOS {
27 namespace FileManagement {
28 namespace ModuleFileIO {
29 using namespace std;
30 
ParseStringToFileInfo(const string & path)31 static tuple<bool, FileInfo, int> ParseStringToFileInfo(const string &path)
32 {
33     OHOS::DistributedFS::FDGuard sfd;
34     auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(sfd, false);
35     if (fdg == nullptr) {
36         HILOGE("Failed to request heap memory.");
37         return { false, FileInfo { false, nullptr, nullptr }, ENOMEM};
38     }
39     size_t length = path.length() + 1;
40     auto chars = std::make_unique<char[]>(length);
41     auto ret = strncpy_s(chars.get(), length, path.c_str(), length - 1);
42     if (ret != EOK) {
43         HILOGE("Copy file path failed!");
44         return { false, FileInfo { false, nullptr, nullptr }, ENOMEM};
45     }
46     return { true, FileInfo { true, move(chars), move(fdg) }, ERRNO_NOERR};
47 }
48 
ParseFdToFileInfo(const int32_t & fd)49 static tuple<bool, FileInfo, int> ParseFdToFileInfo(const int32_t &fd)
50 {
51     if (fd < 0) {
52         HILOGE("Invalid fd");
53         return { false, FileInfo { false, nullptr, nullptr }, EINVAL};
54     }
55     auto dupFd = dup(fd);
56     if (dupFd < 0) {
57         HILOGE("Failed to get valid fd, fail reason: %{public}s, fd: %{public}d", strerror(errno), fd);
58         return { false, FileInfo { false, nullptr, nullptr }, EINVAL};
59     }
60     auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(dupFd, false);
61     if (fdg == nullptr) {
62         HILOGE("Failed to request heap memory.");
63         close(dupFd);
64         return { false, FileInfo { false, nullptr, nullptr }, ENOMEM};
65     }
66     return { true, FileInfo { false, nullptr, move(fdg) }, ERRNO_NOERR};
67 }
68 
ValidRafOptions(const optional<RandomAccessFileOptions> & options)69 static tuple<bool, int64_t, int64_t> ValidRafOptions(const optional<RandomAccessFileOptions> &options)
70 {
71     RandomAccessFileOptions op = options.value();
72     int64_t opStart = INVALID_POS;
73     int64_t opEnd = INVALID_POS;
74 
75     optional<int64_t> startOp = op.start;
76     optional<int64_t> endOp = op.end;
77 
78     if (startOp.has_value()) {
79         int64_t start = 0;
80         start = startOp.value();
81         if (start < 0) {
82             HILOGE("Invalid option.start, positive integer is desired");
83             return {false, opStart, opEnd};
84         }
85         opStart = start;
86     }
87     if (endOp.has_value()) {
88         int64_t end = 0;
89         end = endOp.value();
90         if (end < 0) {
91             HILOGE("Invalid option.end, positive integer is desired");
92             return {false, opStart, opEnd};
93         }
94         opEnd = end;
95     }
96     return {true, opStart, opEnd};
97 }
98 
ValidAndConvertFlags(const optional<int32_t> & mode,const optional<RandomAccessFileOptions> & options,FileInfo & fileInfo)99 static tuple<bool, uint32_t, int64_t, int64_t> ValidAndConvertFlags(const optional<int32_t> &mode,
100     const optional<RandomAccessFileOptions> &options, FileInfo &fileInfo)
101 {
102     uint32_t flags = O_RDONLY;
103     int64_t start = INVALID_POS;
104     int64_t end = INVALID_POS;
105     if (fileInfo.isPath && mode.has_value()) {
106         auto modeValue = mode.value();
107         if (modeValue < 0) {
108             HILOGE("Invalid flags");
109             return {false, flags, start, end};
110         }
111         flags = FsUtils::ConvertFlags(static_cast<uint32_t>(modeValue));
112     }
113 
114     if (options.has_value()) {
115         auto [succOpt, start, end] = ValidRafOptions(options);
116         if (!succOpt) {
117             HILOGE("Invalid RandomAccessFile options");
118             return {false, flags, start, end};
119         }
120     }
121 
122     return {true, flags, start, end};
123 }
124 
InstantiateRandomAccessFile(unique_ptr<DistributedFS::FDGuard> fdg,int64_t fp,int64_t start=INVALID_POS,int64_t end=INVALID_POS)125 static FsResult<FsRandomAccessFile *> InstantiateRandomAccessFile(unique_ptr<DistributedFS::FDGuard> fdg,
126                                                                   int64_t fp,
127                                                                   int64_t start = INVALID_POS,
128                                                                   int64_t end = INVALID_POS)
129 {
130     FsResult<FsRandomAccessFile *> result = FsRandomAccessFile::Constructor();
131     if (!result.IsSuccess()) {
132         HILOGE("Failed to instantiate class");
133         return FsResult<FsRandomAccessFile *>::Error(EIO);
134     }
135 
136     const FsRandomAccessFile *objRAF = result.GetData().value();
137     if (!objRAF) {
138         HILOGE("Cannot instantiate randomaccessfile");
139         return FsResult<FsRandomAccessFile *>::Error(EIO);
140     }
141 
142     auto *rafEntity = objRAF->GetRAFEntity();
143     if (!rafEntity) {
144         HILOGE("Cannot instantiate randomaccessfile because of void entity");
145         return FsResult<FsRandomAccessFile *>::Error(EIO);
146     }
147     rafEntity->fd.swap(fdg);
148     rafEntity->filePointer = fp;
149     rafEntity->start = start;
150     rafEntity->end = end;
151     return result;
152 }
153 
DoCreateRandomAccessFile(const string & path,const optional<int32_t> & mode,const optional<RandomAccessFileOptions> & options)154 FsResult<FsRandomAccessFile *> CreateRandomAccessFileCore::DoCreateRandomAccessFile(
155     const string &path, const optional<int32_t> &mode, const optional<RandomAccessFileOptions> &options)
156 {
157     auto [succ, fileInfo, err] = ParseStringToFileInfo(path);
158     if (!succ) {
159         return FsResult<FsRandomAccessFile *>::Error(err);
160     }
161 
162     auto [succFlags, flags, ignoreStart, ignoreEnd] = ValidAndConvertFlags(mode, options, fileInfo);
163     if (!succFlags) {
164         return FsResult<FsRandomAccessFile *>::Error(EINVAL);
165     }
166 
167     unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup)*> openReq = { new uv_fs_t, FsUtils::FsReqCleanup };
168     if (!openReq) {
169         HILOGE("Failed to request heap memory.");
170         return FsResult<FsRandomAccessFile *>::Error(ENOMEM);
171     }
172 
173     int ret = uv_fs_open(nullptr, openReq.get(), fileInfo.path.get(), flags, S_IRUSR |
174         S_IWUSR | S_IRGRP | S_IWGRP, NULL);
175     if (ret < 0) {
176         return FsResult<FsRandomAccessFile *>::Error(ret);
177     }
178 
179     fileInfo.fdg->SetFD(openReq.get()->result, false);
180 
181     if (options.has_value()) {
182         auto [succ, start, end] = ValidRafOptions(options);
183         if (succ) {
184             return InstantiateRandomAccessFile(move(fileInfo.fdg), 0, start, end);
185         }
186     }
187     return InstantiateRandomAccessFile(move(fileInfo.fdg), 0);
188 }
189 
DoCreateRandomAccessFile(const int32_t & fd,const optional<RandomAccessFileOptions> & options)190 FsResult<FsRandomAccessFile *> CreateRandomAccessFileCore::DoCreateRandomAccessFile(
191     const int32_t &fd, const optional<RandomAccessFileOptions> &options)
192 {
193     auto [succ, fileInfo, err] = ParseFdToFileInfo(fd);
194     if (!succ) {
195         return FsResult<FsRandomAccessFile *>::Error(err);
196     }
197     if (options.has_value()) {
198         auto [succ, start, end] = ValidRafOptions(options);
199         if (succ) {
200             return InstantiateRandomAccessFile(move(fileInfo.fdg), 0, start, end);
201         }
202     }
203     return InstantiateRandomAccessFile(move(fileInfo.fdg), 0);
204 }
205 
206 } // namespace ModuleFileIO
207 } // namespace FileManagement
208 } // namespace OHOS