A resposta comum para isso é descompactar o arquivo iso, modificá-lo e empacotá-lo novamente. Parece que "ISO Master", como mencionado na resposta do dv3500ea, é um bom front-end para fazer isso.
Se:
- você não tem espaço suficiente para isso
- você só quer fazer uma modificação cirúrgica em vez de reescrever a coisa toda
- você deseja modificar um dispositivo de armazenamento que contenha um sistema de arquivos isofs (por exemplo, iso9660) sem copiar o dispositivo inteiro ou
- se você acha que essa coisa de desempacotamento / reembalagem é não apenas hacky o suficiente
Então esta resposta é para você!
Em resumo, substituiremos um arquivo existente no sistema de arquivos isofs por nosso arquivo desejado. Nosso arquivo desejado deve ser menor que o existente (destino), e o espaço em branco (ou lixo) deve ser aceitável. Isso requer apenas dois comandos, mas tenha cuidado: um erro de digitação pode destruir completamente o sistema de arquivos de destino ou até mesmo sobrescrever o arquivo de origem. Backups são seus amigos!
No meu caso, eu queria armazenar um script em uma inicialização ao vivo para não precisar redigitá-lo todas as vezes. O script está em script.py
e meu destino (um pendrive) está em /dev/sdc
. O tamanho do script é de 202 bytes, então nosso primeiro passo é encontrar um arquivo maior que 202 bytes, para que possamos substituí-lo. Depois de montá-lo em /mnt
, encontrei um arquivo adequado em /mnt/info.txt
.
Não podemos simplesmente sobrescrever info.txt
no ponto de montagem, ele vai reclamar que é um sistema de arquivos somente para leitura. Nós somos a raiz, então vamos mostrar a eles o que isso significa! Precisamos descobrir onde info.txt
está no sistema de arquivos. Encontre alguma string que seja (provavelmente) exclusiva para info.txt
, por exemplo, This is the official distribution CD of X.
, e procure por ela no disco:
$ sudo strings -a -t d /dev/sdc | grep 'CD of X.'
2573588480 This is the official distribution CD of X. See INSTALL for how to [...]
Alternativamente, isso também pode ser feito com o grep, que é muito mais rápido, mas você precisa especificá-lo desde o início: $ sudo grep -oba 'This is ...' /dev/sdc
.
Agora que sabemos onde está, precisamos apenas substituir esses bytes por nosso arquivo:
$ sudo dd if=script.py of=/dev/sdc conv=notrunc bs=1 seek=2573588480 count=202
Esta linha:
- copia bytes do arquivo de entrada (
if
) para o arquivo de saída ( of
) e não se importa que o arquivo de saída seja realmente um dispositivo, porque "tudo é um arquivo".
-
conv=notrunc
diz para não truncar o arquivo de saída, porque nós só queremos sobrescrever alguns bytes, não sobrescrever o arquivo de um certo ponto em diante.
-
bs=1
define o tamanho do bloco como 1. Geralmente, você deseja um tamanho de bloco de 4k ou mais, mas isso evita ter que fazer matemática (inline) e nos permite especificar a localização exata do byte.
-
seek=N
procura um certo ponto no arquivo de saída (observe que seek=N
é diferente de skip=N
porque skip
ignora bytes do arquivo de entrada!). Nós definimos, é claro, para onde o texto alvo está.
-
count=N
copia somente esses muitos bytes. Eu acho que isso pode ser omitido porque vai notar o final do arquivo de entrada, mas deixei-o em apenas para ter certeza.
E voila, o arquivo é sobrescrito!
Mas espere, o arquivo de destino era maior que o nosso script, então no pendrive, o arquivo agora é algo como: "while do if run () blah; blah (); yright 2007 X Inc.". Há lixo à direita. Duas maneiras de corrigir isso: tornar nosso arquivo de entrada mais longo (adicionar espaços) ou adicionar um símbolo de comentário no final. Note que muitos editores adicionam uma nova linha no final, então você pode querer definir count=
para N-1
bytes (se o seu arquivo agora é de 203 bytes, e você perceber que o último byte é uma nova linha, defina a contagem como 202) . Você pode verificar um arquivo para novas linhas usando xxd script.py | tail
e verificando se o último byte é 0a
(ou, em casos estranhos, 0d
).
O processo é idêntico para um arquivo .iso
, apenas substitua mentalmente /dev/sdc
por your.iso
.
Observe que, quando você verifica o destino no seu ponto de montagem para ver se funcionou, talvez seja necessário usar strings
novamente (desta vez pesquisando pelo seu script), pois o arquivo provavelmente ainda está no cache de leitura.