Loading

NOM

       fopencookie - ouvrir un flux particulier

SYNOPSIS

       #define _GNU_SOURCE
       #include <stdio.h>

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

       La   fonction   fopencookie()   permet  au  programmeur  de  créer  des
       implémentations  particulières  des   flux   d’entrées-sorties.   Cette
       implémentation  peut  sauvegarder  les  flux  de données à une location
       choisie. Par  exemple,  fopencookie()  est  utilisée  pour  implémenter
       fmemopen(3),  qui  fournit  un  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 :

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

       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
              -1 en cas d’erreur. 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, off64_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 courant 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 renvoyée 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é.

CONFORMITÉ

       Cette fonction est une extension GNU non standard.

EXEMPLE

       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/
           Reached end of file

       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 <sys/types.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <string.h>

       #define INIT_BUF_SIZE 4

       struct memfile_cookie {
           char   *buf;        /* Dynamically sized buffer for data */
           size_t  allocated;  /* Size of buf */
           size_t  endpos;     /* Number of characters in buf */
           off_t   offset;     /* Current file offset in buf */
       };

       ssize_t
       memfile_write(void *c, const char *buf, size_t size)
       {
           char *new_buff;
           struct memfile_cookie *cookie = c;

           /* Buffer too small? Keep doubling size until big enough */

           while (size + cookie->offset > cookie->allocated) {
               new_buff = realloc(cookie->buf, cookie->allocated * 2);
               if (new_buff == NULL) {
                   return -1;
               } else {
                   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;

           /* Fetch minimum of bytes requested and bytes available */

           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, off64_t *offset, int whence)
       {
           off64_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 *fp;
           struct memfile_cookie mycookie;
           ssize_t nread;
           long p;
           int j;
           char buf[1000];

           /* Set up the cookie before calling 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;

           fp = fopencookie(&mycookie,"w+", memfile_func);
           if (fp == NULL) {
               perror("fopencookie");
               exit(EXIT_FAILURE);
           }

           /* Write command-line arguments to our file */

           for (j = 1; j < argc; j++)
               if (fputs(argv[j], fp) == EOF) {
                   perror("fputs");
                   exit(EXIT_FAILURE);
               }

           /* Read two bytes out of every five, until EOF */

           for (p = 0; ; p += 5) {
               if (fseek(fp, p, SEEK_SET) == -1) {
                   perror("fseek");
                   exit(EXIT_FAILURE);
               }
               nread = fread(buf, 1, 2, fp);
               if (nread == -1) {
                   perror("fread");
                   exit(EXIT_FAILURE);
               }
               if (nread == 0) {
                   printf("Reached end of file\n");
                   break;
               }

               printf("/%.*s/\n", nread, buf);
           }

           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

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

COLOPHON

       Cette page fait partie de  la  publication  3.23  du  projet  man-pages
       Linux.  Une description du projet et des instructions pour signaler des
       anomalies      peuvent      être       trouvées       à       l’adresse
       http://www.kernel.org/doc/man-pages/.

TRADUCTION

       Cette  page  de  manuel  a  été traduite et est maintenue par Florentin
       Duneau <fduneau AT gmail DOT com> et l’équipe francophone de traduction
       de Debian.

       Veuillez   signaler   toute   erreur   de   traduction  en  écrivant  à
       <debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
       paquet manpages-fr.

       Vous  pouvez  toujours avoir accès à la version anglaise de ce document
       en utilisant la commande « man -L C <section> <page_de_man> ».