Nel
./binary < file
binary
stdin è il file aperto in modalità sola lettura. Nota che bash
non legge affatto il file, lo apre solo per la lettura sul descrittore di file 0 (stdin) del processo in cui viene eseguito binary
.
Nel:
./binary << EOF
test
EOF
A seconda della shell, lo binary
stdin sarà o un file temporaneo cancellato (AT&T ksh, zsh, bash ...) che contiene test\n
come inserito lì dalla shell o l'estremità di lettura di una pipe ( dash
, yash
; e la shell scrive test\n
in parallelo all'altra estremità del tubo). Nel tuo caso, se lo stai usando bash
, sarebbe un file temporaneo.
Nel:
cat file | ./binary
A seconda della shell, lo binary
stdin sarà o la fine della lettura di una pipe, o un'estremità di una coppia di socket in cui la direzione di scrittura è stata chiusa (ksh93) e cat
sta scrivendo il contenuto file
dell'altra estremità.
Quando stdin è un file normale (temporaneo o no), è ricercabile. binary
può andare all'inizio o alla fine, riavvolgere, ecc. Può anche capovolgerlo, fare qualcosa ioctl()s
come FIEMAP / FIBMAP (se usato al <>
posto di <
, potrebbe troncare / fare buchi in esso, ecc.).
le pipe e le coppie di socket invece sono un mezzo di comunicazione tra processi, non c'è molto da binary
fare oltre read
ai dati (anche se ci sono anche alcune operazioni come alcune specifiche di pipe ioctl()
che potrebbero fare su di esse e non su file regolari) .
La maggior parte delle volte, è la capacità mancante seek
che provoca le applicazioni a fallire / si lamentano quando si lavora con i tubi, ma potrebbe essere una qualsiasi delle altre chiamate di sistema che sono validi in file regolari, ma non su diversi tipi di file (come mmap()
, ftruncate()
, fallocate()
) . Su Linux, c'è anche una grande differenza nel comportamento quando si apre /dev/stdin
mentre fd 0 è su una pipe o su un file normale.
Esistono molti comandi là fuori che possono occuparsi solo di file ricercabili , ma in questo caso, generalmente non è per i file aperti sul loro 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
deve leggere l'indice memorizzato alla fine del file, quindi cercare all'interno del file per leggere i membri dell'archivio. Ma qui, il file (regolare nel primo caso, pipe nel secondo) viene fornito come argomento path unzip
e lo unzip
apre da solo (in genere su fd diverso da 0) invece di ereditare un fd già aperto dal genitore. Non legge i file zip dal suo stdin. stdin è utilizzato principalmente per l'interazione dell'utente.
Se esegui quello binary
tuo senza reindirizzamento al prompt di una shell interattiva in esecuzione in un emulatore di terminale, allora lo binary
stdin verrà ereditato dalla shell madre, che a sua volta lo avrà ereditato dall'emulatore di terminale e sarà un dispositivo pty aperto in modalità lettura + scrittura (qualcosa del genere /dev/pts/n
).
Neanche questi dispositivi sono cercabili. Quindi, se binary
funziona correttamente quando si riceve l'input dal terminale, probabilmente il problema non riguarda la ricerca.
Se quel 14 è pensato per essere un errno (un codice di errore impostato da chiamate di sistema non riuscite), allora sulla maggior parte dei sistemi sarebbe EFAULT
( indirizzo errato ). La read()
chiamata di sistema fallirebbe con quell'errore se si chiedesse di leggere in un indirizzo di memoria non scrivibile. Ciò sarebbe indipendente dal fatto che il fd leggesse i dati da punti a una pipe o un file normale e indicasse generalmente un bug 1 .
binary
probabilmente determina il tipo di file aperto sul suo stdin (con fstat()
) e si imbatte in un bug quando non è né un file normale né un dispositivo tty.
Difficile dirlo senza sapere di più sull'applicazione. Eseguirlo con strace
(o truss
/ tusc
equivalente sul tuo sistema) potrebbe aiutarci a vedere qual è la chiamata di sistema se qualcuno non riesce qui.
1 Lo scenario previsto da Matthew Ife in un commento alla tua domanda suona molto plausibile qui. Citandolo:
Ho il sospetto che stia cercando la fine del file per ottenere una dimensione del buffer per leggere i dati, gestire male il fatto che la ricerca non funziona e tentare di allocare una dimensione negativa (non gestire un malloc non valido). Passare il buffer per leggere quali errori dati al buffer non sono validi.