NFSv3 over TCP file client for MoonBit
moon add cauchyQ/moon-nfs3@0.1.0git clone https://github.com/cauchyQ/moon-nfs3.git
cd moon-nfs3
moon update
moon check --deny-warn
moon test --deny-warn
moon run cmd/main -- --helpcurl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s -- '0.10.14+7d59c7ec9'moon run cmd/main -- ls server.example /shared /
moon run cmd/main -- stat server.example /shared reports/data.bin
moon run cmd/main -- get server.example /shared reports/data.bin ./data.bin
moon run cmd/main -- put server.example /shared ./output.bin reports/output.bin
moon run cmd/main -- mkdir server.example /shared reports/new
moon run cmd/main -- mv server.example /shared reports/output.bin reports/new/output.bin
moon run cmd/main -- rm server.example /shared reports/new/output.bin
moon run cmd/main -- rmdir server.example /shared reports/new
moon run cmd/main -- space server.example /shared| 环境变量 | 默认值 | 说明 |
|---|---|---|
| NFS_UID, NFS_GID | 65534 | AUTH_SYS 使用的 UID 和 GID |
| NFS_PORT | 0 | NFS TCP 端口;0 表示通过 portmapper v2 发现 |
| NFS_MOUNT_PORT | 0 | MOUNTv3 TCP 端口;0 表示自动发现 |
| NFS_BLOCK_SIZE | 65536 | 客户端传输缓冲区上限,单位为字节 |
| NFS_MAX_RECORD | 1048576 | RPC/XDR 记录的大小上限,单位为字节 |
| NFS_TIMEOUT_MS | 10000 | 单次 RPC 的超时时间,单位为毫秒 |
| NFS_MAX_ENTRIES | 100000 | 单目录条目上限;本地目录树传输等操作也将其用作总节点上限 |
| NFS_DEST_PORT, NFS_DEST_MOUNT_PORT | 源连接的端口配置 | 跨连接复制时的目标端口 |
| NFS_DEST_UID, NFS_DEST_GID | 源连接的身份配置 | 目标连接使用的 AUTH_SYS 身份 |
moon run cmd/main -- tree server.example /shared reports
moon run cmd/main -- cp-tree server.example /shared reports backups/reports
moon run cmd/main -- get-tree server.example /shared reports ./reports-copy
moon run cmd/main -- verify-tree server.example /shared ./reports-copy reports
moon run cmd/main -- resume-get server.example /shared large.bin ./partial.bin
moon run cmd/main -- resume-put server.example /shared ./large.bin partial.bin
moon run cmd/main -- atomic-put server.example /shared ./result.bin result.bin .result-upload.tmp
moon run cmd/main -- copy-to source-server /source data.bin target-server /target data.binlet client = @nfs.connect_export("server.example", "/shared")
defer client.close()
let handle = client.resolve("reports/data.bin")
let attrs = client.getattr(handle)
let first = client.read_at(handle, 0UL, 1024)
println("文件大小=\{attrs.size},首块字节数=\{first.data.length()}")| 功能 | 主要接口 |
|---|---|
| 属性与状态 | stat, getattr, metadata, access, readlink, space, fsinfo, pathconf, health_check, ping |
| 查找与路径 | root_handle, lookup, resolve, canonical_path, resolve_following, exists |
| 读取 | read_at, read_exactly_at, read_bytes, read_text, download_to, download, download_range, open_reader |
| 写入 | write_at, write_all, commit, write_committed, write_bytes, write_text, upload_from, upload, upload_range, open_writer |
| 文件管理 | create_file, mkdir, ensure_directory, setattr, set_attributes, chmod, chown, truncate, touch, rename, remove, symlink, hard_link, mknod |
| 目录遍历 | read_directory, list_dir, scan_directory, open_directory, walk, collect_tree, disk_usage |
| 复制与续传 | copy_file, copy_file_checked, copy_range, copy_tree, upload_tree, download_tree, resume_upload, resume_download |
| 原子发布 | upload_atomic, download_atomic, copy_atomic |
| 跨连接复制 | copy_file_to, copy_tree_to, resume_copy_to |
| 校验与诊断 | compare_files, compare_trees, verify_local_file, verify_local_tree, benchmark_read, statistics |
| 原始字节文件名 | lookup_bytes, create_entry, remove_entry, rename_entry |
moon check --deny-warn
moon build --deny-warn
moon test --deny-warn
moon info
moon fmt
git diff --exit-code
python validation/source_lines.py --min-implementation 4000pub suberror NfsError {
InvalidArgument(String)
ProtocolError(String)
RpcFailure(String)
Status(UInt)
OutcomeUnknown(String)
}pub(all) struct AttributeUpdate {
mode : UInt?
uid : UInt?
gid : UInt?
size : UInt64?
accessed : TimeUpdate
modified : TimeUpdate
}pub(all) struct Attributes {
kind : UInt
mode : UInt
links : UInt
uid : UInt
gid : UInt
size : UInt64
used : UInt64
fsid : UInt64
fileid : UInt64
modified_seconds : UInt
}pub struct Client {
// private fields
}async fn Client::benchmark_read(self : Client, path : String, rounds? : Int, max_bytes? : UInt64) -> ReadBenchmarkasync fn Client::compare_trees(self : Client, left : String, right : String, compare_mode? : Bool) -> Array[TreeDifference]async fn Client::copy_tree(self : Client, source : String, destination : String, preserve_mode? : Bool) -> TreeTransferasync fn Client::copy_tree_to(self : Client, destination_client : Client, source : String, destination : String, preserve_mode? : Bool) -> TreeTransferasync fn Client::download_tree(self : Client, remote_path : String, local_path : String) -> TreeTransferasync fn Client::open_reader(self : Client, path : String, offset? : UInt64, length? : UInt64?) -> MemoryReaderasync fn Client::read_at(self : Client, handle : Handle, offset : UInt64, count : Int) -> ReadResultasync fn Client::read_directory(self : Client, directory : Handle, cookie? : UInt64, verifier? : Bytes, plus? : Bool) -> DirectoryPageasync fn Client::set_attributes(self : Client, handle : Handle, update : AttributeUpdate, ctime_guard? : Timestamp?) -> Unitasync fn Client::upload_tree(self : Client, local_path : String, remote_path : String) -> TreeTransferasync fn Client::verify_local_file(self : Client, local_path : String, remote_path : String) -> FileComparisonasync fn Client::verify_local_tree(self : Client, local_path : String, remote_path : String) -> LocalTreeComparisonasync fn Client::walk(self : Client, path : String, max_depth? : Int, max_nodes? : Int) -> TreeWalkerasync fn Client::write_at(self : Client, handle : Handle, offset : UInt64, data : Bytes, stability? : Stability) -> WriteResultpub struct DirectoryCursor {
// private fields
}pub(all) struct DirectoryEntry {
fileid : UInt64
name : Bytes
cookie : UInt64
attributes : Attributes?
handle : Handle?
}pub(all) struct DiskUsage {
files : UInt64
directories : UInt64
symlinks : UInt64
special : UInt64
logical_bytes : UInt64
allocated_bytes : UInt64
}pub(all) struct FileComparison {
equal : Bool
compared_bytes : UInt64
first_difference : UInt64?
}pub(all) struct FileSystemInfo {
read_max : UInt
read_preferred : UInt
read_multiple : UInt
write_max : UInt
write_preferred : UInt
write_multiple : UInt
directory_preferred : UInt
max_file_size : UInt64
time_delta : Timestamp
properties : UInt
}pub(all) struct Handle {
bytes : Bytes
}pub(all) struct HealthReport {
attributes : Attributes
granted_access : UInt
filesystem : FileSystemInfo
space : Space
paths : PathConfig
rpc : RpcStatistics
elapsed_ms : Int64
}pub(all) struct Metadata {
attributes : Attributes
device_major : UInt
device_minor : UInt
accessed : Timestamp
modified : Timestamp
changed : Timestamp
}pub(all) struct Options {
uid : UInt
gid : UInt
groups : Array[UInt]
timeout_ms : Int
block_size : Int
max_record : Int
max_entries : Int
}pub(all) struct PathConfig {
link_max : UInt
name_max : UInt
no_truncation : Bool
chown_restricted : Bool
case_insensitive : Bool
case_preserving : Bool
}pub(all) struct ReadBenchmark {
rounds : Int
bytes : UInt64
elapsed_ms : Int64
fastest_ms : Int64
slowest_ms : Int64
rpc : RpcStatistics
}pub struct RemoteWriter {
// private fields
}impl Writer for RemoteWriterasync fn RemoteWriter::write_once(self : RemoteWriter, bytes : Bytes, offset~ : Int, len~ : Int) -> Intpub struct Rpc {
// private fields
}pub(all) struct RpcStatistics {
calls : UInt64
replies : UInt64
request_bytes : UInt64
response_bytes : UInt64
failures : UInt64
}pub(all) struct ServiceMapping {
program : UInt
version : UInt
protocol : UInt
port : UInt
}pub(all) struct Space {
total_bytes : UInt64
free_bytes : UInt64
available_bytes : UInt64
total_files : UInt64
free_files : UInt64
available_files : UInt64
invariant_seconds : UInt
}pub(all) enum SpecialNode {
BlockDevice(UInt, UInt)
CharacterDevice(UInt, UInt)
UnixSocket
NamedPipe
}pub(all) struct Timestamp {
seconds : UInt
nanoseconds : UInt
}pub(all) enum TreeDifferenceKind {
MissingLeft
MissingRight
DifferentType
DifferentSize
DifferentContent
DifferentMode
DifferentLinkTarget
}pub(all) struct TreeEntry {
path : String
relative : String
depth : Int
handle : Handle
attributes : Attributes
}pub(all) struct TreeTransfer {
files : Int
directories : Int
symlinks : Int
bytes : UInt64
}pub struct TreeWalker {
// private fields
}