【OpenHarmony文件管理子系统】文件访问接口mod_fs解析

发布于:2025-09-05 ⋅ 阅读:(19) ⋅ 点赞:(0)

OpenHarmony文件访问接口mod_fs模块解析

概述

mod_fs模块是OpenHarmony文件访问接口的核心模块之一,位于interfaces/kits/js/src/mod_fs目录下。该模块提供了完整的文件系统操作功能,包括文件读写、目录管理、文件监控、流处理等核心功能。本文将从目录结构、核心组件、接口设计、实现细节等多个维度进行深入解析。

目录结构分析

1. 核心文件

interfaces/kits/js/src/mod_fs/
├── module.cpp              # 模块入口文件
├── common_func.h/.cpp      # 通用功能函数
├── fs_utils.h/.cpp         # 文件系统工具函数
└── properties/             # 属性接口实现
    ├── prop_n_exporter.h/.cpp
    ├── ani/                # 异步接口实现
    └── [各种功能接口文件]

2. 类目录结构

├── class_file/             # 文件类实现
├── class_stat/             # 文件状态类实现
├── class_stream/           # 流处理类实现
├── class_atomicfile/       # 原子文件操作类
├── class_randomaccessfile/ # 随机访问文件类
├── class_readeriterator/   # 读取迭代器类
├── class_watcher/          # 文件监控类
└── class_tasksignal/       # 任务信号类

核心组件详解

1. 模块入口 (module.cpp)

module.cpp是mod_fs模块的入口文件,负责:

  • 模块注册:通过napi_module_register注册为"file.fs"模块
  • 类型初始化:初始化各种枚举类型和常量
  • 类导出:导出所有功能类到JavaScript环境
static napi_module _module = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Export,
    .nm_modname = "file.fs",
    .nm_priv = ((void *)0),
    .reserved = {0}
};

导出的类型包括:

  • AccessModeType:访问模式类型
  • AccessFlagType:访问标志类型
  • LocationType:位置类型(本地/云端)
  • OpenMode:打开模式
  • WhenceType:定位类型

2. 通用功能函数 (common_func.h/.cpp)

common_func提供了模块的核心工具函数:

2.1 常量定义
// 文件打开标志
constexpr int RDONLY = UV_FS_O_RDONLY;
constexpr int WRONLY = UV_FS_O_WRONLY;
constexpr int RDWR = UV_FS_O_RDWR;
constexpr int CREATE = UV_FS_O_CREAT;
constexpr int TRUNC = UV_FS_O_TRUNC;
constexpr int APPEND = UV_FS_O_APPEND;

// 访问模式
constexpr unsigned int MODE_EXIST = 00;
constexpr unsigned int MODE_WRITE = 02;
constexpr unsigned int MODE_READ = 04;
constexpr unsigned int MODE_READ_WRITE = 06;
2.2 核心功能函数

文件信息结构体:

struct FileInfo {
    bool isPath = false;
    std::unique_ptr<char[]> path = { nullptr };
    std::unique_ptr<DistributedFS::FDGuard> fdg = { nullptr };
};

主要功能函数:

  • ConvertJsFlags():转换JavaScript标志到系统标志
  • InstantiateStat():实例化文件状态对象
  • InstantiateFile():实例化文件对象
  • InstantiateStream():实例化流对象
  • GetReadArg():解析读取参数
  • GetWriteArg():解析写入参数
  • GetCopyPathArg():解析复制路径参数

3. 文件系统工具 (fs_utils.h/.cpp)

fs_utils提供了文件系统相关的工具函数:

class FsUtils {
public:
    static tuple<bool, size_t> GetActualLen(size_t bufLen, size_t bufOff, 
                                           const optional<int64_t> &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);
};

类组件详解

1. File类 (class_file/)

File类提供了文件操作的核心功能,包含完整的文件实体管理和操作接口。

1.1 类结构设计

FileEntity结构体:

struct FileEntity {
    std::unique_ptr<DistributedFS::FDGuard> fd_ = { nullptr };
    std::string path_ = "";
    std::string uri_ = "";
};

