Man page - fopencookie(3)

Packages contains this manual

Available languages:

en fr ja ru

Manual

fopencookie

NOM
BIBLIOTHÈQUE
SYNOPSIS
DESCRIPTION
VALEUR RENVOYÉE
ATTRIBUTS
STANDARDS
EXEMPLES
Source du programme
NOTES
VOIR AUSSI
TRADUCTION

NOM

fopencookie – Ouvrir un flux particulier

BIBLIOTHÈQUE

BibliothĂšque C standard ( libc , -lc )

SYNOPSIS

#define _GNU_SOURCE /* Consultez feature_test_macros(7) */
#define _FILE_OFFSET_BITS 64
#include <stdio.h>

FILE *fopencookie(void *restrict cookie , const char *restrict mode ,
cookie_io_functions_t
io_funcs );

DESCRIPTION

La fonction fopencookie () permet au programmeur de crĂ©er des implĂ©mentations particuliĂšres de flux d’entrĂ©es-sorties. Cette implĂ©mentation peut sauvegarder les flux de donnĂ©es dans une location choisie. Par exemple, fopencookie () est utilisĂ©e pour implĂ©menter fmemopen (3), qui fournit une interface qui sauvegarde les flux de donnĂ©es dans un tampon en mĂ©moire.

Pour créer un flux particulier, le programmeur doit :

-

ImplĂ©menter quatre fonctions de « hook » qui seront utilisĂ©es en interne par la bibliothĂšque standard d’entrĂ©es-sorties lors d’opĂ©ration d’E/S.

-

DĂ©finit un type de donnĂ©es « cookie », une structure permettant de sauvegarder des informations (par exemple, oĂč sauvegarder les donnĂ©es) utilisĂ©e par les fonctions de hook. Les fonctions E/S standards ne connaissent rien Ă  propos du contenu de ce cookie (il est passĂ© comme un type void * Ă  fopencookie ()) et celui-ci est automatiquement passĂ© en premier argument des fonctions de hook.

-

Appeler fopencookie () pour ouvrir un nouveau flux et associer le cookie et les fonctions de « hook » à ce flux.

La fonction fopencookie () effectue une tùche similaire à celle de fopen (3) : elle ouvre un nouveau flux et renvoie un pointeur vers un objet FILE utilisé pour manipuler le flux.

L’argument cookie est un pointeur vers la structure cookie appelante qui est associĂ©e au nouveau flux. Ce pointeur est passĂ© en premier argument lorsque les bibliothĂšques d’E/S standard appellent une des fonctions de hook.

L’argument mode a le mĂȘme sens que pour fopen (3). Les modes suivants sont gĂ©rĂ©s : r , w , a , r+ , w+ et a+ . Consultez fopen (3) pour plus de dĂ©tails.

L’argument io_funcs est une structure qui contient quatre champs pointant vers les fonctions de « hook » dĂ©finies par le programmeur qui seront utilisĂ©es dans l’implĂ©mentation du flux. La structure est dĂ©finie comme suit :

typedef struct {
cookie_read_function_t *read;
cookie_write_function_t *write;
cookie_seek_function_t *seek;
cookie_close_function_t *close;
} cookie_io_functions_t;

Les quatre membres sont définis comme suit :
cookie_read_function_t *read

Cette fonction implĂ©mente les opĂ©rations de lecture du flux. Lorsqu’elle est appelĂ©e, elle reçoit trois arguments.

ssize_t read(void *cookie, char *buf, size_t size);

Les argument buf et size sont respectivement, un tampon de donnĂ©es pour sauvegarder les donnĂ©es en provenance du flux et la taille du tampon. La fonction read renvoie le nombre d’octets copiĂ©s depuis le flux ou -1 en cas d’erreur. La fonction read doit mettre Ă  jour la position dans le flux en consĂ©quence.

Si *read est un pointeur NULL, alors les lectures du flux renvoient toujours fin de fichier.

cookie_write_function_t *write

