From 933ca4a6df780db68bfc61c58d845b771f3aca52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E9=91=AB?= Date: Sun, 27 Apr 2025 14:39:23 +0800 Subject: [PATCH 1/3] =?UTF-8?q?stream=20=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周鑫 Change-Id: I3380c892230c77ac77252632b54a8747f70dd1e2 --- .../js/src/mod_fs/ani/bind_function_class.cpp | 3 + .../js/src/mod_fs/ani/ets/@ohos.file.fs.ets | 31 ++- .../ani/randomaccessfile_ani.cpp | 240 +++++++++++++++++- .../ani/randomaccessfile_ani.h | 8 +- .../src/mod_fs/properties/read_text_core.cpp | 3 + 5 files changed, 264 insertions(+), 21 deletions(-) diff --git a/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp b/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp index 690640511..5086029c2 100644 --- a/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp +++ b/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp @@ -72,6 +72,9 @@ static ani_status BindRafFileMethods(ani_env *env) ani_native_function { "close", nullptr, reinterpret_cast(RandomAccessFileAni::Close) }, ani_native_function { "writeSync0", nullptr, reinterpret_cast(RandomAccessFileAni::WriteSync) }, ani_native_function { "readSync0", nullptr, reinterpret_cast(RandomAccessFileAni::ReadSync) }, + ani_native_function { "getReadStream", nullptr, reinterpret_cast(RandomAccessFileAni::GetReadStream) }, + ani_native_function { + "getWriteStream", nullptr, reinterpret_cast(RandomAccessFileAni::GetWriteStream) }, }; return BindClass(env, className, methods); diff --git a/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets index b48f2890c..e8fa2c76b 100644 --- a/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets +++ b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets @@ -1394,6 +1394,8 @@ export interface RandomAccessFile { read(buffer: ArrayBuffer, callback: AsyncCallback): void; read(buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void; readSync(buffer: ArrayBuffer, options?: ReadOptions): number; + getReadStream(): ReadStream; + getWriteStream(): WriteStream; } export class RandomAccessFileInner implements RandomAccessFile { @@ -1524,6 +1526,9 @@ export class RandomAccessFileInner implements RandomAccessFile { callback(e, 0); }); } + + native getReadStream(): ReadStream; + native getWriteStream(): WriteStream; } export interface File { @@ -1872,16 +1877,6 @@ export class StreamInner implements Stream { native seek(offset: number, whence?: number): number; } -export interface ReadStreamOptions { - start?: number; - end?: number; -} - -export interface WriteStreamOptions { - mode?: number; - start?: number; -} - export class ReadStream extends stream.Readable { private pathInner: string; private bytesReadInner: number; @@ -2041,6 +2036,7 @@ export class WriteStream extends stream.Writable { return modeStr; } } + export enum WhenceType { SEEK_SET = 0, SEEK_CUR = 1, @@ -2118,9 +2114,6 @@ export interface ListFileOptions { filter?: Filter; } - - - export interface WriteStreamOptions { mode?: number; start?: number; @@ -2131,6 +2124,18 @@ export interface ReadStreamOptions { end?: number; } +export class ReadStreamOptionsInner implements ReadStreamOptions { + constructor() {} + start?: number; + end?: number; +} + +export class WriteStreamOptionsInner implements WriteStreamOptions { + constructor() {} + mode?: number; + start?: number; +} + export interface ReaderIteratorResult { done: boolean; value: string; diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp index 36f30dad8..fd474b29b 100644 --- a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp @@ -28,6 +28,10 @@ namespace ANI { using namespace OHOS::FileManagement::ModuleFileIO; using namespace std; +const int BUF_SIZE = 1024; +const string READ_STREAM_CLASS = "ReadStream"; +const string WRITE_STREAM_CLASS = "WriteStream"; + static FsRandomAccessFile *Unwrap(ani_env *env, ani_object object) { ani_long nativePtr; @@ -160,8 +164,8 @@ void RandomAccessFileAni::Close(ani_env *env, [[maybe_unused]] ani_object object } } -ani_double RandomAccessFileAni::WriteSync(ani_env *env, [[maybe_unused]] ani_object object, - ani_object buf, ani_object options) +ani_double RandomAccessFileAni::WriteSync( + ani_env *env, [[maybe_unused]] ani_object object, ani_object buf, ani_object options) { auto rafFile = Unwrap(env, object); if (rafFile == nullptr) { @@ -215,8 +219,8 @@ ani_double RandomAccessFileAni::WriteSync(ani_env *env, [[maybe_unused]] ani_obj return -1; } -ani_double RandomAccessFileAni::ReadSync(ani_env *env, [[maybe_unused]] ani_object object, - ani_arraybuffer buf, ani_object options) +ani_double RandomAccessFileAni::ReadSync( + ani_env *env, [[maybe_unused]] ani_object object, ani_arraybuffer buf, ani_object options) { auto rafFile = Unwrap(env, object); if (rafFile == nullptr) { @@ -239,7 +243,7 @@ ani_double RandomAccessFileAni::ReadSync(ani_env *env, [[maybe_unused]] ani_obje return -1; } - auto ret = rafFile-> ReadSync(arrayBuffer, op); + auto ret = rafFile->ReadSync(arrayBuffer, op); if (!ret.IsSuccess()) { HILOGE("Read file content failed!"); const auto &err = ret.GetError(); @@ -249,6 +253,232 @@ ani_double RandomAccessFileAni::ReadSync(ani_env *env, [[maybe_unused]] ani_obje return static_cast(ret.GetData().value()); } +static ani_string GetFilePath(ani_env *env, const int fd) +{ + auto dstFd = dup(fd); + if (dstFd < 0) { + HILOGE("Failed to get valid fd, fail reason: %{public}s, fd: %{public}d", strerror(errno), fd); + return nullptr; + } + + string path = "/proc/self/fd/" + to_string(dstFd); + auto buf = CreateUniquePtr(BUF_SIZE); + int readLinkRes = readlink(path.c_str(), buf.get(), BUF_SIZE); + if (readLinkRes < 0) { + close(dstFd); + return nullptr; + } + + close(dstFd); + auto [succ, filePath] = TypeConverter::ToAniString(env, string(buf.get())); + if (!succ) { + return nullptr; + } + return move(filePath); +} + +static ani_object CreateReadStreamOptions(ani_env *env, int64_t start, int64_t end) +{ + static const char *className = "L@ohos/file/fs/ReadStreamOptionsInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class %s", className); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { + // if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + HILOGE("Cannot find constructor method for class %s", className); + return nullptr; + } + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj)) { + HILOGE("New %s obj Failed", className); + return nullptr; + } + + ani_field startField = nullptr; + ani_field endField = nullptr; + if (ANI_OK != env->Class_FindField(cls, "start", &startField)) { + HILOGE("Cannot find start in class %s", className); + return nullptr; + } + if (ANI_OK != env->Class_FindField(cls, "end", &endField)) { + HILOGE("Cannot find end in class %s", className); + return nullptr; + } + + if (start >= 0) { + env->Object_SetField_Int(obj, startField, start); + } + if (end >= 0) { + env->Object_SetField_Int(obj, endField, end); + } + if (obj == nullptr) { + HILOGE("CreateReadStreamOptions is nullptr"); + } + + return move(obj); +} + +static ani_object CreateWriteStreamOptions(ani_env *env, int64_t start, int flags) +{ + static const char *className = "L@ohos/file/fs/WriteStreamOptionsInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class %s", className); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { + HILOGE("Cannot find constructor method for class %s", className); + return nullptr; + } + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj)) { + HILOGE("New %s obj Failed", className); + return nullptr; + } + + ani_field modeField = nullptr; + ani_field startField = nullptr; + if (ANI_OK != env->Class_FindField(cls, "mode", &modeField)) { + HILOGE("Cannot find mode in class %s", className); + return nullptr; + } + if (ANI_OK != env->Class_FindField(cls, "start", &startField)) { + HILOGE("Cannot find start in class %s", className); + return nullptr; + } + + env->Object_SetField_Int(obj, modeField, flags); + if (start >= 0) { + env->Object_SetField_Int(obj, startField, start); + } + + return move(obj); +} + +static ani_object CreateReadStream(ani_env *env, ani_string filePath, ani_object options) +{ + static const char *className = "L@ohos/file/fs/fileIo/ReadStream;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class %s", className); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", "Lstd/core/String;L@ohos/file/fs/ReadStreamOptions;:V", &ctor)) { + HILOGE("Cannot find constructor method for class %s", className); + return nullptr; + } + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, filePath, options)) { + HILOGE("New %s obj Failed", className); + return nullptr; + } + + return move(obj); +} + +static ani_object CreateWriteStream(ani_env *env, ani_string filePath, ani_object options) +{ + static const char *className = "L@ohos/file/fs/fileIo/WriteStream;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class %s", className); + return nullptr; + } + ani_method ctor; + if (ANI_OK != + env->Class_FindMethod(cls, "", "Lstd/core/String;L@ohos/file/fs/WriteStreamOptions;:V", &ctor)) { + HILOGE("Cannot find constructor method for class %s", className); + return nullptr; + } + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, filePath, options)) { + HILOGE("New %s obj Failed", className); + return nullptr; + } + + return move(obj); +} + +static ani_object CreateStream(ani_env *env, const string &streamName, RandomAccessFileEntity *rafEntity, int flags) +{ + ani_string filePath = GetFilePath(env, rafEntity->fd.get()->GetFD()); + if (!filePath) { + HILOGE("Get file path failed, errno=%{public}d", errno); + ErrorHandler::Throw(env, errno); + return nullptr; + } + + if (streamName == READ_STREAM_CLASS) { + ani_object obj = CreateReadStreamOptions(env, rafEntity->start, rafEntity->end); + return CreateReadStream(env, filePath, obj); + } + if (streamName == WRITE_STREAM_CLASS) { + ani_object obj = CreateWriteStreamOptions(env, rafEntity->start, flags); + return CreateWriteStream(env, filePath, obj); + } + + return nullptr; +} + +ani_object RandomAccessFileAni::GetReadStream(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto rafFile = Unwrap(env, object); + if (rafFile == nullptr) { + HILOGE("Cannot unwrap rafFile!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + auto entity = rafFile->GetRAFEntity(); + if (!entity) { + HILOGE("Get RandomAccessFileEntity failed!"); + ErrorHandler::Throw(env, EIO); + return nullptr; + } + + int flags = fcntl(entity->fd.get()->GetFD(), F_GETFL); + unsigned int uflags = static_cast(flags); + if (((uflags & O_ACCMODE) != O_RDONLY) && ((uflags & O_ACCMODE) != O_RDWR)) { + HILOGE("Failed to check Permission"); + ErrorHandler::Throw(env, EACCES); + return nullptr; + } + + return CreateStream(env, READ_STREAM_CLASS, entity, flags); +} + +ani_object RandomAccessFileAni::GetWriteStream(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto rafFile = Unwrap(env, object); + if (rafFile == nullptr) { + HILOGE("Cannot unwrap rafFile!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + auto entity = rafFile->GetRAFEntity(); + if (!entity) { + HILOGE("Get RandomAccessFileEntity failed!"); + ErrorHandler::Throw(env, EIO); + return nullptr; + } + + int flags = fcntl(entity->fd.get()->GetFD(), F_GETFL); + unsigned int uflags = static_cast(flags); + if (((uflags & O_ACCMODE) != O_RDONLY) && ((uflags & O_ACCMODE) != O_RDWR)) { + HILOGE("Failed to check Permission"); + ErrorHandler::Throw(env, EACCES); + return nullptr; + } + + return CreateStream(env, READ_STREAM_CLASS, entity, flags); +} + } // namespace ANI } // namespace ModuleFileIO } // namespace FileManagement diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.h b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.h index 7fc783bd5..d1a29d8ec 100644 --- a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.h +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.h @@ -28,11 +28,13 @@ public: static void SetFilePointer(ani_env *env, [[maybe_unused]] ani_object object, ani_double fp); static void Close(ani_env *env, [[maybe_unused]] ani_object object); static ani_double WriteSync(ani_env *env, [[maybe_unused]] ani_object object, ani_object buf, ani_object options); - static ani_double ReadSync(ani_env *env, [[maybe_unused]] ani_object object, - ani_arraybuffer buf, ani_object options); + static ani_double ReadSync( + ani_env *env, [[maybe_unused]] ani_object object, ani_arraybuffer buf, ani_object options); + static ani_object GetReadStream(ani_env *env, [[maybe_unused]] ani_object object); + static ani_object GetWriteStream(ani_env *env, [[maybe_unused]] ani_object object); }; } // namespace ANI } // namespace ModuleFileIO } // namespace FileManagement } // namespace OHOS -#endif //INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_RANDOMACCESSFILE_ANI_RANDOMACCESSFILE_ANI_H \ No newline at end of file +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_RANDOMACCESSFILE_ANI_RANDOMACCESSFILE_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp b/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp index 90b1b7109..d62cf1640 100644 --- a/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp @@ -124,13 +124,16 @@ FsResult> ReadTextCore::DoReadText(const std::string &pat len = (!hasLen || len > statbf.st_size) ? statbf.st_size : len; string buffer(len, '\0'); + // HILOGE("TEST: before ReadFromFile res.length: %{public}d", buffer.length()); int readRet = ReadFromFile(sfd.GetFD(), offset, buffer); if (readRet < 0) { HILOGE("Failed to read file by fd: %{public}d", fd); return FsResult>::Error(readRet); } + // HILOGE("TEST: after ReadFromFile res.length: %{public}d", buffer.length()); return FsResult>::Success(make_tuple(move(buffer), readRet)); + // return FsResult>::Success(make_tuple(buffer.c_str(), readRet)); } } // namespace ModuleFileIO -- Gitee From 11f1d20d2695272096b86db9dc19b8bf6fc81ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E9=91=AB?= Date: Mon, 28 Apr 2025 22:48:33 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周鑫 Change-Id: Id852676ae959fefae34afd046736b7d3fa510fda --- interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp b/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp index d62cf1640..90b1b7109 100644 --- a/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/read_text_core.cpp @@ -124,16 +124,13 @@ FsResult> ReadTextCore::DoReadText(const std::string &pat len = (!hasLen || len > statbf.st_size) ? statbf.st_size : len; string buffer(len, '\0'); - // HILOGE("TEST: before ReadFromFile res.length: %{public}d", buffer.length()); int readRet = ReadFromFile(sfd.GetFD(), offset, buffer); if (readRet < 0) { HILOGE("Failed to read file by fd: %{public}d", fd); return FsResult>::Error(readRet); } - // HILOGE("TEST: after ReadFromFile res.length: %{public}d", buffer.length()); return FsResult>::Success(make_tuple(move(buffer), readRet)); - // return FsResult>::Success(make_tuple(buffer.c_str(), readRet)); } } // namespace ModuleFileIO -- Gitee From ca86f552e723aff7e0ca76b2249c561c26c4e048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E9=91=AB?= Date: Tue, 29 Apr 2025 09:01:26 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=8F=96=E6=B6=88=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周鑫 Change-Id: I671c4382c8867945c2dbdd6c82b86e0d3d867319 --- .../mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp index fd474b29b..51c130c07 100644 --- a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp @@ -287,7 +287,6 @@ static ani_object CreateReadStreamOptions(ani_env *env, int64_t start, int64_t e } ani_method ctor; if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { - // if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { HILOGE("Cannot find constructor method for class %s", className); return nullptr; } -- Gitee