主要接口:

class FileNExporter final : public NExporter {
public:
    static napi_value GetPath(napi_env env, napi_callback_info info);
    static napi_value GetName(napi_env env, napi_callback_info info);
    static napi_value GetParent(napi_env env, napi_callback_info info);
    static napi_value Lock(napi_env env, napi_callback_info info);
    static napi_value TryLock(napi_env env, napi_callback_info info);
    static napi_value UnLock(napi_env env, napi_callback_info info);
    static napi_value GetFD(napi_env env, napi_callback_info info);
};
1.2 核心实现细节

文件路径获取实现:

napi_value FileNExporter::GetPath(napi_env env, napi_callback_info info)
{
    // 参数验证
    NFuncArg funcArg(env, info);
    if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }
    
    // 获取文件实体
    auto fileEntity = GetFileEntity(env, funcArg.GetThisVar());
    if (!fileEntity) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }
    
    // 处理URI和路径
    if (fileEntity->uri_.length() != 0) {
        AppFileService::ModuleFileUri::FileUri fileUri(fileEntity->uri_);
        return NVal::CreateUTF8String(env, fileUri.GetPath()).val_;
    }
    
    // 获取真实路径
    auto [realPathRes, realPath] = RealPathCore(fileEntity->path_);
    if (realPathRes != ERRNO_NOERR) {
        NError(realPathRes).ThrowErr(env);
        return nullptr;
    }
    return NVal::CreateUTF8String(env, string(static_cast<const char *>(realPath->ptr))).val_;
}

文件锁定机制实现:

napi_value FileNExporter::Lock(napi_env env, napi_callback_info info)
{
    // 参数解析
    bool exclusive = false;
    if (!GetExclusive(env, funcArg, exclusive)) {
        return nullptr;
    }
    
    // 异步执行回调
    auto cbExec = [exclusive, fileEntity]() -> NError {
        if (!fileEntity || !fileEntity->fd_.get()) {
            return NError(EIO);
        }
        int ret = 0;
        auto mode = exclusive ? LOCK_EX : LOCK_SH;
        ret = flock(fileEntity->fd_.get()->GetFD(), mode);
        if (ret < 0) {
            return NError(errno);
        }
        return NError(ERRNO_NOERR);
    };
    
    // 支持Promise和Callback两种模式
    if (funcArg.GetArgc() == NARG_CNT::ZERO || 
        (funcArg.GetArgc() == NARG_CNT::ONE && 
         !NVal(env, funcArg[NARG_POS::FIRST]).TypeIs(napi_function))) {
        return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_LOCK_NAME, cbExec, cbCompl).val_;
    } else {
        return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_LOCK_NAME, cbExec, cbCompl).val_;
    }
}
1.3 功能特性
  • 文件路径管理:支持URI和本地路径两种模式
  • 文件锁定机制:提供独占锁和共享锁支持
  • 文件描述符获取:安全的FD管理
  • 异步操作支持:Promise和Callback两种异步模式
  • 内存管理:使用智能指针自动管理资源

2. Stat类 (class_stat/)

Stat类提供文件状态信息,包含完整的文件属性查询和类型判断功能。

2.1 类结构设计

StatEntity结构体:

struct StatEntity {
    uv_stat_t stat_;
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
    std::shared_ptr<FileInfo> fileInfo_;
#endif
};

主要接口:

class StatNExporter final : public NExporter {
public:
    // 文件类型判断
    static napi_value IsBlockDevice(napi_env env, napi_callback_info info);
    static napi_value IsCharacterDevice(napi_env env, napi_callback_info info);
    static napi_value IsDirectory(napi_env env, napi_callback_info info);
    static napi_value IsFile(napi_env env, napi_callback_info info);
    static napi_value IsSocket(napi_env env, napi_callback_info info);
    static napi_value IsSymbolicLink(napi_env env, napi_callback_info info);
    
