table of contents
FOPENCOOKIE(3) | Manuel du programmeur Linux | FOPENCOOKIE(3) |
NOM¶
fopencookie - Ouvrir un flux particulierSYNOPSIS¶
#define _GNU_SOURCE /* Consultez feature_test_macros(7) */ #include <stdio.h> FILE *fopencookie(void *cookie, const char *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.- *
- 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.
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);
- 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);
- 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);
- 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.
- 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);
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)COLOPHON¶
Cette page fait partie de la publication 3.44 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¶
Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a <http://po4a.alioth.debian.org/> par l'équipe de traduction francophone au sein du projet perkamon <http://perkamon.alioth.debian.org/>. Florentin Duneau et l'équipe francophone de traduction de Debian (2006-2009). 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> ».30 avril 2012 | Linux |