Provided by: manpages-fr-dev_4.27.0-1_all bug

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).
       ┌──────────────────────────────────────────────────────────────────────┬──────────────────────┬─────────┐
       │ InterfaceAttributValeur  │
       ├──────────────────────────────────────────────────────────────────────┼──────────────────────┼─────────┤
       │ fopencookie()                                                        │ Sécurité des threads │ MT-Safe │
       └──────────────────────────────────────────────────────────────────────┴──────────────────────┴─────────┘

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.

Pages du manuel de Linux 6.9.1                    15 juin 2024                                    fopencookie(3)