Skip to content

Commit 8f260c2

Browse files
committed
less cursors
1 parent 9329d4d commit 8f260c2

5 files changed

Lines changed: 78 additions & 61 deletions

File tree

cli/src/commands/info.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::collections::BTreeMap;
22

33
use box_format::{AttrMap, AttrValue, BoxFileReader, BoxMetadata, BoxPath, Record};
4-
use fastvint::ReadVintExt;
54

65
use crate::cli::InfoArgs;
76
use crate::error::{Error, Result};
@@ -51,24 +50,24 @@ fn format_attr(key: &str, value: &AttrValue<'_>) -> String {
5150
format!("{}[u256 hex]: {}", key, hex)
5251
}
5352
"unix.mode" => {
54-
let mut cursor = std::io::Cursor::new(*bytes);
55-
if let Ok(val) = cursor.read_vu32() {
53+
let (val, len) = fastvint::decode_vu32_slice(bytes);
54+
if len > 0 {
5655
format!("{}[vu32 oct]: {:o}", key, val)
5756
} else {
5857
format!("{}[bytes]: (invalid)", key)
5958
}
6059
}
6160
"unix.uid" | "unix.gid" => {
62-
let mut cursor = std::io::Cursor::new(*bytes);
63-
if let Ok(val) = cursor.read_vu32() {
61+
let (val, len) = fastvint::decode_vu32_slice(bytes);
62+
if len > 0 {
6463
format!("{}[vu32]: {}", key, val)
6564
} else {
6665
format!("{}[bytes]: (invalid)", key)
6766
}
6867
}
6968
"created" | "modified" | "accessed" => {
70-
let mut cursor = std::io::Cursor::new(*bytes);
71-
if let Ok(minutes) = cursor.read_vi64() {
69+
let (minutes, len) = fastvint::decode_vi64_slice(bytes);
70+
if len > 0 {
7271
let unix_secs = minutes * 60 + BOX_EPOCH_UNIX;
7372
let time =
7473
std::time::UNIX_EPOCH + std::time::Duration::new(unix_secs as u64, 0);

cli/src/util.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::path::Path;
22

33
use box_format::{BoxPath, Compression, CompressionConfig};
4-
use fastvint::ReadVintExt;
54
use indicatif::{ProgressBar, ProgressStyle};
65

76
/// Box epoch: 2020-01-01 00:00:00 UTC (seconds since Unix epoch)
@@ -87,8 +86,8 @@ pub fn create_spinner(message: &str) -> ProgressBar {
8786
/// Format a timestamp from bytes (Vi64 minutes since Box epoch)
8887
pub fn format_time(attr: Option<&[u8]>) -> String {
8988
attr.and_then(|x| {
90-
let mut cursor = std::io::Cursor::new(x);
91-
cursor.read_vi64().ok()
89+
let (minutes, len) = fastvint::decode_vi64_slice(x);
90+
if len > 0 { Some(minutes) } else { None }
9291
})
9392
.map(|minutes| {
9493
let unix_seconds = minutes * 60 + BOX_EPOCH_UNIX;
@@ -101,10 +100,13 @@ pub fn format_time(attr: Option<&[u8]>) -> String {
101100
.unwrap_or_else(|| "-".into())
102101
}
103102

104-
/// Format Unix ACL from bytes
103+
/// Format Unix ACL from bytes (fastvint Vu32 encoded mode)
105104
pub fn format_acl(attr: Option<&[u8]>) -> String {
106105
attr.map(|x| {
107-
let acl = u16::from_le_bytes([x[0], x[1]]);
106+
let (mode, len) = fastvint::decode_vu32_slice(x);
107+
let mode = if len > 0 { mode } else { 0o644 };
108+
// Extract just the permission bits (lower 9 bits)
109+
let acl = (mode & 0o777) as u16;
108110
let mut s = String::with_capacity(9);
109111

110112
macro_rules! add {

crates/fskitbox/src/item.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,11 @@ impl BoxItem {
5959
pub fn mode(record: &Record<'_>, meta: &BoxMetadata) -> u32 {
6060
match record.attr(meta, "unix.mode") {
6161
Some(bytes) => {
62-
let mut cursor = std::io::Cursor::new(bytes);
63-
match fastvint::ReadVintExt::read_vu32(&mut cursor) {
64-
Ok(mode) => mode & 0o7777,
65-
Err(_) => Self::default_mode(record),
62+
let (mode, len) = fastvint::decode_vu32_slice(bytes);
63+
if len > 0 {
64+
mode & 0o7777
65+
} else {
66+
Self::default_mode(record)
6667
}
6768
}
6869
None => Self::default_mode(record),
@@ -81,8 +82,8 @@ impl BoxItem {
8182
pub fn uid(record: &Record<'_>, meta: &BoxMetadata) -> u32 {
8283
match record.attr(meta, "unix.uid") {
8384
Some(bytes) => {
84-
let mut cursor = std::io::Cursor::new(bytes);
85-
fastvint::ReadVintExt::read_vu32(&mut cursor).unwrap_or(501)
85+
let (v, len) = fastvint::decode_vu32_slice(bytes);
86+
if len > 0 { v } else { 501 }
8687
}
8788
None => 501, // Default to current user
8889
}
@@ -92,8 +93,8 @@ impl BoxItem {
9293
pub fn gid(record: &Record<'_>, meta: &BoxMetadata) -> u32 {
9394
match record.attr(meta, "unix.gid") {
9495
Some(bytes) => {
95-
let mut cursor = std::io::Cursor::new(bytes);
96-
fastvint::ReadVintExt::read_vu32(&mut cursor).unwrap_or(20)
96+
let (v, len) = fastvint::decode_vu32_slice(bytes);
97+
if len > 0 { v } else { 20 }
9798
}
9899
None => 20, // Default staff group
99100
}
@@ -117,15 +118,14 @@ impl BoxItem {
117118
fn get_time(record: &Record<'_>, meta: &BoxMetadata, attr_name: &str) -> SystemTime {
118119
match record.attr(meta, attr_name) {
119120
Some(bytes) => {
120-
let mut cursor = std::io::Cursor::new(bytes);
121-
match fastvint::ReadVintExt::read_vi64(&mut cursor) {
122-
Ok(minutes) => {
123-
let unix_secs = (minutes * 60 + BOX_EPOCH_UNIX) as u64;
124-
UNIX_EPOCH
125-
.checked_add(Duration::from_secs(unix_secs))
126-
.unwrap_or(UNIX_EPOCH)
127-
}
128-
Err(_) => UNIX_EPOCH,
121+
let (minutes, len) = fastvint::decode_vi64_slice(bytes);
122+
if len > 0 {
123+
let unix_secs = (minutes * 60 + BOX_EPOCH_UNIX) as u64;
124+
UNIX_EPOCH
125+
.checked_add(Duration::from_secs(unix_secs))
126+
.unwrap_or(UNIX_EPOCH)
127+
} else {
128+
UNIX_EPOCH
129129
}
130130
}
131131
None => UNIX_EPOCH,

crates/fusebox/src/main.rs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::path::PathBuf;
44
use std::time::{Duration, SystemTime, UNIX_EPOCH};
55

66
use clap::Parser;
7-
use fastvint::ReadVintExt;
87
use fuser::{
98
FileAttr, FileType, Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty,
109
ReplyEntry, Request,
@@ -92,16 +91,18 @@ const TTL: Duration = Duration::from_secs(1);
9291

9392
fn parse_archive_time(meta: &BoxMetadata, name: &str) -> Option<SystemTime> {
9493
let bytes = meta.file_attr(name)?;
95-
let mut cursor = std::io::Cursor::new(bytes.as_slice());
96-
let minutes = cursor.read_vi64().ok()?;
94+
let (minutes, len) = fastvint::decode_vi64_slice(bytes.as_slice());
95+
if len == 0 {
96+
return None;
97+
}
9798
let unix_secs = (minutes * 60 + BOX_EPOCH_UNIX) as u64;
9899
UNIX_EPOCH.checked_add(Duration::from_secs(unix_secs))
99100
}
100101

101102
fn archive_uid(meta: &BoxMetadata) -> u32 {
102103
if let Some(bytes) = meta.file_attr("unix.uid") {
103-
let mut cursor = std::io::Cursor::new(bytes.as_slice());
104-
if let Ok(uid) = cursor.read_vu32() {
104+
let (uid, len) = fastvint::decode_vu32_slice(bytes.as_slice());
105+
if len > 0 {
105106
return uid;
106107
}
107108
}
@@ -110,8 +111,8 @@ fn archive_uid(meta: &BoxMetadata) -> u32 {
110111

111112
fn archive_gid(meta: &BoxMetadata) -> u32 {
112113
if let Some(bytes) = meta.file_attr("unix.gid") {
113-
let mut cursor = std::io::Cursor::new(bytes.as_slice());
114-
if let Ok(gid) = cursor.read_vu32() {
114+
let (gid, len) = fastvint::decode_vu32_slice(bytes.as_slice());
115+
if len > 0 {
115116
return gid;
116117
}
117118
}
@@ -203,16 +204,15 @@ impl RecordExt for box_format::Record<'_> {
203204
fn perm(&self, meta: &BoxMetadata) -> u16 {
204205
match self.attr(meta, "unix.mode") {
205206
Some(bytes) => {
206-
let mut cursor = std::io::Cursor::new(bytes);
207-
match cursor.read_vu32() {
208-
Ok(mode) => (mode & 0o7777) as u16,
209-
Err(_) => {
210-
use box_format::Record::*;
211-
match self {
212-
File(_) => 0o644,
213-
Directory(_) => 0o755,
214-
Link(_) => 0o644,
215-
}
207+
let (mode, len) = fastvint::decode_vu32_slice(bytes);
208+
if len > 0 {
209+
(mode & 0o7777) as u16
210+
} else {
211+
use box_format::Record::*;
212+
match self {
213+
File(_) => 0o644,
214+
Directory(_) => 0o755,
215+
Link(_) => 0o644,
216216
}
217217
}
218218
}
@@ -230,15 +230,15 @@ impl RecordExt for box_format::Record<'_> {
230230
fn uid(&self, meta: &BoxMetadata) -> u32 {
231231
// Try record attribute
232232
if let Some(bytes) = self.attr(meta, "unix.uid") {
233-
let mut cursor = std::io::Cursor::new(bytes);
234-
if let Ok(uid) = cursor.read_vu32() {
233+
let (uid, len) = fastvint::decode_vu32_slice(bytes);
234+
if len > 0 {
235235
return uid;
236236
}
237237
}
238238
// Try archive-level default
239239
if let Some(bytes) = meta.file_attr("unix.uid") {
240-
let mut cursor = std::io::Cursor::new(bytes);
241-
if let Ok(uid) = cursor.read_vu32() {
240+
let (uid, len) = fastvint::decode_vu32_slice(bytes);
241+
if len > 0 {
242242
return uid;
243243
}
244244
}
@@ -249,15 +249,15 @@ impl RecordExt for box_format::Record<'_> {
249249
fn gid(&self, meta: &BoxMetadata) -> u32 {
250250
// Try record attribute
251251
if let Some(bytes) = self.attr(meta, "unix.gid") {
252-
let mut cursor = std::io::Cursor::new(bytes);
253-
if let Ok(gid) = cursor.read_vu32() {
252+
let (gid, len) = fastvint::decode_vu32_slice(bytes);
253+
if len > 0 {
254254
return gid;
255255
}
256256
}
257257
// Try archive-level default
258258
if let Some(bytes) = meta.file_attr("unix.gid") {
259-
let mut cursor = std::io::Cursor::new(bytes);
260-
if let Ok(gid) = cursor.read_vu32() {
259+
let (gid, len) = fastvint::decode_vu32_slice(bytes);
260+
if len > 0 {
261261
return gid;
262262
}
263263
}

src/file/reader.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,9 @@ impl BoxFileReader {
331331
/// Checks: record attr -> archive attr -> default (0o644 for files, 0o755 for dirs)
332332
#[cfg(unix)]
333333
pub fn get_mode(&self, record: &Record<'_>) -> u32 {
334-
use fastvint::ReadVintExt;
335-
336334
if let Some(mode_bytes) = self.get_attr(record, "unix.mode") {
337-
let mut cursor = std::io::Cursor::new(mode_bytes);
338-
if let Ok(mode) = cursor.read_vu32() {
335+
let (mode, len) = fastvint::decode_vu32_slice(mode_bytes);
336+
if len > 0 {
339337
return mode;
340338
}
341339
}
@@ -490,7 +488,11 @@ impl BoxFileReader {
490488
.record
491489
.attr(self.metadata(), "blake3")
492490
.map(|h| h.to_vec());
493-
files.push((item.path.clone(), f.clone(), expected_hash));
491+
#[cfg(unix)]
492+
let mode = self.get_mode(&item.record);
493+
#[cfg(not(unix))]
494+
let mode = 0u32;
495+
files.push((item.path.clone(), f.clone(), expected_hash, mode));
494496
}
495497
Record::Link(_) => symlinks.push((item.path.clone(), item.record.clone())),
496498
}
@@ -562,7 +564,7 @@ impl BoxFileReader {
562564

563565
// Seed initial tasks up to concurrency limit
564566
for _ in 0..concurrency {
565-
if let Some((box_path, record, expected_hash)) = files_iter.next() {
567+
if let Some((box_path, record, expected_hash, mode)) = files_iter.next() {
566568
let mmap = mmap.clone();
567569
let out_base = output_path.to_path_buf();
568570
let progress = progress.clone();
@@ -582,6 +584,7 @@ impl BoxFileReader {
582584
&record,
583585
verify_checksums,
584586
expected_hash.as_deref(),
587+
mode,
585588
)
586589
.await;
587590

@@ -612,7 +615,7 @@ impl BoxFileReader {
612615
}
613616

614617
// Spawn next task if more files remain
615-
if let Some((box_path, record, expected_hash)) = files_iter.next() {
618+
if let Some((box_path, record, expected_hash, mode)) = files_iter.next() {
616619
let mmap = mmap.clone();
617620
let out_base = output_path.to_path_buf();
618621
let progress = progress.clone();
@@ -632,6 +635,7 @@ impl BoxFileReader {
632635
&record,
633636
verify_checksums,
634637
expected_hash.as_deref(),
638+
mode,
635639
)
636640
.await;
637641

@@ -1139,6 +1143,7 @@ async fn extract_single_file_from_mmap(
11391143
record: &FileRecord<'_>,
11401144
verify_checksum: bool,
11411145
expected_hash: Option<&[u8]>,
1146+
mode: u32,
11421147
) -> Result<ExtractStats, ExtractError> {
11431148
use crate::hashing::HashingWriter;
11441149
use tokio::io::AsyncWriteExt;
@@ -1223,6 +1228,17 @@ async fn extract_single_file_from_mmap(
12231228
stats.bytes_written = record.decompressed_length;
12241229
}
12251230

1231+
// Set file permissions
1232+
#[cfg(unix)]
1233+
{
1234+
use std::os::unix::fs::PermissionsExt;
1235+
let permissions = std::fs::Permissions::from_mode(mode);
1236+
fs::set_permissions(&out_path, permissions).await.ok();
1237+
}
1238+
1239+
#[cfg(not(unix))]
1240+
let _ = mode;
1241+
12261242
Ok(stats)
12271243
}
12281244

0 commit comments

Comments
 (0)