    // 属性获取
    static napi_value GetIno(napi_env env, napi_callback_info info);
    static napi_value GetMode(napi_env env, napi_callback_info info);
    static napi_value GetSize(napi_env env, napi_callback_info info);
    static napi_value GetAtime(napi_env env, napi_callback_info info);
    static napi_value GetMtime(napi_env env, napi_callback_info info);
    static napi_value GetCtime(napi_env env, napi_callback_info info);
    static napi_value GetAtimeNs(napi_env env, napi_callback_info info);
    static napi_value GetMtimeNs(napi_env env, napi_callback_info info);
    static napi_value GetCtimeNs(napi_env env, napi_callback_info info);
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
    static napi_value GetLocation(napi_env env, napi_callback_info info);
#endif
};
2.2 核心实现细节

文件类型判断实现:

static napi_value CheckStatMode(napi_env env, napi_callback_info info, mode_t mode)
{
    NFuncArg funcArg(env, info);
    if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }

    auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
    if (!statEntity) {
        HILOGE("Failed to get stat entity");
        return nullptr;
    }

    bool check = (statEntity->stat_.st_mode & S_IFMT) == mode;
    return NVal::CreateBool(env, check).val_;
}

napi_value StatNExporter::IsFile(napi_env env, napi_callback_info info)
{
    return CheckStatMode(env, info, S_IFREG);
}

时间属性获取实现:

napi_value StatNExporter::GetAtimeNs(napi_env env, napi_callback_info info)
{
    NFuncArg funcArg(env, info);
    if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }

    auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
    if (!statEntity) {
        NError(UNKROWN_ERR).ThrowErr(env);
        return nullptr;
    }

    return NVal::CreateBigIntUint64(env, static_cast<uint64_t>
        (statEntity->stat_.st_atim.tv_sec * SECOND_TO_NANOSECOND +
         statEntity->stat_.st_atim.tv_nsec)).val_;
}

云端位置获取实现:

#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
napi_value StatNExporter::GetLocation(napi_env env, napi_callback_info info)
{
    auto statEntity = NClass::GetEntityOf<StatEntity>(env, funcArg.GetThisVar());
    if (!statEntity) {
        return nullptr;
    }
    
    std::unique_ptr<char[]> value = CreateUniquePtr<char[]>(MAX_ATTR_NAME);
    if (value == nullptr) {
        NError(ENOMEM).ThrowErr(env);
        return nullptr;
    }

    ssize_t size = 0;
    if (statEntity->fileInfo_->isPath) {
        size = getxattr(statEntity->fileInfo_->path.get(), 
                       CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME);
    } else {
        size = fgetxattr(statEntity->fileInfo_->fdg->GetFD(), 
                        CLOUD_LOCATION_ATTR.c_str(), value.get(), MAX_ATTR_NAME);
    }
    
    Location defaultLocation = LOCAL;
    if (size <= 0) {
        if (errno != ENODATA && errno != EOPNOTSUPP) {
            HILOGE("Getxattr value failed, errno is %{public}d", errno);
        }
        return NVal::CreateInt32(env, static_cast<int32_t>(defaultLocation)).val_;
    }
    
    std::string location = string(value.get(), static_cast<size_t>(size));
    if (!std::all_of(location.begin(), location.end(), ::isdigit)) {
        HILOGE("Getxattr location is not all digit!");
        return NVal::CreateInt32(env, static_cast<int32_t>(defaultLocation)).val_;
    }
    defaultLocation = static_cast<Location>(atoi(location.c_str()));
    return NVal::CreateInt32(env, static_cast<int32_t>(defaultLocation)).val_;
}
#endif
2.3 功能特性
  • 文件类型判断:支持7种文件类型检测
  • 属性获取:提供完整的文件属性信息
  • 时间精度:支持秒级和纳秒级时间获取
  • 云端支持:支持云端文件位置检测
  • 跨平台兼容:针对不同平台的条件编译

3. Stream类 (class_stream/)

Stream类提供流式文件操作,支持高效的流式读写和异步处理。

3.1 类结构设计

StreamEntity结构体:

struct StreamEntity {
    std::shared_ptr<FILE> fp{ nullptr };
};

