diff --git a/bundle.json b/bundle.json index 2edbfd663a7d9e4d1faf6169501620f2868c0bd5..e447cd9068ea7e9a93810c3b0e01ffb405817ce8 100644 --- a/bundle.json +++ b/bundle.json @@ -114,6 +114,15 @@ "header_base": "//foundation/filemanagement/file_api/interfaces/kits/rust/include" } }, + { + "name": "//foundation/filemanagement/file_api/utils/filemgmt_libfs:filemgmt_libfs", + "header": { + "header_files": [ + "filemgmt_libfs.h" + ], + "header_base": "//foundation/filemanagement/file_api/utils/filemgmt_libfs/include" + } + }, { "name": "//foundation/filemanagement/file_api/utils/filemgmt_libn:filemgmt_libn", "header": { diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 1fad4e0e9161834e3cb76c4bbe3db8b80ce6d624..f329723fcb4e71291b4acb156580ccd92f0efec3 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -623,3 +623,101 @@ group("build_kits_js") { ":statvfs", ] } + + +group("ani_file_api") { + deps = [ + ":ani_file_fs", + ] +} + +config("ani_config") { + include_dirs = [ + "./include", + "${file_api_path}/interfaces/kits/rust/include", + "${utils_path}/common/include", + "${utils_path}/filemgmt_libfs/include", + "${utils_path}/filemgmt_libhilog", + "src/common", + "src/common/ani_helper", + "src/common/file_helper", + "src/mod_fs", + ] + + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-std=c++17", + "-fvisibility-inlines-hidden", + "-Oz", + ] +} + +ohos_shared_library("ani_file_fs") { + public_configs = [ ":ani_config" ] + include_dirs = [ + ] + sources = [ + ] + deps = [ + ":ohos_file_fs_abc_etc", + "${file_api_path}/interfaces/kits/native:remote_uri_native", + "${file_api_path}/interfaces/kits/native:task_signal_native", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + use_exceptions = true + external_deps = [ + "ability_runtime:ability_manager", + "app_file_service:fileuri_native", + "bounds_checking_function:libsec_static", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "data_share:datashare_common", + "data_share:datashare_consumer", + "dfs_service:distributed_file_daemon_kit_inner", + "dfs_service:libdistributedfileutils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "libuv:uv", + "runtime_core:ani", + "runtime_core:ani_helpers", + "runtime_core:libarkruntime", + "samgr:samgr_proxy", + ] + + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + output_extension = "so" + subsystem_name = "filemanagement" + part_name = "file_api" +} + +generate_static_abc("ohos_file_fs_abc") { + base_url = "./src/mod_fs/ani/ets" + files = [ "./src/mod_fs/ani/ets/@ohos.file.fs.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ohos_file_fs_abc.abc" +} + +ohos_prebuilt_etc("ohos_file_fs_abc_etc") { + source = "$target_out_dir/ohos_file_fs_abc.abc" + module_install_dir = "framework" + subsystem_name = "filemanagement" + part_name = "file_api" + deps = [ ":ohos_file_fs_abc" ] +} \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..496fe808e737e2a43bc1706f91b2c1b8f6a26b9c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets @@ -0,0 +1,2173 @@ +/* + * Copyright (c) 2025 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. + */ +import { BusinessError, AsyncCallback } from '@ohos.base'; +// import stream from '@ohos.util.stream'; + +const UNKNOWN_ERR: number = 13900042 +const UNKNOWN_MSG: string = "Unknown error" + +function createBusinessError(code: number, msg: string): BusinessError { + let err = new BusinessError(); + err.code = code; + err.message = msg; + return err; +} + +namespace fileIo { + export namespace OpenMode { + export const READ_ONLY = 0o0; + export const WRITE_ONLY = 0o1; + export const READ_WRITE = 0o2; + export const CREATE = 0o100; + export const TRUNC = 0o1000; + export const APPEND = 0o2000; + export const NONBLOCK = 0o4000; + export const DIR = 0o200000; + export const NOFOLLOW = 0o400000; + export const SYNC = 0o4010000; + } + +function access(path: string, mode?: AccessModeType): Promise { + return new Promise((resolve: (result: boolean) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string, mode?: AccessModeType): boolean => { + return FileIoImpl.doAccessSync(path, mode); + }, path, mode); + promise.then((ret: NullishType): void => { + let result = ret as boolean; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function access(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): boolean => { + return FileIoImpl.doAccessSync(path); + }, path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as boolean; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, false); + }); +} + +function access(path: string, mode: AccessModeType, flag: AccessFlagType): Promise { + return new Promise((resolve: (result: boolean) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string, mode: AccessModeType, flag: AccessFlagType): boolean => { + return FileIoImpl.doAccessSync(path, mode, flag); + }, path, mode, flag); + promise.then((ret: NullishType): void => { + let result = ret as boolean; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }) +} + +function accessSync(path: string, mode?: AccessModeType): boolean { + return FileIoImpl.doAccessSync(path, mode); +} + +function accessSync(path: string, mode: AccessModeType, flag: AccessFlagType): boolean { + return FileIoImpl.doAccessSync(path, mode, flag); +} + +function close(file: number | File): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((file: number | File): undefined => FileIoImpl.closeSync(file), file); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function close(file: number | File, callback: AsyncCallback): void { + let promise = taskpool.execute((file: number | File): undefined => FileIoImpl.closeSync(file), file); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function closeSync(file: number | File): void { + return FileIoImpl.closeSync(file) +} + +function connectDfs(networkId: string, listeners: DfsListeners): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((networkId: string, listeners: DfsListeners): void => + FileIoImpl.connectDfs(networkId, listeners), networkId, listeners); + promise.then((): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function disconnectDfs(networkId: string): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((networkId: string): void => FileIoImpl.disConnectDfs(networkId), networkId); + promise.then((): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function getxattrSync(path: string, key: string): string { + return FileIoImpl.getxattrSync(path, key) +} + +function getxattr(path: string, key: string): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string, key: string): string => { + return FileIoImpl.getxattrSync(path, key); + }, path, key); + promise.then((ret: NullishType): void => { + let result = ret as string; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function dup(fd: number): File { + return FileIoImpl.dup(fd); +} + +function copyDirSync(src: string, dest: string, mode?: number): void { + return FileIoImpl.copyDirSync(src, dest, mode); +} + +function copyDir(src: string, dest: string, mode?: number): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError>) => void): void => { + let promise = taskpool.execute((src: string, dest: string, mode?: number): undefined => + FileIoImpl.copyDirSync(src, dest, mode), src, dest, mode); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError>): void => { + reject(e); + }); + }); +} + +function copyDir(src: string, dest: string, callback: AsyncCallback>): void { + let promise = taskpool.execute((src: string, dest: string): undefined => + FileIoImpl.copyDirSync(src, dest), src, dest); + promise.then((ret: NullishType): void => { + let e = new BusinessError>(); + e.code = 0; + e.data = new Array(0); + callback(e, undefined); + }).catch((e: BusinessError>): void => { + callback(e, undefined); + }); +} + +function copyDir(src: string, dest: string, mode: number, callback: AsyncCallback>): void { + let promise = taskpool.execute((src: string, dest: string, mode: number): undefined => + FileIoImpl.copyDirSync(src, dest, mode), src, dest, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError>(); + e.code = 0; + e.data = new Array(0); + callback(e, undefined); + }).catch((e: BusinessError>): void => { + callback(e, undefined); + }); +} + +function copyDir(arg0: Object, arg1: Object, arg2: NullishType, arg3: NullishType): void { + let src = arg0 as string; + let dest = arg1 as string; + if (typeof arg2 === 'number' && typeof arg3 === 'function') { + let mode: number = 0; + try { + mode = arg2 as number; + } catch (error) { + mode = (arg2 as int) + 0; + } + let callback = arg3 as AsyncCallback>; + copyDir(src, dest, mode, callback); + return; + } + if (typeof arg2 === 'function') { + let callback = arg2 as AsyncCallback>; + copyDir(src, dest, callback); + return; + } +} + +function mkdirSync(path: string): void { + return FileIoImpl.mkdirSync(path) +} + +function fdatasyncSync(fd: number): void { + return FileIoImpl.fdatasyncSync(fd) +} + +function fdatasync(fd: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((fd: number): undefined => FileIoImpl.fdatasyncSync(fd), fd); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e as BusinessError); + }); + }); +} + +function fdatasync(fd: number, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number): undefined => FileIoImpl.fdatasyncSync(fd), fd); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function mkdirSync(path: string, recursion: boolean): void { + return FileIoImpl.mkdirSync(path, recursion) +} + +function mkdirSync1(path: string): undefined { + FileIoImpl.mkdirSync(path); + return undefined; +} + +function mkdirSync2(path: string, recursion: boolean): undefined { + FileIoImpl.mkdirSync(path, recursion); + return undefined; +} + +function mkdir(path: string): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string): undefined => mkdirSync1(path), path); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e as BusinessError); + }); + }); +} + +function mkdir(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): undefined => mkdirSync1(path), path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function mkdir(path: string, recursion: boolean): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string, recursion: boolean): undefined => + mkdirSync2(path, recursion), path, recursion); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: NullishType): void => { + reject(e as BusinessError); + }); + }); +} + +function mkdir(path: string, recursion: boolean, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string, recursion: boolean): undefined => + mkdirSync2(path, recursion), path, recursion); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function moveDirSync(src: string, dest: string, mode?: number): void { + return FileIoImpl.movedirSync(src, dest, mode) +} + +function moveDir(src: string, dest: string, mode?: number): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError>) => void): void => { + let promise = taskpool.execute((src: string, dest: string, mode?: number): undefined => { + return FileIoImpl.movedirSync(src, dest, mode); + }, src, dest, mode); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError>): void => { + reject(e); + }); + }) +} + +function moveDir(src: string, dest: string, callback: AsyncCallback>): void { + let promise = taskpool.execute((src: string, dest: string): undefined => { + return FileIoImpl.movedirSync(src, dest); + }, src, dest); + promise.then((ret: NullishType): void => { + let e = new BusinessError>(); + e.code = 0; + e.data = new Array(0); + callback(e, undefined); + }).catch((e: BusinessError>): void => { + callback(e, undefined); + }); +} + +function moveDir(src: string, dest: string, mode: number, callback: AsyncCallback>): void { + let promise = taskpool.execute((src: string, dest: string, mode: number): undefined => { + return FileIoImpl.movedirSync(src, dest, mode); + }, src, dest, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError>(); + e.code = 0; + e.data = new Array(0); + callback(e, undefined); + }).catch((e: BusinessError>): void => { + callback(e, undefined); + }); +} + +function moveDir(arg0: Object, arg1: Object, arg2: NullishType, arg3: NullishType): void { + let src = arg0 as string; + let dest = arg1 as string; + if (typeof arg2 === 'number' && typeof arg3 === 'function') { + let mode: number = 0; + try { + mode = arg2 as number; + } catch (error) { + mode = (arg2 as int) + 0; + } + let callback = arg3 as AsyncCallback>; + moveDir(src, dest, mode, callback); + return; + } + if (typeof arg2 === 'function') { + let callback = arg2 as AsyncCallback>; + moveDir(src, dest, callback); + return; + } +} + +function mkdtempSync(prefix: string): string { + return FileIoImpl.mkdtempSync(prefix); +} + +function mkdtemp(prefix: string): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((prefix: string): string => { + return FileIoImpl.mkdtempSync(prefix); + }, prefix); + promise.then((ret: NullishType): void => { + let result = ret as string; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function mkdtemp(prefix: string, callback: AsyncCallback): void { + let promise = taskpool.execute((prefix: string): string => { + return FileIoImpl.mkdtempSync(prefix); + }, prefix); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as string; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, ""); + }); +} + +function moveFileSync(src: string, dest: string, mode?: number): void { + return FileIoImpl.moveFileSync(src, dest, mode); +} + +function moveFile(src: string, dest: string, mode?: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((src: string, dest: string, mode?: number): undefined => { + return FileIoImpl.moveFileSync(src, dest, mode); + }, src, dest, mode); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function moveFile(src: string, dest: string, mode: number, callback: AsyncCallback): void { + let promise = taskpool.execute((src: string, dest: string, mode: number): undefined => { + return FileIoImpl.moveFileSync(src, dest, mode); + }, src, dest, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function moveFile(src: string, dest: string, callback: AsyncCallback): void { + let promise = taskpool.execute((src: string, dest: string): undefined => { + return FileIoImpl.moveFileSync(src, dest); + }, src, dest); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function openSync(path: string, mode?: number): File { + return FileIoImpl.openSync(path, mode); +} + +function open(path: String, mode?: number): Promise { + return new Promise((resolve: (result: File) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: String, mode?: number): File => { + return FileIoImpl.openSync(path, mode); + },path, mode); + promise.then((ret: NullishType): void => { + let file = ret as File; + resolve(file); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function open(path: String, mode: number, callback: AsyncCallback): void { + let promise = taskpool.execute((path: String, mode: number): File => { + return FileIoImpl.openSync(path, mode); + }, path, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let file = ret as File; + callback(e, file); + }).catch((e: BusinessError): void => { + let f: File = new FileInner(0); + callback(e, f); + }); +} + +function open(path: String, callback: AsyncCallback): void { + let promise = taskpool.execute((path: String): File => { + return FileIoImpl.openSync(path); + }, path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let file = ret as File; + callback(e, file); + }).catch((e: BusinessError): void => { + let f: File = new FileInner(0); + callback(e, f); + }); +} + +function writeSync(fd: number, buffer: string | ArrayBuffer, options?: WriteOptions): number { + return FileIoImpl.writeSync(fd, buffer, options); +} + +function write(fd: number, buffer: string | ArrayBuffer, options?: WriteOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((fd: number, buffer: string | ArrayBuffer, options?: WriteOptions): number => { + return FileIoImpl.writeSync(fd, buffer, options); + }, fd, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function write(fd: number, buffer: string | ArrayBuffer, options: WriteOptions, + callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, buffer: string | ArrayBuffer, options: WriteOptions): number => { + return FileIoImpl.writeSync(fd, buffer, options); + }, fd, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); +} + +function write(fd: number, buffer: string | ArrayBuffer, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, buffer: string | ArrayBuffer): number => { + return FileIoImpl.writeSync(fd, buffer); + }, fd, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); +} + +function readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number { + return FileIoImpl.readSync(fd, buffer, options) +} + +function read(fd: number, buffer: ArrayBuffer, options?: ReadOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((fd: number, buffer: ArrayBuffer, options?: ReadOptions): number => { + return FileIoImpl.readSync(fd, buffer, options) + }, fd, buffer, options); + promise.then((ret: NullishType) => { + let result = ret as number; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function read(fd: number, buffer: ArrayBuffer, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, buffer: ArrayBuffer): number => { + return FileIoImpl.readSync(fd, buffer); + }, fd, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); +} + +function read(fd: number, buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, buffer: ArrayBuffer, options: ReadOptions): number => { + return FileIoImpl.readSync(fd, buffer, options); + }, fd, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); +} + +function readLinesSync(filePath: string, options?: Options): ReaderIterator { + return FileIoImpl.readlinesSync(filePath, options) +} + +function readLines(filePath: string, options?: Options): Promise { + return new Promise((resolve: (result: ReaderIterator) => void, + reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((filePath: string, options?: Options): ReaderIterator => { + return FileIoImpl.readlinesSync(filePath, options); + }, filePath, options); + promise.then((ret: NullishType): void => { + let it = ret as ReaderIterator; + resolve(it); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function readLines(filePath: string, callback: AsyncCallback): void { + let promise = taskpool.execute((filePath: string): ReaderIterator => { + return FileIoImpl.readlinesSync(filePath); + }, filePath); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let it = ret as ReaderIterator; + callback(e, it); + }).catch((e: BusinessError): void => { + let r: ReaderIterator = new ReaderIteratorInner(0); + callback(e, r); + }); +} + +function readLines(filePath: string, options: Options, callback: AsyncCallback): void { + let promise = taskpool.execute((filePath: string, options: Options): ReaderIterator => { + return FileIoImpl.readlinesSync(filePath, options); + }, filePath, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let it = ret as ReaderIterator; + callback(e, it); + }).catch((e: BusinessError): void => { + let r: ReaderIterator = new ReaderIteratorInner(0); + callback(e, r); + }); +} + +function rmdirSync(path: string): void { + return FileIoImpl.rmdirSync(path) +} + +function rmdir(path: string): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string): void => FileIoImpl.rmdirSync(path), path); + promise.then((ret: NullishType) => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function rmdir(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): void => FileIoImpl.rmdirSync(path), path); + promise.then((ret: NullishType) => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function truncateSync(file: string | number, len?: number): void { + return FileIoImpl.truncateSync(file, len) +} + +function truncate(file: string | number, len?: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((file: string | number, len?: number): undefined => { + return FileIoImpl.truncateSync(file, len); + }, file, len); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }) +} + +function truncate(file: string | number, callback: AsyncCallback): void { + let promise = taskpool.execute((file: string | number): undefined => { + return FileIoImpl.truncateSync(file); + }, file); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function truncate(file: string | number, len: number, callback: AsyncCallback): void { + let promise = taskpool.execute((file: string | number, len: number): undefined => { + return FileIoImpl.truncateSync(file, len); + }, file, len); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function unlinkSync(path: string): void { + return FileIoImpl.unlinkSync(path) +} + +function unlink(path: string): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string): undefined => unlinkSync(path), path); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function unlink(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): undefined => unlinkSync(path), path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function readText(filePath: string, options?: ReadTextOptions): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((filePath: string, options?: ReadTextOptions): string => { + return FileIoImpl.readTextSync(filePath, options); + }, filePath, options); + promise.then((ret: NullishType): void => { + let r = ret as string; + resolve(r); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function readText(filePath: string, callback: AsyncCallback): void { + let promise = taskpool.execute((filePath: string): string => { + return FileIoImpl.readTextSync(filePath); + }, filePath); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as string; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, ""); + }); +} + +function readText(filePath: string, options: ReadTextOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((filePath: string, options: ReadTextOptions): string => { + return FileIoImpl.readTextSync(filePath, options); + }, filePath, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as string; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, ""); + }); +} + +function readTextSync(filePath: string, options?: ReadTextOptions): string { + return FileIoImpl.readTextSync(filePath, options); +} + +function listFile(path: string, options?: ListFileOptions): Promise { + return new Promise((resolve: (result: string[]) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string, options?: ListFileOptions): string[] => { + return FileIoImpl.listFileSync(path, options); + }, path, options); + promise.then((ret: NullishType): void => { + let r = ret as string[]; + resolve(r); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function listFile(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string): string[] => { + return FileIoImpl.listFileSync(path); + }, path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as string[]; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, []); + }); +} + +function listFile(path: string, options: ListFileOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string, options: ListFileOptions): string[] => { + return FileIoImpl.listFileSync(path, options); + }, path, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as string[]; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, []); + }); +} + +function listFileSync(path: string, options?: ListFileOptions): string[] { + return FileIoImpl.listFileSync(path, options); +} + +function copyFileSync(src: string | number, dest: string | number, mode?: number): void { + return FileIoImpl.copyFileSync(src, dest, mode) +} + +function statSync(file: string | number): Stat { + return FileIoImpl.statSync(file) +} + +function stat(file: string | number): Promise { + return new Promise((resolve: (result: Stat) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((file: string | number): Stat => { + return FileIoImpl.statSync(file); + }, file); + promise.then((ret: NullishType): void => { + let r = ret as Stat; + resolve(r); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function stat(file: string | number, callback: AsyncCallback): void { + let p = taskpool.execute((file: string | number): Stat => { + return FileIoImpl.statSync(file); + }, file); + p.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let r = ret as Stat; + callback(e, r); + }).catch((e: BusinessError): void => { + callback(e, new StatInner(0)); + }); +} + +function fsyncSync(fd: number): void { + return FileIoImpl.fsyncSync(fd); +} + +function fsync(fd: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((fd: number): undefined => { + return FileIoImpl.fsyncSync(fd); + }, fd); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function fsync(fd: number, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number): undefined => { + return FileIoImpl.fsyncSync(fd); + }, fd); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function symlinkSync(target: string, srcPath: string): void { + return FileIoImpl.symlinkSync(target, srcPath); +} + +function symlink(target: string, srcPath: string): Promise { + return new Promise((resolve: (result: undefined) => void, + reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((target: string, srcPath: string): undefined => { + return FileIoImpl.symlinkSync(target, srcPath); + }, target, srcPath); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} +function renameSync(oldPath: string, newPath: string): void { + return FileIoImpl.renameSync(oldPath, newPath); +} + +function rename(oldPath: string, newPath: string): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((oldPath: string, newPath: string): undefined => { + return FileIoImpl.renameSync(oldPath, newPath); + }, oldPath, newPath); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function rename(oldPath: string, newPath: string, callback: AsyncCallback): void { + let promise = taskpool.execute((oldPath: string, newPath: string): undefined => { + return FileIoImpl.renameSync(oldPath, newPath); + }, oldPath, newPath); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function createRandomAccessFileSync(file: string | File, mode?: number, + options?: RandomAccessFileOptions): RandomAccessFile { + return FileIoImpl.createRandomAccessFileSync(file, mode, options); +} + +function createRandomAccessFile(file: string | File, mode?: number, + options?: RandomAccessFileOptions): Promise { + return new Promise((resolve: (result: RandomAccessFile) => void, + reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((file: string | File, mode?: number, + options?: RandomAccessFileOptions): RandomAccessFile => { + return FileIoImpl.createRandomAccessFileSync(file, mode, options); + }, file, mode, options); + promise.then((ret: NullishType): void => { + let raffile = ret as RandomAccessFileInner; + resolve(raffile); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function fdopenStream(fd: number, mode: string): Promise { + return new Promise((resolve: (result: Stream) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((fd: number, mode: string): Stream => { + return FileIoImpl.fdopenStreamSync(fd, mode); + }, fd, mode); + promise.then((ret: NullishType): void => { + let stream = ret as Stream; + resolve(stream); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function setxattrSync(path: string, key: string, value: string): void { + return FileIoImpl.setxattrSync(path, key, value) +} + +function setxattr(path: string, key: string, value: string): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((path: string, key: string, value: string): undefined => + FileIoImpl.setxattrSync(path, key, value), path, key, value); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e as BusinessError); + }); + }); +} + +function createRandomAccessFile(file: string | File, callback: AsyncCallback): void { + let promise = taskpool.execute((file: string | File): RandomAccessFile => { + return FileIoImpl.createRandomAccessFileSync(file); + }, file); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let raffile = ret as RandomAccessFile; + callback(e, raffile); + }).catch((e: BusinessError): void => { + let f: RandomAccessFile = new RandomAccessFileInner(0); + callback(e, f); + }); +} + +function createRandomAccessFile(file: string | File, mode: number, + callback: AsyncCallback): void { + let promise = taskpool.execute((file: string | File, mode: number): RandomAccessFile => { + return FileIoImpl.createRandomAccessFileSync(file, mode); + }, file, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let raffile = ret as RandomAccessFile; + callback(e, raffile); + }).catch((e: BusinessError): void => { + let f: RandomAccessFile = new RandomAccessFileInner(0); + callback(e, f); + }); +} + +function fdopenStream(fd: number, mode: string, callback: AsyncCallback): void { + let promise = taskpool.execute((fd: number, mode: string): Stream => { + return FileIoImpl.fdopenStreamSync(fd, mode); + }, fd, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let stream = ret as Stream; + callback(e, stream); + }).catch((e: BusinessError): void => { + let r: Stream = new StreamInner(0); + callback(e, r); + }); +} + +function fdopenStreamSync(fd: number, mode: string): Stream { + return FileIoImpl.fdopenStreamSync(fd, mode); +} + +function createStream(path: string, mode: string): Promise { + return new Promise((resolve: (result: Stream) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string, mode: string): Stream => { + return FileIoImpl.createStreamSync(path, mode); + }, path, mode); + promise.then((ret: NullishType): void => { + let stream = ret as Stream; + resolve(stream); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function createStream(path: string, mode: string, callback: AsyncCallback): void { + let promise = taskpool.execute((path: string, mode: string): Stream => { + return FileIoImpl.createStreamSync(path, mode); + }, path, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let stream = ret as Stream; + callback(e, stream); + }).catch((e: BusinessError): void => { + let r: Stream = new StreamInner(0); + callback(e, r); + }); +} + +function createStreamSync(path: string, mode: string): Stream { + return FileIoImpl.createStreamSync(path, mode); +} + +// function createReadStream(path: string, options?: ReadStreamOptions): ReadStream { +// return new ReadStream(path, options) +// } + +// function createWriteStream(path: string, options?: WriteStreamOptions): WriteStream { +// return new WriteStream(path, options); +// } + +function createWatcher(path: string, events: number, listener: WatchEventListener): Watcher { + return FileIoImpl.createWatcherSync(path, events, listener); +} + +function symlink(target: string, srcPath: string, callback: AsyncCallback): void { + let promise = taskpool.execute((target: string, srcPath: string): undefined => { + return FileIoImpl.symlinkSync(target, srcPath); + }, target, srcPath); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function utimes(path: string, mtime: number): void { + return FileIoImpl.utimes(path, mtime); +} + +function lstatSync(path: string): Stat { + return FileIoImpl.lstatSync(path) +} + +function lstat(path: string): Promise { + return new Promise((resolve: (result: Stat) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((path: string): Stat => { + return FileIoImpl.lstatSync(path); + }, path); + promise.then((ret: NullishType): void => { + if (ret === null || ret === undefined) { + let e = new BusinessError(); + e.code = -1; + reject(e); + } else { + let r = ret as Stat; + resolve(r); + } + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function lstat(path: string, callback: AsyncCallback): void { + let p = taskpool.execute((path: string): Stat => { + return FileIoImpl.lstatSync(path); + }, path); + p.then((ret: NullishType): void => { + let e = new BusinessError(); + if (ret === null || ret === undefined) { + e.code = -1; + let stat: Stat = new StatInner(0); + callback(e, stat); + } else { + e.code = 0; + let r = ret as Stat; + callback(e, r); + } + }).catch((e: BusinessError): void => { + callback(e, new StatInner(0)); + }); +} +function copyFile(src: string | number, dest: string | number, mode?: number): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((src: string | number, dest: string | number, mode?: number): undefined => + FileIoImpl.copyFileSync(src, dest, mode), src, dest, mode); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function copy(srcUri: string, destUri: string, options?: CopyOptions): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((srcUri: string, destUri: string, options?: CopyOptions): undefined => + FileIoImpl.copySync(srcUri, destUri, options), srcUri, destUri, options); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); +} + +function copyFile(src: string | number, dest: string | number, mode: number, callback: AsyncCallback): void { + let promise = taskpool.execute((src: string | number, dest: string | number, mode: number): undefined => + FileIoImpl.copyFileSync(src, dest, mode), src, dest, mode); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function copy(srcUri: string, destUri: string, options: CopyOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((srcUri: string, destUri: string, options: CopyOptions): undefined => + FileIoImpl.copySync(srcUri, destUri, options), srcUri, destUri, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function copyFile(src: string | number, dest: string | number, callback: AsyncCallback): void { + let promise = taskpool.execute((src: string | number, dest: string | number): undefined => + FileIoImpl.copyFileSync(src, dest), src, dest); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function copy(srcUri: string, destUri: string, callback: AsyncCallback): void { + let promise = taskpool.execute((srcUri: string, destUri: string): undefined => + FileIoImpl.copySync(srcUri, destUri), srcUri, destUri); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); +} + +function lseek(fd: number, offset: number, whence?: WhenceType): number { + return FileIoImpl.lseekSync(fd, offset, whence); +} + +export interface Filter { + suffix?: Array; + displayName?: Array; + mimeType?: Array; + fileSizeOver?: number; + lastModifiedAfter?: number; + excludeMedia?: boolean; +} + +export interface Progress { + processedSize: number; + totalSize: number; +} + +export interface DfsListeners { + onStatus(networkId: string, status: number): void; +} + +export class ProgressInner implements Progress { + processedSize: number; + totalSize: number; + + constructor(pSize: number, tSize: number) { + this.processedSize = pSize; + this.totalSize = tSize; + } +} + +export type ProgressListener = (progress: Progress) => void; + +export class TaskSignal { + private nativeTaskSignal: long = 0; + private native onCancelNative(): void; + private onCancelResolve: (path: string) => void = (path: string): void => {}; + private onCancelCallback(path: string): void { + if (this.onCancelResolve) { + this.onCancelResolve(path); + } + } + native cancel(): void; + onCancel(): Promise { + return new Promise((resolve: (path: string) => void, reject: (e: BusinessError) => void): void => { + this.onCancelResolve = resolve; + this.onCancelNative(); + }); + } +} + +export interface CopyOptions { + progressListener?: ProgressListener; + copySignal?: TaskSignal; +} + +export enum AccessModeType { + EXIST = 0, + WRITE = 2, + READ = 4, + READ_WRITE = 6, +} + +export enum AccessFlagType { + LOCAL = 0, +} + +export interface RandomAccessFile { + fd: number; + filePointer: number; + + setFilePointer(filePointer: number): void; + close(): void; + write(buffer: ArrayBuffer | string, options?: WriteOptions): Promise; + write(buffer: ArrayBuffer | string, callback: AsyncCallback): void; + write(buffer: ArrayBuffer | string, options: WriteOptions, callback: AsyncCallback): void; + writeSync(buffer: ArrayBuffer | string, options?: WriteOptions): number; + read(buffer: ArrayBuffer, options?: ReadOptions): Promise; + 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 { + fd: number = -1; + filePointer: number = -1; + + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + setFilePointer(filePointer: number): void { + this.setFilePointer0(filePointer); + this.filePointer = filePointer; + } + + native setFilePointer0(filePointer: number): void; + + native close(): void; + + writeSync(buffer: ArrayBuffer | string, options?: WriteOptions): number { + let length = options ? this.writeSync0(buffer, options) : this.writeSync0(buffer); + this.filePointer += (options?.offset?? 0) + length; + return length; + } + + native writeSync0(buffer: ArrayBuffer | string, options?: WriteOptions): number; + + write(buffer: ArrayBuffer | string, options?: WriteOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((buffer: ArrayBuffer | string, options?: WriteOptions): number => { + return this.writeSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + write(buffer: ArrayBuffer | string, options: WriteOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer | string, options: WriteOptions): number => { + return this.writeSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + write(buffer: ArrayBuffer | string, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer | string): number => { + return this.writeSync(buffer); + }, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + readSync(buffer: ArrayBuffer, options?: ReadOptions): number { + const length = options ? this.readSync0(buffer, options) : this.readSync0(buffer); + this.filePointer += (options?.offset?? 0) + length; + return length; + } + + native readSync0(buffer: ArrayBuffer, options?: ReadOptions): number; + + read(buffer: ArrayBuffer, options?: ReadOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((buffer: ArrayBuffer, options?: ReadOptions): number => { + return this.readSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number; + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + read(buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer, options: ReadOptions): number => { + return this.readSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + read(buffer: ArrayBuffer, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer): number => { + return this.readSync(buffer); + }, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + // native getReadStream(): ReadStream; + // native getWriteStream(): WriteStream; +} + +export interface File { + fd: number; + path: String; + name: String; + + getParent(): String; + lock(exclusive?: boolean): Promise; + lock(callback: AsyncCallback): void; + lock(exclusive: boolean, callback: AsyncCallback): void; + tryLock(exclusive?: boolean): void; + unlock(): void; +} + +export class FileInner implements File { + fd: number = -1; + path: String = ""; + name: String = ""; + + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + native getParent(): String; + native lockSync(exclusive?: boolean): void; + + lock(exclusive?: boolean): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((exclusive?: boolean): undefined => { + return this.lockSync(exclusive); + }, exclusive); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + lock(callback: AsyncCallback): void { + let promise = taskpool.execute((): undefined => { + return this.lockSync(); + }); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); + } + + lock(exclusive: boolean, callback: AsyncCallback): void { + let promise = taskpool.execute((exclusive: boolean): undefined => { + return this.lockSync(exclusive); + }, exclusive); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); + } + + native tryLock(exclusive?: boolean): void; + native unlock(): void; + +} + +export enum LocationType { + LOCAL = 1, + CLOUD = 2 +} + + +export class ReaderIteratorResultInner implements ReaderIteratorResult { + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + done: boolean = false; + value: string = ""; +} + +export interface ReaderIterator { + next(): ReaderIteratorResult; +} + +export class ReaderIteratorInner implements ReaderIterator { + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + native next(): ReaderIteratorResult; +} + +export interface Stat { + ino: bigint; + mode: number; + uid: number; + gid: number; + size: number; + atime: number; + mtime: number; + ctime: number; + atimeNs: bigint; + mtimeNs: bigint; + ctimeNs: bigint; + location: LocationType; + + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isDirectory(): boolean; + isFIFO(): boolean; + isFile(): boolean; + isSocket(): boolean; + isSymbolicLink(): boolean; +} + +export class StatInner implements Stat { + ino: bigint = 0n; + mode: number; + uid: number; + gid: number; + size: number; + atime: number; + mtime: number; + ctime: number; + atimeNs: bigint = 0n; + mtimeNs: bigint = 0n; + ctimeNs: bigint = 0n; + location: LocationType = LocationType.LOCAL; + + private nativeStat: long = 0; + + constructor(stat: long) { + if (this.nativeStat === 0) { + this.nativeStat = stat; + } + } + + native isBlockDevice(): boolean; + native isCharacterDevice(): boolean; + native isDirectory(): boolean; + native isFIFO(): boolean; + native isFile(): boolean; + native isSocket(): boolean; + native isSymbolicLink(): boolean; +} + +export interface Stream { + close(): Promise; + close(callback: AsyncCallback): void; + closeSync(): void; + flush(): Promise; + flush(callback: AsyncCallback): void; + flushSync(): void; + write(buffer: ArrayBuffer | string, options?: WriteOptions): Promise; + write(buffer: ArrayBuffer | string, callback: AsyncCallback): void; + write(buffer: ArrayBuffer | string, options: WriteOptions, callback: AsyncCallback): void; + writeSync(buffer: ArrayBuffer | string, options?: WriteOptions): number; + read(buffer: ArrayBuffer, options?: ReadOptions): Promise; + read(buffer: ArrayBuffer, callback: AsyncCallback): void; + read(buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void; + readSync(buffer: ArrayBuffer, options?: ReadOptions): number; + seek(offset: number, whence?: number): number; +} + +export class StreamInner implements Stream { + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + close(): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((): undefined => this.closeSync()); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + close(callback: AsyncCallback): void { + let promise = taskpool.execute((): undefined => this.closeSync()); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); + } + + native closeSync(): void; + + flush(): Promise { + return new Promise((resolve: (result: undefined) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute((): undefined => this.flushSync()); + promise.then((ret: NullishType): void => { + resolve(undefined); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + flush(callback: AsyncCallback): void { + let promise = taskpool.execute((): undefined => this.flushSync()); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + callback(e, undefined); + }).catch((e: BusinessError): void => { + callback(e, undefined); + }); + } + + native flushSync(): void; + + write(buffer: ArrayBuffer | string, options?: WriteOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((buffer: ArrayBuffer | string, options?: WriteOptions): number => { + return this.writeSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + write(buffer: ArrayBuffer | string, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer | string): number => { + return this.writeSync(buffer); + }, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + write(buffer: ArrayBuffer | string, options: WriteOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer | string, options: WriteOptions): number => { + return this.writeSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + native writeSync(buffer: ArrayBuffer | string, options?: WriteOptions): number; + + read(buffer: ArrayBuffer, options?: ReadOptions): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void) => { + let promise = taskpool.execute((buffer: ArrayBuffer, options?: ReadOptions): number => { + return this.readSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: BusinessError): void => { + reject(e); + }); + }); + } + + read(buffer: ArrayBuffer, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer): number => { + return this.readSync(buffer); + }, buffer); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + read(buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void { + let promise = taskpool.execute((buffer: ArrayBuffer, options: ReadOptions): number => { + return this.readSync(buffer, options); + }, buffer, options); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: BusinessError): void => { + callback(e, 0); + }); + } + + native readSync(buffer: ArrayBuffer, options?: ReadOptions): number; + native seek(offset: number, whence?: number): number; +} + +// export class ReadStream extends stream.Readable { +// path: string; +// bytesRead: number; +// private offset: number; +// private start?: number; +// private end?: number; +// private stream?: Stream; + +// constructor(path: string, options?: ReadStreamOptions) { +// super(); +// this.path = path; +// this.bytesRead = 0; +// this.start = options?.start; +// this.end = options?.end; +// this.stream = createStreamSync(this.path, 'r'); +// this.offset = this.start ?? 0; +// } + +// seek(offset: number, whence?: WhenceType): number { +// if (whence === undefined) { +// let off = this.stream?.seek(offset); +// if (off !== undefined) { +// this.offset = off +// } +// } else { +// let off = this.stream?.seek(offset, whence); +// if (off !== undefined) { +// this.offset = off +// } +// } +// return this.offset; +// } + +// close(): void { +// this.stream?.close(); +// } + +// doInitialize(callback: () => void): void { +// callback(); +// } + +// doRead(size: number): void { +// let readSize = size; +// let end = this.end +// if (end !== undefined) { +// if (this.offset > end) { +// this.push(null); +// return; +// } +// if (this.offset + readSize > end) { +// readSize = end - this.offset; +// } +// } +// let buffer = new ArrayBuffer(readSize); +// const off = this.offset; +// this.offset += readSize; +// this.stream?.read(buffer, { offset: off, length: readSize }) +// .then((readOut: number) => { +// if (readOut > 0) { +// this.bytesRead += readOut; +// this.push(new Uint8Array(buffer.slice(0, readOut))); +// } +// if (readOut !== readSize || readOut < size) { +// this.offset = this.offset - readSize + readOut; +// this.push(null); +// } +// }); +// } +// } + +// export class WriteStream extends stream.Writable { +// path: string; +// bytesWritten: number; +// private offset: number; +// private mode: string; +// private start?: number; +// private stream?: Stream; + +// constructor(path: string, options?: WriteStreamOptions) { +// super(); +// this.path = path; +// this.bytesWritten = 0; +// this.start = options?.start; +// this.mode = this.convertOpenMode(options?.mode); +// this.stream = createStreamSync(this.path, this.mode); +// this.offset = this.start ?? 0; +// } + +// seek(offset: number, whence?: WhenceType): number { +// if (whence === undefined) { +// let off = this.stream?.seek(offset); +// if (off !== undefined) { +// this.offset = off +// } +// } else { +// let off = this.stream?.seek(offset, whence); +// if (off !== undefined) { +// this.offset = off +// } +// } +// return this.offset; +// } + +// close(): void { +// this.stream?.close(); +// } + +// closeSync(): void { +// this.stream?.closeSync(); +// } + +// doInitialize(callback: () => void): void { +// callback(); +// } + +// doWrite(chunk: string | ArrayBuffer, encoding: string, callback: () => void): void { +// this.stream?.write(chunk, { offset: this.offset }) +// .then((writeIn: number) => { +// this.offset += writeIn; +// this.bytesWritten += writeIn; +// callback(); +// }) +// .finally(() => { +// this.stream?.flush(); +// }); +// } + +// convertOpenMode(mode?: number): string { +// let modeStr = 'w'; +// if (mode === undefined) { +// return modeStr; +// } +// if ((mode as number) & fileIo.OpenMode.WRITE_ONLY) { +// modeStr = 'w'; +// } +// if ((mode as number) & fileIo.OpenMode.READ_WRITE) { +// modeStr = 'w+'; +// } +// if (((mode as number) & fileIo.OpenMode.WRITE_ONLY) && ((mode as number) & fileIo.OpenMode.APPEND)) { +// modeStr = 'a'; +// } +// if (((mode as number) & fileIo.OpenMode.READ_WRITE) && ((mode as number) & fileIo.OpenMode.APPEND)) { +// modeStr = 'a+'; +// } +// return modeStr; +// } +// } + +export class AtomicFile { + static { + loadLibrary("ani_file_fs"); + } + + private nativePtr: long = 0; + private native getPath(): string; + // private writeStream: WriteStream | null = null; + + native constructor(path: string); + + native getBaseFile(): File; + + // native openRead(): ReadStream; + + native readFully(): ArrayBuffer; + + // native nativeStartWrite(): WriteStream; + // startWrite(): WriteStream { + // let ws = this.nativeStartWrite(); + // this.writeStream = ws; + // return ws; + // } + + native nativeFinishWrite(): void; + finishWrite(): void { + if (!this.writeStream) { + throw createBusinessError(UNKNOWN_ERR, UNKNOWN_MSG); + } + this.writeStream?.close(); + this.nativeFinishWrite(); + this.writeStream = null; + }; + + native nativeFailWrite(): void; + failWrite(): void { + if (!this.writeStream) { + throw createBusinessError(UNKNOWN_ERR, UNKNOWN_MSG); + } + this.writeStream?.close(); + this.nativeFailWrite(); + this.writeStream = null; + }; + + native delete(): void; +} + +export enum WhenceType { + SEEK_SET = 0, + SEEK_CUR = 1, + SEEK_END = 2 +} + +export interface Watcher { + start(): void; + stop(): void; +} + +class WatcherInner implements Watcher { + private nativePtr: long = 0; + + constructor(ptr: long) { + if (this.nativePtr === 0) { + this.nativePtr = ptr; + } + } + + native start(): void; + + native stop(): void; +} + +} // namespace fileIo + +export interface ConflictFiles { + srcFile: string; + destFile: string; +} + +class ConflictFilesInner implements ConflictFiles { + srcFile: string = ""; + destFile: string = ""; + + constructor(src: string, dest: string) { + this.srcFile = src; + this.destFile = dest; + } +} + +export interface WatchEvent { + fileName: string; + event: number; + cookie: number; +} + +class WatchEventInner implements WatchEvent { + fileName: string = ''; + event: number; + cookie: number; + + constructor(fileName: string, event: number, cookie: number) { + this.fileName = fileName; + this.event = event; + this.cookie = cookie; + } + +} + +export type WatchEventListener = (event: WatchEvent) => void; + +export interface Options { + encoding?: string; +} + +export interface ReadOptions { + offset?: number; + length?: number; +} + +export interface ReadTextOptions extends ReadOptions { + encoding?: string; +} + +export interface WriteOptions extends Options { + offset?: number; + length?: number; +} + +export interface RandomAccessFileOptions { + start?: number; + end?: number; +} + +export interface ListFileOptions { + recursion?: boolean; + listNum?: number; + filter?: Filter; +} + +export interface WriteStreamOptions { + mode?: number; + start?: number; +} + +export interface ReadStreamOptions { + start?: number; + 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; +} + +export interface Filter { + suffix?: Array; + displayName?: Array; + mimeType?: Array; + fileSizeOver?: number; + lastModifiedAfter?: number; + excludeMedia?: boolean; +} + +type TaskSignal = fileIo.TaskSignal; +type DfsListeners = fileIo.DfsListeners; + + +export class FileIoImpl { + + static { + loadLibrary("ani_file_fs"); + } + + static native doAccessSync(path: string, mode?: fileIo.AccessModeType, flag?: fileIo.AccessFlagType): boolean; + + static native closeSync(file: number | fileIo.File): void; + + static native copySync(srcUri: string, destUri: string, options?: fileIo.CopyOptions): void; + + static native connectDfs(networkId: string, listeners: DfsListeners): void; + + static native copyDirSync(src: string, dest: string, mode?: number): void; + + static native copyFileSync(src: string | number, dest: string | number, mode?: number): void; + + static native disConnectDfs(networkId: string): void; + + static native fdatasyncSync(fd: number): void; + + static native getxattrSync(path: string, key: string): string; + + static native createStreamSync(path: string, mode: string): fileIo.Stream; + + static native createWatcherSync(path: string, events: number, listener: WatchEventListener): fileIo.Watcher; + + static native fdopenStreamSync(fd: number, mode: string): fileIo.Stream; + + static native dup(fd: number): fileIo.File; + + static native listFileSync(path: string, options?: ListFileOptions): string[]; + + static native lstatSync(path: string): fileIo.Stat; + + static native lseekSync(fd: number, offset: number, whence?: fileIo.WhenceType): number; + + static native mkdirSync(path: string): void; + + static native mkdirSync(path: string, recursion: boolean): void; + + static native movedirSync(src: string, dest: string, mode?: number): void; + + static native mkdtempSync(prefix: string): string; + + static native moveFileSync(src: String, dest: String, mode?: number): void; + + static native openSync(path: String, mode?: number): fileIo.File; + + static native readlinesSync(filePath: string, options?: Options): fileIo.ReaderIterator; + + static native readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number; + + static native readTextSync(filePath: string, options?: ReadTextOptions): string; + + static native rmdirSync(path: string): void; + + static native setxattrSync(path: string, key: string, value: string): void; + + static native statSync(file: string | number): fileIo.Stat; + + static native truncateSync(file: string | number, len?: number): void; + + static native unlinkSync(path: string): void; + + static native writeSync(fd: number, buffer: string | ArrayBuffer, options?: WriteOptions): number; + + static native fsyncSync(fd: number): void; + + static native renameSync(oldPath: string, newPath: string): void; + + static native createRandomAccessFileSync(file: string | fileIo.File, mode?: number, + options?: RandomAccessFileOptions): fileIo.RandomAccessFile; + + static native symlinkSync(target: string, srcPath: string): void; + + static native utimes(path: string, mtime: number): void; +} diff --git a/interfaces/kits/js/src/mod_fs/fs_utils.cpp b/interfaces/kits/js/src/mod_fs/fs_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..94b7b81bd336cfecce0ba093bd48fa5c9d6fd4f2 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/fs_utils.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025 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 "fs_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +namespace { +const vector PUBLIC_DIR_PATHS = { "/Documents" }; +} + +tuple FsUtils::GetActualLen(size_t bufLen, size_t bufOff, const optional &length) +{ + size_t retLen = bufLen - bufOff; + + if (length.has_value()) { + int64_t opLength = length.value(); + if (opLength < 0 || static_cast(opLength) > retLen) { + HILOGE("Invalid option.length"); + return { false, 0 }; + } + retLen = static_cast(opLength); + } + return { true, retLen }; +} + +uint32_t FsUtils::ConvertFlags(const uint32_t &flags) +{ + // default value is usrReadOnly 00 + uint32_t flagsABI = 0; + flagsABI |= ((flags & USR_WRITE_ONLY) == USR_WRITE_ONLY) ? WRONLY : 0; + flagsABI |= ((flags & USR_RDWR) == USR_RDWR) ? RDWR : 0; + flagsABI |= ((flags & USR_CREATE) == USR_CREATE) ? CREATE : 0; + flagsABI |= ((flags & USR_TRUNC) == USR_TRUNC) ? TRUNC : 0; + flagsABI |= ((flags & USR_APPEND) == USR_APPEND) ? APPEND : 0; + flagsABI |= ((flags & USR_NONBLOCK) == USR_NONBLOCK) ? NONBLOCK : 0; + flagsABI |= ((flags & USR_DIRECTORY) == USR_DIRECTORY) ? DIRECTORY : 0; + flagsABI |= ((flags & USR_NOFOLLOW) == USR_NOFOLLOW) ? NOFOLLOW : 0; + flagsABI |= ((flags & USR_SYNC) == USR_SYNC) ? SYNC : 0; + return flagsABI; +} + +void FsUtils::FsReqCleanup(uv_fs_t *req) +{ + uv_fs_req_cleanup(req); + if (req) { + delete req; + req = nullptr; + } +} + +string FsUtils::GetModeFromFlags(const uint32_t &flags) +{ + const string readMode = "r"; + const string writeMode = "w"; + const string appendMode = "a"; + const string truncMode = "t"; + string mode = readMode; + mode += (((flags & O_RDWR) == O_RDWR) ? writeMode : ""); + mode = (((flags & O_WRONLY) == O_WRONLY) ? writeMode : mode); + if (mode != readMode) { + mode += ((flags & O_TRUNC) ? truncMode : ""); + mode += ((flags & O_APPEND) ? appendMode : ""); + } + return mode; +} + +bool FsUtils::CheckPublicDirPath(const string &sandboxPath) +{ + for (const string &path : PUBLIC_DIR_PATHS) { + if (sandboxPath.find(path) == 0) { + return true; + } + } + return false; +} + +string FsUtils::Decode(const string &uri) +{ + ostringstream outPutStream; + const int32_t encodeLen = 2; + size_t index = 0; + while (index < uri.length()) { + if (uri[index] == '%') { + int hex = 0; + istringstream inputStream(uri.substr(index + 1, encodeLen)); + inputStream >> hex >> hex; + outPutStream << static_cast(hex); + index += encodeLen + 1; + } else { + outPutStream << uri[index]; + index++; + } + } + + return outPutStream.str(); +} + +} // namespace OHOS::FileManagement::ModuleFileIO diff --git a/interfaces/kits/js/src/mod_fs/fs_utils.h b/interfaces/kits/js/src/mod_fs/fs_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..e75809ff245043e9ba71165decfb66689ce8113c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/fs_utils.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2025 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 FILEMANAGEMENT_FS_UTILS_H +#define FILEMANAGEMENT_FS_UTILS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "fd_guard.h" +#include "uv.h" + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +#include "iremote_broker.h" +#endif + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +constexpr int32_t RDONLY = UV_FS_O_RDONLY; +constexpr int32_t WRONLY = UV_FS_O_WRONLY; +constexpr int32_t RDWR = UV_FS_O_RDWR; +constexpr int32_t CREATE = UV_FS_O_CREAT; +constexpr int32_t TRUNC = UV_FS_O_TRUNC; +constexpr int32_t APPEND = UV_FS_O_APPEND; +constexpr int32_t NONBLOCK = UV_FS_O_NONBLOCK; +constexpr int32_t DIRECTORY = UV_FS_O_DIRECTORY; +constexpr int32_t NOFOLLOW = UV_FS_O_NOFOLLOW; +constexpr int32_t SYNC = UV_FS_O_SYNC; + +constexpr uint32_t MODE_EXIST = 00; +constexpr uint32_t MODE_WRITE = 02; +constexpr uint32_t MODE_READ = 04; +constexpr uint32_t MODE_READ_WRITE = 06; + +constexpr uint32_t USR_READ_ONLY = 00; +constexpr uint32_t USR_WRITE_ONLY = 01; +constexpr uint32_t USR_RDWR = 02; +constexpr uint32_t USR_CREATE = 0100; +constexpr uint32_t USR_TRUNC = 01000; +constexpr uint32_t USR_APPEND = 02000; +constexpr uint32_t USR_NONBLOCK = 04000; +constexpr uint32_t USR_DIRECTORY = 0200000; +constexpr uint32_t USR_NOFOLLOW = 0400000; +constexpr uint32_t USR_SYNC = 04010000; + +const double NS = 1e9; +const double MS = 1e3; + +struct FileInfo { + bool isPath = false; + unique_ptr path = { nullptr }; + unique_ptr fdg = { nullptr }; +}; + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) +class FileIoToken : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.fileio.open"); + + FileIoToken() = default; + virtual ~FileIoToken() noexcept = default; +}; +#endif + +class FsUtils { +public: + static tuple GetActualLen(size_t bufLen, size_t bufOff, const optional &length = nullopt); + static uint32_t ConvertFlags(const uint32_t &flags); + static void FsReqCleanup(uv_fs_t *req); + static string GetModeFromFlags(const uint32_t &flags); + static bool CheckPublicDirPath(const string &sandboxPath); + static string Decode(const string &uri); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // FILEMANAGEMENT_FS_UTILS_H \ No newline at end of file diff --git a/utils/filemgmt_libfs/BUILD.gn b/utils/filemgmt_libfs/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..39bd586157bfa89fb951ac0308315a9126974afd --- /dev/null +++ b/utils/filemgmt_libfs/BUILD.gn @@ -0,0 +1,72 @@ +# Copyright (c) 2025 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. + +import("//build/ohos.gni") +import("//foundation/filemanagement/file_api/file_api.gni") + +config("libfs_public_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "${utils_path}/common/include", + ] +} + +ohos_shared_library("filemgmt_libfs") { + cflags_cc = [ "-std=c++17" ] + if (!use_mingw_win && !use_mac) { + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc += [ + "-fvisibility-inlines-hidden", + "-Oz", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + } + + sources = [ "src/fs_error.cpp" ] + + if (use_mingw_win) { + defines = [ "WIN_PLATFORM" ] + } + if (use_mac) { + defines = [ "IOS_PLATFORM" ] + } + + public_configs = [ ":libfs_public_config" ] + + deps = [ "${utils_path}/filemgmt_libhilog:filemgmt_libhilog" ] + + external_deps = [ + "hilog:libhilog", + "libuv:uv", + ] + + use_exceptions = true + + subsystem_name = "filemanagement" + innerapi_tags = [ "platformsdk" ] + part_name = "file_api" +} diff --git a/utils/filemgmt_libfs/include/filemgmt_libfs.h b/utils/filemgmt_libfs/include/filemgmt_libfs.h new file mode 100644 index 0000000000000000000000000000000000000000..facda9a16481c7367cc1e0e179b4933ac5202837 --- /dev/null +++ b/utils/filemgmt_libfs/include/filemgmt_libfs.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 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 FILEMGMT_LIBN_FILEMGMT_LIBFS_H +#define FILEMGMT_LIBN_FILEMGMT_LIBFS_H + +#include "fs_array_buffer.h" +#include "fs_error.h" +#include "fs_result.h" + +#endif // FILEMGMT_LIBN_FILEMGMT_LIBFS_H \ No newline at end of file diff --git a/utils/filemgmt_libfs/include/fs_array_buffer.h b/utils/filemgmt_libfs/include/fs_array_buffer.h new file mode 100644 index 0000000000000000000000000000000000000000..52b28a996b7e93c9fd1b2a411330507c0c11c7bc --- /dev/null +++ b/utils/filemgmt_libfs/include/fs_array_buffer.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 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 FILEMANAGEMENT_FS_ARRAY_BUFFER_H +#define FILEMANAGEMENT_FS_ARRAY_BUFFER_H + +#include + +namespace OHOS::FileManagement::ModuleFileIO { + +struct ArrayBuffer { + void *buf; + size_t length; + + ArrayBuffer(void *buffer, size_t len) : buf(buffer), length(len) {} +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // FILEMANAGEMENT_FS_ARRAY_BUFFER_H \ No newline at end of file diff --git a/utils/filemgmt_libfs/include/fs_error.h b/utils/filemgmt_libfs/include/fs_error.h new file mode 100644 index 0000000000000000000000000000000000000000..94525eec342459861a8b37682b4714ccfad86a6f --- /dev/null +++ b/utils/filemgmt_libfs/include/fs_error.h @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2025 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 FILEMANAGEMENT_FS_ERROR_H +#define FILEMANAGEMENT_FS_ERROR_H + +#include +#include +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +#if (defined IOS_PLATFORM) || (defined WIN_PLATFORM) +constexpr int EBADR = 53; +constexpr int EBADFD = 77; +constexpr int ERESTART = 85; +#endif +#ifdef WIN_PLATFORM +constexpr int EDQUOT = 122; +#endif +constexpr int UNKNOWN_ERR = -1; +constexpr int NO_TASK_ERR = -2; +constexpr int CANCEL_ERR = -3; +constexpr int ERRNO_NOERR = 0; +constexpr int ECONNECTIONFAIL = 45; +constexpr int ECONNECTIONABORT = 46; +constexpr int STORAGE_SERVICE_SYS_CAP_TAG = 13600000; +constexpr int FILEIO_SYS_CAP_TAG = 13900000; +constexpr int USER_FILE_MANAGER_SYS_CAP_TAG = 14000000; +constexpr int USER_FILE_SERVICE_SYS_CAP_TAG = 14300000; +constexpr int DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG = 22400000; +constexpr int SOFTBUS_TRANS_FILE_PERMISSION_DENIED = -426114938; +constexpr int SOFTBUS_TRANS_FILE_DISK_QUOTA_EXCEEDED = -426114937; +constexpr int SOFTBUS_TRANS_FILE_NO_MEMORY = -426114936; +constexpr int SOFTBUS_TRANS_FILE_NETWORK_ERROR = -426114935; +constexpr int SOFTBUS_TRANS_FILE_NOT_FOUND = -426114934; +constexpr int SOFTBUS_TRANS_FILE_EXISTED = -426114933; +constexpr int DFS_CANCEL_SUCCESS = 204; +const std::string FILEIO_TAG_ERR_CODE = "code"; +const std::string FILEIO_TAG_ERR_DATA = "data"; + +enum ErrCodeSuffixOfFileIO { + E_PERM = 1, + E_NOENT, + E_SRCH, + E_INTR, + E_IO, + E_NXIO, + E_2BIG, + E_BADF, + E_CHILD, + E_AGAIN, + E_NOMEM, + E_ACCES, + E_FAULT, + E_BUSY, + E_EXIST, + E_XDEV, + E_NODEV, + E_NOTDIR, + E_ISDIR, + E_INVAL, + E_NFILE, + E_MFILE, + E_TXTBSY, + E_FBIG, + E_NOSPC, + E_SPIPE, + E_ROFS, + E_MLINK, + E_DEADLK, + E_NAMETOOLONG, + E_NOSYS, + E_NOTEMPTY, + E_LOOP, + E_WOULDBLOCK, + E_BADR, + E_NOSTR, + E_NODATA, + E_OVERFLOW, + E_BADFD, + E_RESTART, + E_DQUOT, + E_UKERR, + E_NOLCK, + E_NETUNREACH, + E_CONNECTION_FAIL, + E_CONNECTION_ABORT, + E_NOTASK, + E_UNCANCELED, + E_CANCELED, +}; + +enum ErrCodeSuffixOfUserFileManager { + E_DISPLAYNAME = 1, + E_URIM, + E_SUFFIX, + E_TRASH, + E_OPEN_MODE, + E_NOT_ALBUM, + E_ROOT_DIR, + E_MOVE_DENIED, + E_RENAME_DENIED, + E_RELATIVEPATH, + E_INNER_FAIL, + E_FILE_TYPE, + E_FILE_KEY, + E_INPUT +}; + +enum ErrCodeSuffixOfStorageService { + E_IPCSS = 1, + E_NOTSUPPORTEDFS, + E_MOUNT, + E_UNMOUNT, + E_VOLUMESTATE, + E_PREPARE, + E_DELETE, + E_NOOBJECT, + E_OUTOFRANGE +}; + +enum ErrCodeSuffixOfUserFileService { + E_IPCS = 1, + E_URIS, + E_GETINFO, + E_GETRESULT, + E_REGISTER, + E_REMOVE, + E_INIT, + E_NOTIFY, + E_CONNECT, + E_CALLBACK_AND_URI_HAS_NOT_RELATIONS, + E_CALLBACK_IS_NOT_REGISTER, + E_CAN_NOT_FIND_URI, + E_DO_NOT_HAVE_PARENT, + E_LOAD_SA, + E_COUNT +}; + +enum ErrCodeSuffixOfDistributedFile { + E_CLOUD_NOT_READY = 1, + E_NETWORK_ERR, + E_BATTERY_WARNING, + E_EXCEED_MAX_LIMIT, + E_DATABASE_FAILED +}; + +enum CommonErrCode { + E_PERMISSION = 201, + E_PERMISSION_SYS = 202, + E_PARAMS = 401, + E_DEVICENOTSUPPORT = 801, + E_OSNOTSUPPORT = 901, + E_UNKNOWN_ERROR = 13900042 +}; + +static inline std::unordered_map softbusErr2ErrCodeTable { + { SOFTBUS_TRANS_FILE_PERMISSION_DENIED, EPERM }, + { SOFTBUS_TRANS_FILE_DISK_QUOTA_EXCEEDED, EIO }, + { SOFTBUS_TRANS_FILE_NO_MEMORY, ENOMEM }, + { SOFTBUS_TRANS_FILE_NETWORK_ERROR, ENETUNREACH }, + { SOFTBUS_TRANS_FILE_NOT_FOUND, ENOENT }, + { SOFTBUS_TRANS_FILE_EXISTED, EEXIST }, + { DFS_CANCEL_SUCCESS, ECANCELED }, +}; + +static inline std::unordered_map uvCode2ErrCodeTable { + { "EPERM", EPERM }, + { "ENOENT", ENOENT }, + { "ESRCH", ESRCH }, + { "EINTR", EINTR }, + { "EIO", EIO }, + { "ENXIO", ENXIO }, + { "E2BIG", E2BIG }, + { "EBADF", EBADF }, + { "ECHILD", ECHILD }, + { "EAGAIN", EAGAIN }, + { "ENOMEM", ENOMEM }, + { "EACCES", EACCES }, + { "EFAULT", EFAULT }, + { "EBUSY", EBUSY }, + { "EEXIST", EEXIST }, + { "EXDEV", EXDEV }, + { "ENODEV", ENODEV }, + { "ENOTDIR", ENOTDIR }, + { "EISDIR", EISDIR }, + { "EINVAL", EINVAL }, + { "ENFILE", ENFILE }, + { "EMFILE", EMFILE }, + { "ETXTBSY", ETXTBSY }, + { "EFBIG", EFBIG }, + { "ENOSPC", ENOSPC }, + { "ESPIPE", ESPIPE }, + { "EROFS", EROFS }, + { "EMLINK", EMLINK }, + { "EDEADLK", EDEADLK }, + { "ENAMETOOLONG", ENAMETOOLONG }, + { "ENOSYS", ENOSYS }, + { "ENOTEMPTY", ENOTEMPTY }, + { "ELOOP", ELOOP }, + { "EWOULDBLOCK", EWOULDBLOCK }, + { "EBADR", EBADR }, + { "ENOSTR", ENOSTR }, + { "ENODATA", ENODATA }, + { "EOVERFLOW", EOVERFLOW }, + { "EBADFD", EBADFD }, + { "ERESTART", ERESTART }, + { "EDQUOT", EDQUOT }, + { "ENETUNREACH", ENETUNREACH }, + { "ECONNECTIONFAIL", ECONNECTIONFAIL }, + { "ECONNECTIONABORT", ECONNECTIONABORT }, + { "ECANCELED", ECANCELED }, +}; + +static inline std::unordered_map> errCodeTable { + { ERRNO_NOERR, { ERRNO_NOERR, "No error imformation" } }, + { EPERM, { FILEIO_SYS_CAP_TAG + E_PERM, "Operation not permitted" } }, + { ENOENT, { FILEIO_SYS_CAP_TAG + E_NOENT, "No such file or directory" } }, + { ESRCH, { FILEIO_SYS_CAP_TAG + E_SRCH, "No such process" } }, + { EINTR, { FILEIO_SYS_CAP_TAG + E_INTR, "Interrupted system call" } }, + { EIO, { FILEIO_SYS_CAP_TAG + E_IO, "I/O error" } }, + { ENXIO, { FILEIO_SYS_CAP_TAG + E_NXIO, "No such device or address" } }, + { E2BIG, { FILEIO_SYS_CAP_TAG + E_2BIG, "Arg list too long" } }, + { EBADF, { FILEIO_SYS_CAP_TAG + E_BADF, "Bad file descriptor" } }, + { ECHILD, { FILEIO_SYS_CAP_TAG + E_CHILD, "No child processes" } }, + { EAGAIN, { FILEIO_SYS_CAP_TAG + E_AGAIN, "Try again" } }, + { ENOMEM, { FILEIO_SYS_CAP_TAG + E_NOMEM, "Out of memory" } }, + { EACCES, { FILEIO_SYS_CAP_TAG + E_ACCES, "Permission denied" } }, + { EFAULT, { FILEIO_SYS_CAP_TAG + E_FAULT, "Bad address" } }, + { EBUSY, { FILEIO_SYS_CAP_TAG + E_BUSY, "Device or resource busy" } }, + { EEXIST, { FILEIO_SYS_CAP_TAG + E_EXIST, "File exists" } }, + { EXDEV, { FILEIO_SYS_CAP_TAG + E_XDEV, "Cross-device link" } }, + { ENODEV, { FILEIO_SYS_CAP_TAG + E_NODEV, "No such device" } }, + { ENOTDIR, { FILEIO_SYS_CAP_TAG + E_NOTDIR, "Not a directory" } }, + { EISDIR, { FILEIO_SYS_CAP_TAG + E_ISDIR, "Is a directory" } }, + { EINVAL, { FILEIO_SYS_CAP_TAG + E_INVAL, "Invalid argument" } }, + { ENFILE, { FILEIO_SYS_CAP_TAG + E_NFILE, "File table overflow" } }, + { EMFILE, { FILEIO_SYS_CAP_TAG + E_MFILE, "Too many open files" } }, + { ETXTBSY, { FILEIO_SYS_CAP_TAG + E_TXTBSY, "Text file busy" } }, + { EFBIG, { FILEIO_SYS_CAP_TAG + E_FBIG, "File too large" } }, + { ENOSPC, { FILEIO_SYS_CAP_TAG + E_NOSPC, "No space left on device" } }, + { ESPIPE, { FILEIO_SYS_CAP_TAG + E_SPIPE, "Illegal seek" } }, + { EROFS, { FILEIO_SYS_CAP_TAG + E_ROFS, "Read-only file system" } }, + { EMLINK, { FILEIO_SYS_CAP_TAG + E_MLINK, "Too many links" } }, + { EDEADLK, { FILEIO_SYS_CAP_TAG + E_DEADLK, "Resource deadlock would occur" } }, + { ENAMETOOLONG, { FILEIO_SYS_CAP_TAG + E_NAMETOOLONG, "File name too long" } }, + { ENOSYS, { FILEIO_SYS_CAP_TAG + E_NOSYS, "Function not implemented" } }, + { ENOTEMPTY, { FILEIO_SYS_CAP_TAG + E_NOTEMPTY, "Directory not empty" } }, + { ELOOP, { FILEIO_SYS_CAP_TAG + E_LOOP, "Too many symbolic links encountered" } }, + { EWOULDBLOCK, { FILEIO_SYS_CAP_TAG + E_WOULDBLOCK, "Operation would block" } }, + { EBADR, { FILEIO_SYS_CAP_TAG + E_BADR, "Invalid request descriptor" } }, + { ENOSTR, { FILEIO_SYS_CAP_TAG + E_NOSTR, "Device not a stream" } }, + { ENODATA, { FILEIO_SYS_CAP_TAG + E_NODATA, "No data available" } }, + { EOVERFLOW, { FILEIO_SYS_CAP_TAG + E_OVERFLOW, "Value too large for defined data type" } }, + { EBADFD, { FILEIO_SYS_CAP_TAG + E_BADFD, "File descriptor in bad state" } }, + { ERESTART, { FILEIO_SYS_CAP_TAG + E_RESTART, "Interrupted system call should be restarted" } }, + { EDQUOT, { FILEIO_SYS_CAP_TAG + E_DQUOT, "Quota exceeded" } }, + { UNKNOWN_ERR, { FILEIO_SYS_CAP_TAG + E_UKERR, "Unknown error" } }, + { ENOLCK, { FILEIO_SYS_CAP_TAG + E_NOLCK, "No record locks available" } }, + { ENETUNREACH, { FILEIO_SYS_CAP_TAG + E_NETUNREACH, "Network is unreachable" } }, + { ECONNECTIONFAIL, { FILEIO_SYS_CAP_TAG + E_CONNECTION_FAIL, "Connection failed" } }, + { ECONNECTIONABORT, { FILEIO_SYS_CAP_TAG + E_CONNECTION_ABORT, "Software caused connection abort" } }, + { NO_TASK_ERR, { FILEIO_SYS_CAP_TAG + E_NOTASK, "No task can be canceled" } }, + { CANCEL_ERR, { FILEIO_SYS_CAP_TAG + E_UNCANCELED, "Failed to cancel" } }, + { ECANCELED, { FILEIO_SYS_CAP_TAG + E_CANCELED, "Operation canceled" } }, + { FILEIO_SYS_CAP_TAG + E_PERM, { FILEIO_SYS_CAP_TAG + E_PERM, "Operation not permitted" } }, + { FILEIO_SYS_CAP_TAG + E_NOENT, { FILEIO_SYS_CAP_TAG + E_NOENT, "No such file or directory" } }, + { FILEIO_SYS_CAP_TAG + E_SRCH, { FILEIO_SYS_CAP_TAG + E_SRCH, "No such process" } }, + { FILEIO_SYS_CAP_TAG + E_INTR, { FILEIO_SYS_CAP_TAG + E_INTR, "Interrupted system call" } }, + { FILEIO_SYS_CAP_TAG + E_IO, { FILEIO_SYS_CAP_TAG + E_IO, "I/O error" } }, + { FILEIO_SYS_CAP_TAG + E_NXIO, { FILEIO_SYS_CAP_TAG + E_NXIO, "No such device or address" } }, + { FILEIO_SYS_CAP_TAG + E_2BIG, { FILEIO_SYS_CAP_TAG + E_2BIG, "Arg list too long" } }, + { FILEIO_SYS_CAP_TAG + E_BADF, { FILEIO_SYS_CAP_TAG + E_BADF, "Bad file descriptor" } }, + { FILEIO_SYS_CAP_TAG + E_CHILD, { FILEIO_SYS_CAP_TAG + E_CHILD, "No child processes" } }, + { FILEIO_SYS_CAP_TAG + E_AGAIN, { FILEIO_SYS_CAP_TAG + E_AGAIN, "Try again" } }, + { FILEIO_SYS_CAP_TAG + E_NOMEM, { FILEIO_SYS_CAP_TAG + E_NOMEM, "Out of memory" } }, + { FILEIO_SYS_CAP_TAG + E_ACCES, { FILEIO_SYS_CAP_TAG + E_ACCES, "Permission denied" } }, + { FILEIO_SYS_CAP_TAG + E_FAULT, { FILEIO_SYS_CAP_TAG + E_FAULT, "Bad address" } }, + { FILEIO_SYS_CAP_TAG + E_BUSY, { FILEIO_SYS_CAP_TAG + E_BUSY, "Device or resource busy" } }, + { FILEIO_SYS_CAP_TAG + E_EXIST, { FILEIO_SYS_CAP_TAG + E_EXIST, "File exists" } }, + { FILEIO_SYS_CAP_TAG + E_XDEV, { FILEIO_SYS_CAP_TAG + E_XDEV, "Cross-device link" } }, + { FILEIO_SYS_CAP_TAG + E_NODEV, { FILEIO_SYS_CAP_TAG + E_NODEV, "No such device" } }, + { FILEIO_SYS_CAP_TAG + E_NOTDIR, { FILEIO_SYS_CAP_TAG + E_NOTDIR, "Not a directory" } }, + { FILEIO_SYS_CAP_TAG + E_ISDIR, { FILEIO_SYS_CAP_TAG + E_ISDIR, "Is a directory" } }, + { FILEIO_SYS_CAP_TAG + E_INVAL, { FILEIO_SYS_CAP_TAG + E_INVAL, "Invalid argument" } }, + { FILEIO_SYS_CAP_TAG + E_NFILE, { FILEIO_SYS_CAP_TAG + E_NFILE, "File table overflow" } }, + { FILEIO_SYS_CAP_TAG + E_MFILE, { FILEIO_SYS_CAP_TAG + E_MFILE, "Too many open files" } }, + { FILEIO_SYS_CAP_TAG + E_TXTBSY, { FILEIO_SYS_CAP_TAG + E_TXTBSY, "Text file busy" } }, + { FILEIO_SYS_CAP_TAG + E_FBIG, { FILEIO_SYS_CAP_TAG + E_FBIG, "File too large" } }, + { FILEIO_SYS_CAP_TAG + E_NOSPC, { FILEIO_SYS_CAP_TAG + E_NOSPC, "No space left on device" } }, + { FILEIO_SYS_CAP_TAG + E_SPIPE, { FILEIO_SYS_CAP_TAG + E_SPIPE, "Illegal seek" } }, + { FILEIO_SYS_CAP_TAG + E_ROFS, { FILEIO_SYS_CAP_TAG + E_ROFS, "Read-only file system" } }, + { FILEIO_SYS_CAP_TAG + E_MLINK, { FILEIO_SYS_CAP_TAG + E_MLINK, "Too many links" } }, + { FILEIO_SYS_CAP_TAG + E_DEADLK, { FILEIO_SYS_CAP_TAG + E_DEADLK, "Resource deadlock would occur" } }, + { FILEIO_SYS_CAP_TAG + E_NAMETOOLONG, { FILEIO_SYS_CAP_TAG + E_NAMETOOLONG, "File name too long" } }, + { FILEIO_SYS_CAP_TAG + E_NOSYS, { FILEIO_SYS_CAP_TAG + E_NOSYS, "Function not implemented" } }, + { FILEIO_SYS_CAP_TAG + E_NOTEMPTY, { FILEIO_SYS_CAP_TAG + E_NOTEMPTY, "Directory not empty" } }, + { FILEIO_SYS_CAP_TAG + E_LOOP, { FILEIO_SYS_CAP_TAG + E_LOOP, "Too many symbolic links encountered" } }, + { FILEIO_SYS_CAP_TAG + E_WOULDBLOCK, { FILEIO_SYS_CAP_TAG + E_WOULDBLOCK, "Operation would block" } }, + { FILEIO_SYS_CAP_TAG + E_BADR, { FILEIO_SYS_CAP_TAG + E_BADR, "Invalid request descriptor" } }, + { FILEIO_SYS_CAP_TAG + E_NOSTR, { FILEIO_SYS_CAP_TAG + E_NOSTR, "Device not a stream" } }, + { FILEIO_SYS_CAP_TAG + E_NODATA, { FILEIO_SYS_CAP_TAG + E_NODATA, "No data available" } }, + { FILEIO_SYS_CAP_TAG + E_OVERFLOW, { FILEIO_SYS_CAP_TAG + E_OVERFLOW, "Value too large for defined data type" } }, + { FILEIO_SYS_CAP_TAG + E_BADFD, { FILEIO_SYS_CAP_TAG + E_BADFD, "File descriptor in bad state" } }, + { FILEIO_SYS_CAP_TAG + E_RESTART, + { FILEIO_SYS_CAP_TAG + E_RESTART, "Interrupted system call should be restarted" } }, + { FILEIO_SYS_CAP_TAG + E_DQUOT, { FILEIO_SYS_CAP_TAG + E_DQUOT, "Quota exceeded" } }, + { FILEIO_SYS_CAP_TAG + E_UKERR, { FILEIO_SYS_CAP_TAG + E_UKERR, "Unknown error" } }, + { FILEIO_SYS_CAP_TAG + E_NOLCK, { FILEIO_SYS_CAP_TAG + E_NOLCK, "No record locks available" } }, + { FILEIO_SYS_CAP_TAG + E_NETUNREACH, { FILEIO_SYS_CAP_TAG + E_NETUNREACH, "Network is unreachable" } }, + { FILEIO_SYS_CAP_TAG + E_CONNECTION_FAIL, { FILEIO_SYS_CAP_TAG + E_CONNECTION_FAIL, "Connection failed" } }, + { FILEIO_SYS_CAP_TAG + E_CONNECTION_ABORT, + { FILEIO_SYS_CAP_TAG + E_CONNECTION_ABORT, "Software caused connection abort" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_DISPLAYNAME, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_DISPLAYNAME, "Invalid display name" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_URIM, { USER_FILE_MANAGER_SYS_CAP_TAG + E_URIM, "Invalid uri" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_SUFFIX, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_SUFFIX, "Invalid file extension" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_TRASH, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_TRASH, "File has been put into trash bin" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_OPEN_MODE, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_OPEN_MODE, "Invalid open mode" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_NOT_ALBUM, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_NOT_ALBUM, "The uri is not album" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_ROOT_DIR, { USER_FILE_MANAGER_SYS_CAP_TAG + E_ROOT_DIR, "Invalid root dir" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_MOVE_DENIED, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_MOVE_DENIED, "Failed to move as dir check failed" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_RENAME_DENIED, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_RENAME_DENIED, "Failed to rename as dir check failed" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_RELATIVEPATH, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_RELATIVEPATH, "Relative path not exist or invalid" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_INNER_FAIL, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_INNER_FAIL, "MediaLibrary inner fail" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_FILE_TYPE, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_FILE_TYPE, "File type is not allow in the directory" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_FILE_KEY, { USER_FILE_MANAGER_SYS_CAP_TAG + E_FILE_KEY, "Member not exist" } }, + { USER_FILE_MANAGER_SYS_CAP_TAG + E_INPUT, { USER_FILE_MANAGER_SYS_CAP_TAG + E_INPUT, "Wrong input parameter" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_IPCSS, { STORAGE_SERVICE_SYS_CAP_TAG + E_IPCSS, "IPC error" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_NOTSUPPORTEDFS, + { STORAGE_SERVICE_SYS_CAP_TAG + E_NOTSUPPORTEDFS, "Not supported filesystem" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_MOUNT, { STORAGE_SERVICE_SYS_CAP_TAG + E_MOUNT, "Failed to mount" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_UNMOUNT, { STORAGE_SERVICE_SYS_CAP_TAG + E_UNMOUNT, "Failed to unmount" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_VOLUMESTATE, + { STORAGE_SERVICE_SYS_CAP_TAG + E_VOLUMESTATE, "Incorrect volume state" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_PREPARE, + { STORAGE_SERVICE_SYS_CAP_TAG + E_PREPARE, "Prepare directory or node error" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_DELETE, + { STORAGE_SERVICE_SYS_CAP_TAG + E_DELETE, "Delete directory or node error" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_NOOBJECT, { STORAGE_SERVICE_SYS_CAP_TAG + E_NOOBJECT, "No such object" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_OUTOFRANGE, + { STORAGE_SERVICE_SYS_CAP_TAG + E_OUTOFRANGE, "User id out of range" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_NOOBJECT, { STORAGE_SERVICE_SYS_CAP_TAG + E_NOOBJECT, "No such object" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_IPCS, { USER_FILE_SERVICE_SYS_CAP_TAG + E_IPCS, "IPC error" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_URIS, { USER_FILE_SERVICE_SYS_CAP_TAG + E_URIS, "Invalid uri" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_GETINFO, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_GETINFO, "Fail to get fileextension info" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_GETRESULT, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_GETRESULT, "Get wrong result" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_REGISTER, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_REGISTER, "Fail to register notification" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_REMOVE, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_REMOVE, "Fail to remove notification" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_INIT, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_INIT, "Fail to init notification agent" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_NOTIFY, { USER_FILE_SERVICE_SYS_CAP_TAG + E_NOTIFY, "Fail to notify agent" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CONNECT, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CONNECT, "Fail to connect file access extension ability" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CALLBACK_AND_URI_HAS_NOT_RELATIONS, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CALLBACK_AND_URI_HAS_NOT_RELATIONS, + "The uri has no relationship with the callback and cannot be unregistered" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CALLBACK_IS_NOT_REGISTER, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CALLBACK_IS_NOT_REGISTER, + "Cannot unregister the callback that has not been registered" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CAN_NOT_FIND_URI, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_CAN_NOT_FIND_URI, "Can not find registered uri" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_DO_NOT_HAVE_PARENT, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_DO_NOT_HAVE_PARENT, "Do not have parent uri" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_LOAD_SA, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_LOAD_SA, "Fail to load system ability" } }, + { USER_FILE_SERVICE_SYS_CAP_TAG + E_COUNT, { USER_FILE_SERVICE_SYS_CAP_TAG + E_COUNT, "Too many records" } }, + { E_PERMISSION, { E_PERMISSION, "Permission verification failed" } }, + { E_PERMISSION_SYS, { E_PERMISSION_SYS, "The caller is not a system application" } }, + { E_PARAMS, { E_PARAMS, "The input parameter is invalid" } }, + { E_DEVICENOTSUPPORT, { E_DEVICENOTSUPPORT, "The device doesn't support this api" } }, + { E_OSNOTSUPPORT, { E_OSNOTSUPPORT, "The os doesn't support this api" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_CLOUD_NOT_READY, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_CLOUD_NOT_READY, "Cloud status not ready" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_NETWORK_ERR, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_NETWORK_ERR, "Network unavailable" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_BATTERY_WARNING, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_BATTERY_WARNING, "Battery level warning" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_EXCEED_MAX_LIMIT, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_EXCEED_MAX_LIMIT, "Exceed the maximum limit" } }, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_DATABASE_FAILED, + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_DATABASE_FAILED, "Database operation failed" } }, +}; + +class FsError { +public: + FsError(int errCode); + int GetErrNo() const; + const std::string &GetErrMsg() const; + ~FsError() = default; + explicit operator bool() const; + +private: + int errno_ = ERRNO_NOERR; + std::string errMsg_; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // FILEMANAGEMENT_FS_ERROR_H \ No newline at end of file diff --git a/utils/filemgmt_libfs/include/fs_result.h b/utils/filemgmt_libfs/include/fs_result.h new file mode 100644 index 0000000000000000000000000000000000000000..0aaab49eabaa8b99b1bc64ecee284209d7bf2b2b --- /dev/null +++ b/utils/filemgmt_libfs/include/fs_result.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2025 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 FILEMANAGEMENT_FS_RESULT_H +#define FILEMANAGEMENT_FS_RESULT_H + +#include "fs_error.h" + +#include +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO { + +template +class FsResult { + using OptionalData = std::optional; + +public: + static FsResult Success() + { + return FsResult(FsError(ERRNO_NOERR), std::nullopt); + } + + static FsResult Success(const T &data) + { + return FsResult(FsError(ERRNO_NOERR), std::make_optional(data)); + } + + static FsResult Success(T &&data) + { + return FsResult(FsError(ERRNO_NOERR), std::make_optional(std::move(data))); + } + + template , int> = 0> + static FsResult Success(const char *data) + { + return FsResult(FsError(ERRNO_NOERR), std::make_optional(std::string(data))); + } + + static FsResult Error(const int32_t code) + { + return FsResult(FsError(code), std::nullopt); + } + + bool IsSuccess() const + { + return !error_; + } + + const OptionalData &GetData() const + { + return data_; + } + + OptionalData &GetData() + { + return data_; + } + + const FsError &GetError() const + { + return error_; + } + + FsResult(const FsResult &) = delete; + FsResult &operator=(const FsResult &) = delete; + + FsResult(FsResult &&other) noexcept : error_(std::move(other.error_)), data_(std::move(other.data_)) {} + + FsResult &operator=(FsResult &&other) noexcept + { + if (this != &other) { + error_ = std::move(other.error_); + data_ = std::move(other.data_); + } + return *this; + } + + ~FsResult() = default; + +private: + FsError error_; + OptionalData data_; + + FsResult(const FsError &err, const OptionalData &data) : error_(err), data_(data) {} + + FsResult(const FsError &err, OptionalData &&data) : error_(err), data_(std::move(data)) {} +}; + +template <> +class FsResult { +private: + FsError error_; + explicit FsResult(const FsError &err) : error_(err) {} + +public: + static FsResult Success() + { + return FsResult(FsError(ERRNO_NOERR)); + } + + static FsResult Error(const int32_t code) + { + return FsResult(FsError(code)); + } + + bool IsSuccess() const + { + return !error_; + } + + const FsError &GetError() const + { + return error_; + } + + FsResult(const FsResult &) = delete; + FsResult &operator=(const FsResult &) = delete; + + FsResult(FsResult &&other) noexcept : error_(std::move(other.error_)) {} + + FsResult &operator=(FsResult &&other) noexcept + { + if (this != &other) { + error_ = std::move(other.error_); + } + return *this; + } + + ~FsResult() = default; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // FILEMANAGEMENT_FS_RESULT_H \ No newline at end of file diff --git a/utils/filemgmt_libfs/src/fs_error.cpp b/utils/filemgmt_libfs/src/fs_error.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3636a7d5f966a4633f5f57b73d7d705af0196de5 --- /dev/null +++ b/utils/filemgmt_libfs/src/fs_error.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 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 "fs_error.h" +#include "uv.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +static int ConvertUVCode2ErrCode(int errCode) +{ + if (errCode >= 0) { + return errCode; + } + auto uvCode = string_view(uv_err_name(errCode)); + if (uvCode2ErrCodeTable.find(uvCode) != uvCode2ErrCodeTable.end()) { + return uvCode2ErrCodeTable.at(uvCode); + } + return UNKNOWN_ERR; +} + +FsError::FsError(int errCode) +{ + int genericCode = ConvertUVCode2ErrCode(errCode); + auto it = errCodeTable.find(genericCode); + if (it != errCodeTable.end()) { + errno_ = it->second.first; + errMsg_ = it->second.second; + } else { + errno_ = errCodeTable.at(UNKNOWN_ERR).first; + errMsg_ = errCodeTable.at(UNKNOWN_ERR).second + ", errno is " + to_string(abs(errCode)); + } +} + +int FsError::GetErrNo() const +{ + return errno_; +} + +const std::string &FsError::GetErrMsg() const +{ + return errMsg_; +} + +FsError::operator bool() const +{ + return errno_ != ERRNO_NOERR; +} + +} // namespace OHOS::FileManagement::ModuleFileIO