diff --git a/.tangled/workflows/rust-test-knot.yml b/.tangled/workflows/rust-test-knot.yml index eab77a02..cafbcdae 100644 --- a/.tangled/workflows/rust-test-knot.yml +++ b/.tangled/workflows/rust-test-knot.yml @@ -47,8 +47,10 @@ steps: - name: knot tests command: | + ulimit -n "$(ulimit -Hn)" && cargo test --locked -p 'knot-*' - name: knot instrumented tests command: | + ulimit -n "$(ulimit -Hn)" && cd knot2 && just instrument-tests diff --git a/knot2/crates/knot-pack/src/idxwrite.rs b/knot2/crates/knot-pack/src/idxwrite.rs index 0776b401..e4157b6e 100644 --- a/knot2/crates/knot-pack/src/idxwrite.rs +++ b/knot2/crates/knot-pack/src/idxwrite.rs @@ -22,35 +22,35 @@ struct Record { offset: PackOffset, } +type Bucket = Mutex>>; + pub(crate) struct Spool { - buckets: Vec>>, + buckets: Vec, record_len: usize, hash_len: usize, } impl Spool { - pub(crate) fn new(kind: gix::hash::Kind) -> io::Result { + pub(crate) fn new(kind: gix::hash::Kind) -> Self { let hash_len = kind.len_in_bytes(); - let buckets = (0..BUCKETS) - .map(|_| { - tempfile::tempfile() - .map(|file| Mutex::new(BufWriter::with_capacity(BUCKET_BUF, file))) - }) - .collect::>>()?; - Ok(Self { - buckets, + Self { + buckets: (0..BUCKETS).map(|_| Mutex::new(None)).collect(), record_len: hash_len + CRC_LEN + OFFSET_LEN, hash_len, - }) + } } pub(crate) fn push(&self, id: ObjectId, crc32: Crc32, offset: PackOffset) -> io::Result<()> { let mut guard = self.buckets[id.first_byte() as usize] .lock() .expect("spool bucket poisoned"); - guard.write_all(id.as_slice())?; - guard.write_all(&crc32.get().to_be_bytes())?; - guard.write_all(&offset.get().to_be_bytes()) + let writer = match guard.as_mut() { + Some(writer) => writer, + None => guard.insert(BufWriter::with_capacity(BUCKET_BUF, tempfile::tempfile()?)), + }; + writer.write_all(id.as_slice())?; + writer.write_all(&crc32.get().to_be_bytes())?; + writer.write_all(&offset.get().to_be_bytes()) } fn cumulative_fanout(&self) -> Result<[u32; 256], PackError> { @@ -58,9 +58,13 @@ impl Spool { self.buckets.iter().enumerate().try_for_each( |(bucket, cell)| -> Result<(), PackError> { let mut guard = cell.lock().expect("spool bucket poisoned"); - guard.flush()?; - let len = guard.get_ref().metadata()?.len() as usize; - fanout[bucket] = (len / self.record_len) as u32; + fanout[bucket] = match guard.as_mut() { + None => 0, + Some(writer) => { + writer.flush()?; + (writer.get_ref().metadata()?.len() as usize / self.record_len) as u32 + } + }; Ok(()) }, )?; @@ -82,16 +86,19 @@ impl Spool { }) } - fn read_bucket( - &self, - cell: &Mutex>, - ) -> Result, PackError> { + fn read_bucket(&self, cell: &Bucket) -> Result, PackError> { let mut guard = cell.lock().expect("spool bucket poisoned"); - guard.flush()?; - let file = guard.get_ref(); - let len = file.metadata()?.len() as usize; - let mut bytes = vec![0u8; len]; - file.read_exact_at(&mut bytes, 0)?; + let bytes = match guard.as_mut() { + None => Vec::new(), + Some(writer) => { + writer.flush()?; + let file = writer.get_ref(); + let len = file.metadata()?.len() as usize; + let mut bytes = vec![0u8; len]; + file.read_exact_at(&mut bytes, 0)?; + bytes + } + }; drop(guard); bytes .chunks_exact(self.record_len) @@ -179,7 +186,7 @@ mod tests { (oid(0x80), 0x3333_3333, 0x1_2345_6789), (oid(0xc0), 0x4444_4444, LARGE_OFFSET_THRESHOLD + 1), ]; - let spool = Spool::new(gix::hash::Kind::Sha1).unwrap(); + let spool = Spool::new(gix::hash::Kind::Sha1); records.iter().for_each(|(id, crc32, offset)| { spool .push(*id, Crc32::new(*crc32), PackOffset::new(*offset)) diff --git a/knot2/crates/knot-pack/src/objects.rs b/knot2/crates/knot-pack/src/objects.rs index 6ee95f9d..7a08c2bc 100644 --- a/knot2/crates/knot-pack/src/objects.rs +++ b/knot2/crates/knot-pack/src/objects.rs @@ -742,7 +742,7 @@ fn spool_pack( .map_err(|error| PackError::Pack(error.to_string()))?; let stored = gix_pack::data::File::at(pack_path, kind) .map_err(|error| PackError::Pack(error.to_string()))?; - let spool = crate::idxwrite::Spool::new(kind)?; + let spool = crate::idxwrite::Spool::new(kind); run_ingest_traverse( tree, &stored, diff --git a/shuttle/src/exec.rs b/shuttle/src/exec.rs index b1868444..20f7ac43 100644 --- a/shuttle/src/exec.rs +++ b/shuttle/src/exec.rs @@ -167,37 +167,36 @@ fn resolve_user(spec: &str) -> Result { } fn lookup_user(name: &str) -> Result { - match User::from_name(name) { - Ok(Some(user)) => Ok(ResolvedUser { + match name.parse::() { + Ok(uid) => Ok(ResolvedUser { name: name.to_owned(), - uid: user.uid.as_raw(), - gid: user.gid.as_raw(), - home: user.dir.into_os_string(), - shell: user.shell.into_os_string(), + uid, + gid: uid, + home: OsString::from("/"), + shell: OsString::from("/bin/sh"), }), - Ok(None) => { - let uid = name - .parse::() - .map_err(|_| format!("workflow user {name:?} was not found"))?; - Ok(ResolvedUser { + Err(_) => match User::from_name(name) { + Ok(Some(user)) => Ok(ResolvedUser { name: name.to_owned(), - uid, - gid: uid, - home: OsString::from("/"), - shell: OsString::from("/bin/sh"), - }) - } - Err(error) => Err(format!("lookup workflow user {name:?}: {error}")), + uid: user.uid.as_raw(), + gid: user.gid.as_raw(), + home: user.dir.into_os_string(), + shell: user.shell.into_os_string(), + }), + Ok(None) => Err(format!("workflow user {name:?} was not found")), + Err(error) => Err(format!("lookup workflow user {name:?}: {error}")), + }, } } fn lookup_group(name: &str) -> Result { - match Group::from_name(name) { - Ok(Some(group)) => Ok(group.gid.as_raw()), - Ok(None) => name - .parse::() - .map_err(|_| format!("workflow group {name:?} was not found")), - Err(error) => Err(format!("lookup workflow group {name:?}: {error}")), + match name.parse::() { + Ok(gid) => Ok(gid), + Err(_) => match Group::from_name(name) { + Ok(Some(group)) => Ok(group.gid.as_raw()), + Ok(None) => Err(format!("workflow group {name:?} was not found")), + Err(error) => Err(format!("lookup workflow group {name:?}: {error}")), + }, } } @@ -214,14 +213,20 @@ mod tests { use super::*; #[test] - fn refuses_root_exec_user() { - let err = resolve_user("root").unwrap_err(); + fn refuses_exec_as_uid_zero() { + let err = resolve_user("0").unwrap_err(); assert!(err.contains("refusing to run exec as privileged user")); } #[test] - fn refuses_root_exec_group() { + fn refuses_exec_as_gid_zero() { let err = resolve_user("65534:0").unwrap_err(); assert!(err.contains("refusing to run exec as privileged user")); } + + #[test] + fn resolves_numeric_spec_without_a_user_database() { + let user = resolve_user("65534:65533").unwrap(); + assert_eq!((user.uid, user.gid), (65534, 65533)); + } }