Se você já tentou usar programas baseados em POSIX para processar arquivos estruturados do VOS, talvez tenha se deparado com algumas restrições ou observado algum comportamento que não conseguiu entender. Nesta postagem, tentarei explicar o que está acontecendo.
O VOS suporta quatro tipos de arquivos: sequencial, relativo, fixo e de fluxo. Os três primeiros formatos são chamados de arquivos “estruturados”, pois o sistema de arquivos mantém o controle dos limites dos registros. As operações de E/S disponíveis leem e gravam registros inteiros. O último formato é chamado de “não estruturado”, pois os limites dos registros são implícitos; o caractere de nova linha delimita os registros. As operações de E/S disponíveis leem e gravam sequências de bytes.
Um ambiente compatível com POSIX, como o encontrado em um sistema Unix® ou Linux©, possui apenas um tipo de arquivo nativo, denominado “arquivo regular”. A organização de arquivos em fluxo do VOS é equivalente a um arquivo regular POSIX.
O ambiente de execução VOS POSIX classifica todos os quatro tipos de arquivos como arquivos regulares POSIX. Portanto, pelo menos em teoria, qualquer programa POSIX pode ler ou gravar qualquer um desses quatro tipos de arquivo. No entanto, não é tão simples assim.
Como a API POSIX define todas as operações de E/S em termos de sequências de bytes, enquanto o VOS define as operações de E/S (em arquivos estruturados) em termos de sequências de registros, o ambiente de execução VOS POSIX resolve essa diferença armazenando o registro atual em buffer no espaço do usuário, realizando as operações de E/S POSIX nesse buffer e, em seguida, gravando o registro armazenado em buffer nos momentos apropriados.
Se o programa POSIX conhece o tamanho de cada registro (por exemplo, no caso de um arquivo fixo) e se lê e grava exatamente o número de bytes, a presença do buffer não afeta a operação, e o mapeamento dos dois tipos de operações de E/S é fácil de entender e eficiente.
Mas se o programa POSIX estiver apenas lendo ou gravando um fluxo de bytes sem levar em conta o tamanho do registro subjacente, então o mapeamento da semântica POSIX para a semântica VOS, embora bem definido, geralmente não é muito útil e costuma ser bastante ineficiente. Certas operações, como saltar para uma posição de byte ou reescrever uma sequência de bytes que se estende além do limite de um registro, são, na melhor das hipóteses, ineficientes e, na pior, impossíveis.
Depois, há a questão do tratamento dos caracteres de nova linha.
Tanto um arquivo regular POSIX quanto um arquivo de fluxo VOS utilizam o caractere de nova linha para marcar o limite de um registro. No entanto, os registros VOS em arquivos estruturados normalmente não contêm caracteres de nova linha. Por exemplo, quando um editor VOS (como o edit, o emacs ou o line_edit) cria um novo arquivo sequencial, cada registro contém uma linha de texto. Mas o registro não termina com um caractere de nova linha. Por convenção, todos os programas assumem que um arquivo sequencial que contém texto possui uma nova linha implícita no final de cada registro. O mesmo se aplica a arquivos relativos e fixos. Mas há um ponto importante: nenhum atributo de qualquer arquivo (VOS, Unix, estruturado ou não estruturado) registra se o arquivo contém texto ou dados binários. A distinção fica a cargo dos programas que acessam o arquivo.
Essa situação cria uma espécie de dilema para o ambiente de execução POSIX do VOS. Ele precisa saber se um arquivo estruturado do VOS contém texto ou dados para determinar se deve ou não acrescentar uma nova linha a cada registro. Se o arquivo contiver texto, deve-se acrescentar uma nova linha. Se contiver dados, não deve-se acrescentar uma nova linha.
A resposta é que o tempo de execução POSIX do VOS depende do chamador para fornecer essa informação. Por padrão, o tempo de execução POSIX trata os arquivos estruturados como se contivessem texto e acrescenta uma nova linha; um chamador pode solicitar explicitamente esse comportamento fornecendo o modo de abertura O_TEXT. Um chamador que deseje tratar um arquivo estruturado VOS como contendo dados deve fornecer o modo de abertura O_BINARY. Esses dois modos são mutuamente exclusivos; se você especificar um deles, não deve especificar o outro. Esses modos não são necessários para arquivos de fluxo e, portanto, são ignorados nesse caso.
Para os especialistas em linguagem de programação que estão lendo este post, gostaria de observar rapidamente que tanto O_TEXT quanto O_BINARY são extensões do padrão POSIX; elas não são definidas pelo próprio POSIX. Normalmente, elas só estão presentes em sistemas operacionais que distinguem entre arquivos de texto e binários (como o VOS), ou que possuem uma convenção especial de fim de linha (como o Windows; usando CR-LF).
Por política, quando a Stratus porta software baseado em POSIX para o OpenVOS, nós o modificamos para excluir o uso de arquivos FIXED e RELATIVE, e restringimos os arquivos SEQUENTIAL ao acesso somente leitura. Também assumimos que todos os arquivos sequenciais contêm texto. Em nossa experiência, essas regras tornam prático o uso de arquivos STREAM ou SEQUENTIAL como entrada para programas POSIX, evitando as ineficiências inerentes à tentativa de realizar operações orientadas por bytes em arquivos de saída SEQUENTIAL.
Em resumo, a melhor abordagem é limitar-se a usar apenas arquivos STREAM (para entrada ou saída) e arquivos SEQUENTIAL (apenas para entrada de texto) com programas baseados em POSIX. Se você tiver dados binários em um arquivo estruturado, escreva um pequeno programa para copiá-los para um arquivo STREAM e, em seguida, use a versão STREAM do arquivo com programas POSIX. Se você tiver dados de texto em um arquivo FIXED ou RELATIVE que deseja processar com programas POSIX, copie o arquivo para um arquivo STREAM primeiro.