主要接口:

class StreamNExporter final : public NExporter {
public:
    static napi_value WriteSync(napi_env env, napi_callback_info cbInfo);
    static napi_value Flush(napi_env env, napi_callback_info cbInfo);
    static napi_value FlushSync(napi_env env, napi_callback_info cbInfo);
    static napi_value ReadSync(napi_env env, napi_callback_info cbInfo);
    static napi_value CloseSync(napi_env env, napi_callback_info cbInfo);
    static napi_value Write(napi_env env, napi_callback_info cbInfo);
    static napi_value Read(napi_env env, napi_callback_info cbInfo);
    static napi_value Close(napi_env env, napi_callback_info cbInfo);
    static napi_value Seek(napi_env env, napi_callback_info cbInfo);
};
3.2 核心实现细节

流式写入实现:

napi_value StreamNExporter::WriteSync(napi_env env, napi_callback_info cbInfo)
{
    NFuncArg funcArg(env, cbInfo);
    if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }

    auto streamEntity = GetEntityOf(env, funcArg);
    if (streamEntity == nullptr) {
        NError(UNKROWN_ERR).ThrowErr(env);
        return nullptr;
    }
    
    auto fp = GetFilePtr(streamEntity);
    if (fp == nullptr) {
        NError(EIO).ThrowErr(env);
        return nullptr;
    }

    // 解析写入参数
    auto [succ, bufGuard, buf, len, offset] =
        CommonFunc::GetWriteArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
    if (!succ) {
        return nullptr;
    }
    
    // 设置文件偏移
    if (offset >= 0) {
        int ret = fseek(fp.get(), static_cast<long>(offset), SEEK_SET);
        if (ret < 0) {
            NError(errno).ThrowErr(env);
            return nullptr;
        }
    }

    // 执行写入
    size_t writeLen = fwrite(buf, 1, len, fp.get());
    if ((writeLen == 0) && (writeLen != len)) {
        NError(EIO).ThrowErr(env);
        return nullptr;
    }

    return NVal::CreateInt64(env, static_cast<int64_t>(writeLen)).val_;
}

异步读取实现:

static napi_value ReadExec(napi_env env, NFuncArg &funcArg, shared_ptr<FILE> fp)
{
    auto [succ, buf, len, offset] =
        CommonFunc::GetReadArg(env, funcArg[NARG_POS::FIRST], funcArg[NARG_POS::SECOND]);
    if (!succ) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }

    auto arg = CreateSharedPtr<AsyncReadArg>(NVal(env, funcArg[NARG_POS::FIRST]));
    if (arg == nullptr) {
        NError(ENOMEM).ThrowErr(env);
        return nullptr;
    }
    
    // 异步执行回调
    auto cbExec = [arg, buf = buf, len = len, fp, offset = offset]() -> NError {
        if (!fp.get()) {
            return NError(EIO);
        }
        if (offset >= 0) {
            if (fseek(fp.get(), static_cast<long>(offset), SEEK_SET) < 0) {
                return NError(errno);
            }
        }
        size_t actLen = fread(buf, 1, len, fp.get());
        if ((actLen != static_cast<size_t>(len) && !feof(fp.get())) || ferror(fp.get())) {
            return NError(EIO);
        } else {
            arg->lenRead = actLen;
            return NError(ERRNO_NOERR);
        }
    };

    auto cbCompl = [arg](napi_env env, NError err) -> NVal {
        if (err) {
            return { env, err.GetNapiErr(env) };
        }
        return { NVal::CreateInt64(env, arg->lenRead) };
    };

    // 支持Promise和Callback模式
    NVal thisVar(env, funcArg.GetThisVar());
    if (funcArg.GetArgc() == NARG_CNT::ONE || 
        (funcArg.GetArgc() == NARG_CNT::TWO && 
         !NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function))) {
        return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_STREAM_READ_NAME, cbExec, cbCompl).val_;
    } else {
        int cbIdx = ((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD);
        NVal cb(env, funcArg[cbIdx]);
        return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_STREAM_READ_NAME, cbExec, cbCompl).val_;
    }
}

