Si alguna vez has intentado utilizar programas basados en POSIX para procesar archivos estructurados de VOS, es posible que te hayas encontrado con algunas restricciones o hayas observado un comportamiento que no entendías. En esta entrada intentaré explicarte qué está pasando.
VOS admite cuatro tipos de archivos: secuencial, relativo, fijo y de flujo. Los tres primeros formatos se denominan archivos «estructurados», ya que el sistema de archivos lleva un registro de los límites de los registros. Las operaciones de E/S disponibles leen y escriben registros completos. El último formato se denomina «no estructurado», ya que los límites de los registros son implícitos; el carácter de nueva línea delimita los registros. Las operaciones de E/S disponibles leen y escriben secuencias de bytes.
Un entorno compatible con POSIX, como el que se encuentra en un sistema Unix® o Linux©, solo tiene un tipo de archivo nativo, denominado «archivo normal». La organización de archivos en forma de flujo de VOS es equivalente a un archivo normal de POSIX.
El entorno de ejecución POSIX de VOS clasifica los cuatro tipos de archivos como archivos normales POSIX. Por lo tanto, al menos en teoría, cualquier programa POSIX puede leer o escribir cualquiera de los cuatro tipos de archivos. Sin embargo, no es tan sencillo.
Dado que la API POSIX define todas las operaciones de E/S en términos de secuencias de bytes, mientras que VOS define las operaciones de E/S (en archivos estructurados) en términos de secuencias de registros, el entorno de ejecución VOS POSIX compensa esta diferencia almacenando en búfer el registro actual en el espacio de usuario, realizando las operaciones de E/S POSIX en el búfer y, a continuación, volviendo a escribir el registro almacenado en los momentos oportunos.
Si el programa POSIX conoce el tamaño de cada registro (por ejemplo, en el caso de un archivo fijo) y lee y escribe el número exacto de bytes, la presencia del búfer no afecta a la operación, y la correspondencia entre los dos tipos de operaciones de E/S resulta fácil de entender y eficiente.
Pero si el programa POSIX se limita a leer o escribir un flujo de bytes sin tener en cuenta el tamaño del registro subyacente, la correspondencia entre la semántica POSIX y la semántica VOS, aunque está bien definida, no suele ser muy útil y, a menudo, resulta bastante ineficaz. Ciertas operaciones, como la búsqueda de una posición de byte o la reescritura de una secuencia de bytes que traspasa el límite de un registro, son, en el mejor de los casos, ineficaces y, en el peor, imposibles.
Luego está la cuestión del tratamiento de los caracteres de salto de línea.
Tanto los archivos normales POSIX como los archivos de flujo VOS utilizan el carácter de salto de línea para marcar el límite de un registro. Sin embargo, los registros VOS en archivos estructurados no suelen contener caracteres de salto de línea. Por ejemplo, cuando un editor VOS (como edit, emacs o line_edit) crea un nuevo archivo secuencial, cada registro contiene una línea de texto. Pero el registro no termina con un carácter de salto de línea. Por convención, todos los programas asumen que un archivo secuencial que contiene texto tiene un salto de línea implícito al final de cada registro. Lo mismo ocurre con los archivos relativos y fijos. Pero aquí hay un punto importante: ningún atributo de ningún archivo (VOS, Unix, estructurado o no estructurado) registra si el archivo contiene texto o datos binarios. La distinción se deja en manos de los programas que acceden al archivo.
Esta situación plantea un dilema para el entorno de ejecución POSIX de VOS. Necesita saber si un archivo estructurado de VOS contiene texto o datos para determinar si debe añadir un salto de línea al final de cada registro o no. Si el archivo contiene texto, debe añadir un salto de línea. Si contiene datos, no debe añadir un salto de línea.
La respuesta es que el tiempo de ejecución POSIX de VOS depende de que la aplicación solicitante proporcione esta información. Por defecto, el tiempo de ejecución POSIX trata los archivos estructurados como si contuvieran texto y añade un salto de línea; una aplicación solicitante puede solicitar explícitamente este comportamiento indicando el modo de apertura O_TEXT. Un llamante que desee tratar un archivo estructurado VOS como si contuviera datos debe proporcionar el modo de apertura O_BINARY. Estos dos modos son mutuamente excluyentes; si se especifica uno de ellos, no se debe especificar el otro. Estos modos no son necesarios para los archivos de flujo, por lo que se ignoran en este caso.
Para los expertos en lenguaje que estén leyendo esta entrada, permítanme señalar brevemente que tanto O_TEXT como O_BINARY son extensiones del estándar POSIX; no están definidas por el propio POSIX. Por lo general, solo están presentes en sistemas operativos que distinguen entre archivos de texto y binarios (como hace VOS), o que tienen una convención especial para el fin de línea (como hace Windows, que utiliza CR-LF).
Por norma, cuando Stratus software basado en POSIX a OpenVOS, lo modificamos para excluir el uso de archivos FIXED y RELATIVE, y restringimos los archivos SEQUENTIAL a un acceso de solo lectura. También asumimos que todos los archivos secuenciales contienen texto. Según nuestra experiencia, estas reglas hacen que resulte práctico utilizar archivos STREAM o SEQUENTIAL como entrada para programas POSIX, al tiempo que se evitan las ineficiencias inherentes a intentar realizar operaciones orientadas a bytes en archivos de salida SEQUENTIAL.
En resumen, lo mejor es limitarse a utilizar únicamente archivos STREAM (para entrada o salida) y archivos SEQUENTIAL (solo para la entrada de texto) con programas basados en POSIX. Si tienes datos binarios en un archivo estructurado, escribe un pequeño programa para copiarlos a un archivo STREAM y, a continuación, utiliza la versión STREAM del archivo con programas POSIX. Si tienes datos de texto en un archivo FIXED o RELATIVE que deseas procesar con programas POSIX, copia primero el archivo a un archivo STREAM.
