fmemopen - Ouvrir de la mémoire en tant que flux
Bibliothèque C standard (
libc,
-lc)
#include <stdio.h>
FILE *fmemopen(void tampon[.taille], size_t taille, const char *mode);
fmemopen() :
Depuis la glibc 2.10 :
_POSIX_C_SOURCE >= 200809L
Avant la glibc 2.10 :
_GNU_SOURCE
La fonction
fmemopen() ouvre un flux qui permet l'accès
spécifié par
mode. Le flux permet d'effectuer des
entrées/sorties sur la chaîne ou le tampon mémoire
pointé par
tampon.
L'argument
mode spécifie le mode d'ouverture du flux et peut avoir
pour valeurs :
- r
- Le flux est ouvert en lecture.
- w
- Le flux est ouvert en écriture.
- a
- Ajout ; le flux est ouvert en écriture, la
position initiale du tampon étant définie au premier octet
de valeur zéro.
- r+
- Le flux est ouvert en lecture et en écriture.
- w+
- Le flux est ouvert en lecture et en écriture. Le
contenu du tampon est écrasé (autrement dit, '\0' est
placé dans le premier octet du tampon.
- a+
- Ajout ; le flux est ouvert en lecture et
écriture, la position initiale du tampon étant
définie au premier octet de valeur zéro.
Le flux conserve la notion de position actuelle qui est l'endroit du tampon
où la prochaine opération d'entrée/sortie aura lieu. La
position actuelle est automatiquement mise à jour par les
opérations d'entrées/sorties. Elle peut aussi être
définie de manière explicite à l'aide de
fseek(3)
et obtenue à l'aide de
ftell(3). Dans tous les modes autres que
Ajout, la position actuelle est initialisée au début du tampon.
En mode Ajout, si aucun octet de valeur zéro n'est trouvé dans
le tampon, la position actuelle est initialisée à
taille+1.
Si l'argument
tampon vaut NULL, alors la fonction
fmemopen()
alloue un tampon de
taille octets. C'est utile pour les applications
qui veulent écrire des données dans un tampon temporaire et les
lire ensuite. La position initiale est définie au début du
tampon. Le tampon est automatiquement supprimé lorsque le flux est
fermé. Notez que l'appelant ne peut pas obtenir de pointeur vers le
tampon temporaire alloué avec cette fonction (voir à ce sujet
open_memstream(3)).
Si
tampon est différent de NULL, il doit pointer vers un tampon
d'une taille minimale de
taille octets alloués par l'appelant.
Lorsqu'un flux ouvert en écriture est vidé (consultez
fflush(3)), ou fermé (consultez
fclose(3)), un octet nul
est écrit à la fin du tampon s'il y a de la place. Pour ce
faire, l'appelant doit s'assurer qu'un octet supplémentaire est
disponible dans le tampon (et que
taille en tient compte).
Avec un flux ouvert en lecture, si le tampon contient des octets de
valeur ('\0'), les opérations de lecture ne renverront pas une
indication de fin de fichier. Une lecture depuis le tampon n'indiquera la fin
du fichier que lorsque la position actuelle du tampon aura atteint la valeur
taille.
Les opérations d'écriture s'effectuent soit à la position
actuelle (pour les modes autres que Ajout), ou à une position
correspondant à la taille du flux (pour les mode Ajout).
Essayer d'écrire plus de
taille octets dans le tampon crée
une erreur. Par défaut, de telles erreurs ne seront visibles (en
l'absence de données) que lorsque le tampon
stdio sera
vidé. Désactiver cette mise en tampon avec l'appel suivant peut
s'avérer utile pour détecter les erreurs au moment d'une
opération de sortie :
setbuf(flux, NULL);
En cas de succès,
fmemopen() renvoie un pointeur de type
FILE. Sinon, elle renvoie NULL et
errno contient le code
d'erreur.
fmemopen() était déjà disponible dans la
version 1.0.x. de la glibc.
Pour une explication des termes utilisés dans cette section, consulter
attributes(7).
Interface |
Attribut |
Valeur |
fmemopen(), |
Sécurité des threads |
MT-Safe |
POSIX.1-2008. Cette fonction n'est pas spécifiée dans POSIX.1-2001
et n'est que rarement disponible sur d'autres systèmes.
POSIX.1-2008 spécifie que « b » dans
mode sera ignoré. Cependant, Technical Corrigendum 1
ajuste la norme pour permettre un traitement spécifique à
l'implémentation dans ce cas, permettant ainsi à la glibc de
traiter « b ».
Il n'y a pas de descripteur de fichier associé avec le flux
renvoyé par cette fonction (par exemple,
fileno(3) retournera
une erreur si elle est appelée avec un tel flux).
Avec la glibc 2.22, le mode binaire a été supprimé
(voir ci-dessous), de nombreux bogues anciens dans l'implémentation de
fmemopen() ont été résolus et un nouveau symbole
versionné a été créé pour cette interface.
De la glibc 2.9 à la glibc 2.21, l'implémentation
dans la glibc de
fmemopen() prenait en charge un mode
« binaire » qui pouvait être activé
en spécifiant la lettre « b » comme second
caractère de
mode. Dans ce mode, les opérations
d'écriture n'ajoutaient pas de manière implicite l'octet de
valeur zéro terminal, et la valeur
SEEK_END du troisième
argument de
fseek(3) est relative à la fin du tampon
(c'est-à-dire la valeur spécifiée par l'argument
taille), et non à la longueur de la chaîne courante.
Un bogue de l'API affectait l'implémentation du mode binaire :
pour indiquer le mode binaire, le « b » doit
être le
second caractère de
mode. Ainsi, par
exemple, « wb+ » a le comportement attendu, mais
pas « w+b ». Ce n'était pas cohérent
avec le traitement de
mode par
fopen(3).
Le mode binaire a été supprimé à partir de la
version 2.22 de la glibc et un « b »
spécifié dans
mode n'a dorénavant aucun effet.
Avant la glibc 2.22, si
taille est égale à
zéro,
fmemopen() échoue avec l'erreur
EINVAL. Il
est plus cohérent dans ce cas de créer un flux renvoyant la fin
de fichier au premier essai de lecture, et c'est ce que fait
l'implémentation de la glibc depuis la glibc 2.22.
Avant la glibc 2.22, indiquer un mode d'ajout
(« a » ou « a+ ») pour
fmemopen() définit la position initiale du fichier au premier
octet de valeur zéro, mais ne force pas l'ajout des écritures
suivantes à la fin du flux si la position actuelle dans le fichier est
réinitialisée à un autre endroit que la fin du flux. Ce
bogue a été corrigé avec la glibc 2.22.
Avant la glibc 2.22, si l'argument
mode de
fmemopen()
indiquait un ajout (« a » ou
« a+ »), et si l'argument
taille ne
couvrait pas d'octet de valeur zéro dans
tampon, alors,
d'après POSIX.1-2008, la position initiale du fichier devait
être définie à l'octet qui suit la fin du tampon. Dans ce
cas cependant, l'implémentation de
fmemopen() de la glibc
définissait la position du fichier à
-1. Ce bogue
a été corrigé avec la glibc 2.22.
Avant la glibc 2.22, lorsqu'un appel à
fseek(3) avec une
valeur de
départ égale à
SEEK_END
était effectué sur un flux créé à l'aide de
fmemopen(), le
décalage était
soustrait
à la position de fin de flux au lieu d'y être ajouté. Ce
bogue a été corrigé à partir de la glibc 2.22.
L'ajout du mode « binaire » dans la glibc 2.9
pour
fmemopen() a modifié silencieusement l'ABI :
auparavant,
fmemopen() ignorait « b » dans
mode.
Le programme ci-dessous utilise
fmemopen() pour ouvrir un tampon
d'entrée et
open_memstream(3) pour ouvrir un tampon de sortie de
taille dynamique. Ce programme scrute la chaîne en entrée
(récupérée du premier argument de la ligne de commande du
programme) sous forme d'entiers, et écrit le carré de ces
entiers dans le tampon de sortie. Voici un exemple de la sortie produite par
ce programme :
$ ./a.out '1 23 43'
taille=11; ptr=1 529 1849
#define _GNU_SOURCE
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
FILE *out, *in;
int v, s;
size_t taille;
char *ptr;
if (argc != 2) {
fprintf(stderr, "Utilisation : %s '<num>...'\n", argv[0]);
exit(EXIT_FAILURE);
}
in = fmemopen(argv[1], strlen(argv[1]), "r");
if (in == NULL)
err(EXIT_FAILURE, "fmemopen");
out = open_memstream(&ptr, &taille);
if (out == NULL)
err(EXIT_FAILURE, "open_memstream");
for (;;) {
s = fscanf(in, "%d", &v);
if (s <= 0)
break;
s = fprintf(out, "%d ", v * v);
if (s == -1)
err(EXIT_FAILURE, "fprintf");
}
fclose(in);
fclose(out);
printf("taille=%zu; ptr=%s\n", taille, ptr);
free(ptr);
exit(EXIT_SUCCESS);
}
fopen(3),
fopencookie(3),
open_memstream(3)
La traduction française de cette page de manuel a été
créée par Christophe Blaess
<
https://www.blaess.fr/christophe/>, Stéphan Rafin
<
[email protected]>, Thierry Vignaud
<
[email protected]>, François Micaux, Alain Portal
<
[email protected]>, Jean-Philippe Guérard
<
[email protected]>, Jean-Luc Coulon (f5ibh)
<
[email protected]>, Julien Cristau
<
[email protected]>, Thomas Huriaux <
[email protected]>,
Nicolas François <
[email protected]>, Florentin
Duneau <
[email protected]>, Simon Paillard
<
[email protected]>, Denis Barbier
<
[email protected]>, David Prévot <
[email protected]>,
Frédéric Hantrais <
[email protected]> et Lucien Gentis
<
[email protected]>
Cette traduction est une documentation libre ; veuillez vous reporter
à la
GNU
General Public License version 3 concernant les conditions de copie
et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
[email protected]