文件定位实现:

napi_value StreamNExporter::Seek(napi_env env, napi_callback_info cbInfo)
{
    NFuncArg funcArg(env, cbInfo);
    if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }

    auto streamEntity = GetEntityOf(env, funcArg);
    if (streamEntity == nullptr) {
        NError(UNKROWN_ERR).ThrowErr(env);
        return nullptr;
    }
    
    auto fp = GetFilePtr(streamEntity);
    if (fp == nullptr) {
        NError(EIO).ThrowErr(env);
        return nullptr;
    }
    
    // 获取偏移量
    auto [succGetOffset, offset] = NVal(env, funcArg[NARG_POS::FIRST]).ToInt64();
    if (!succGetOffset) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }

    // 获取定位类型
    int whence = SEEK_SET;
    if (funcArg.GetArgc() == NARG_CNT::TWO) {
        auto [succGetWhence, pos] = NVal(env, funcArg[NARG_POS::SECOND]).ToInt32(SEEK_SET);
        if (!succGetWhence || pos < SEEK_SET || pos > SEEK_END) {
            NError(EINVAL).ThrowErr(env);
            return nullptr;
        }
        whence = pos;
    }

    // 执行定位
    if (offset >= 0) {
        int ret = fseek(fp.get(), static_cast<long>(offset), whence);
        if (ret < 0) {
            NError(errno).ThrowErr(env);
            return nullptr;
        }
    }
    
    // 返回当前位置
    int64_t res = ftell(fp.get());
    if (res < 0) {
        NError(errno).ThrowErr(env);
        return nullptr;
    }

    return NVal::CreateInt64(env, res).val_;
}
3.3 功能特性
  • 流式读写操作:基于标准C库FILE*的高效流操作
  • 异步处理支持:完整的Promise和Callback异步模式
  • 缓冲区管理:智能的缓冲区参数解析和管理
  • 错误处理机制:完善的错误检查和异常处理
  • 线程安全:使用互斥锁保护关键操作
  • 内存管理:智能指针自动管理资源生命周期

4. AtomicFile类 (class_atomicfile/)

AtomicFile类提供原子文件操作:

功能特点:

  • 原子性写入保证
  • 事务性操作支持
  • 数据一致性保护

5. RandomAccessFile类 (class_randomaccessfile/)

RandomAccessFile类提供随机访问文件操作:

核心功能:

  • 随机位置读写
  • 文件指针管理
  • 高效的数据访问

6. ReaderIterator类 (class_readeriterator/)

ReaderIterator类提供文件读取迭代器:

主要特性:

  • 迭代式文件读取
  • 内存效率优化
  • 大数据文件处理

7. Watcher类 (class_watcher/)

Watcher类提供文件系统监控功能:

监控功能:

  • 文件变化监听
  • 目录监控
  • 事件回调机制
  • 实时通知支持

8. TaskSignal类 (class_tasksignal/)

TaskSignal类提供任务信号处理:

信号功能:

  • 任务状态管理
  • 信号传递机制
  • 异步任务协调

Properties目录详解

Properties目录包含了大量的文件操作接口实现,每个接口都有对应的同步和异步版本,以及核心实现和包装层。

1. 核心文件操作接口

1.1 文件打开接口 (open.cpp)

同步打开实现:

napi_value Open::Sync(napi_env env, napi_callback_info info)
{
    NFuncArg funcArg(env, info);
    if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }
    
    // 解析路径参数
    auto [succPath, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8StringPath();
    if (!succPath) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }
    
    // 解析打开模式
    auto [succMode, mode] = GetJsFlags(env, funcArg);
    if (!succMode) {
        return nullptr;
    }
    
    string pathStr(path.get());
    
    // 处理URI路径
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
    if (pathStr.find("://") != string::npos) {
        auto [res, uriStr] = OpenFileByUri(pathStr, mode);
        if (res < 0) {
            NError(res).ThrowErr(env);
            return nullptr;
        }
        return InstantiateFile(env, res, uriStr, true).val_;
    }
