Palavras-chave: C, stdin, stdout, descritor, descriptor, inode, comparar, compare
Ao escrever filtros (programas que processam dados provenientes da entrada padrão e os escrevem na saída padrão) pode-se querer evitar que o arquivo de entrada seja o mesmo arquivo utilizado para saída. Um exemplo de um programa assim seria um conversor de formato: o que fazer caso o filtro seja invocado como
$ gif2png < tempfile > tempfile
ou ainda
$ sig2uns tempfile > tempfile
potencialmente corrompendo dados quando eles são lidos e processados em blocos?
Uma solução simples em sistemas que utilizam sistemas de arquivo similares aos do UNIX é comparar o número do inode e o dispositivo dos descritores de entrada e saída, sejam eles arquivos ou stdin/stdout. Isso pode ser implementado em C como:
fstat(ifd, &st); st.st_mode &= S_IFMT; if (st.st_mode != S_IFCHR && st.st_mode != S_IFBLK) { dev = st.st_dev; ino = st.st_ino; } fstat(ofd, &st); st.st_mode &= S_IFMT; if (st.st_dev == dev && st.st_ino == ino) { /* entrada e saída são iguais */ return 1; }
Isso é exatamente o que o programa “cat” faz. Se você experimentar fazer cat de um arquivo para ele mesmo, o resultado é:
$ cat a.out > a.out cat: a.out: input file is output file
Finalmente, note que isso não vale para dispositivos de caractere ou bloco, como tratado no trecho de código acima.