chiark / gitweb /
bundles: Pass size through
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 14 May 2021 23:56:17 +0000 (00:56 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 15 May 2021 00:15:42 +0000 (01:15 +0100)
The progress report wants it, and it's probably good to send it in the
metadata.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/cmdlistener.rs
src/bin/otter.rs
src/bundles.rs
src/commands.rs

index 4436a8d5b9c259e94ea7c1aa78afaf532d19170a..d4afb9f18034c77ae0a74568d985f050a607a7b4 100644 (file)
@@ -221,7 +221,7 @@ fn execute_and_respond<R,W>(cs: &mut CommandStreamData, cmd: MgmtCommand,
       resp
     }
 
-    MC::UploadBundle { game, hash, kind } => {
+    MC::UploadBundle { game, size, hash, kind } => {
       let (upload, auth) = {
         let ag = AccountsGuard::lock();
         let gref = Instance::lookup_by_name_unauth(&game)?;
@@ -233,7 +233,8 @@ fn execute_and_respond<R,W>(cs: &mut CommandStreamData, cmd: MgmtCommand,
         let upload = bundles.start_upload(ig, kind)?;
         (upload, auth)
       };
-      let uploaded = upload.bulk(&mut bulk_upload, &hash, &mut for_response)?;
+      let uploaded = upload.bulk(&mut bulk_upload, size,
+                                 &hash, &mut for_response)?;
       {
         let gref = Instance::lookup_by_name(&game, auth)?;
         let mut bundles = gref.lock_bundles();
index b978437e37996d56a6edf22cb07d473c3471560c..8257fd8bd4678978233b8f6b8a14aa7f65f73c32 100644 (file)
@@ -1340,12 +1340,17 @@ mod upload_bundle {
     let f = File::open(&args.bundle_file)
       .with_context(|| args.bundle_file.clone())
       .context("open bundle file")?;
+    let size = f
+      .metadata().context("fstat bundle file")?
+      .len()
+      .try_into().map_err(|_| anyhow!("bundle file far too large"))?;
     let mut f = BufReader::new(f);
     let hash = bundles::DigestWrite::of(&mut f)
       .context("read bundle file (for hash)")?;
     let kind = bundles::Kind::only();
     f.rewind().context("rewind bundle file")?;
     let cmd = MC::UploadBundle {
+      size,
       game: instance_name.clone(),
       hash: bundles::Hash(hash.into()), kind,
     };
index 71e307c323aa06372597eb9cb49e1388c7e5912c..6518f07741f8f6f68dbaf0bc3a549fa945f03e6d 100644 (file)
@@ -825,7 +825,7 @@ impl InstanceBundles {
 
 impl Uploading {
   #[throws(MgmtError)]
-  pub fn bulk<R,PW>(self, data: &mut R, expected: &Hash,
+  pub fn bulk<R,PW>(self, data: &mut R, size: usize, expected: &Hash,
                     for_progress: &mut ResponseWriter<PW>) -> Uploaded
   where R: Read, PW: Write
   {
@@ -837,12 +837,14 @@ impl Uploading {
     let Uploading { id, mut file, instance } = self;
     let tmp = id.path_tmp(&instance);
 
-    io::copy(data, &mut file)
+    let copied_size = io::copy(data, &mut file)
       .with_context(|| tmp.clone())
       .context("copy").map_err(IE::from)?;
 
     let (hash, file) = file.finish();
 
+    if copied_size != size as u64 { throw!(ME::UploadTruncated) }
+
     let mut file = file.into_inner().map_err(|e| e.into_error())
       .with_context(|| tmp.clone()).context("flush").map_err(IE::from)?;
     if hash.as_slice() != &expected.0[..] { throw!(ME::UploadCorrupted) }
index e18a4bad60ca09b653ebb508012fed9b9fb2d3bb..8ca26f144e2ad3d671c0b7f7923d7fe27d11b195 100644 (file)
@@ -43,6 +43,7 @@ pub enum MgmtCommand {
   },*/
   UploadBundle {
     game: InstanceName,
+    size: usize,
     hash: bundles::Hash,
     kind: bundles::Kind,
   },
@@ -230,6 +231,7 @@ pub enum MgmtError {
   TomlSyntaxError(String),
   TomlStructureError(String),
   RngIsReal,
+  UploadTruncated,
   UploadCorrupted,
   TooManyBundles,
   BadBundle(String),