fn path_for_name(&mut self, name: &str, status: &mut dyn StatusBackend) -> OpenResult<PathBuf> {
        if let Some(info) = self.contents.get(name) {
            return match info.digest.create_two_part_path(&self.data_base) {
                Ok(p) => OpenResult::Ok(p),
                Err(e) => OpenResult::Err(e),
            };
        }

        // The file is not in the cache and we are asked not to try to fetch it.
        if self.only_cached {
            return OpenResult::NotAvailable;
        }

        let info = match self.index.get(name).cloned() {
            Some(info) => info,
            None => return OpenResult::NotAvailable,
        };

        // Bummer, we haven't seen this file before. We need to (try to) fetch
        // the item from the backend, saving it to disk and calculating its
        // digest ourselves, then enter it in the cache and in our manifest.
        // Fun times. Because we're touching the backend, we need to verify that
        // its digest is what we think.

        if let Err(e) = self.check_digest(status) {
            return OpenResult::Err(e);
        }

        // The bundle's overall digest is OK. Now try open the file. If it's
        // not available, cache that result, since LaTeX compilations commonly
        // touch nonexistent files. If we didn't maintain the negative cache,
        // we'd have to touch the network for virtually every compilation.

        let content = match get_file(
            &mut self.tar_data,
            name,
            info.offset,
            info.length as usize,
            status,
        ) {
            Ok(c) => c,
            Err(e) => return OpenResult::Err(e),
        };

        // OK, we can stream the file to a temporary location on disk,
        // computing its SHA256 as we go.

        let length = content.len();

        let mut digest_builder = digest::create();
        digest_builder.input(&content);

        let digest = DigestData::from(digest_builder);

        let final_path = match digest.create_two_part_path(&self.data_base) {
            Ok(p) => p,
            Err(e) => return OpenResult::Err(e),
        };

        // Perform a racy check for the destination existing, because this
        // matters on Windows: if the destination is already there, we'll get
        // an error because the destination is marked read-only. Assuming
        // non-pathological filesystem manipulation, though, we'll only be
        // subject to the race once.

        if !final_path.exists() {
            if let Err(e) = file_create_write(&final_path, |f| f.write_all(&content)) {
                return OpenResult::Err(e);
            }

            // Now we can make the file readonly. It would be nice to set the
            // permissions using the already-open file handle owned by the
            // tempfile, but mkstemp doesn't give us access.
            let mut perms = match fs::metadata(&final_path) {
                Ok(p) => p,
                Err(e) => {
                    return OpenResult::Err(e.into());
                }
            }
            .permissions();
            perms.set_readonly(true);

            if let Err(e) = fs::set_permissions(&final_path, perms) {
                return OpenResult::Err(e.into());
            }
        }

        // And finally add a record of this file to our manifest. Note that
        // we're opening and closing this file every time we load a new file;
        // not so efficient, but whatever.

        if let Err(e) = self.record_cache_result(name, length as u64, digest) {
            return OpenResult::Err(e);
        }

        OpenResult::Ok(final_path)
    }
/// Find the path in the local cache for the provided file. Download the file first if it is
/// not in the local cache already.
Find the path in the local cache for the provided file. Download the file first if it is
not in the local cache already.
Find the path in the local cache for the provided file . Download the file first if it is not in the local cache already .
fn path_for_name(&mut self, name: &str, status: &mut dyn StatusBackend) -> OpenResult<PathBuf> {
        if let Some(info) = self.contents.get(name) {
            return match info.digest.create_two_part_path(&self.data_base) {
                Ok(p) => OpenResult::Ok(p),
                Err(e) => OpenResult::Err(e),
            };
        }
        // The file is not in the cache and we are asked not to try to fetch it.
        if self.only_cached {
            return OpenResult::NotAvailable;
        }
        let info = match self.index.get(name).cloned() {
            Some(info) => info,
            None => return OpenResult::NotAvailable,
        };
        // Bummer, we haven't seen this file before. We need to (try to) fetch
        // the item from the backend, saving it to disk and calculating its
        // digest ourselves, then enter it in the cache and in our manifest.
        // Fun times. Because we're touching the backend, we need to verify that
        // its digest is what we think.
        if let Err(e) = self.check_digest(status) {
            return OpenResult::Err(e);
        }
        // The bundle's overall digest is OK. Now try open the file. If it's
        // not available, cache that result, since LaTeX compilations commonly
        // touch nonexistent files. If we didn't maintain the negative cache,
        // we'd have to touch the network for virtually every compilation.
        let content = match get_file(
            &mut self.tar_data,
            name,
            info.offset,
            info.length as usize,
            status,
        ) {
            Ok(c) => c,
            Err(e) => return OpenResult::Err(e),
        };
        // OK, we can stream the file to a temporary location on disk,
        // computing its SHA256 as we go.
        let length = content.len();
        let mut digest_builder = digest::create();
        digest_builder.input(&content);
        let digest = DigestData::from(digest_builder);
        let final_path = match digest.create_two_part_path(&self.data_base) {
            Ok(p) => p,
            Err(e) => return OpenResult::Err(e),
        };
        // Perform a racy check for the destination existing, because this
        // matters on Windows: if the destination is already there, we'll get
        // an error because the destination is marked read-only. Assuming
        // non-pathological filesystem manipulation, though, we'll only be
        // subject to the race once.
        if !final_path.exists() {
            if let Err(e) = file_create_write(&final_path, |f| f.write_all(&content)) {
                return OpenResult::Err(e);
            }
            // Now we can make the file readonly. It would be nice to set the
            // permissions using the already-open file handle owned by the
            // tempfile, but mkstemp doesn't give us access.
            let mut perms = match fs::metadata(&final_path) {
                Ok(p) => p,
                Err(e) => {
                    return OpenResult::Err(e.into());
                }
            }
            .permissions();
            perms.set_readonly(true);
            if let Err(e) = fs::set_permissions(&final_path, perms) {
                return OpenResult::Err(e.into());
            }
        }
        // And finally add a record of this file to our manifest. Note that
        // we're opening and closing this file every time we load a new file;
        // not so efficient, but whatever.
        if let Err(e) = self.record_cache_result(name, length as u64, digest) {
            return OpenResult::Err(e);
        }
        OpenResult::Ok(final_path)
    }