#endif
    
    // 处理普通路径
    int ret = OpenFileByPath(pathStr, mode);
    if (ret < 0) {
        NError(ret).ThrowErr(env);
        return nullptr;
    }
    return InstantiateFile(env, ret, pathStr, false).val_;
}

异步打开实现:

napi_value Open::Async(napi_env env, napi_callback_info info)
{
    // 参数解析
    auto [succPath, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8StringPath();
    auto [succMode, mode] = GetJsFlags(env, funcArg);
    
    // 创建异步参数
    auto arg = CreateSharedPtr<AsyncOpenFileArg>();
    if (arg == nullptr) {
        NError(ENOMEM).ThrowErr(env);
        return nullptr;
    }
    
    // 异步执行回调
    auto cbExec = [arg, path = string(path.get()), mode = mode]() -> NError {
        return AsyncCbExec(arg, path, mode);
    };
    
    // 完成回调
    auto cbCompl = [arg](napi_env env, NError err) -> NVal {
        if (err) {
            return { env, err.GetNapiErr(env) };
        }
        if (arg->path.empty() && arg->uri.size()) {
            return InstantiateFile(env, arg->fd, arg->uri, true, true);
        }
        return InstantiateFile(env, arg->fd, arg->path, false, true);
    };
    
    // 支持Promise和Callback模式
    NVal thisVar(env, funcArg.GetThisVar());
    if (funcArg.GetArgc() == NARG_CNT::ONE || 
        (funcArg.GetArgc() == NARG_CNT::TWO && 
         !NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function))) {
        return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_OPEN_NAME, cbExec, cbCompl).val_;
    } else {
        int cbIdx = ((funcArg.GetArgc() == NARG_CNT::THREE) ? NARG_POS::THIRD : NARG_POS::SECOND);
        NVal cb(env, funcArg[cbIdx]);
        return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_OPEN_NAME, cbExec, cbCompl).val_;
    }
}
1.2 文件读取接口 (read_core.cpp)

核心读取实现:

FsResult<int64_t> ReadCore::DoRead(const int32_t &fd, ArrayBuffer &arrayBuffer, 
                                   const optional<ReadOptions> &options)
{
    if (fd < 0) {
        return FsResult<int64_t>::Error(EINVAL);
    }

    // 验证读取参数
    auto [succ, buf, len, offset] = ValidReadArg(arrayBuffer, options);
    if (!succ) {
        return FsResult<int64_t>::Error(EINVAL);
    }

    // 创建libuv读取请求
    uv_buf_t buffer = uv_buf_init(static_cast<char *>(buf), static_cast<uint32_t>(len));
    unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *> readReq = { 
        new uv_fs_t, FsUtils::FsReqCleanup };
    if (!readReq) {
        return FsResult<int64_t>::Error(ENOMEM);
    }
    
    // 执行异步读取
    int ret = uv_fs_read(nullptr, readReq.get(), fd, &buffer, 1, offset, nullptr);
    if (ret < 0) {
        return FsResult<int64_t>::Error(ret);
    }

    return FsResult<int64_t>::Success(static_cast<int64_t>(ret));
}
1.3 文件写入接口 (write_core.cpp)

核心写入实现:

FsResult<int64_t> WriteCore::DoWrite(const int32_t fd, void *buf, const size_t len, 
                                     const int64_t offset)
{
    // 创建libuv写入请求
    uv_buf_t buffer = uv_buf_init(static_cast<char *>(buf), static_cast<unsigned int>(len));
    unique_ptr<uv_fs_t, decltype(FsUtils::FsReqCleanup) *> writeReq = { 
        new uv_fs_t, FsUtils::FsReqCleanup };
    if (!writeReq) {
        return FsResult<int64_t>::Error(ENOMEM);
    }
    
    // 执行异步写入
    int ret = uv_fs_write(nullptr, writeReq.get(), fd, &buffer, 1, offset, nullptr);
    if (ret < 0) {
        return FsResult<int64_t>::Error(ret);
    }
    return FsResult<int64_t>::Success(static_cast<int64_t>(ret));
}
1.4 文件状态接口 (stat.cpp)

