fopencookie(3) Library Functions Manual fopencookie(3) NOM fopencookie - Ouvrir un flux particulier BIBLIOTHEQUE Bibliotheque C standard (libc, -lc) SYNOPSIS #define _GNU_SOURCE /* Consultez feature_test_macros(7) */ #define _FILE_OFFSET_BITS 64 #include FILE *fopencookie(void *restrict cookie, const char *restrict mode, cookie_io_functions_t io_funcs); DESCRIPTION La fonction fopencookie() permet au programmeur de creer des implementations particulieres de flux d'entrees-sorties. Cette implementation peut sauvegarder les flux de donnees dans une location choisie. Par exemple, fopencookie() est utilisee pour implementer fmemopen(3), qui fournit une interface qui sauvegarde les flux de donnees dans un tampon en memoire. Pour creer un flux particulier, le programmeur doit : - Implementer quatre fonctions de << hook >> qui seront utilisees en interne par la bibliotheque standard d'entrees-sorties lors d'operation d'E/S. - Definit un type de donnees << cookie >>, une structure permettant de sauvegarder des informations (par exemple, ou sauvegarder les donnees) utilisee par les fonctions de hook. Les fonctions E/S standards ne connaissent rien a propos du contenu de ce cookie (il est passe comme un type void * a fopencookie()) et celui-ci est automatiquement passe en premier argument des fonctions de hook. - Appeler fopencookie() pour ouvrir un nouveau flux et associer le cookie et les fonctions de << hook >> a ce flux. La fonction fopencookie() effectue une tache similaire a celle de fopen(3) : elle ouvre un nouveau flux et renvoie un pointeur vers un objet FILE utilise pour manipuler le flux. L'argument cookie est un pointeur vers la structure cookie appelante qui est associee au nouveau flux. Ce pointeur est passe en premier argument lorsque les bibliotheques d'E/S standard appellent une des fonctions de hook. L'argument mode a le meme sens que pour fopen(3). Les modes suivants sont geres : r, w, a, r+, w+ et a+. Consultez fopen(3) pour plus de details. L'argument io_funcs est une structure qui contient quatre champs pointant vers les fonctions de << hook >> definies par le programmeur qui seront utilisees dans l'implementation du flux. La structure est definie 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 definis comme suit : cookie_read_function_t *read Cette fonction implemente les operations de lecture du flux. Lorsqu'elle est appelee, elle recoit trois arguments. ssize_t read(void *cookie, char *buf, size_t size); Les argument buf et size sont respectivement, un tampon de donnees pour sauvegarder les donnees en provenance du flux et la taille du tampon. La fonction read renvoie le nombre d'octets copies depuis le flux ou -1 en cas d'erreur. La fonction read doit mettre a jour la position dans le flux en consequence. Si *read est un pointeur NULL, alors les lectures du flux renvoient toujours fin de fichier. cookie_write_function_t *write Cette fonction implemente les operations d'ecriture du flux. Lorsqu'elle est appelee, elle recoit trois arguments : ssize_t write(void *cookie, const char *buf, size_t size); Les argument buf et size sont respectivement, un tampon de donnees a ecrire dans le flux et la taille du tampon. La fonction write renvoie le nombre d'octets copies depuis buf ou 0 en cas d'erreur (la fonction ne doit pas renvoyer de valeur negative). La fonction write doit mettre a jour la position dans le flux en consequence. Si *write est un pointeur NULL, alors les ecritures dans le flux ne sont pas realisees. cookie_seek_function_t *seek Cette fonction implemente les operations de positionnement dans le flux. Lorsqu'elle est appelee, elle prend trois arguments : int seek(void *cookie, off_t *offset, int whence); L'argument *offset specifie le nouveau decalage du fichier selon les trois valeurs suivantes fournies a whence : SEEK_SET Le decalage du flux doit etre defini a *offset octets apres le debut du flux. SEEK_CUR *offset doit etre ajoute a l'offset actuel du flux. SEEK_END L'offset du flux doit etre defini a la taille du flux plus *offset. La fonction seek doit mettre a jour *offset pour indiquer le nouvel offset du flux avant de renvoyer. La function seek devrait renvoyer 0 en cas de succes 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 desallouer des tampons alloues pour le flux. Lorsqu'elle est appelee, elle prend un argument : int close(void *cookie); L'argument cookie est le cookie que le programmeur fournit a fopencookie(). La function close devrait renvoyee 0 en cas de succes et EOF en cas d'erreur. Si *close est NULL, alors aucune action n'est realisee lorsque le flux est ferme. VALEUR RENVOYEE En cas de succes, fopencookie() renvoie un pointeur sur le nouveau flux. En cas d'erreur, NULL est renvoye. ATTRIBUTS Pour une explication des termes utilises dans cette section, consulter attributes(7). +---------------------------------+--------------------------+---------+ |Interface | Attribut | Valeur | +---------------------------------+--------------------------+---------+ |fopencookie() | Securite des threads | MT-Safe | +---------------------------------+--------------------------+---------+ STANDARDS GNU. EXEMPLES Le programme ci-dessous implemente un flux particulier dont la fonctionnalite est similaire (mais non identique) a celle de fmemopen(3). Il implemente un flux dont les donnees sont sauvegardees dans un tampon. Le programme ecrit les options de sa ligne de commande dans le flux et se positionne dans le flux afin de lire 2 caracteres sur 5 et les ecrit 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 generique et plus robuste du programme ci-dessous, avec une gestion des erreurs pourrait etre implemente (par exemple, l'ouverture d'un flux avec un cookie en cours d'utilisation par un autre flux ; la fermeture d'un flux deja ferme). Source du programme #define _GNU_SOURCE #include #include #include #include #include #define INIT_BUF_SIZE 4 struct memfile_cookie { char *buf; /* Tampon de taille dynamique pour les donnees */ size_t allocated; /* Taille du tampon */ size_t endpos; /* Nombre de caracteres dans le tampon */ off_t offset; /* Decalage 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'a 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]; /* Definir 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); } /* Ecrire 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'a 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, "echec 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 etre defini a 64 dans du code qui utilise une valeur de seek non NULL ou qui prend l'adresse de fopencookie, si le code est destine a etre portable pour les plateformes traditionelles x86 et ARM 32 bits ou la taille par defaut de off_t est 32 bits. VOIR AUSSI fclose(3), fmemopen(3), fopen(3), fseek(3) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot , Frederic Hantrais et Jean- Pierre Giraud Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 29 decembre 2023 fopencookie(3)