File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -526,6 +526,38 @@ impl<ObjectID: FsVerityHashValue> Repository<ObjectID> {
526526 Ok ( id)
527527 }
528528
529+ /// Store an object from a file descriptor, using reflink (FICLONE) when possible.
530+ ///
531+ /// Tries FICLONE first for an instant copy-on-write clone (works when the
532+ /// source fd and the repository are on the same filesystem). Falls back to
533+ /// a buffered data copy using the caller-provided `buf`. Passing a large
534+ /// buffer avoids the small default used by `std::io::copy`.
535+ #[ context( "Ensuring object from fd exists in repository" ) ]
536+ pub fn ensure_object_from_fd (
537+ & self ,
538+ fd : OwnedFd ,
539+ size : u64 ,
540+ buf : & mut [ u8 ] ,
541+ ) -> Result < ObjectID > {
542+ let tmpfile = self . create_object_tmpfile ( ) ?;
543+ let src = File :: from ( fd) ;
544+ let mut dst = File :: from ( tmpfile) ;
545+
546+ if rustix:: fs:: ioctl_ficlone ( & dst, & src) . is_err ( ) {
547+ let mut src = src;
548+ loop {
549+ let n = src. read ( buf) . context ( "reading from source fd" ) ?;
550+ if n == 0 {
551+ break ;
552+ }
553+ dst. write_all ( & buf[ ..n] )
554+ . context ( "writing to repository tmpfile" ) ?;
555+ }
556+ }
557+
558+ self . finalize_object_tmpfile ( dst, size)
559+ }
560+
529561 #[ context( "Opening file '{filename}' with verity verification" ) ]
530562 fn open_with_verity ( & self , filename : & str , expected_verity : & ObjectID ) -> Result < OwnedFd > {
531563 let fd = self
You can’t perform that action at this time.
0 commit comments