同步状态获取:

napi_value Stat::Sync(napi_env env, napi_callback_info info)
{
    NFuncArg funcArg(env, info);
    if (!funcArg.InitArgs(NARG_CNT::ONE)) {
        NError(EINVAL).ThrowErr(env);
        return nullptr;
    }
    
    // 解析文件参数(路径或文件描述符)
    auto [succ, fileInfo] = ParseJsFile(env, funcArg[NARG_POS::FIRST]);
    if (!succ) {
        return nullptr;
    }

    // 创建libuv状态请求
    std::unique_ptr<uv_fs_t, decltype(CommonFunc::fs_req_cleanup)*> stat_req = {
        new (std::nothrow) uv_fs_t, CommonFunc::fs_req_cleanup };
    if (!stat_req) {
        NError(ENOMEM).ThrowErr(env);
        return nullptr;
    }
    
    // 执行状态检查
    auto err = CheckFsStat(fileInfo, stat_req.get());
    if (err) {
        err.ThrowErr(env);
        return nullptr;
    }
    
    // 实例化Stat对象
#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
    auto arg = CreateSharedPtr<FileInfo>(move(fileInfo));
    if (arg == nullptr) {
        NError(ENOMEM).ThrowErr(env);
        return nullptr;
    }
    auto stat = CommonFunc::InstantiateStat(env, stat_req->statbuf, arg).val_;
#else
    auto stat = CommonFunc::InstantiateStat(env, stat_req->statbuf).val_;
#endif
    return stat;
}

2. 高级功能接口

文件基础操作:

  • open.cpp/.h:文件打开(支持URI和本地路径)
  • close.cpp/.h:文件关闭
  • read_core.cpp/.h:文件读取核心实现
  • write_core.cpp/.h:文件写入核心实现
  • lseek.cpp/.h:文件定位

目录操作:

  • mkdir.cpp/.h:创建目录
  • rmdir.cpp/.h:删除目录
  • listfile.cpp/.h:列出文件

文件管理:

  • copy.cpp/.h:文件复制
  • move.cpp/.h:文件移动
  • rename.cpp/.h:文件重命名
  • unlink.cpp/.h:删除文件

流处理:

  • create_stream.cpp/.h:创建流
  • fdopen_stream.cpp/.h:从文件描述符创建流

文件监控:

  • watcher.cpp/.h:文件监控

扩展属性:

  • xattr.cpp/.h:扩展属性操作

同步操作:

  • fsync.cpp/.h:强制同步
  • fdatasync.cpp/.h:数据同步

3. 异步接口实现 (ani目录)

每个功能都有对应的异步实现,位于ani子目录中:

异步接口特点:

  • 非阻塞操作:使用libuv进行异步I/O操作
  • 回调机制:支持Promise和Callback两种异步模式
  • 错误处理:完善的异步错误处理机制
  • 进度通知:支持操作进度回调
  • 内存管理:异步操作中的智能内存管理

技术架构特点

1. 分层架构设计

mod_fs模块采用了清晰的分层架构:

JavaScript API层
    ↓
NAPI接口层 (NExporter)
    ↓
业务逻辑层 (Entity类)
    ↓
系统调用层 (libuv/系统API)

2. 异步处理机制

模块大量使用libuv进行异步I/O操作:

// 异步操作示例
static void AsyncCallback(uv_fs_t* req) {
    // 处理异步操作结果
    uv_fs_req_cleanup(req);
}

3. 内存管理

使用智能指针进行内存管理:

std::unique_ptr<DistributedFS::FDGuard> fdg;
std::unique_ptr<char[]> path;

4. 错误处理

统一的错误处理机制:

NError(EINVAL).ThrowErr(env);

平台兼容性

1. 平台特定代码

模块通过宏定义处理不同平台的差异:

#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM)
// 非Windows和非iOS平台的特定代码
#endif

#ifndef WIN_PLATFORM
// 非Windows平台的特定代码
#endif

