Como encontro o primeiro byte diferente de zero em um dispositivo de bloco, com um deslocamento opcional?

Como encontro o primeiro byte diferente de zero em um dispositivo de bloco, com um deslocamento opcional?

Estou tentando encontrar o primeiro byte diferente de zero (começando em um deslocamento opcional) em um dispositivo de bloco usando dde imprimindo seu deslocamento, mas estou preso. Não mencionei ddno título porque imaginei que poderia haver uma ferramenta mais apropriada do que ddfazer isso, mas achei que dddeveria ser um bom começo. Se você conhece uma ferramenta mais adequada e/ou mais eficiente para atingir meu objetivo, tudo bem também.

Enquanto isso, mostrarei até onde cheguei ddno bash até agora.

#!/bin/bash

# infile is just a temporary test file for now, which will be replaced with /dev/sdb, for instance
infile=test.txt
offset=0

while true; do
  byte=`dd status='none' bs=1 count=1 if="$infile" skip=$offset`
  ret=$?

  # the following doesn't appear to work
  # ret is always 0, even when the end of file/device is reached
  # how do I correctly determine if dd has reached the end of file/device?
  if [ $ret -gt 0 ]; then
    echo 'error, or end of file reached'
    break
  fi

  # I don't know how to correctly determine if the byte is non-zero
  # how do I determine if the read byte is non-zero?
  if [ $byte ???? ]; then
    echo "non-zero byte found at $offset"
    break
  fi

  ((++offset))
done


Como você pode ver, estou preso a dois problemas que não sei como resolver:
a. Como faço o whileloop breakquando ddchega ao final do arquivo/dispositivo? ddfornece um código de saída de 0, onde eu esperava um código de saída diferente de zero.
b. Como avalio se o byte que ddlê e retorna no stdout é diferente de zero? Acho que li em algum lugar que cuidado especial \0também deve ser tomado no bash com bytes, mas nem tenho certeza se isso se aplica a essa situação.

Você pode me dar algumas dicas sobre como proceder ou talvez sugerir uma forma alternativa de atingir meu objetivo?

Responder1

Você pode fazer isso usandocmp, comparando à /dev/zero:

cmp /path/to/block-device /dev/zero

cmpfornecerá o deslocamento do primeiro byte diferente de zero.

Se quiser pular bytes, você pode usar a opção cmpdo GNU -i, ou se não estiver usando o GNU cmp, alimente-o com os dados apropriados usando dd:

cmp -i 100 /path/to/block-device /dev/zero
dd if=/path/to/block-device bs=1 skip=100 | cmp - /dev/zero

Isso funcionará com qualquer arquivo, não apenas com dispositivos de bloqueio.

Responder2

A resposta de Stephen Kitttorna isso um pouco inútil (é mais conciso e mais de uma ordem de magnitude mais rápido), mas uma alternativa que você tem é despejar (hex) o conteúdo do seu dispositivo, um byte por linha, e canalizá-lo para um programa que imprime o endereço do primeiro byte cuja representação não é 00e sai assim que o encontra:

od -Ad -w1 -tx1 /dev/device | awk '$2 && $2 != "00" { print $1 + 1; exit }'

odA -jopção permite selecionar opcionalmente o número de bytes a serem ignorados (no início da entrada).

Uma variação muito mais rápida (graças aPedro Cordes' comentários) requer um pouco mais de digitação:

od -Ad -tx1 | awk '
  {
    for (i=2; i<=NF; i++)
      if ($i != "00") {
        print ($1 + i -1)
        exit
      }
  }'

Permitir oda saída de dados em seu formato preferido requer calcular o deslocamento do primeiro byte diferente de zero adicionando sua posição na linha em que aparece ao endereço da linha.

informação relacionada