Crie o arquivo cpio com um diretório absoluto diferente

2

Estou tentando modificar uma imagem do sistema de arquivos compactada com cpio . Por esse motivo, primeiro preciso extrair e depois embalar a imagem. Como a imagem contém todo um sistema de arquivos, todos os arquivos são dados em nomes absolutos, portanto não posso empacotá-lo e descompactá-lo diretamente, pois ele estaria em conflito com o sistema raiz da minha máquina.

Então, ao descompactar, usei --no-absolute-filenames para descompactá-lo em um diretório de trabalho de minha escolha. Agora quero empacotá-lo novamente. Se eu apenas empacotasse, só conseguiria arquivos assim:

/path/to/working/directory/file1
/path/to/working/directory/file2
/path/to/working/directory/file3

ou

./file1
./file2
./file3

em vez de

/file1
/file2
/file3

Alguém sabe como eu poderia obter o resultado desejado? O Google não me ajudou até agora.

Eu realmente preciso de nomes absolutos de caminho no arquivo de saída, porque estou usando-o para uma imagem do sistema de arquivos uImage de inicialização, e isso requer que os caminhos sejam absolutos ou não inicializem.

    
por Dakkaron 25.06.2015 / 16:45

3 respostas

1

Use a pax e sua opção -s para renomear os arquivos à medida que são adicionados ao arquivo. O Pax é o substituto do POSIX para os utilitários tradicionais tar e cpio ; algumas distribuições Linux não o instalam por padrão, mas devem estar sempre disponíveis como um pacote.

pax -w -x cpio -s '~^[/]*~~' root-directory >archive.cpio
    
por 26.06.2015 / 03:44
2

Se você tem python e:

  • instale libarchive-c (por exemplo, usando pip install libarchive-c )
  • tem todos os seus arquivos no diretório root no diretório atual (usei mkdir -p root/xyz ; echo 1 > root/abc.txt ; echo 2> root/xyz/def.txt )
  • salve o seguinte como abscpio e torne-o executável ( chmod 755 abscpio )

    #! /usr/bin/env python
    import os
    import sys
    from libarchive import ffi
    from libarchive.write import (
       new_archive_write, ArchiveWrite, new_archive_read_disk)
    from libarchive.entry import new_archive_entry, ArchiveEntry
    from libarchive.ffi import (
        ARCHIVE_EOF,
        entry_sourcepath,
        entry_clear,
        read_next_header2,
        read_disk_descend,
        write_header,
        write_data,
        write_finish_entry,
    )
    
    
    class AbsArchiveWrite(ArchiveWrite):
    
       def add_abs_file(self, path, store_path):
          """Read the given paths from disk and add them to the archive.
          """
          write_p = self._pointer
    
          block_size = ffi.write_get_bytes_per_block(write_p)
          if block_size <= 0:
             block_size = 10240  # pragma: no cover
    
          with new_archive_entry() as entry_p:
             entry = ArchiveEntry(None, entry_p)
             with new_archive_read_disk(path) as read_p:
                while 1:
                   r = read_next_header2(read_p, entry_p)
                   if r == ARCHIVE_EOF:
                      break
                   entry.pathname = store_path
                   read_disk_descend(read_p)
                   write_header(write_p, entry_p)
                   try:
                      with open(entry_sourcepath(entry_p), 'rb') as f:
                         while 1:
                            data = f.read(block_size)
                            if not data:
                               break
                            write_data(write_p, data, len(data))
                   except IOError as e:
                      if e.errno != 21:
                         raise  # pragma: no cover
                   write_finish_entry(write_p)
                   entry_clear(entry_p)
                   if os.path.isdir(path):
                      break
    
    
    base_dir = sys.argv[2]
    
    with new_archive_write('cpio', None) as archive_p:
       ffi.write_open_filename_w(archive_p, sys.argv[1])
       a = AbsArchiveWrite(archive_p)
    
       for root, dir_names, file_names in os.walk(base_dir):
          for dir_name in dir_names:
             full_name = os.path.join(root, dir_name)
             a.add_abs_file(full_name, full_name.replace(base_dir, '/', 1))
          for file_name in file_names:
             full_name = os.path.join(root, file_name)
             a.add_abs_file(full_name, full_name.replace(base_dir, '/', 1))
    
    print '----- listing ' + sys.argv[1]
    os.system('cpio -itv -I ' + sys.argv[1])
    

você pode fazer:

abscpio my_arch.cpio root/

com um resultado semelhante a:

----- listing my_arch.cpio
drwxrwxr-x   2 anthon   users           0 Jun 25 18:59 /xyz
-rw-rw-r--   1 anthon   users           2 Jun 25 18:59 /abc.txt
-rw-rw-r--   1 anthon   users           0 Jun 25 18:59 /xyz/def.txt

para produção, você pode querer excluir as duas últimas linhas do script.

Links também são armazenados, mas eu não tentei outros tipos de "arquivos".

    
por 25.06.2015 / 19:03
-1

Quando eu costumava usar cpio , eu sempre usava em um nome de caminho relativo.

Então, com o seu exemplo, eu faria

cd /to/where/the/root/is/
find . -print -depth | cpio -ov > /myarchivestore/archive.cpio

Em seguida, para restaurar os caminhos relativos (em /),

cd /
cpio -iv < archive.cpio < /myarchivestore.cpio

caso contrário, você encontrará exatamente o seu problema original.

    
por 25.06.2015 / 17:01

Tags