Cette fonction implĂ©mente les opĂ©rations d’écriture du flux. Lorsqu’elle est appelĂ©e, elle reçoit trois arguments :

ssize_t write(void *cookie, const char *buf, size_t size);

Les argument buf et size sont respectivement, un tampon de donnĂ©es Ă  Ă©crire dans le flux et la taille du tampon. La fonction write renvoie le nombre d’octets copiĂ©s depuis buf ou 0 en cas d’erreur (la fonction ne doit pas renvoyer de valeur nĂ©gative). La fonction write doit mettre Ă  jour la position dans le flux en consĂ©quence.

Si *write est un pointeur NULL, alors les écritures dans le flux ne sont pas réalisées.

cookie_seek_function_t *seek

Cette fonction implĂ©mente les opĂ©rations de positionnement dans le flux. Lorsqu’elle est appelĂ©e, elle prend trois arguments :

int seek(void *cookie, off_t *offset, int whence);

L’argument *offset spĂ©cifie le nouveau dĂ©calage du fichier selon les trois valeurs suivantes fournies Ă  whence :
SEEK_SET

Le dĂ©calage du flux doit ĂȘtre dĂ©fini Ă  *offset octets aprĂšs le dĂ©but du flux.

SEEK_CUR

*offset doit ĂȘtre ajoutĂ© Ă  l’offset actuel du flux.

SEEK_END

L’offset du flux doit ĂȘtre dĂ©fini Ă  la taille du flux plus *offset .

La fonction seek doit mettre Ă  jour *offset pour indiquer le nouvel offset du flux avant de renvoyer.

La function seek devrait renvoyer 0 en cas de succùs et -1 en cas d’erreur.

Si *seek est un pointeur NULL, alors il est impossible de se positionner dans le flux.

cookie_close_function_t *close

Cette fonction ferme le flux. Par exemple, la fonction de hook peut dĂ©sallouer des tampons allouĂ©s pour le flux. Lorsqu’elle est appelĂ©e, elle prend un argument :

int close(void *cookie);

L’argument cookie est le cookie que le programmeur fournit à fopencookie ().

La function close devrait renvoyĂ©e 0 en cas de succĂšs et EOF en cas d’erreur.

Si *close est NULL, alors aucune action n’est rĂ©alisĂ©e lorsque le flux est fermĂ©.

VALEUR RENVOYÉE

En cas de succĂšs, fopencookie () renvoie un pointeur sur le nouveau flux. En cas d’erreur, NULL est renvoyĂ©.

ATTRIBUTS

Pour une explication des termes utilisés dans cette section, consulter attributes (7).

Image grohtml-3874267-1.png

STANDARDS

GNU.

EXEMPLES

Le programme ci-dessous implémente un flux particulier dont la fonctionnalité est similaire (mais non identique) à celle de fmemopen (3). Il implémente un flux dont les données sont sauvegardées dans un tampon. Le programme écrit les options de sa ligne de commande dans le flux et se positionne dans le flux afin de lire 2 caractÚres sur 5 et les écrit sur la sortie standard. La session shell suivante explique comment utiliser ce programme.

$ ./a.out 'hello world'
/he/
/ w/
/d/
Fin de fichier atteinte

Notez qu’une version plus gĂ©nĂ©rique et plus robuste du programme ci-dessous, avec une gestion des erreurs pourrait ĂȘtre implĂ©mentĂ© (par exemple, l’ouverture d’un flux avec un cookie en cours d’utilisation par un autre flux ; la fermeture d’un flux dĂ©jĂ  fermĂ©).

