Provided by: manpages-fr-dev_4.23.1-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  ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩   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⟩.