Em
./binary < file
O stdin de binary
é o arquivo aberto no modo somente leitura. Note que bash
não lê o arquivo, apenas o abre para leitura no descritor de arquivo 0 (stdin) do processo que executa binary
in.
Em:
./binary << EOF
test
EOF
Dependendo do shell, o stdin de binary
será um arquivo temporário excluído (AT & T ksh, zsh, bash ...) que contém test\n
como colocado lá pelo shell ou o final de leitura de um pipe ( dash
, yash
; e o shell grava test\n
em paralelo na outra extremidade do pipe). No seu caso, se você estiver usando bash
, seria um arquivo temporário.
Em:
cat file | ./binary
Dependendo do shell, o stdin de binary
será o final de leitura de um pipe ou uma extremidade de um par de soquetes onde a direção de escrita foi encerrada (ksh93) e cat
está gravando o conteúdo de file
no outro extremo.
Quando stdin é um arquivo regular (temporário ou não), é procurado. binary
pode ir para o início ou fim, retroceder, etc. Ele também pode mapear, fazer alguns ioctl()s
como FIEMAP / FIBMAP (se usar <>
em vez de <
, ele poderá truncar / furar nele , etc).
pipes e pares de soquetes, por outro lado, são meios de comunicação entre processos, não há muito binary
a fazer além de read
ing os dados (embora também existam algumas operações como ioctl()
s específicas de canal que poderia fazer com eles e não em arquivos regulares).
Na maioria das vezes, é a capacidade perdida de seek
que faz com que os aplicativos falhem / reclamem ao trabalhar com pipes, mas poderia ser qualquer outra chamada de sistema válida em arquivos regulares, mas não em tipos diferentes de arquivos (como mmap()
, ftruncate()
, fallocate()
). No Linux, também há uma grande diferença no comportamento quando você abre /dev/stdin
enquanto o fd 0 está em um canal ou em um arquivo regular.
Existem muitos comandos por aí que só podem lidar com arquivos buscáveis , mas quando esse é o caso, geralmente não são os arquivos abertos no stdin.
$ unzip -l file.zip
Archive: file.zip
Length Date Time Name
--------- ---------- ----- ----
11 2016-12-21 14:43 file
--------- -------
11 1 file
$ unzip -l <(cat file.zip)
# more or less the same as cat file.zip | unzip -l /dev/stdin
Archive: /proc/self/fd/11
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of /proc/self/fd/11 or
/proc/self/fd/11.zip, and cannot find /proc/self/fd/11.ZIP, period.
unzip
precisa ler o índice armazenado no final do arquivo e, em seguida, procurar dentro do arquivo para ler os membros do arquivo. Mas aqui, o arquivo (regular no primeiro caso, pipe no segundo) é dado como um argumento de caminho para unzip
e unzip
abre ele mesmo (normalmente em fd diferente de 0) em vez de herdar um fd já aberto pelo pai. Não lê arquivos zip de seu stdin. O stdin é usado principalmente para interação do usuário.
Se você executar esse binary
do seu sem redirecionamento no prompt de um shell interativo em execução em um emulador de terminal, então o stdin de binary
será herdado de seu pai do shell, que por sua vez o herdará de seu pai, o emulador de terminal, e será um dispositivo pty aberto no modo de leitura + gravação (algo como /dev/pts/n
).
Esses dispositivos também não são procurados. Portanto, se binary
funcionar bem ao receber entradas do terminal, talvez o problema não seja a busca.
Se esse 14 for um errno (um código de erro definido por chamadas de sistema com falha), então, na maioria dos sistemas, isso seria EFAULT
( Endereço incorreto ). A chamada do sistema read()
falharia com esse erro se solicitada a leitura em um endereço de memória que não seja gravável. Isso seria independente do fato de o fd ler os dados de pontos para um pipe ou arquivo regular e geralmente indicaria um bug 1 .
binary
possivelmente determina o tipo de arquivo aberto em seu stdin (com fstat()
) e é executado em um bug quando não é um arquivo regular nem um dispositivo tty.
Difícil dizer sem saber mais sobre o aplicativo. Executá-lo em strace
(ou truss
/ tusc
equivalente em seu sistema) pode nos ajudar a ver qual é a chamada do sistema, se houver alguma falha aqui.
1 O cenário imaginado por Matthew Ife em um comentário à sua pergunta parece bastante plausível aqui. Citando ele:
I suspect it is seeking to the end of file to get a buffer size for reading the data, badly handling the fact that seek doesn't work and attempting to allocate a negative size (not handling a bad malloc). Passing the buffer to read which faults given the buffer is not valid.