Files
One-KVM/libs/ventoy-img-rs/docs/LIBRARY.md
mofeng-git d143d158e4 init
2025-12-28 18:19:16 +08:00

580 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ventoy-img 库使用说明
## 安装
### 作为依赖添加
```toml
[dependencies]
ventoy-img = { path = "path/to/ventoy-img-rs" }
```
或发布到 crates.io 后:
```toml
[dependencies]
ventoy-img = "0.1"
```
## 快速开始
```rust
use ventoy_img::{VentoyImage, Result};
use std::path::Path;
fn main() -> Result<()> {
// 创建 8GB Ventoy 镜像
let img = VentoyImage::create(
Path::new("ventoy.img"),
"8G",
"Ventoy"
)?;
// 打开已有镜像
let mut img = VentoyImage::open(Path::new("ventoy.img"))?;
// 列出文件
for file in img.list_files()? {
println!("{}: {} bytes", file.name, file.size);
}
Ok(())
}
```
## API 参考
### VentoyImage
主要的镜像操作结构体。
#### 创建镜像
```rust
pub fn create(path: &Path, size_str: &str, label: &str) -> Result<Self>
```
创建新的 Ventoy IMG 文件。
**参数:**
- `path`: 输出文件路径
- `size_str`: 镜像大小,支持格式:`"8G"`, `"16G"`, `"1024M"`, `"1073741824"`
- `label`: 数据分区卷标(最长 11 字符)
**示例:**
```rust
// 创建 8GB 镜像
let img = VentoyImage::create(Path::new("ventoy.img"), "8G", "Ventoy")?;
// 创建 512MB 镜像
let img = VentoyImage::create(Path::new("small.img"), "512M", "MyUSB")?;
```
#### 打开镜像
```rust
pub fn open(path: &Path) -> Result<Self>
```
打开已有的 Ventoy IMG 文件。会验证 Ventoy 签名。
**示例:**
```rust
let img = VentoyImage::open(Path::new("ventoy.img"))?;
```
#### 列出文件
```rust
pub fn list_files(&self) -> Result<Vec<FileInfo>>
pub fn list_files_at(&self, path: &str) -> Result<Vec<FileInfo>>
pub fn list_files_recursive(&self) -> Result<Vec<FileInfo>>
```
列出数据分区中的文件。
**返回:**
```rust
pub struct FileInfo {
pub name: String,
pub size: u64,
pub is_directory: bool,
pub path: String, // 完整路径(用于递归列出)
}
```
**示例:**
```rust
let img = VentoyImage::open(Path::new("ventoy.img"))?;
// 列出根目录
for file in img.list_files()? {
if file.is_directory {
println!("[DIR] {}", file.name);
} else {
println!("[FILE] {} ({} bytes)", file.name, file.size);
}
}
// 列出指定目录
for file in img.list_files_at("iso/linux")? {
println!("{}", file.name);
}
// 递归列出所有文件
for file in img.list_files_recursive()? {
println!("{}: {} bytes", file.path, file.size);
}
```
#### 添加文件
```rust
pub fn add_file(&mut self, src_path: &Path) -> Result<()>
pub fn add_file_overwrite(&mut self, src_path: &Path, overwrite: bool) -> Result<()>
pub fn add_file_to_path(&mut self, src_path: &Path, dest_path: &str, create_parents: bool, overwrite: bool) -> Result<()>
```
将文件添加到数据分区。
**示例:**
```rust
let mut img = VentoyImage::open(Path::new("ventoy.img"))?;
// 添加到根目录
img.add_file(Path::new("/path/to/ubuntu.iso"))?;
// 添加并覆盖已存在的文件
img.add_file_overwrite(Path::new("/path/to/new-ubuntu.iso"), true)?;
// 添加到子目录(自动创建父目录)
img.add_file_to_path(
Path::new("/path/to/ubuntu.iso"),
"iso/linux/ubuntu.iso",
true, // create_parents
false, // overwrite
)?;
// 添加并覆盖子目录中的文件
img.add_file_to_path(
Path::new("/path/to/new-ubuntu.iso"),
"iso/linux/ubuntu.iso",
false, // create_parents (目录已存在)
true, // overwrite
)?;
```
#### 创建目录
```rust
pub fn create_directory(&mut self, path: &str, create_parents: bool) -> Result<()>
```
在数据分区中创建目录。
**示例:**
```rust
let mut img = VentoyImage::open(Path::new("ventoy.img"))?;
// 创建单级目录
img.create_directory("iso", false)?;
// 递归创建多级目录(类似 mkdir -p
img.create_directory("iso/linux/ubuntu", true)?;
```
#### 删除文件
```rust
pub fn remove_file(&mut self, name: &str) -> Result<()>
pub fn remove_path(&mut self, path: &str) -> Result<()>
pub fn remove_recursive(&mut self, path: &str) -> Result<()>
```
从数据分区删除文件或目录。
**示例:**
```rust
let mut img = VentoyImage::open(Path::new("ventoy.img"))?;
// 删除根目录的文件
img.remove_file("ubuntu.iso")?;
// 删除子目录中的文件或空目录
img.remove_path("iso/linux/ubuntu.iso")?;
img.remove_path("iso/empty-dir")?;
// 递归删除目录及其所有内容
img.remove_recursive("iso")?;
```
#### 获取分区布局
```rust
pub fn layout(&self) -> &PartitionLayout
```
获取分区布局信息。
**示例:**
```rust
let img = VentoyImage::open(Path::new("ventoy.img"))?;
let layout = img.layout();
println!("Data partition: {} MB", layout.data_size() / 1024 / 1024);
println!("EFI partition: {} MB", layout.efi_size_sectors * 512 / 1024 / 1024);
```
### ExfatFs
底层 exFAT 文件系统操作。
#### 打开文件系统
```rust
pub fn open(path: &Path, layout: &PartitionLayout) -> Result<Self>
```
**示例:**
```rust
use ventoy_img::exfat::ExfatFs;
let layout = PartitionLayout::calculate(8 * 1024 * 1024 * 1024)?;
let mut fs = ExfatFs::open(Path::new("ventoy.img"), &layout)?;
```
#### 写入文件
```rust
// 基本写入(根目录)
pub fn write_file(&mut self, name: &str, data: &[u8]) -> Result<()>
// 带覆盖选项
pub fn write_file_overwrite(&mut self, name: &str, data: &[u8], overwrite: bool) -> Result<()>
// 写入到指定路径
pub fn write_file_path(&mut self, path: &str, data: &[u8], create_parents: bool, overwrite: bool) -> Result<()>
```
**示例:**
```rust
// 写入到根目录
fs.write_file("config.txt", b"content")?;
// 覆盖已存在的文件
fs.write_file_overwrite("config.txt", b"new content", true)?;
// 写入到子目录(自动创建父目录)
fs.write_file_path("iso/linux/config.txt", b"content", true, false)?;
```
#### 读取文件
```rust
pub fn read_file(&mut self, name: &str) -> Result<Vec<u8>>
pub fn read_file_path(&mut self, path: &str) -> Result<Vec<u8>>
```
读取文件内容到内存。
**示例:**
```rust
// 从根目录读取
let data = fs.read_file("config.txt")?;
// 从子目录读取
let data = fs.read_file_path("iso/linux/config.txt")?;
println!("{}", String::from_utf8_lossy(&data));
```
#### 流式读取(大文件)
```rust
pub fn read_file_to_writer<W: Write>(&mut self, name: &str, writer: &mut W) -> Result<u64>
pub fn read_file_path_to_writer<W: Write>(&mut self, path: &str, writer: &mut W) -> Result<u64>
```
流式读取文件到 Writer适合大文件。返回读取的字节数。
**示例:**
```rust
use std::fs::File;
use std::io::BufWriter;
// 从镜像中提取文件
let mut output = BufWriter::new(File::create("extracted.iso")?);
let bytes = fs.read_file_to_writer("ubuntu.iso", &mut output)?;
println!("Extracted {} bytes", bytes);
// 从子目录流式读取
let mut output = Vec::new();
fs.read_file_path_to_writer("iso/linux/ubuntu.iso", &mut output)?;
```
#### 删除文件
```rust
pub fn delete_file(&mut self, name: &str) -> Result<()>
pub fn delete_path(&mut self, path: &str) -> Result<()>
pub fn delete_recursive(&mut self, path: &str) -> Result<()>
```
删除文件或目录并释放空间。
**示例:**
```rust
// 删除根目录的文件
fs.delete_file("config.txt")?;
// 删除子目录中的文件或空目录
fs.delete_path("iso/linux/config.txt")?;
// 递归删除目录
fs.delete_recursive("iso")?;
```
#### 创建目录
```rust
pub fn create_directory(&mut self, path: &str, create_parents: bool) -> Result<()>
```
**示例:**
```rust
// 创建单级目录
fs.create_directory("iso", false)?;
// 递归创建多级目录
fs.create_directory("iso/linux/ubuntu", true)?;
```
#### 列出文件
```rust
pub fn list_files(&mut self) -> Result<Vec<FileInfo>>
pub fn list_files_at(&mut self, path: &str) -> Result<Vec<FileInfo>>
pub fn list_files_recursive(&mut self) -> Result<Vec<FileInfo>>
```
**示例:**
```rust
// 列出根目录
let files = fs.list_files()?;
// 列出指定目录
let files = fs.list_files_at("iso/linux")?;
// 递归列出所有文件
let all_files = fs.list_files_recursive()?;
```
#### 流式写入(大文件)
```rust
pub fn write_file_from_reader<R: Read>(&mut self, name: &str, reader: &mut R, size: u64) -> Result<()>
pub fn write_file_from_reader_overwrite<R: Read>(&mut self, name: &str, reader: &mut R, size: u64, overwrite: bool) -> Result<()>
pub fn write_file_from_reader_path<R: Read>(&mut self, path: &str, reader: &mut R, size: u64, create_parents: bool, overwrite: bool) -> Result<()>
```
从 Reader 流式写入文件,适合大文件。
**示例:**
```rust
use std::fs::File;
use std::io::BufReader;
let file = File::open("large.iso")?;
let size = file.metadata()?.len();
let mut reader = BufReader::new(file);
// 写入到根目录
fs.write_file_from_reader("large.iso", &mut reader, size)?;
// 写入到子目录并覆盖
fs.write_file_from_reader_path(
"iso/linux/large.iso",
&mut reader,
size,
true, // create_parents
true, // overwrite
)?;
```
### ExfatFileWriter
手动控制的流式写入器。
```rust
use ventoy_img::exfat::ExfatFileWriter;
// 创建写入器(根目录)
let mut writer = ExfatFileWriter::create(&mut fs, "file.iso", total_size)?;
// 创建写入器(带覆盖选项)
let mut writer = ExfatFileWriter::create_overwrite(&mut fs, "file.iso", total_size, true)?;
// 创建写入器(指定路径,支持创建父目录和覆盖)
let mut writer = ExfatFileWriter::create_at_path(
&mut fs,
"iso/linux/file.iso",
total_size,
true, // create_parents
false, // overwrite
)?;
// 分块写入
loop {
let n = source.read(&mut buffer)?;
if n == 0 { break; }
writer.write(&buffer[..n])?;
}
// 完成写入(创建目录条目)
writer.finish()?;
```
### ExfatFileReader
手动控制的流式读取器,实现 `std::io::Read``std::io::Seek` 特征。
```rust
use ventoy_img::exfat::ExfatFileReader;
use std::io::{Read, Seek, SeekFrom};
// 打开文件读取器(根目录)
let mut reader = ExfatFileReader::open(&mut fs, "file.iso")?;
// 打开文件读取器(指定路径)
let mut reader = ExfatFileReader::open_path(&mut fs, "iso/linux/file.iso")?;
// 获取文件信息
println!("File size: {} bytes", reader.file_size());
println!("Current position: {}", reader.position());
println!("Remaining: {} bytes", reader.remaining());
// 读取数据
let mut buffer = [0u8; 4096];
let n = reader.read(&mut buffer)?;
// 读取全部内容
let mut data = Vec::new();
reader.read_to_end(&mut data)?;
// Seek 操作
reader.seek(SeekFrom::Start(1000))?; // 从开头偏移
reader.seek(SeekFrom::Current(100))?; // 从当前位置偏移
reader.seek(SeekFrom::End(-100))?; // 从结尾偏移
// 精确读取
let mut exact_buffer = [0u8; 100];
reader.read_exact(&mut exact_buffer)?;
```
**特性:**
- 实现 `std::io::Read``std::io::Seek`
- 自动 cluster 缓存,减少 I/O 次数
- 支持任意位置的 seek
- 内存占用低,只缓存当前 cluster
## 错误处理
所有操作返回 `Result<T, VentoyError>`
```rust
use ventoy_img::{Result, VentoyError};
fn example() -> Result<()> {
let img = VentoyImage::open(Path::new("ventoy.img"))
.map_err(|e| {
match &e {
VentoyError::Io(io_err) => eprintln!("IO error: {}", io_err),
VentoyError::ImageError(msg) => eprintln!("Image error: {}", msg),
VentoyError::FilesystemError(msg) => eprintln!("FS error: {}", msg),
_ => eprintln!("Error: {}", e),
}
e
})?;
Ok(())
}
```
## 完整示例
### 创建镜像并添加 ISO
```rust
use ventoy_img::{VentoyImage, Result};
use std::path::Path;
fn main() -> Result<()> {
// 创建 16GB 镜像
println!("Creating Ventoy image...");
let mut img = VentoyImage::create(
Path::new("ventoy.img"),
"16G",
"Ventoy"
)?;
// 添加 ISO 文件
println!("Adding ISO files...");
img.add_file(Path::new("/isos/ubuntu-22.04.iso"))?;
img.add_file(Path::new("/isos/windows11.iso"))?;
// 列出文件
println!("\nFiles in image:");
for file in img.list_files()? {
println!(" {} ({:.1} MB)", file.name, file.size as f64 / 1024.0 / 1024.0);
}
println!("\nDone! Write ventoy.img to USB drive.");
Ok(())
}
```
### 批量处理 ISO 文件
```rust
use ventoy_img::{VentoyImage, Result};
use std::path::Path;
use std::fs;
fn main() -> Result<()> {
let iso_dir = Path::new("/path/to/isos");
// 计算所需大小
let total_size: u64 = fs::read_dir(iso_dir)?
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().map_or(false, |ext| ext == "iso"))
.map(|e| e.metadata().map(|m| m.len()).unwrap_or(0))
.sum();
// 添加 1GB 余量 + 32MB EFI
let image_size = total_size + 1024 * 1024 * 1024 + 32 * 1024 * 1024;
let size_str = format!("{}M", image_size / 1024 / 1024);
// 创建镜像
let mut img = VentoyImage::create(Path::new("ventoy.img"), &size_str, "Ventoy")?;
// 添加所有 ISO
for entry in fs::read_dir(iso_dir)? {
let entry = entry?;
let path = entry.path();
if path.extension().map_or(false, |ext| ext == "iso") {
println!("Adding: ", path.display());
img.add_file(&path)?;
}
}
Ok(())
}
```
## 注意事项
1. **文件大小限制**: 单个文件最大支持 exFAT 限制(约 16 EB
2. **文件名**: 最长 255 个 UTF-16 字符,大小写不敏感
3. **Unicode 支持**: 完整支持国际字符中日韩、西里尔、希腊字母、Emoji 等)
4. **并发**: `ExfatFs` 不是线程安全的,需要外部同步
5. **磁盘空间**: 创建镜像时会预分配全部空间(稀疏文件)
6. **最小大小**: 镜像最小 64MB32MB EFI + 32MB 数据)
7. **动态簇大小**: 根据卷大小自动选择(<256MB: 4KB, 256MB-8GB: 32KB, >8GB: 128KB