2. 条件编译

根据平台特性进行条件编译:

#ifdef WIN_PLATFORM
    string nExporterName = product->GetNExporterName();
#else
    string nExporterName = product->GetClassName();
#endif

性能优化

1. 异步I/O

大量使用异步I/O操作,避免阻塞主线程:

uv_fs_open(loop, req, path, flags, mode, AsyncCallback);

2. 内存池管理

使用FDGuard进行文件描述符的自动管理:

auto fdg = CreateUniquePtr<DistributedFS::FDGuard>(fd, false);

3. 缓冲区优化

针对不同操作类型优化缓冲区使用:

tuple<bool, void *, size_t, int64_t> GetReadArg(napi_env env,
                                                napi_value readBuf,
                                                napi_value option);

安全特性

1. 权限检查

bool CheckPublicDirPath(const std::string &sandboxPath);

2. 用户ID验证

bool GetAndCheckUserId(Uri* uri, std::string &userId);

3. 系统应用检查

bool IsSystemApp();

使用示例

1. 基本文件操作

import fs from '@ohos.file.fs';

// 打开文件
let file = fs.openSync('/path/to/file', fs.OpenMode.READ_ONLY);

// 读取文件
let buffer = new ArrayBuffer(1024);
let bytesRead = fs.readSync(file.fd, buffer);

// 关闭文件
fs.closeSync(file.fd);

2. 异步文件操作

import fs from '@ohos.file.fs';

// 异步读取
fs.read(file.fd, buffer, (err, bytesRead) => {
    if (err) {
        console.error('Read failed:', err);
        return;
    }
    console.log('Bytes read:', bytesRead);
});

3. 文件监控

import fs from '@ohos.file.fs';

// 创建文件监控器
let watcher = fs.createWatcher('/path/to/watch');

// 监听文件变化
watcher.on('change', (event) => {
    console.log('File changed:', event);
});

4. 流式操作

import fs from '@ohos.file.fs';

// 创建流
let stream = fs.createStream(file.fd);

// 流式写入
let data = "Hello, World!";
let bytesWritten = stream.writeSync(data);

// 流式读取
let buffer = new ArrayBuffer(1024);
let bytesRead = stream.readSync(buffer);

// 关闭流
stream.closeSync();

5. 文件状态查询

import fs from '@ohos.file.fs';

// 获取文件状态
let stat = fs.statSync('/path/to/file');

// 检查文件类型
if (stat.isFile()) {
    console.log('This is a file');
}

// 获取文件大小
console.log('File size:', stat.size);

// 获取修改时间
console.log('Modified time:', stat.mtime);

6. 文件锁定

import fs from '@ohos.file.fs';

// 打开文件
let file = fs.openSync('/path/to/file', fs.OpenMode.READ_WRITE);

// 获取独占锁
file.lock(true, (err) => {
    if (err) {
        console.error('Lock failed:', err);
        return;
    }
    console.log('File locked successfully');
    
    // 执行需要独占访问的操作
    // ...
    
    // 释放锁
    file.unlock();
});

7. 云端文件操作

import fs from '@ohos.file.fs';

// 打开云端文件
let cloudFile = fs.openSync('file://media/image/123', fs.OpenMode.READ_ONLY);

// 获取文件状态(包含云端位置信息)
let stat = fs.statSync(cloudFile.fd);
console.log('File location:', stat.location); // LOCAL or CLOUD

// 获取文件路径
console.log('File path:', cloudFile.path);
console.log('File name:', cloudFile.name);
console.log('Parent directory:', cloudFile.getParent());

总结

mod_fs模块是OpenHarmony文件访问接口的核心组件,提供了完整的文件系统操作功能。其设计具有以下特点:

  1. 模块化设计:清晰的目录结构和组件分离
  2. 异步优先:大量使用异步I/O提高性能
  3. 平台兼容:支持多平台的条件编译
  4. 安全可靠:完善的权限检查和错误处理
  5. 易于使用:简洁的JavaScript API接口

网站公告

今日签到

点亮在社区的每一天
去签到