Source du programme

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define INIT_BUF_SIZE 4
struct memfile_cookie {
char *buf; /* Tampon de taille dynamique pour les données */
size_t allocated; /* Taille du tampon */
size_t endpos; /* Nombre de caractĂšres dans le tampon */
off_t offset; /* Décalage du fichier actuel dans le tampon */
};
ssize_t
memfile_write(void *c, const char *buf, size_t size)
{
char *new_buff;
struct memfile_cookie *cookie = c;
/* Tampon trop petit : doubler sa taille jusqu’à ce
qu’il soit assez grand. */
while (size + cookie->offset > cookie->allocated) {
new_buff = realloc(cookie->buf, cookie->allocated * 2);
if (new_buff == NULL)
return -1;
cookie->allocated *= 2;
cookie->buf = new_buff;
}
memcpy(cookie->buf + cookie->offset, buf, size);
cookie->offset += size;
if (cookie->offset > cookie->endpos)
cookie->endpos = cookie->offset;
return size;
}
ssize_t
memfile_read(void *c, char *buf, size_t size)
{
ssize_t xbytes;
struct memfile_cookie *cookie = c;
/* Obtenir le minimum d’octets requis et d’octets disponibles. */
xbytes = size;
if (cookie->offset + size > cookie->endpos)
xbytes = cookie->endpos - cookie->offset;
if (xbytes < 0) /* offset may be past endpos */
xbytes = 0;
memcpy(buf, cookie->buf + cookie->offset, xbytes);
cookie->offset += xbytes;
return xbytes;
}
int
memfile_seek(void *c, off_t *offset, int whence)
{
off_t new_offset;
struct memfile_cookie *cookie = c;
if (whence == SEEK_SET)
new_offset = *offset;
else if (whence == SEEK_END)
new_offset = cookie->endpos + *offset;
else if (whence == SEEK_CUR)
new_offset = cookie->offset + *offset;
else
return -1;
if (new_offset < 0)
return -1;
cookie->offset = new_offset;
*offset = new_offset;
return 0;
}
int
memfile_close(void *c)
{
struct memfile_cookie *cookie = c;
free(cookie->buf);
cookie->allocated = 0;
cookie->buf = NULL;
return 0;
}
int
main(int argc, char *argv[])
{
cookie_io_functions_t memfile_func = {
.read = memfile_read,
.write = memfile_write,
.seek = memfile_seek,
.close = memfile_close
};
FILE *stream;
struct memfile_cookie mycookie;
size_t nread;
char buf[1000];
/* DĂ©finir le cookie avant l’appel de fopencookie(). */
mycookie.buf = malloc(INIT_BUF_SIZE);
if (mycookie.buf == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
mycookie.allocated = INIT_BUF_SIZE;
mycookie.offset = 0;
mycookie.endpos = 0;
stream = fopencookie(&mycookie, "w+", memfile_func);
if (stream == NULL) {
perror("fopencookie");
exit(EXIT_FAILURE);
}
/* Écrire les arguments de la ligne de commande sur le fichier. */
for (size_t j = 1; j < argc; j++)
if (fputs(argv[j], stream) == EOF) {
perror("fputs");
exit(EXIT_FAILURE);
}
/* Lire deux octets tous les cinq octets jusqu’à EOF. */
for (long p = 0; ; p += 5) {
if (fseek(stream, p, SEEK_SET) == -1) {
perror("fseek");
exit(EXIT_FAILURE);
}
nread = fread(buf, 1, 2, stream);
if (nread == 0) {
if (ferror(stream) != 0) {
fprintf(stderr, "échec fread\n");
exit(EXIT_FAILURE);
}
printf("Fin de fichier atteinte\n");
break;
}
printf("/%.*s/\n", (int) nread, buf);
}
free(mycookie.buf);
exit(EXIT_SUCCESS);
}

NOTES

_FILE_OFFSET_BITS devrait ĂȘtre dĂ©fini Ă  64 dans du code qui utilise une valeur de seek non NULL ou qui prend l’adresse de fopencookie , si le code est destinĂ© Ă  ĂȘtre portable pour les plateformes traditionelles x86 et ARM 32 bits oĂč la taille par dĂ©faut de off_t est 32 bits.

VOIR AUSSI

fclose (3), fmemopen (3), fopen (3), fseek (3)

TRADUCTION

La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org>, Frédéric Hantrais <fhantrais@gmail.com> et Jean-Pierre Giraud <jean-pierregiraud@neuf.fr>

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 à debian-l10n-french@lists.debian.org .