Jun 15, 2007

Stream de dados alternativas

Para muitos usuários (e mesmo desenvolvedores) do Windows o conceito de arquivo esta tão sedimentado que muitas vezes melhorias significativas no sistema de arquivos deste sistema operacional (no caso o NTFS) são ignoradas.

Neste post apresento um dos recursos mais desconhecidos, stream alternativas de dados ou ADS (do inglês, Alternate Data Stream).

Para compreendermos este recurso é necessário primeiro definirmos (ou relembrarmos) alguns conceitos:

  • Uma stream de dados nada mais é que um conjunto de bytes arranjados de forma seqüencial.
  • Um arquivo é composto por uma ou mais streams de dados.
  • Streams de dados possuem um nome associado através do qual a mesma é referenciada. A regra básica para formação do nome de streams é: nome-arquivo.ext:nome-stream:tipo-stream
  • O nome da stream pode conter qualquer caracter válido para um nome de arquivo.

Como o Windows não possui meios (tanto no Explorer quanto no console) para detectar / mostrar arquivos que possuem ADS, abaixo listei algumas ferramentas úteis para tal finalidade:

Usando ADSs

A forma mais simples para demonstrarmos este conceito é através do console do Windows. Abra o console (cmd.exe) e digite:

echo teste de streams > teste.txt:dados

Simples assim! O comando acima cria uma stream chamada dados com o conteúdo teste de streams.

Agora você pode conferir que o arquivo teste.txt foi criado mas o comando dir reporta o mesmo com 0 (zero) bytes.

Finalmente, para visualisar o conteúdo da stream digite

more < teste.txt:dados

Abaixo apresento um pequeno programa de exemplo para criar ADSs (note que o mesmo não possui nenhum tratamento especial, ou seja, a forma de acessar data streams alternativas é idêntica à utilizada para acessar a data stream default).

#include "stdio.h"
#include "Windows.h" 
void main(int argc, char *argv[])
{
    HANDLE handle;
    if (argc < 3)
    {
        printf("Nome da stream (formato: arquivo.ext:stream) ou dados nao especificados.\r\nUso: ads.exe nome-stream dados");
        return;
    }
    else    
    {
        printf("\r\nGravando dados em %s", argv[1]);
    }
    
    handle = CreateFile(argv[1], 
                        GENERIC_WRITE, 
                        0, 
                        NULL, 
                        OPEN_ALWAYS, 
                        0, 0);
                        
    if (handle != INVALID_HANDLE_VALUE)
    {
        DWORD numberOfBytesWritten;
        int n = WriteFile(  handle, 
                            argv[2], 
                            strlen(argv[2]), 
                            &numberOfBytesWritten, 
                            NULL);
                            
        printf("\r\n%ld bytes gravados", numberOfBytesWritten);
        
        CloseHandle(handle);
    }
    else
    {
        printf("Não foi possivel criar a stream de dados.");
    }
}
[Editado: Correção de um erros de português]

experimente executar o programa com alguns parâmetros como por exemplo:

ads teste.txt:dados "Teste de streams"

É isso ai.

Até a próxima.