Si alguna vez ha intentado usar programas basados en POSIX para procesar archivos estructurados VOS, puede que se haya encontrado con algunas restricciones o haya visto algún comportamiento que no haya entendido. En este post intentaré explicar lo que está pasando.
VOS soporta 4 tipos de archivos: secuenciales, relativos, fijos y de flujo. Los 3 primeros formatos se llaman archivos "estructurados" porque el sistema de archivos mantiene los límites de los registros. Las operaciones de E/S disponibles leen y escriben registros completos. El último formato se denomina "no estructurado" porque los límites del registro están 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©, sólo tiene un tipo de archivo nativo, que se llama "archivo regular". La organización del archivo de flujo VOS es equivalente a un archivo regular POSIX.
El entorno de ejecución de VOS POSIX clasifica los 4 tipos de archivos como archivos POSIX regulares. Así que al menos en teoría, cualquier programa POSIX puede leer o escribir cualquiera de los 4 tipos de archivos. Sin embargo, no es tan simple.
Dado que la API POSIX define todas las operaciones de E/S en términos de secuencias de bytes, mientras que la VOS define las operaciones de E/S (en archivos estructurados) en términos de secuencias de registros, el tiempo de ejecución POSIX de la VOS media la diferencia almacenando el registro actual en el espacio de usuario, realizando las operaciones de E/S POSIX en el búfer y luego escribiendo el registro almacenado en el búfer en los puntos apropiados.
Si el programa POSIX conoce el tamaño de cada registro (por ejemplo, para un archivo fijo), y si lee y escribe el número exacto de bytes, entonces la presencia del buffer no afecta a la operación, y la asignación de los dos tipos de operaciones de E/S es fácil de entender y eficiente.
Pero si el programa POSIX sólo está leyendo o escribiendo un flujo de bytes sin tener en cuenta el tamaño del registro subyacente, entonces el mapeo de la semántica de POSIX a la semántica de VOS, aunque bien definida, no es generalmente muy útil, y a menudo es bastante ineficiente. Ciertas operaciones, como la búsqueda de una posición de bytes, o la reescritura de una secuencia de bytes que se extiende a través de un límite de registro, son ineficientes en el mejor de los casos e imposibles en el peor.
Luego está el asunto del manejo de los personajes de la nueva línea.
Tanto un archivo regular POSIX como un archivo de flujo VOS utilizan el carácter de nueva línea para distinguir un límite de registro. Sin embargo, los registros VOS en los archivos estructurados no suelen contener ningún carácter de nueva línea. Por ejemplo, cuando un editor VOS (por ejemplo, edit, emacs o line_edit) crea un nuevo archivo secuencial, cada registro contiene una línea de texto. Pero el registro no termina en un carácter de nueva línea. Por convención, todos los programas asumen que un archivo secuencial que contiene texto tiene una nueva línea implícita 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 a los programas que acceden al archivo.
Esta situación crea una especie de cuandria para el tiempo de ejecución de VOS POSIX. Necesita saber si un archivo estructurado de VOS contiene texto o datos para saber si debe añadir una nueva línea a cada registro o no. Si el archivo contiene texto, debería añadir una nueva línea. Si contiene datos, no debería añadir una nueva línea.
La respuesta es que el tiempo de ejecución de VOS POSIX depende de la persona que llama para proporcionar esta información. Por defecto, el tiempo de ejecución de POSIX trata los archivos estructurados como si contuvieran texto, y añade una nueva línea; un llamador puede solicitar explícitamente este comportamiento proporcionando el modo de apertura O_TEXT. Un llamador que quiera tratar un archivo estructurado VOS como si contuviera datos debe proveer 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 streaming, por lo que se ignoran en este caso.
Para los abogados lingüistas que están leyendo este post, permítanme señalar rápidamente que tanto O_TEXT como O_BINARY son extensiones del estándar POSIX; no están definidos por el propio POSIX. Por lo general, sólo están presentes en los sistemas operativos que distinguen entre archivos de texto y binarios (como lo hace VOS), o tienen una convención especial de fin de línea (como lo hace Windows; usando CR-LF).
Por política, cuando Stratus porta el software basado en POSIX a OpenVOS, lo modificamos para excluir el uso de archivos FIJOS y RELATIVOS, y restringimos los archivos SECUENCIALES al acceso de sólo lectura. También asumimos que todos los archivos secuenciales contienen texto. En nuestra experiencia, estas reglas hacen práctico el uso de archivos STREAM o SECUENCIALES como entrada a los programas POSIX, mientras que se evitan las ineficiencias inherentes al intento de realizar operaciones orientadas a bytes en los archivos de salida SECUENCIALES.
En resumen, el mejor enfoque es atenerse a usar sólo archivos STREAM (para entrada o salida) y archivos SECUENCIALES (para entrada de texto solamente) con programas basados en POSIX. Si tiene datos binarios en un archivo estructurado, escriba un pequeño programa para copiarlos en un archivo de flujo, y luego use la versión de flujo del archivo con programas POSIX. Si tiene datos de texto en un archivo FIJO o RELATIVO que desea procesar con programas POSIX, copie primero el archivo en un archivo STREAM.