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
16 #include "fs_file.h"
17
18 #include <sys/file.h>
19
20 #include "file_uri.h"
21 #include "file_utils.h"
22 #include "filemgmt_libhilog.h"
23 #include "fs_utils.h"
24
25 namespace OHOS {
26 namespace FileManagement {
27 namespace ModuleFileIO {
28 using namespace std;
29
30 #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
RealPathCore(const string & srcPath)31 static tuple<int, unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *>> RealPathCore(const string &srcPath)
32 {
33 std::unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *> realpathReq = { new (std::nothrow) uv_fs_t,
34 FsUtils::FsReqCleanup };
35 if (!realpathReq) {
36 HILOGE("Failed to request heap memory.");
37 return { ENOMEM, move(realpathReq) };
38 }
39 int ret = uv_fs_realpath(nullptr, realpathReq.get(), srcPath.c_str(), nullptr);
40 return { ret, move(realpathReq) };
41 }
42
RemoveEntity()43 void FsFile::RemoveEntity()
44 {
45 fileEntity = nullptr;
46 }
47
GetFD() const48 FsResult<int32_t> FsFile::GetFD() const
49 {
50 if (!fileEntity) {
51 HILOGE("Failed to get file entity");
52 return FsResult<int32_t>::Error(EINVAL);
53 }
54 return FsResult<int32_t>::Success(fileEntity->fd_.get()->GetFD());
55 }
56
GetPath() const57 FsResult<string> FsFile::GetPath() const
58 {
59 if (!fileEntity) {
60 HILOGE("Failed to get file entity");
61 return FsResult<string>::Error(EINVAL);
62 }
63 if (fileEntity->uri_.length() != 0) {
64 AppFileService::ModuleFileUri::FileUri fileUri(fileEntity->uri_);
65 return FsResult<string>::Success(fileUri.GetPath());
66 }
67 auto [realPathRes, realPath] = RealPathCore(fileEntity->path_);
68 if (realPathRes != ERRNO_NOERR) {
69 HILOGE("Failed to get real path");
70 return FsResult<string>::Error(realPathRes);
71 }
72 return FsResult<string>::Success(string(static_cast<const char *>(realPath->ptr)));
73 }
74
GetName() const75 FsResult<string> FsFile::GetName() const
76 {
77 if (!fileEntity) {
78 HILOGE("Failed to get file entity");
79 return FsResult<string>::Error(EINVAL);
80 }
81 if (fileEntity->uri_.length() != 0) {
82 AppFileService::ModuleFileUri::FileUri fileUri(fileEntity->uri_);
83 return FsResult<string>::Success(fileUri.GetName());
84 }
85 auto [realPathRes, realPath] = RealPathCore(fileEntity->path_);
86 if (realPathRes != ERRNO_NOERR) {
87 HILOGE("Failed to get real path");
88 return FsResult<string>::Error(realPathRes);
89 }
90 string path(static_cast<const char *>(realPath->ptr));
91 auto pos = path.find_last_of('/');
92 if (pos == string::npos) {
93 HILOGE("Failed to split filename from path");
94 return FsResult<string>::Error(ENOENT);
95 }
96 return FsResult<string>::Success(path.substr(pos + 1));
97 }
98
GetParent() const99 FsResult<string> FsFile::GetParent() const
100 {
101 if (!fileEntity) {
102 HILOGE("Failed to get file entity");
103 return FsResult<string>::Error(EINVAL);
104 }
105
106 string path(fileEntity->path_);
107 if (fileEntity->uri_.length() != 0) {
108 AppFileService::ModuleFileUri::FileUri fileUri(fileEntity->uri_);
109 path = fileUri.GetPath();
110 } else {
111 auto [realPathRes, realPath] = RealPathCore(path);
112 if (realPathRes) {
113 HILOGE("Failed to get real path");
114 return FsResult<string>::Error(realPathRes);
115 }
116 path = static_cast<const char *>(realPath->ptr);
117 }
118 auto pos = path.find_last_of('/');
119 if (pos == string::npos) {
120 HILOGE("Failed to split filename from path");
121 return FsResult<string>::Error(ENOENT);
122 }
123 return FsResult<string>::Success(path.substr(0, pos));
124 }
125
Lock(bool exclusive) const126 FsResult<void> FsFile::Lock(bool exclusive) const
127 {
128 if (!fileEntity) {
129 HILOGE("Failed to get file entity");
130 return FsResult<void>::Error(EINVAL);
131 }
132
133 if (!fileEntity || !fileEntity->fd_.get()) {
134 HILOGE("File has been closed in Lock cbExec possibly");
135 return FsResult<void>::Error(EIO);
136 }
137 int ret = 0;
138 auto mode = exclusive ? LOCK_EX : LOCK_SH;
139 ret = flock(fileEntity->fd_.get()->GetFD(), mode);
140 if (ret < 0) {
141 HILOGE("Failed to lock file");
142 return FsResult<void>::Error(errno);
143 } else {
144 return FsResult<void>::Success();
145 }
146 }
147
TryLock(bool exclusive) const148 FsResult<void> FsFile::TryLock(bool exclusive) const
149 {
150 if (!fileEntity) {
151 HILOGE("Failed to get file entity");
152 return FsResult<void>::Error(EINVAL);
153 }
154
155 int ret = 0;
156 auto mode = static_cast<uint32_t>(exclusive ? LOCK_EX : LOCK_SH);
157 ret = flock(fileEntity->fd_.get()->GetFD(), mode | LOCK_NB);
158 if (ret < 0) {
159 HILOGE("Failed to try to lock file");
160 return FsResult<void>::Error(errno);
161 }
162
163 return FsResult<void>::Success();
164 }
165
UnLock() const166 FsResult<void> FsFile::UnLock() const
167 {
168 if (!fileEntity) {
169 HILOGE("Failed to get file entity");
170 return FsResult<void>::Error(EINVAL);
171 }
172
173 int ret = 0;
174 ret = flock(fileEntity->fd_.get()->GetFD(), LOCK_UN);
175 if (ret < 0) {
176 HILOGE("Failed to unlock file");
177 return FsResult<void>::Error(errno);
178 }
179 return FsResult<void>::Success();
180 }
181 #endif
182
Constructor()183 FsResult<FsFile *> FsFile::Constructor()
184 {
185 auto rafEntity = CreateUniquePtr<FileEntity>();
186 if (rafEntity == nullptr) {
187 HILOGE("Failed to request heap memory.");
188 return FsResult<FsFile *>::Error(ENOMEM);
189 }
190 FsFile *fsFilePtr = new FsFile(move(rafEntity));
191
192 if (fsFilePtr == nullptr) {
193 HILOGE("Failed to create FsFile object on heap.");
194 return FsResult<FsFile *>::Error(ENOMEM);
195 }
196
197 return FsResult<FsFile *>::Success(move(fsFilePtr));
198 }
199
200 } // namespace ModuleFileIO
201 } // namespace FileManagement
202 } // namespace OHOS
203