Re: Ada.Text_IO - Interruption pendant l 'écriture

Stephane Carrez via Ada-france <[email protected]> Mon, 10 Jan 2022 22:27:45 +0100
Newsgroups gmane.comp.lang.ada.france
Message-ID <[email protected]>
Hi!

On 10/01/2022 00:52, Thomas De Contes via Ada-france wrote:
> 
> Le 6 déc. 2021 à 22:34, Jean-Pierre Rosen a écrit :
> 
>> Le 06/12/2021 à 16:25, Thomas De Contes a écrit :
>>> En fait, l'usage que je voulais en faire c'est implémenter un mécanisme pour minimiser les inconvénients en cas d'interruption pendant l'écriture  :
>>> - Trouver un répertoire pour fichiers temporaires
>>> - Écrire le nouveau fichier dedans
>>> - Effacer l'ancien fichier
>>> - Déplacer le nouveau fichier à sa place
>>> Ça permet de remplacer l'ancien fichier par le nouveau de façon quasi-atomique (pas tout à fait, puisqu'on doit faire Ada.Directories.Delete_File avant Ada.Directories.Rename, mais presque).
>>> As-tu des recommandations à me donner dans ce domaine ?
>> En fait, il y a une séquence critique, et il parait que certains trous de sécurité exploitent des choses comme ça: entre le moment où tu effaces le fichier et celui du move, un intrus peut créer un fichier piégé avec le nom qui va bien... C'est un peu parano, mais plutôt que d'effacer l'ancien fichier, il vaut peut-être mieux l'écraser avec le nouveau.
> 
> Ada.Directories.Rename refuse d'écraser un fichier.
> 

Oui, et c'est problématique pour moi.

> Est-ce que ta suggestion c'est de :
> - Créer un fichier temporaire, et le fabriquer comme on veut
> - Ouvrir l'ancien fichier en écriture, et recopier le fichier temporaire dedans le plus rapidement possible
> ?
> 

En fait cela pose plus des problèmes d'intégrité d'écriture de fichier.

Avec ce pattern Ada, si on n'a pas assez d'espace sur le disque, il y a une écriture partielle.
Comme on écrit (copie) sur le même nom, on a perdu l'ancien fichier.
A mon avis, il faut éviter cela.

L'autre pattern Ada qui consiste à supprimer l'ancien fichier avant le Ada.Directories.Rename
est moins problématique mais toujours incorrect si le programme est interrompu/suspendu/tué entre
le Delete et le Rename.

Le pattern recommandé sous Unix depuis plus de 40 ans est:

- écrire dans un fichier temporaire sur le même file système que le fichier à remplacer,
- une fois qu'on est sûr que ce fichier temporaire est bien écrit correctement,
   utiliser rename(2) pour remplacer le fichier par le fichier temporaire.

Bonus: sous Unix, le rename(2) est atomique.
Le fichier existe toujours: soit c'est l'ancien, soit c'est le nouveau.
Les systèmes de fichiers Unix ont été conçus de longue date pour garantir
cela même si l'OS crash pendant l'appel système rename(2).

J'avais proposé en 2018 de faire évoluer Ada.Directories.Rename pour supporter cela.
Cela aurait pu être fait facilement en ajoutant un paramètre optionnel autorisant
le remplacement si le fichier cible existe déjà.

Pour éviter ces problèmes, j'utilise mon propre Util.Files.Rename(Old_Name, New_Name : String)
qui fonctionne pour Unix et Windows.


> J'ai un peu de mal à voir quel genre de faille ça évite.
> Mais bon je ne suis pas calé là dessus, d'une manière générale je crains bien plus les pannes que les vols (typiquement, la sécurité des données pour moi c'est beaucoup plus synonyme de sauvegardes multiples que de chiffrement).
> 
> Avec ma formule, le temps pendant lequel il n'y a pas de fichier complet est plus court, et il n'y a pas de moment où le fichier est incomplet. Pour la cohérence des données, ça me parait plus sur.
> (C'est à comparer au problème de sécurité que je n'ai pas bien compris, bien sur. Et si j'ai bien compris, pour ce problème de sécurité, ce qui importe c'est qu'à tout instant le fichier existe, peu importe son contenu.)
> 
> 

Le pattern Ada (Delete, Rename) a effectivement un trou de sécurité si après le Delete
mais avant le Rename, un autre process écrit le fichier: le Rename échouera et on se
retrouve avec le fichier écrit par l'autre process.

Maintenant, la séquence Delete, Rename est beaucoup plus rapide que de faire une copie.

Stephane
_______________________________________________
Ada-france mailing list
[email protected]
https://mail.ada-france.org/cgi-bin/mailman/listinfo/ada-france