src/pxar/decoder.rs: implement dump_archive
use this to debug archive problems ...
This commit is contained in:
		@ -84,44 +84,18 @@ fn dump_archive(
 | 
			
		||||
) -> Result<Value, Error> {
 | 
			
		||||
 | 
			
		||||
    let archive = tools::required_string_param(¶m, "archive")?;
 | 
			
		||||
    let mut file = std::fs::File::open(archive)?;
 | 
			
		||||
    let file = std::fs::File::open(archive)?;
 | 
			
		||||
 | 
			
		||||
    println!("PXAR {}", archive);
 | 
			
		||||
    let mut reader = std::io::BufReader::new(file);
 | 
			
		||||
 | 
			
		||||
    let mut buffer = [0u8; 16];
 | 
			
		||||
    let mut decoder = PxarDecoder::new(&mut reader);
 | 
			
		||||
 | 
			
		||||
    let mut nesting = 0;
 | 
			
		||||
    let stdout = std::io::stdout();
 | 
			
		||||
    let mut out = stdout.lock();
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        file.read_exact(&mut buffer)?;
 | 
			
		||||
    println!("PXAR dump: {}", archive);
 | 
			
		||||
 | 
			
		||||
        let header = map_struct::<CaFormatHeader>(&mut buffer)?;
 | 
			
		||||
 | 
			
		||||
        println!("Type: {:016x}", header.htype);
 | 
			
		||||
        println!("Size: {}", header.size);
 | 
			
		||||
 | 
			
		||||
        let mut rest = vec![0u8; (header.size as usize) - 16];
 | 
			
		||||
        file.read_exact(&mut rest)?;
 | 
			
		||||
 | 
			
		||||
        if header.htype == CA_FORMAT_FILENAME {
 | 
			
		||||
            let name = read_os_string(&rest);
 | 
			
		||||
            let hash = compute_goodbye_hash(&rest[..rest.len()-1]);
 | 
			
		||||
            println!("Name: {:?} {:016x}",  name, hash);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if header.htype == CA_FORMAT_ENTRY {
 | 
			
		||||
            let entry = map_struct::<CaFormatEntry>(&mut rest)?;
 | 
			
		||||
            println!("Mode: {:08x} {:08x}", entry.mode, (entry.mode as u32) & libc::S_IFDIR);
 | 
			
		||||
            if ((entry.mode as u32) & libc::S_IFMT) == libc::S_IFDIR {
 | 
			
		||||
                nesting += 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if header.htype == CA_FORMAT_GOODBYE {
 | 
			
		||||
            nesting -= 1;
 | 
			
		||||
            print_goodby_entries(&rest)?;
 | 
			
		||||
            if nesting == 0 { break; }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    decoder.dump_archive(&mut out);
 | 
			
		||||
 | 
			
		||||
    Ok(Value::Null)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -216,6 +216,18 @@ impl <'a, R: Read> PxarDecoder<'a, R> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn skip_bytes(&mut self, count: usize) -> Result<(), Error> {
 | 
			
		||||
        let mut done = 0;
 | 
			
		||||
        while done < count  {
 | 
			
		||||
            let todo = count - done;
 | 
			
		||||
            let n = if todo > self.skip_buffer.len() { self.skip_buffer.len() } else { todo };
 | 
			
		||||
            let data = &mut self.skip_buffer[..n];
 | 
			
		||||
            self.reader.read_exact(data)?;
 | 
			
		||||
            done += n;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn restore<F>(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        path: &Path, // used for error reporting
 | 
			
		||||
@ -286,17 +298,7 @@ impl <'a, R: Read> PxarDecoder<'a, R> {
 | 
			
		||||
            println!("Skip Goodbye");
 | 
			
		||||
            if head.size < HEADER_SIZE { bail!("detected short goodbye table"); }
 | 
			
		||||
 | 
			
		||||
            // self.reader.seek(SeekFrom::Current((head.size - HEADER_SIZE) as i64))?;
 | 
			
		||||
            let mut done = 0;
 | 
			
		||||
            let skip = (head.size - HEADER_SIZE) as usize;
 | 
			
		||||
            while done < skip  {
 | 
			
		||||
                let todo = skip - done;
 | 
			
		||||
                let n = if todo > self.skip_buffer.len() { self.skip_buffer.len() } else { todo };
 | 
			
		||||
                let data = &mut self.skip_buffer[..n];
 | 
			
		||||
                self.reader.read_exact(data)?;
 | 
			
		||||
                done += n;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            self.skip_bytes((head.size - HEADER_SIZE) as usize)?;
 | 
			
		||||
 | 
			
		||||
            self.restore_mode(&entry, dir.as_raw_fd())?;
 | 
			
		||||
            self.restore_mtime(&entry, dir.as_raw_fd())?;
 | 
			
		||||
@ -419,6 +421,81 @@ impl <'a, R: Read> PxarDecoder<'a, R> {
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Dump archive format details. This is ment for debugging.
 | 
			
		||||
    pub fn dump_archive<W: std::io::Write>(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        output: &mut W,
 | 
			
		||||
    ) -> Result<(), Error> {
 | 
			
		||||
 | 
			
		||||
        let mut nesting = 0;
 | 
			
		||||
 | 
			
		||||
        let mut dirpath = PathBuf::new();
 | 
			
		||||
 | 
			
		||||
        let head: CaFormatHeader = self.read_item()?;
 | 
			
		||||
        check_ca_header::<CaFormatEntry>(&head, CA_FORMAT_ENTRY)?;
 | 
			
		||||
        let entry: CaFormatEntry = self.read_item()?;
 | 
			
		||||
        println!("Root: {:08x} {:08x}", entry.mode, (entry.mode as u32) & libc::S_IFDIR);
 | 
			
		||||
 | 
			
		||||
        loop {
 | 
			
		||||
            let head: CaFormatHeader = self.read_item()?;
 | 
			
		||||
 | 
			
		||||
            println!("Type: {:016x}", head.htype);
 | 
			
		||||
            println!("Size: {}", head.size);
 | 
			
		||||
 | 
			
		||||
            match head.htype {
 | 
			
		||||
 | 
			
		||||
                CA_FORMAT_FILENAME =>  {
 | 
			
		||||
                    let name = self.read_filename(head.size)?;
 | 
			
		||||
                    //let hash = compute_goodbye_hash(&rest[..rest.len()-1]);
 | 
			
		||||
                    println!("Name: {:?}", name);
 | 
			
		||||
 | 
			
		||||
                    let head: CaFormatHeader = self.read_item()?;
 | 
			
		||||
                    check_ca_header::<CaFormatEntry>(&head, CA_FORMAT_ENTRY)?;
 | 
			
		||||
                    let entry: CaFormatEntry = self.read_item()?;
 | 
			
		||||
                    println!("Mode: {:08x} {:08x}", entry.mode, (entry.mode as u32) & libc::S_IFDIR);
 | 
			
		||||
 | 
			
		||||
                    if ((entry.mode as u32) & libc::S_IFMT) == libc::S_IFDIR {
 | 
			
		||||
                        nesting += 1;
 | 
			
		||||
                        dirpath.push(&name);
 | 
			
		||||
                        println!("Path: {:?}", dirpath);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        dirpath.push(&name);
 | 
			
		||||
                        println!("Path: {:?}", dirpath);
 | 
			
		||||
                        dirpath.pop();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                CA_FORMAT_GOODBYE => {
 | 
			
		||||
                    self.skip_bytes((head.size - HEADER_SIZE) as usize)?;
 | 
			
		||||
                    nesting -= 1;
 | 
			
		||||
                    println!("Goodbye: {:?}", dirpath);
 | 
			
		||||
                    dirpath.pop();
 | 
			
		||||
                    if nesting == 0 {
 | 
			
		||||
                        // fixme: check eof??
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                CA_FORMAT_SYMLINK => {
 | 
			
		||||
                    let target = self.read_symlink(head.size)?;
 | 
			
		||||
                    println!("Symlink: {:?}", target);
 | 
			
		||||
                }
 | 
			
		||||
                CA_FORMAT_DEVICE => {
 | 
			
		||||
                    let device: CaFormatDevice = self.read_item()?;
 | 
			
		||||
                    println!("Device: {}, {}", device.major, device.minor);
 | 
			
		||||
                }
 | 
			
		||||
                CA_FORMAT_PAYLOAD => {
 | 
			
		||||
                    let payload_size = (head.size - HEADER_SIZE) as usize;
 | 
			
		||||
                    println!("Payload: {}", payload_size);
 | 
			
		||||
                    self.skip_bytes(payload_size)?;
 | 
			
		||||
                }
 | 
			
		||||
                _ => {
 | 
			
		||||
                    panic!("unknown header type");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn file_openat(parent: RawFd, filename: &OsStr, flags: OFlag, mode: Mode) -> Result<std::fs::File, Error> {
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user