From 7a8690ebe8c9b6c1af0b5cedc13cea461d765723 Mon Sep 17 00:00:00 2001 From: atreeof_wind Date: Fri, 10 May 2024 10:53:49 +0800 Subject: [PATCH 1/2] [file]:add code Signed-off-by: atreeof_wind --- interfaces/kits/cj/src/file_impl.cpp | 381 +++++++++++++++++++++++++++ interfaces/kits/cj/src/file_impl.h | 80 ++++++ 2 files changed, 461 insertions(+) create mode 100644 interfaces/kits/cj/src/file_impl.cpp create mode 100644 interfaces/kits/cj/src/file_impl.h diff --git a/interfaces/kits/cj/src/file_impl.cpp b/interfaces/kits/cj/src/file_impl.cpp new file mode 100644 index 000000000..a385f77cf --- /dev/null +++ b/interfaces/kits/cj/src/file_impl.cpp @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ffi_remote_data.h" +#include "cj_common_ffi.h" +#include "uni_error.h" +#include "uri.h" +#include "open.h" +#include "datashare_helper.h" +#include "utils.h" +#include "iremote_stub.h" +#include "file_uri.h" +#include "want.h" +#include "ability_manager_client.h" +#include "remote_uri.h" +#include "file_utils.h" +#include "securec.h" +#include "file_impl.h" + +static const std::string PROCEDURE_OPEN_NAME = "FileIOOpen"; +static const std::string MEDIALIBRARY_DATA_URI = "datashare:///media"; +static const std::string FILE_DATA_URI = "file://"; +static const std::string PATH_SHARE = "/data/storage/el2/share"; +static const std::string MODE_RW = "/rw/"; +static const std::string MODE_R = "/r/"; +static const std::string DOCS = "docs"; +static const std::string DATASHARE = "datashare"; +static const std::string SCHEME_BROKER = "content"; +constexpr uint32_t MAX_WANT_FLAG = 4; + +namespace { +using Uri = OHOS::Uri; +using namespace OHOS; +using namespace DistributedFS; +using namespace OHOS::CJSystemapi; +using namespace OHOS::CJSystemapi::FileFs; +using namespace OHOS::FileManagement; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::DistributedFS::ModuleRemoteUri; +using namespace std; + +static int OpenFileByPath(const std::string &path, unsigned int mode) +{ + std::unique_ptr open_req = { + new uv_fs_t, CommonFunc::FsReqCleanup }; + if (!open_req) { + LOGE("Failed to request heap memory."); + return -ENOMEM; + } + int ret = uv_fs_open(nullptr, open_req.get(), path.c_str(), mode, S_IRUSR | + S_IWUSR | S_IRGRP | S_IWGRP, nullptr); + if (ret < 0) { + LOGE("Failed to open OpenFileByPath error %{public}d", ret); + } + return ret; +} + +static int OpenFileByDatashare(const std::string &path, int64_t flags) +{ + std::shared_ptr dataShareHelper = nullptr; + sptr remote = new (std::nothrow) OHOS::IRemoteStub(); + if (!remote) { + LOGE("Failed to get remote object"); + return -ENOMEM; + } + + dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI); + if (!dataShareHelper) { + LOGE("Failed to connect to datashare"); + return -E_PERMISSION; + } + Uri uri(path); + int fd = dataShareHelper->OpenFile(uri, CommonFunc::GetModeFromFlags(flags)); + return fd; +} + +static std::tuple OpenByFileDataUri(Uri &uri, const std::string &uriStr, unsigned int mode) +{ + std::string bundleName = uri.GetAuthority(); + AppFileService::ModuleFileUri::FileUri fileUri(uriStr); + std::string realPath = fileUri.GetRealPath(); + if ((bundleName == MEDIA || bundleName == DOCS) && access(realPath.c_str(), F_OK) != 0) { + int res = OpenFileByDatashare(uri.ToString(), mode); + if (res < 0) { + LOGE("Failed to open file by Datashare error %{public}d", res); + } + return { res, uri.ToString() }; + } + int ret = OpenFileByPath(realPath, mode); + if (ret < 0) { + if (bundleName == MEDIA) { + ret = OpenFileByDatashare(uriStr, mode); + if (ret < 0) { + LOGE("Failed to open file by Datashare error %{public}d", ret); + } + } else { + LOGE("Failed to open file for libuv error %{public}d", ret); + } + } + return { ret, uriStr }; +} + +static std::tuple OpenFileByBroker(const Uri &uri, uint32_t mode) +{ + uint32_t flag = (mode % MAX_WANT_FLAG) > 0 ? + AAFwk::Want::FLAG_AUTH_WRITE_URI_PERMISSION : + AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION; + int ret = AAFwk::AbilityManagerClient::GetInstance()->OpenFile(uri, flag); + if (ret < 0) { + LOGE("Failed to open file by Broker error %{public}d", ret); + } + return { ret, uri.ToString() }; +} + +static std::tuple CheckDataShareUri(const std::string &path, uint32_t mode) +{ + // datashare:////#fdFromBinder=xx + int fd = -1; + if (RemoteUri::IsRemoteUri(path, fd, mode)) { + if (fd >= 0) { + return { fd, path }; + } + LOGE("Failed to open file by RemoteUri"); + } + return { -EINVAL, path }; +} + +static std::tuple OpenFileByUri(const std::string &path, uint32_t mode) +{ + Uri uri(path); + std::string uriType = uri.GetScheme(); + if (uriType == SCHEME_FILE) { + return OpenByFileDataUri(uri, path, mode); + } else if (uriType == SCHEME_BROKER) { + return OpenFileByBroker(uri, mode); + } else if (uriType == DATASHARE) { + return CheckDataShareUri(path, mode); + } + LOGE("Failed to open file by invalid uri"); + return { -EINVAL, path }; +} + +FileEntity* InstantiateFile(int fd, std::string pathOrUri, bool isUri) +{ + auto fdg = CreateUniquePtr(fd, false); + if (fdg == nullptr) { + LOGE("Failed to request heap memory."); + return nullptr; + } + FileEntity *fileEntity = new FileEntity(); + fileEntity->fd_.swap(fdg); + if (isUri) { + fileEntity->path_ = ""; + fileEntity->uri_ = pathOrUri; + } else { + fileEntity->path_ = pathOrUri; + fileEntity->uri_ = ""; + } + return fileEntity; +} + +static tuple GetCjFlags(int64_t mode) +{ + unsigned int flags = O_RDONLY; + int32_t invalidMode = (O_WRONLY | O_RDWR); + if (mode < 0 || ((mode & invalidMode) == invalidMode)) { + LOGE("Invalid mode"); + return { false, flags }; + } + flags = static_cast(mode); + (void)CommonFunc::ConvertCjFlags(flags); + return { true, flags }; +} +} + +namespace OHOS { +namespace CJSystemapi { +namespace FileFs { +using namespace OHOS::FFI; +std::tuple> FileEntity::Open(const char* path, int64_t mode) +{ + auto [succMode, flags] = GetCjFlags(mode); + if (!succMode) { + return {EINVAL, nullptr}; + } + std::string pathStr(path); + if (pathStr.find("://") != string::npos) { + auto [res, uriStr] = OpenFileByUri(pathStr, flags); + if (res < 0) { + return {res, nullptr}; + } + auto fileEntity = InstantiateFile(res, uriStr, true); + auto fileUri = FFIData::Create(std::move(fileEntity->fd_), fileEntity->path_, fileEntity->uri_); + return {SUCCESS_CODE, fileUri}; + } + int ret = OpenFileByPath(pathStr, flags); + if (ret < 0) { + LOGE("Failed to open file for libuv error %{public}d", ret); + return {ret, nullptr}; + } + auto file = InstantiateFile(ret, pathStr, false); + auto filePath = FFIData::Create(std::move(file->fd_), file->path_, file->uri_); + return {SUCCESS_CODE, filePath}; +} + +std::tuple> FileEntity::Dup(int32_t fd) +{ + LOGI("FS_TEST::FileEntity::Dup start"); + if (fd < 0) { + LOGE("Invalid fd"); + return {EINVAL, nullptr}; + } + int dstFd = dup(fd); + if (dstFd < 0) { + LOGE("Failed to dup fd, errno: %{public}d", errno); + return {errno, nullptr}; + } + unique_ptr readlink_req = { + new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup }; + if (!readlink_req) { + LOGE("Failed to request heap memory."); + return {ENOMEM, nullptr}; + } + string path = "/proc/self/fd/" + to_string(dstFd); + int ret = uv_fs_readlink(nullptr, readlink_req.get(), path.c_str(), nullptr); + if (ret < 0) { + LOGE("Failed to readlink fd, ret: %{public}d", ret); + return {ret, nullptr}; + } + auto fdPrt = CreateUniquePtr(ret, false); + if (fdPrt == nullptr) { + LOGE("Failed to request heap memory."); + return {ENOMEM, nullptr}; + } + auto pathStr = string(static_cast(readlink_req->ptr)); + auto fileEntity = FFIData::Create(std::move(fdPrt), pathStr, ""); + return {SUCCESS_CODE, fileEntity}; +} + +static tuple> RealPathCore(const string &srcPath) +{ + std::unique_ptr realpath_req = { + new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup }; + if (!realpath_req) { + LOGE("Failed to request heap memory."); + return { ENOMEM, move(realpath_req)}; + } + int ret = uv_fs_realpath(nullptr, realpath_req.get(), srcPath.c_str(), nullptr); + if (ret < 0) { + LOGE("Failed to realpath, ret: %{public}d", ret); + return { ret, move(realpath_req)}; + } + return { ERRNO_NOERR, move(realpath_req) }; +} + +int FileEntity::GetFD(int64_t id) +{ + auto fileEntity = FFIData::GetData(id); + if (!fileEntity) { + LOGE("FileEntity instance not exist %{public}" PRId64, id); + return ERR_INVALID_INSTANCE_CODE; + } + return fileEntity->fd_.get()->GetFD(); +} + +const char* FileEntity::GetPath(int64_t id) +{ + auto fileEntity = FFIData::GetData(id); + if (!fileEntity) { + LOGE("FileEntity instance not exist %{public}" PRId64, id); + return nullptr; + } + auto [realPathRes, realPath] = RealPathCore(fileEntity->path_); + if (realPathRes != ERRNO_NOERR) { + return nullptr; + } + return static_cast(realPath->ptr); +} + +const char* FileEntity::GetName(int64_t id) +{ + string path = FileEntity::GetPath(id); + auto pos = path.find_last_of('/'); + if (pos == string::npos) { + LOGE("Failed to split filename from path"); + return nullptr; + } + auto name = path.substr(pos + 1); + char* value = static_cast(malloc((name.size() + 1) * sizeof(char))); + if (value == nullptr) { + return nullptr; + } + if (strcpy_s(value, name.size() + 1, name.c_str()) != 0) { + free(value); + return nullptr; + } + return value; +} + +int FileEntity::TryLock(int64_t id, bool exclusive) +{ + auto fileEntity = FFIData::GetData(id); + if (!fileEntity) { + LOGE("FileEntity instance not exist %{public}" PRId64, id); + return ERR_INVALID_INSTANCE_CODE; + } + int ret = 0; + auto mode = exclusive ? LOCK_EX : LOCK_SH; + ret = flock(fileEntity->fd_.get()->GetFD(), mode | LOCK_NB); + if (ret < 0) { + LOGE("Failed to try to lock file"); + return GetErrorCode(ETXTBSY); + } + return SUCCESS_CODE; +} + +int FileEntity::UnLock(int64_t id) +{ + auto fileEntity = FFIData::GetData(id); + if (!fileEntity) { + LOGE("FileEntity instance not exist %{public}" PRId64, id); + return ERR_INVALID_INSTANCE_CODE; + } + int ret = 0; + ret = flock(fileEntity->fd_.get()->GetFD(), LOCK_UN); + if (ret < 0) { + LOGE("Failed to unlock file"); + return GetErrorCode(ETXTBSY); + } + return SUCCESS_CODE; +} + +RetDataCString FileEntity::GetParent() +{ + LOGI("FS_TEST::FileEntity::GetParent start"); + RetDataCString ret = { .code = EINVAL, .data = nullptr }; + string path(path_); + if (uri_.length() != 0) { + AppFileService::ModuleFileUri::FileUri fileUri(uri_); + path = fileUri.GetRealPath(); + } + auto [realPathRes, realPath] = RealPathCore(path); + if (realPathRes != ERRNO_NOERR) { + LOGE("realPath error"); + ret.code = realPathRes; + return ret; + } + path = string(static_cast(realPath->ptr)); + auto pos = path.find_last_of('/'); + if (pos == string::npos) { + LOGE("Failed to split filename from path"); + ret.code = ENOENT; + return ret; + } + ret.code = SUCCESS_CODE; + auto parent = path.substr(0, pos); + char* result = new char[parent.length() + 1]; + if (strcpy_s(result, parent.length() + 1, parent.c_str()) != 0) { + ret.code = ENOMEM; + return ret; + } + ret.data = result; + LOGI("FS_TEST::FileEntity::GetParent success"); + return ret; +} + +} // namespace FileFs +} // namespace CJSystemapi +} // namespace OHOS diff --git a/interfaces/kits/cj/src/file_impl.h b/interfaces/kits/cj/src/file_impl.h new file mode 100644 index 000000000..2a27e392a --- /dev/null +++ b/interfaces/kits/cj/src/file_impl.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_FILE_FS_FILE_IMPL_H +#define OHOS_FILE_FS_FILE_IMPL_H + +#include +#include +#include "macro.h" +#include "fd_guard.h" +#include "ffi_remote_data.h" +#include "cj_common_ffi.h" +#include +#include + +namespace OHOS { +namespace CJSystemapi { +namespace FileFs { + +class FileEntity : public OHOS::FFI::FFIData { +public: + std::unique_ptr fd_ = { nullptr }; + std::string path_; + std::string uri_; + ~FileEntity() override + { + if (!fd_.get()) { + return; + } + int32_t fd = fd_.get()->GetFD(); + int ret = flock(fd, LOCK_UN); + if (ret == 0) { + struct stat buf; + if (fstat(fd, &buf) == 0) { + LOGI("Unlock succeeded inode = %llu", buf.st_ino); + } else { + LOGI("Failed to get inode number"); + } + } + } + FileEntity(std::unique_ptr fd_, std::string path_, std::string uri_) + : fd_(std::move(fd_)), path_(path_), uri_(uri_) {} + FileEntity() {}; + static std::tuple> Open(const char* path, int64_t mode); + static std::tuple> Dup(int32_t fd); + static int GetFD(int64_t id); + static const char* GetPath(int64_t id); + static const char* GetName(int64_t id); + int TryLock(int64_t id, bool exclusive); + int UnLock(int64_t id); + RetDataCString GetParent(); + + OHOS::FFI::RuntimeType* GetRuntimeType() override { return GetClassType(); } + +private: + friend class OHOS::FFI::RuntimeType; + friend class OHOS::FFI::TypeBase; + static OHOS::FFI::RuntimeType* GetClassType() + { + static OHOS::FFI::RuntimeType runtimeType = OHOS::FFI::RuntimeType::Create("FileEntity"); + return &runtimeType; + } +}; + +} +} +} +#endif //OHOS_FILE_FS_FILE_IMPL_H -- Gitee From 7837743880dcb95fe6bf863e424366ae5495a571 Mon Sep 17 00:00:00 2001 From: atreeof_wind Date: Fri, 10 May 2024 11:19:22 +0800 Subject: [PATCH 2/2] [fs]:add code Signed-off-by: atreeof_wind --- interfaces/kits/cj/src/file_impl.cpp | 381 --------------------------- interfaces/kits/cj/src/file_impl.h | 80 ------ interfaces/kits/cj/src/fsync.cpp | 47 ++++ interfaces/kits/cj/src/fsync.h | 31 +++ interfaces/kits/cj/src/lseek.cpp | 52 ++++ interfaces/kits/cj/src/lseek.h | 31 +++ 6 files changed, 161 insertions(+), 461 deletions(-) delete mode 100644 interfaces/kits/cj/src/file_impl.cpp delete mode 100644 interfaces/kits/cj/src/file_impl.h create mode 100644 interfaces/kits/cj/src/fsync.cpp create mode 100644 interfaces/kits/cj/src/fsync.h create mode 100644 interfaces/kits/cj/src/lseek.cpp create mode 100644 interfaces/kits/cj/src/lseek.h diff --git a/interfaces/kits/cj/src/file_impl.cpp b/interfaces/kits/cj/src/file_impl.cpp deleted file mode 100644 index a385f77cf..000000000 --- a/interfaces/kits/cj/src/file_impl.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ffi_remote_data.h" -#include "cj_common_ffi.h" -#include "uni_error.h" -#include "uri.h" -#include "open.h" -#include "datashare_helper.h" -#include "utils.h" -#include "iremote_stub.h" -#include "file_uri.h" -#include "want.h" -#include "ability_manager_client.h" -#include "remote_uri.h" -#include "file_utils.h" -#include "securec.h" -#include "file_impl.h" - -static const std::string PROCEDURE_OPEN_NAME = "FileIOOpen"; -static const std::string MEDIALIBRARY_DATA_URI = "datashare:///media"; -static const std::string FILE_DATA_URI = "file://"; -static const std::string PATH_SHARE = "/data/storage/el2/share"; -static const std::string MODE_RW = "/rw/"; -static const std::string MODE_R = "/r/"; -static const std::string DOCS = "docs"; -static const std::string DATASHARE = "datashare"; -static const std::string SCHEME_BROKER = "content"; -constexpr uint32_t MAX_WANT_FLAG = 4; - -namespace { -using Uri = OHOS::Uri; -using namespace OHOS; -using namespace DistributedFS; -using namespace OHOS::CJSystemapi; -using namespace OHOS::CJSystemapi::FileFs; -using namespace OHOS::FileManagement; -using namespace OHOS::FileManagement::ModuleFileIO; -using namespace OHOS::DistributedFS::ModuleRemoteUri; -using namespace std; - -static int OpenFileByPath(const std::string &path, unsigned int mode) -{ - std::unique_ptr open_req = { - new uv_fs_t, CommonFunc::FsReqCleanup }; - if (!open_req) { - LOGE("Failed to request heap memory."); - return -ENOMEM; - } - int ret = uv_fs_open(nullptr, open_req.get(), path.c_str(), mode, S_IRUSR | - S_IWUSR | S_IRGRP | S_IWGRP, nullptr); - if (ret < 0) { - LOGE("Failed to open OpenFileByPath error %{public}d", ret); - } - return ret; -} - -static int OpenFileByDatashare(const std::string &path, int64_t flags) -{ - std::shared_ptr dataShareHelper = nullptr; - sptr remote = new (std::nothrow) OHOS::IRemoteStub(); - if (!remote) { - LOGE("Failed to get remote object"); - return -ENOMEM; - } - - dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI); - if (!dataShareHelper) { - LOGE("Failed to connect to datashare"); - return -E_PERMISSION; - } - Uri uri(path); - int fd = dataShareHelper->OpenFile(uri, CommonFunc::GetModeFromFlags(flags)); - return fd; -} - -static std::tuple OpenByFileDataUri(Uri &uri, const std::string &uriStr, unsigned int mode) -{ - std::string bundleName = uri.GetAuthority(); - AppFileService::ModuleFileUri::FileUri fileUri(uriStr); - std::string realPath = fileUri.GetRealPath(); - if ((bundleName == MEDIA || bundleName == DOCS) && access(realPath.c_str(), F_OK) != 0) { - int res = OpenFileByDatashare(uri.ToString(), mode); - if (res < 0) { - LOGE("Failed to open file by Datashare error %{public}d", res); - } - return { res, uri.ToString() }; - } - int ret = OpenFileByPath(realPath, mode); - if (ret < 0) { - if (bundleName == MEDIA) { - ret = OpenFileByDatashare(uriStr, mode); - if (ret < 0) { - LOGE("Failed to open file by Datashare error %{public}d", ret); - } - } else { - LOGE("Failed to open file for libuv error %{public}d", ret); - } - } - return { ret, uriStr }; -} - -static std::tuple OpenFileByBroker(const Uri &uri, uint32_t mode) -{ - uint32_t flag = (mode % MAX_WANT_FLAG) > 0 ? - AAFwk::Want::FLAG_AUTH_WRITE_URI_PERMISSION : - AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION; - int ret = AAFwk::AbilityManagerClient::GetInstance()->OpenFile(uri, flag); - if (ret < 0) { - LOGE("Failed to open file by Broker error %{public}d", ret); - } - return { ret, uri.ToString() }; -} - -static std::tuple CheckDataShareUri(const std::string &path, uint32_t mode) -{ - // datashare:////#fdFromBinder=xx - int fd = -1; - if (RemoteUri::IsRemoteUri(path, fd, mode)) { - if (fd >= 0) { - return { fd, path }; - } - LOGE("Failed to open file by RemoteUri"); - } - return { -EINVAL, path }; -} - -static std::tuple OpenFileByUri(const std::string &path, uint32_t mode) -{ - Uri uri(path); - std::string uriType = uri.GetScheme(); - if (uriType == SCHEME_FILE) { - return OpenByFileDataUri(uri, path, mode); - } else if (uriType == SCHEME_BROKER) { - return OpenFileByBroker(uri, mode); - } else if (uriType == DATASHARE) { - return CheckDataShareUri(path, mode); - } - LOGE("Failed to open file by invalid uri"); - return { -EINVAL, path }; -} - -FileEntity* InstantiateFile(int fd, std::string pathOrUri, bool isUri) -{ - auto fdg = CreateUniquePtr(fd, false); - if (fdg == nullptr) { - LOGE("Failed to request heap memory."); - return nullptr; - } - FileEntity *fileEntity = new FileEntity(); - fileEntity->fd_.swap(fdg); - if (isUri) { - fileEntity->path_ = ""; - fileEntity->uri_ = pathOrUri; - } else { - fileEntity->path_ = pathOrUri; - fileEntity->uri_ = ""; - } - return fileEntity; -} - -static tuple GetCjFlags(int64_t mode) -{ - unsigned int flags = O_RDONLY; - int32_t invalidMode = (O_WRONLY | O_RDWR); - if (mode < 0 || ((mode & invalidMode) == invalidMode)) { - LOGE("Invalid mode"); - return { false, flags }; - } - flags = static_cast(mode); - (void)CommonFunc::ConvertCjFlags(flags); - return { true, flags }; -} -} - -namespace OHOS { -namespace CJSystemapi { -namespace FileFs { -using namespace OHOS::FFI; -std::tuple> FileEntity::Open(const char* path, int64_t mode) -{ - auto [succMode, flags] = GetCjFlags(mode); - if (!succMode) { - return {EINVAL, nullptr}; - } - std::string pathStr(path); - if (pathStr.find("://") != string::npos) { - auto [res, uriStr] = OpenFileByUri(pathStr, flags); - if (res < 0) { - return {res, nullptr}; - } - auto fileEntity = InstantiateFile(res, uriStr, true); - auto fileUri = FFIData::Create(std::move(fileEntity->fd_), fileEntity->path_, fileEntity->uri_); - return {SUCCESS_CODE, fileUri}; - } - int ret = OpenFileByPath(pathStr, flags); - if (ret < 0) { - LOGE("Failed to open file for libuv error %{public}d", ret); - return {ret, nullptr}; - } - auto file = InstantiateFile(ret, pathStr, false); - auto filePath = FFIData::Create(std::move(file->fd_), file->path_, file->uri_); - return {SUCCESS_CODE, filePath}; -} - -std::tuple> FileEntity::Dup(int32_t fd) -{ - LOGI("FS_TEST::FileEntity::Dup start"); - if (fd < 0) { - LOGE("Invalid fd"); - return {EINVAL, nullptr}; - } - int dstFd = dup(fd); - if (dstFd < 0) { - LOGE("Failed to dup fd, errno: %{public}d", errno); - return {errno, nullptr}; - } - unique_ptr readlink_req = { - new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup }; - if (!readlink_req) { - LOGE("Failed to request heap memory."); - return {ENOMEM, nullptr}; - } - string path = "/proc/self/fd/" + to_string(dstFd); - int ret = uv_fs_readlink(nullptr, readlink_req.get(), path.c_str(), nullptr); - if (ret < 0) { - LOGE("Failed to readlink fd, ret: %{public}d", ret); - return {ret, nullptr}; - } - auto fdPrt = CreateUniquePtr(ret, false); - if (fdPrt == nullptr) { - LOGE("Failed to request heap memory."); - return {ENOMEM, nullptr}; - } - auto pathStr = string(static_cast(readlink_req->ptr)); - auto fileEntity = FFIData::Create(std::move(fdPrt), pathStr, ""); - return {SUCCESS_CODE, fileEntity}; -} - -static tuple> RealPathCore(const string &srcPath) -{ - std::unique_ptr realpath_req = { - new (std::nothrow) uv_fs_t, CommonFunc::FsReqCleanup }; - if (!realpath_req) { - LOGE("Failed to request heap memory."); - return { ENOMEM, move(realpath_req)}; - } - int ret = uv_fs_realpath(nullptr, realpath_req.get(), srcPath.c_str(), nullptr); - if (ret < 0) { - LOGE("Failed to realpath, ret: %{public}d", ret); - return { ret, move(realpath_req)}; - } - return { ERRNO_NOERR, move(realpath_req) }; -} - -int FileEntity::GetFD(int64_t id) -{ - auto fileEntity = FFIData::GetData(id); - if (!fileEntity) { - LOGE("FileEntity instance not exist %{public}" PRId64, id); - return ERR_INVALID_INSTANCE_CODE; - } - return fileEntity->fd_.get()->GetFD(); -} - -const char* FileEntity::GetPath(int64_t id) -{ - auto fileEntity = FFIData::GetData(id); - if (!fileEntity) { - LOGE("FileEntity instance not exist %{public}" PRId64, id); - return nullptr; - } - auto [realPathRes, realPath] = RealPathCore(fileEntity->path_); - if (realPathRes != ERRNO_NOERR) { - return nullptr; - } - return static_cast(realPath->ptr); -} - -const char* FileEntity::GetName(int64_t id) -{ - string path = FileEntity::GetPath(id); - auto pos = path.find_last_of('/'); - if (pos == string::npos) { - LOGE("Failed to split filename from path"); - return nullptr; - } - auto name = path.substr(pos + 1); - char* value = static_cast(malloc((name.size() + 1) * sizeof(char))); - if (value == nullptr) { - return nullptr; - } - if (strcpy_s(value, name.size() + 1, name.c_str()) != 0) { - free(value); - return nullptr; - } - return value; -} - -int FileEntity::TryLock(int64_t id, bool exclusive) -{ - auto fileEntity = FFIData::GetData(id); - if (!fileEntity) { - LOGE("FileEntity instance not exist %{public}" PRId64, id); - return ERR_INVALID_INSTANCE_CODE; - } - int ret = 0; - auto mode = exclusive ? LOCK_EX : LOCK_SH; - ret = flock(fileEntity->fd_.get()->GetFD(), mode | LOCK_NB); - if (ret < 0) { - LOGE("Failed to try to lock file"); - return GetErrorCode(ETXTBSY); - } - return SUCCESS_CODE; -} - -int FileEntity::UnLock(int64_t id) -{ - auto fileEntity = FFIData::GetData(id); - if (!fileEntity) { - LOGE("FileEntity instance not exist %{public}" PRId64, id); - return ERR_INVALID_INSTANCE_CODE; - } - int ret = 0; - ret = flock(fileEntity->fd_.get()->GetFD(), LOCK_UN); - if (ret < 0) { - LOGE("Failed to unlock file"); - return GetErrorCode(ETXTBSY); - } - return SUCCESS_CODE; -} - -RetDataCString FileEntity::GetParent() -{ - LOGI("FS_TEST::FileEntity::GetParent start"); - RetDataCString ret = { .code = EINVAL, .data = nullptr }; - string path(path_); - if (uri_.length() != 0) { - AppFileService::ModuleFileUri::FileUri fileUri(uri_); - path = fileUri.GetRealPath(); - } - auto [realPathRes, realPath] = RealPathCore(path); - if (realPathRes != ERRNO_NOERR) { - LOGE("realPath error"); - ret.code = realPathRes; - return ret; - } - path = string(static_cast(realPath->ptr)); - auto pos = path.find_last_of('/'); - if (pos == string::npos) { - LOGE("Failed to split filename from path"); - ret.code = ENOENT; - return ret; - } - ret.code = SUCCESS_CODE; - auto parent = path.substr(0, pos); - char* result = new char[parent.length() + 1]; - if (strcpy_s(result, parent.length() + 1, parent.c_str()) != 0) { - ret.code = ENOMEM; - return ret; - } - ret.data = result; - LOGI("FS_TEST::FileEntity::GetParent success"); - return ret; -} - -} // namespace FileFs -} // namespace CJSystemapi -} // namespace OHOS diff --git a/interfaces/kits/cj/src/file_impl.h b/interfaces/kits/cj/src/file_impl.h deleted file mode 100644 index 2a27e392a..000000000 --- a/interfaces/kits/cj/src/file_impl.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OHOS_FILE_FS_FILE_IMPL_H -#define OHOS_FILE_FS_FILE_IMPL_H - -#include -#include -#include "macro.h" -#include "fd_guard.h" -#include "ffi_remote_data.h" -#include "cj_common_ffi.h" -#include -#include - -namespace OHOS { -namespace CJSystemapi { -namespace FileFs { - -class FileEntity : public OHOS::FFI::FFIData { -public: - std::unique_ptr fd_ = { nullptr }; - std::string path_; - std::string uri_; - ~FileEntity() override - { - if (!fd_.get()) { - return; - } - int32_t fd = fd_.get()->GetFD(); - int ret = flock(fd, LOCK_UN); - if (ret == 0) { - struct stat buf; - if (fstat(fd, &buf) == 0) { - LOGI("Unlock succeeded inode = %llu", buf.st_ino); - } else { - LOGI("Failed to get inode number"); - } - } - } - FileEntity(std::unique_ptr fd_, std::string path_, std::string uri_) - : fd_(std::move(fd_)), path_(path_), uri_(uri_) {} - FileEntity() {}; - static std::tuple> Open(const char* path, int64_t mode); - static std::tuple> Dup(int32_t fd); - static int GetFD(int64_t id); - static const char* GetPath(int64_t id); - static const char* GetName(int64_t id); - int TryLock(int64_t id, bool exclusive); - int UnLock(int64_t id); - RetDataCString GetParent(); - - OHOS::FFI::RuntimeType* GetRuntimeType() override { return GetClassType(); } - -private: - friend class OHOS::FFI::RuntimeType; - friend class OHOS::FFI::TypeBase; - static OHOS::FFI::RuntimeType* GetClassType() - { - static OHOS::FFI::RuntimeType runtimeType = OHOS::FFI::RuntimeType::Create("FileEntity"); - return &runtimeType; - } -}; - -} -} -} -#endif //OHOS_FILE_FS_FILE_IMPL_H diff --git a/interfaces/kits/cj/src/fsync.cpp b/interfaces/kits/cj/src/fsync.cpp new file mode 100644 index 000000000..e6d36ba1b --- /dev/null +++ b/interfaces/kits/cj/src/fsync.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fsync.h" +#include "file_fs_impl.h" + +#include +#include + + +namespace OHOS { +namespace CJSystemapi { + +using namespace std; + +int FsyncImpl::Fsync(int32_t fd) +{ + LOGI("FS_TEST::FsyncImpl::Fsync start"); + std::unique_ptr fsync_req = { + new uv_fs_t, CommonFunc::FsReqCleanup }; + if (!fsync_req) { + LOGE("Failed to request heap memory."); + return ENOMEM; + } + int ret = uv_fs_fsync(nullptr, fsync_req.get(), fd, nullptr); + if (ret < 0) { + LOGE("Failed to transfer data associated with file descriptor: %{public}d", fd); + return ret; + } + LOGI("FS_TEST::FsyncImpl::Fsync success"); + return ret; +} + +} // namespace CJSystemapi +} // namespace OHOS diff --git a/interfaces/kits/cj/src/fsync.h b/interfaces/kits/cj/src/fsync.h new file mode 100644 index 000000000..8a826b443 --- /dev/null +++ b/interfaces/kits/cj/src/fsync.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_FILE_FS_FSYNC_H +#define OHOS_FILE_FS_FSYNC_H + +#include + +namespace OHOS { +namespace CJSystemapi { + +class FsyncImpl { +public: + static int Fsync(int32_t fd); +}; + +} +} +#endif //OHOS_FILE_FS_FDATASYNC_H diff --git a/interfaces/kits/cj/src/lseek.cpp b/interfaces/kits/cj/src/lseek.cpp new file mode 100644 index 000000000..e8e2cb5b1 --- /dev/null +++ b/interfaces/kits/cj/src/lseek.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "lseek.h" + +#include "stat_impl.h" +#include "macro.h" +#include "n_error.h" +#include "file_utils.h" +#include "rust_file.h" + +namespace OHOS { +namespace CJSystemapi { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +RetDataI64 LseekImpl::Lseek(int32_t fd, int64_t offset, int pos) +{ + LOGI("FS_TEST:: LseekImpl::Lseek start"); + RetDataI64 ret = { .code = EINVAL, .data = 0 }; + if (fd < 0) { + LOGE("Invalid fd"); + return ret; + } + + SeekPos whence = SeekPos::START; + whence = static_cast(pos); + + int64_t seekRet = ::Lseek(fd, offset, whence); + if (seekRet < 0) { + LOGE("Failed to lseek, error:%{public}d", errno); + ret.code = errno; + return ret; + } + ret.code = SUCCESS_CODE; + ret.data = seekRet; + return ret; +} + +} // CJSystemapi +} // OHOS diff --git a/interfaces/kits/cj/src/lseek.h b/interfaces/kits/cj/src/lseek.h new file mode 100644 index 000000000..912ac7ddf --- /dev/null +++ b/interfaces/kits/cj/src/lseek.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_FILE_FS_LSEEK_H +#define OHOS_FILE_FS_LSEEK_H + +#include "cj_common_ffi.h" + +namespace OHOS { +namespace CJSystemapi { + +class LseekImpl { +public: + static RetDataI64 Lseek(int32_t fd, int64_t offset, int pos); +}; + + +} // namespace CJSystemapi +} // namespace OHOS +#endif // OHOS_FILE_FS_LSEEK_H -- Gitee