Como exibir as partes não esparsas de um arquivo esparso?

8

Imagine um arquivo criado com:

truncate -s1T file
echo test >> file
truncate -s2T file

Agora tenho um arquivo de 2 tebibytes (que ocupa 4 kB no disco), com "test\n" escrito no meio.

Como eu recuperaria esse "test" de forma eficiente, ou seja, sem precisar ler o arquivo inteiro.

tr -d '
truncate -s1T file
echo test >> file
truncate -s2T file
' < file

Me daria o resultado, mas isso levaria horas.

O que eu gostaria é de algo que produza apenas as partes não esparsas do arquivo (portanto, acima apenas "test\n" ou mais provavelmente, o bloco 4kiB alocado no disco que armazena esses dados).

Existem APIs para descobrir qual parte do arquivo está alocada (FIBMAP, FIEMAP, SEEK_HOLE, SEEK_DATA ...), mas quais ferramentas expõem essas?

Uma solução portátil (pelo menos para os sistemas operacionais que suportam essas APIs) seria apreciada.

    
por Stéphane Chazelas 26.03.2014 / 16:05

1 resposta

6

O melhor que eu pude chegar até agora é (ksh93, usando filefrag de e2fsprogs 1.42.9 (algumas versões mais antigas têm uma API diferente), em sistemas de arquivos baseados em extensão no Linux):

#! /bin/ksh93
export LC_ALL=C
for file do
filefrag -vb1 -- "$file" |
  while IFS=": ." read -A a; do
    [[ $a = +([0-9]) ]] && [[ ${a[@]} != *unwritten* ]] &&
      command /opt/ast/bin/head -s "${a[1]}" -c "${a[7]}" -- "$file"
  done
done

filefrag informa as extensões do arquivo usando o FIEMAP ioctl para os sistemas de arquivos que o suportam.

A parte *unwritten* cobre os arquivos (não esparsos, mas ainda cheios de zeros nos quais não estou interessado) que foram fallocated , mas não gravados em.

As versões recentes de bsdtar ou star podem usar algumas dessas APIs para gerar um arquivo tar que identifica as seções esparsas como tal. Isso criaria uma solução mais portátil , mas seria necessário analisar o arquivo tar gerado para obter as seções não esparsas.

    
por 26.03.2014 / 16:05