@@ -411,12 +411,7 @@ impl ImageProxy {
411411 } ) ;
412412 }
413413 let fdret = match ( fdret, reply. pipeid ) {
414- ( Some ( fd) , n) => {
415- if n == 0 {
416- return Err ( Error :: Other ( "got fd but no pipeid" . into ( ) ) ) ;
417- }
418- Some ( ( fd, n) )
419- }
414+ ( Some ( fd) , n) => Some ( ( fd, n) ) ,
420415 ( None , n) => {
421416 if n != 0 {
422417 return Err ( Error :: Other ( format ! ( "got no fd with pipeid {}" , n) . into ( ) ) ) ;
@@ -458,6 +453,7 @@ impl ImageProxy {
458453 #[ instrument]
459454 async fn finish_pipe ( & self , pipeid : u32 ) -> Result < ( ) > {
460455 tracing:: debug!( "closing pipe" ) ;
456+ debug_assert ! ( pipeid > 0 ) ;
461457 let ( r, fd) = self . impl_request ( "FinishPipe" , [ pipeid] ) . await ?;
462458 if fd. is_some ( ) {
463459 return Err ( Error :: Other ( "Unexpected fd in finish_pipe reply" . into ( ) ) ) ;
@@ -496,6 +492,9 @@ impl ImageProxy {
496492
497493 async fn read_all_fd ( & self , fd : Option < ( OwnedFd , u32 ) > ) -> Result < Vec < u8 > > {
498494 let ( fd, pipeid) = fd. ok_or_else ( || Error :: Other ( "Missing fd from reply" . into ( ) ) ) ?;
495+ if pipeid == 0 {
496+ return Err ( Error :: Other ( "got fd but no pipeid" . into ( ) ) ) ;
497+ }
499498 let fd = tokio:: fs:: File :: from_std ( std:: fs:: File :: from ( fd) ) ;
500499 let mut fd = tokio:: io:: BufReader :: new ( fd) ;
501500 let mut r = Vec :: new ( ) ;
@@ -570,12 +569,33 @@ impl ImageProxy {
570569 vec ! [ img. 0 . into( ) , digest. to_string( ) . into( ) , size. into( ) ] ;
571570 let ( _bloblen, fd) = self . impl_request :: < i64 , _ , _ > ( "GetBlob" , args) . await ?;
572571 let ( fd, pipeid) = fd. ok_or_else ( || Error :: new_other ( "Missing fd from reply" ) ) ?;
572+ if pipeid == 0 {
573+ return Err ( Error :: Other ( "got fd but no pipeid" . into ( ) ) ) ;
574+ }
573575 let fd = tokio:: fs:: File :: from_std ( std:: fs:: File :: from ( fd) ) ;
574576 let fd = tokio:: io:: BufReader :: new ( fd) ;
575577 let finish = Box :: pin ( self . finish_pipe ( pipeid) ) ;
576578 Ok ( ( fd, finish) )
577579 }
578580
581+ /// Fetch a blob identified by e.g. `sha256:<digest>`; does not perform
582+ /// any verification that the blob matches the digest. The size of the
583+ /// blob and a pipe file descriptor are returned.
584+ #[ instrument]
585+ pub async fn get_raw_blob (
586+ & self ,
587+ img : & OpenedImage ,
588+ digest : & Digest ,
589+ ) -> Result < ( u64 , tokio:: fs:: File ) > {
590+ tracing:: debug!( "fetching blob" ) ;
591+ let args: Vec < serde_json:: Value > = vec ! [ img. 0 . into( ) , digest. to_string( ) . into( ) ] ;
592+ let ( bloblen, fd) = self . impl_request :: < u64 , _ , _ > ( "GetRawBlob" , args) . await ?;
593+ let ( fd, pipeid) = fd. ok_or_else ( || Error :: new_other ( "Missing fd from reply" ) ) ?;
594+ debug_assert_eq ! ( pipeid, 0 ) ;
595+ let fd = tokio:: fs:: File :: from_std ( std:: fs:: File :: from ( fd) ) ;
596+ Ok ( ( bloblen, fd) )
597+ }
598+
579599 /// Fetch a descriptor. The requested size and digest are verified (by the proxy process).
580600 #[ instrument]
581601 pub async fn get_descriptor (
0 commit comments