fn path_for_name ( & mut self , name : & str , status : & mut dyn StatusBackend ) -> OpenResult < PathBuf > { if let Some ( info ) = self . contents . get ( name ) { return match info . digest . create_two_part_path ( & self . data_base ) { Ok ( p ) => OpenResult :: Ok ( p ) , Err ( e ) => OpenResult :: Err ( e ) , } ; } // The file is not in the cache and we are asked not to try to fetch it. if self . only_cached { return OpenResult :: NotAvailable ; } let info = match self . index . get ( name ) . cloned ( ) { Some ( info ) => info , None => return OpenResult :: NotAvailable , } ; // Bummer, we haven't seen this file before. We need to (try to) fetch // the item from the backend, saving it to disk and calculating its // digest ourselves, then enter it in the cache and in our manifest. // Fun times. Because we're touching the backend, we need to verify that // its digest is what we think. if let Err ( e ) = self . check_digest ( status ) { return OpenResult :: Err ( e ) ; } // The bundle's overall digest is OK. Now try open the file. If it's // not available, cache that result, since LaTeX compilations commonly // touch nonexistent files. If we didn't maintain the negative cache, // we'd have to touch the network for virtually every compilation. let content = match get_file ( & mut self . tar_data , name , info . offset , info . length as usize , status , ) { Ok ( c ) => c , Err ( e ) => return OpenResult :: Err ( e ) , } ; // OK, we can stream the file to a temporary location on disk, // computing its SHA256 as we go. let length = content . len ( ) ; let mut digest_builder = digest :: create ( ) ; digest_builder . input ( & content ) ; let digest = DigestData :: from ( digest_builder ) ; let final_path = match digest . create_two_part_path ( & self . data_base ) { Ok ( p ) => p , Err ( e ) => return OpenResult :: Err ( e ) , } ; // Perform a racy check for the destination existing, because this // matters on Windows: if the destination is already there, we'll get // an error because the destination is marked read-only. Assuming // non-pathological filesystem manipulation, though, we'll only be // subject to the race once. if ! final_path . exists ( ) { if let Err ( e ) = file_create_write ( & final_path , | f | f . write_all ( & content ) ) { return OpenResult :: Err ( e ) ; } // Now we can make the file readonly. It would be nice to set the // permissions using the already-open file handle owned by the // tempfile, but mkstemp doesn't give us access. let mut perms = match fs :: metadata ( & final_path ) { Ok ( p ) => p , Err ( e ) => { return OpenResult :: Err ( e . into ( ) ) ; } } . permissions ( ) ; perms . set_readonly ( true ) ; if let Err ( e ) = fs :: set_permissions ( & final_path , perms ) { return OpenResult :: Err ( e . into ( ) ) ; } } // And finally add a record of this file to our manifest. Note that // we're opening and closing this file every time we load a new file; // not so efficient, but whatever. if let Err ( e ) = self . record_cache_result ( name , length as u64 , digest ) { return OpenResult :: Err ( e ) ; } OpenResult :: Ok ( final_path ) }
Find the path in the local cache for the provided file.
Find the path in the local cache for the provided file .
&mut self
name
&str
status
&mut dyn StatusBackend