Si vous avez déjà essayé d'utiliser des programmes basés sur POSIX pour traiter des fichiers structurés VOS, vous avez peut-être rencontré certaines restrictions ou vu certains comportements que vous n'avez pas compris. Dans cet article, je vais essayer d'expliquer ce qui se passe.
VOS supporte 4 types de fichiers : séquentiel, relatif, fixe et en flux. Les 3 premiers formats sont appelés fichiers "structurés" car le système de fichiers garde une trace des limites des enregistrements. Les opérations d'E/S disponibles lisent et écrivent des enregistrements entiers. Le dernier format est appelé "non structuré" parce que les limites des enregistrements sont implicites ; le caractère de nouvelle ligne délimite les enregistrements. Les opérations d'entrée/sortie disponibles lisent et écrivent des séquences d'octets.
Un environnement compatible POSIX, tel que celui d'un système Unix® ou Linux©, ne possède qu'un seul type de fichier natif, appelé "fichier régulier". L'organisation des fichiers de flux VOS est équivalente à un fichier régulier POSIX.
L'environnement d'exécution VOS POSIX classifie les 4 types de fichiers comme des fichiers POSIX réguliers. Donc, au moins en théorie, tout programme POSIX peut lire ou écrire n'importe lequel des 4 types de fichiers. Cependant, ce n'est pas aussi simple.
Parce que l'API POSIX définit toutes les opérations d'entrée/sortie en termes de séquences d'octets, alors que VOS définit les opérations d'entrée/sortie (sur des fichiers structurés) en termes de séquences d'enregistrements, le runtime VOS POSIX fait la différence en mettant en mémoire tampon l'enregistrement courant dans l'espace utilisateur, en effectuant les opérations d'entrée/sortie POSIX sur la mémoire tampon, puis en réécrivant l'enregistrement mis en mémoire tampon à des endroits appropriés.
Si le programme POSIX connaît la taille de chaque enregistrement (par exemple, pour un fichier fixe), et s'il lit et écrit le nombre exact d'octets, alors la présence du tampon n'affecte pas l'opération, et la mise en correspondance des deux types d'opérations d'E/S est facile à comprendre et efficace.
Mais si le programme POSIX ne fait que lire ou écrire un flux d'octets sans tenir compte de la taille de l'enregistrement sous-jacent, alors le mappage de la sémantique POSIX à la sémantique VOS, bien que bien défini, n'est généralement pas très utile, et est souvent assez inefficace. Certaines opérations, telles que la recherche d'une position d'octet ou la réécriture d'une séquence d'octets qui s'étend au-delà de la limite d'un enregistrement, sont au mieux inefficaces et au pire impossibles.
Ensuite, il y a la question du traitement des caractères de nouvelle ligne.
Un fichier POSIX normal et un fichier VOS stream utilisent tous deux le caractère de saut de ligne pour distinguer une limite d'enregistrement. Cependant, les enregistrements VOS dans les fichiers structurés ne contiennent généralement pas de caractères de retour à la ligne. Par exemple, lorsqu'un éditeur VOS (par exemple, edit, emacs ou line_edit) crée un nouveau fichier séquentiel, chaque enregistrement contient une ligne de texte. Mais l'enregistrement ne se termine pas par un caractère de retour à la ligne. Par convention, les programmes supposent tous qu'un fichier séquentiel qui contient du texte a un retour à la ligne implicite à la fin de chaque enregistrement. Il en va de même pour les fichiers relatifs et fixes. Mais voici un point important : aucun attribut d'un fichier (VOS, Unix, structuré ou non structuré) n'enregistre si le fichier contient du texte ou des données binaires. La distinction est laissée aux programmes qui accèdent au fichier.
Cette situation crée une sorte de quandry pour le runtime VOS POSIX. Il doit savoir si un fichier structuré VOS contient du texte ou des données afin de savoir s'il faut ou non ajouter une nouvelle ligne à chaque enregistrement. Si le fichier contient du texte, il doit ajouter une nouvelle ligne. S'il contient des données, il ne doit pas ajouter de nouvelle ligne.
La réponse est que la durée d'exécution de VOS POSIX dépend de l'appelant pour fournir cette information. Par défaut, le runtime POSIX traite les fichiers structurés comme s'ils contenaient du texte, et ajoute une nouvelle ligne ; un appelant peut explicitement demander ce comportement en fournissant le mode d'ouverture O_TEXT. Un appelant qui veut traiter un fichier structuré VOS comme s'il contenait des données doit fournir le mode d'ouverture O_BINARY. Ces deux modes sont mutuellement exclusifs ; si vous spécifiez l'un d'entre eux, vous ne devez pas spécifier l'autre. Ces modes ne sont pas nécessaires pour les fichiers de flux, et sont donc ignorés dans ce cas.
Pour les linguistes qui lisent ce billet, permettez-moi de noter rapidement que O_TEXT et O_BINARY sont tous deux des extensions de la norme POSIX ; ils ne sont pas définis par POSIX lui-même. Elles ne sont généralement présentes que sur les systèmes d'exploitation qui font la distinction entre les fichiers texte et binaires (comme le fait VOS), ou qui ont une convention spéciale de fin de ligne (comme le fait Windows ; en utilisant CR-LF).
Par principe, lorsque Stratus porte un logiciel basé sur POSIX vers OpenVOS, nous le modifions pour exclure l'utilisation de fichiers FIXES et RELATIFS, et nous limitons les fichiers SÉQUENTIELS à un accès en lecture seule. Nous supposons également que tous les fichiers séquentiels contiennent du texte. D'après notre expérience, ces règles rendent pratique l'utilisation de fichiers STREAM ou SEQUENTIAL en entrée des programmes POSIX, tout en évitant les inefficacités inhérentes à la tentative d'effectuer des opérations orientées octet sur les fichiers de sortie SEQUENTIAL.
En résumé, la meilleure approche est de s'en tenir à l'utilisation de fichiers STREAM (pour l'entrée ou la sortie) et de fichiers SEQUENTIAL (pour l'entrée de texte uniquement) avec des programmes basés sur POSIX. Si vous avez des données binaires dans un fichier structuré, écrivez un petit programme pour le copier dans un fichier stream, puis utilisez la version stream du fichier avec des programmes POSIX. Si vous avez des données textuelles dans un fichier FIXE ou RELATIF que vous souhaitez traiter avec des programmes POSIX, copiez d'abord le fichier dans un fichier STREAM.