Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/toolkit/library/buildid_reader/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 5 kB image not shown  

Quelle  reader.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use std::ffi::CStr;
use std::fs::File;
use std::io::{Read, Result as IOResult, Seek, SeekFrom};
use std::path::Path;

use nserror::{nsresult, NS_ERROR_INVALID_ARG, NS_ERROR_NOT_AVAILABLE, NS_ERROR_OUT_OF_MEMORY};

pub struct BuildIdReader {
    file: File,
}

use log::{error, trace};

#[cfg(target_os = "windows")]
const MAX_BUFFER_READ: usize = std::mem::size_of::<goblin::pe::header::Header>();

#[cfg(any(target_os = "macos", target_os = "ios"))]
const MAX_BUFFER_READ: usize = std::mem::size_of::<goblin::mach::header::Header64>();

// Target Android, Linux, *BSD, Solaris, ... Anything using ELF
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))]
const MAX_BUFFER_READ: usize = std::mem::size_of::<goblin::elf::header::Header>();

impl BuildIdReader {
    pub fn new(filename: &Path) -> Result<Self, nsresult> {
        trace!("BuildIdReader::new {:?}", filename);
        let f = File::open(filename).map_err(|e| {
            error!(
                "BuildIdReader::new failed to open {:?} with error {}",
                filename, e
            );
            NS_ERROR_INVALID_ARG
        })?;
        Ok(BuildIdReader { file: f })
    }

    fn read_raw_build_id(&mut self, note_name: &str) -> Result<Vec<u8>, nsresult> {
        trace!("BuildIdReader::read_raw_build_id {}", note_name);
        let mut buffer = [0; MAX_BUFFER_READ];
        let _ = self.file.read_exact(&mut buffer).map_err(|e| {
            error!("BuildIdReader::read_raw_build_id failed to read exact buffer of size {} with error {}", MAX_BUFFER_READ, e);
            NS_ERROR_OUT_OF_MEMORY
        })?;

        // This does actually depend on the platform, so it's not in this
        // impl nor source file but in the platform-dependant modules listed at
        // the end of this file
        self.get_build_id_bytes(&buffer, note_name)
    }

    pub fn read_string_build_id(&mut self, note_name: &str) -> Result<String, nsresult> {
        trace!("BuildIdReader::read_string_build_id {}", note_name);
        let b = self.read_raw_build_id(note_name).map_err(|err| {
            error!(
                "BuildIdReader::read_string_build_id failed to read raw build id with error {}",
                err
            );
            err
        })?;
        Self::string_from_bytes(&b).ok_or(NS_ERROR_NOT_AVAILABLE)
    }

    fn string_from_bytes(bytes: &[u8]) -> Option<String> {
        trace!("BuildIdReader::string_from_bytes {:?}", bytes);
        if let Ok(cstr) = CStr::from_bytes_until_nul(bytes) {
            trace!("BuildIdReader::string_from_bytes{:?}", cstr);
            if let Ok(s) = cstr.to_str() {
                trace!("BuildIdReader::string_from_bytes{}", s);
                return Some(s.to_string());
            }
        }
        trace!("BuildIdReader::string_from_bytesNone");
        None
    }

    fn copy_bytes_into(&mut self, offset: usize, buffer: &mut [u8]) -> IOResult<()> {
        trace!("BuildIdReader::copy_bytes_into @{}", offset);
        self.file.seek(SeekFrom::Start(offset as u64))?;
        self.file
            .by_ref()
            .take(buffer.len() as u64)
            .read_exact(buffer)
    }

    pub fn copy_bytes(&mut self, offset: usize, count: usize) -> IOResult<Vec<u8>> {
        trace!("BuildIdReader::copy_bytes @{} : {} bytes", offset, count);
        let mut buf = vec![0; count];
        self.copy_bytes_into(offset, &mut buf).map_err(|e| {
            error!(
                "BuildIdReader::copy_bytes failed to copy bytes with error {}",
                e
            );
            e
        })?;
        Ok(buf)
    }

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    /// SAFETY: Caller need to ensure that `T` is safe to cast to bytes
    pub unsafe fn copy<T>(&mut self, offset: usize) -> IOResult<T> {
        trace!("BuildIdReader::copy @{}", offset);
        self.copy_array(offset, 1)
            .map(|v| v.into_iter().next().unwrap())
    }

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    /// SAFETY: Caller need to ensure that `T` is safe to cast to bytes
    pub unsafe fn copy_array<T>(&mut self, offset: usize, num: usize) -> IOResult<Vec<T>> {
        trace!("BuildIdReader::copy_array @{} : {} num", offset, num);
        let mut uninit: Vec<std::mem::MaybeUninit<T>> = Vec::with_capacity(num);
        for _ in 0..num {
            uninit.push(std::mem::MaybeUninit::uninit());
        }
        let slice = std::slice::from_raw_parts_mut(
            uninit.as_mut_ptr() as *mut u8,
            uninit.len() * std::mem::size_of::<T>(),
        );
        self.copy_bytes_into(offset, slice)?;
        std::mem::transmute(uninit)
    }
}

#[cfg(target_os = "windows")]
pub mod windows;

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub mod macos;

// Target Android, Linux, *BSD, Solaris, ... Anything using ELF
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))]
pub mod elf;

[ Dauer der Verarbeitung: 0.45 Sekunden  ]