open, openat, creat
Ouvrir ou créer éventuellement un fichier
- Provided by: manpages-fr-dev (Version: 3.65d1p1-1)
- Source: manpages-fr
- Report a bug
Ouvrir ou créer éventuellement un fichier
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); int creat(const char *pathname, mode_t mode); int openat(int dirfd, const char *pathname, int flags); int openat(int dirfd, const char *pathname, int flags, mode_t mode);
Exigences de macros de test de fonctionnalités pour la glibc (consultez
feature_test_macros(7)) :
openat():
Étant donné le chemin pathname d'un fichier, open() renvoie un descripteur de fichier (petit entier positif ou nul) qui pourra ensuite être utilisé dans d'autres appels système (read(2), write(2), lseek(2), fcntl(2), etc.). Le descripteur de fichier renvoyé par un appel réussi sera le plus petit descripteur de fichier non actuellement ouvert par le processus.
Par défaut, le nouveau descripteur de fichier est configuré pour rester ouvert après un appel à execve(2) (son attribut FD_CLOEXEC décrit dans fcntl(2) est initialement désactivé). L'attribut O_CLOEXEC décrit ci-dessous permet de modifier ce comportement par défaut. La position dans le fichier est définie au début du fichier (consultez lseek(2)).
Un appel à open() crée une nouvelle description de fichier ouvert, une entrée dans la table de fichiers ouverts du système. Cette entrée enregistre la position dans le fichier et les attributs d'état du fichier (modifiables par l'opération F_SETFL de fcntl(2)). Un descripteur de fichier est une référence à l'une de ces entrées ; cette référence n'est pas modifiée si pathname est ensuite supprimé ou modifié pour correspondre à un autre fichier. La nouvelle description de fichier ouvert n'est initialement partagée avec aucun autre processus, mais ce partage peut apparaître après un fork(2).
Le paramètre flags est l'un des éléments O_RDONLY, O_WRONLY ou O_RDWR qui réclament respectivement l'ouverture du fichier en lecture seule, écriture seule, ou lecture/écriture.
De plus, zéro ou plusieurs attributs de création de fichier et attributs d'état de fichier peuvent être indiqués dans flags avec un OU binaire. Les attributs de création de fichier sont O_CLOEXEC, O_CREAT, O_DIRECTORY, O_EXCL, O_NOCTTY, O_NOFOLLOW, O_TMPFILE, O_TRUNC et O_TTY_INIT. Les attributs d'état de fichier sont tous les autres attributs indiqués ci-dessous. La distinction entre ces deux groupes est que les attributs d'état de fichier peuvent être lus et (dans certains cas) modifiés ; consultez fcntl(2) pour plus de précisions.
La liste complète des attributs de création et d'état de fichier est la suivante.
Notez que le recours à cet attribut est indispensable pour certains programmes multithreadés. En effet, l'utilisation d'une opération fcntl(2) F_SETFD pour positionner l'attribut FD_CLOEXEC ne suffit pas à éviter une situation d'accès concurrents si un thread ouvre un descripteur de fichier et tente d'activer l'attribut « close-on-exec » au moyen de fcntl(2) au moment où un autre thread execute fork(2) suivi de execve(2). Selon l'ordre dans lequel ces opérations s'exécutent, cette concurrence peut aboutir à ce que le descripteur de fichier renvoyé par open() soit involontairement mis à disposition du programme exécuté par le processus fils créé par fork(2). (Ce type concurrence est en principe possible pour tout appel système qui crée un descripteur de fichier dont l'attribut « close-on-exec » est actif ; certains appels système de Linux offrent des équivalents de l'attribut O_CLOEXEC pour régler ce problème.)
Le paramètre mode indique les droits à utiliser si un nouveau fichier est créé. Ce paramètre doit être fourni quand O_CREAT ou O_TMPFILE sont indiqués dans flags ; si ni O_CREAT ni O_TMPFILE ne sont précisés, mode est ignoré. Les droits effectifs sont modifiées par le umask du processus : la véritable valeur utilisée est (mode & ~umask). Remarquez que ce mode ne s'applique qu'aux accès ultérieurs au fichier nouvellement créé. L'appel open() qui crée un fichier dont le mode est en lecture seule fournira quand même un descripteur de fichier en lecture et écriture.
Les constantes symboliques suivantes sont disponibles pour mode :
Une interface à la sémantique similaire (mais dépréciée) pour les périphériques blocs est décrite à la page raw(8).
Au moment où write(2) (ou un appel similaire) renvoie une donnée, elle a été transmise au matériel sur lequel s'exécute l'appel, avec toutes les métadonnées du fichier qui pourraient être nécessaires à la récupération de cette donnée (c'est à dire comme si chaque appel à write(2) était suivi d'un appel à fdatasync(2)). Consultez NOTES ci-dessous.
Lorsque ces deux attributs sont spécifiés, les liens symboliques ne sont pas suivis : si pathname est un lien symbolique, open() échouera quelque soit l'endroit où pointe le lien symbolique.
En général, le comportement de O_EXCL est indéterminé s'il est utilisé sans O_CREAT. Il existe une exception toutefois : à partir de Linux 2.6, O_EXCL peut être utilisé sans O_CREAT si pathname fait référence à un périphérique bloc. Si le périphérique bloc est utilisé par le système (par exemple, s'il est monté), open() échoue avec l'erreur EBUSY.
Sur les systèmes de fichiers NFS, O_EXCL n'est pris en charge qu'avec la version NFSv3 ou ultérieure, sur les noyaux 2.6 ou plus récents. Dans les environnements NFS où la prise en charge d'O_EXCL n'est pas fournie, les programmes qui ont besoin de cette fonctionnalité pour verrouiller des tâches risquent de rencontrer une concurrence critique (race condition). Les programmes portables qui veulent effectuer un verrouillage fichier atomique en utilisant un fichier verrou et qui doivent éviter la dépendance de la prise en charge NFS pour O_EXCL peuvent créer un fichier unique sur le même système de fichiers (par exemple, avec le PID et le nom de l'hôte), et utiliser link(2) pour créer un lien sur un fichier de verrouillage. Si link(2) renvoie 0, le verrouillage est réussi. Sinon, utiliser stat(2) sur ce fichier unique pour vérifier si le nombre de liens a augmenté jusqu'à 2, auquel cas le verrouillage est également réussi.pour vérifier si le nombre de liens a augmenté jusqu'à 2. Ne pas utiliser la valeur de retour de link(2).
Les opérations suivantes peuvent être réalisées sur le descripteur de fichier obtenu :
Si pathname est un lien symbolique et si l'attribut O_NOFOLLOW est précisé, alors l'appel renvoie le descripteur de fichier d'un lien symbolique. Ce descripteur de fichier peut être utilisé comme l'argument dirfd lors d'appels aux fonctions fchownat(2), fstatat(2), linkat(2) et readlinkat(2) avec un chemin d'accès vide pour permettre à l'appel de s'exécuter sur le lien symbolique.
Au moment où write(2) (ou un appel similaire) renvoie une donnée, cette donnée et les métadonnées associées au fichier ont été transmises au matériel sur lequel s'exécute l'appel (autrement dit, comme si chaque appel à write(2) était suivi d'un appel à fsync(2)). Consultez NOTES ci-dessous.
O_TMPFILE doit être indiqué avec soit O_RDWR, soit O_WRONLY, et facultativement O_EXCL. Si O_EXCL s’est pas indiqué, alors linkat(2) peut être utilisé pour lier le fichier temporaire dans le système de fichier, le rendant permanent, en utilisant du code comme :
char chemin[PATH_MAX];
df = open("/chemin/vers/rép.", O_TMPFILE | O_RDWR,
S_IRUSR | S_IWUSR);
/* Entrée et sortie du fichier sur « df »… */
snprintf(chemin, PATH_MAX, "/proc/self/fd/%d", df);
linkat(AT_FDCWD, chemin, AT_FDCWD, "/chemin/vers/fichier",
AT_SYMLINK_FOLLOW);
Dans ce cas, l’argument mode d’open() détermine le mode de droits du fichier, comme avec O_CREAT.
Indiquer O_EXCL en conjonction avec O_TMPFILE empêche de lier un fichier temporaire dans le système de fichiers comme précédemment (remarquez que la signification de O_EXCL dans ce cas est différente de la signification habituelle de O_EXCL).
Les deux principaux cas d’utilisation de O_TMPFILE sont présentés ci-dessous :
creat() est équivalent à open() avec l'attribut flags égal à O_CREAT | O_WRONLY | O_TRUNC.
L'appel système openat() fonctionne de la même façon que open(), les différences étant décrites ici.
Si le chemin donné dans pathname est relatif, il est interprété par rapport au répertoire auquel le descripteur de fichier dirfd fait référence (et non par rapport au répertoire courant du processus, comme pour open()).
Si pathname est un chemin relatif, et si dirfd a la valeur spéciale AT_FDCWD, alors pathname est interprété par rapport au répertoire courant du processus appelant, comme dans open().
Si pathname est un chemin absolu, dirfd est ignoré.
open(), openat() et creat() renvoient le nouveau descripteur de fichier s'ils réussissent, ou -1 s'ils échouent, auquel cas errno contient le code d'erreur.
open(), openat() et creat() peuvent échouer avec les erreurs suivantes :
Les erreurs supplémentaires suivantes peuvent également se produire pour openat() :
openat() a été ajouté au noyau Linux dans sa version 2.6.16 ; la glibc le gère depuis la version 2.4.
open(), creat() : SVr4, 4.3BSD, POSIX.1-2001, POSIX.1-2008.
openat() : POSIX.1-2008.
Les attributs O_DIRECT, O_NOATIME, O_PATH et O_TMPFILE sont spécifiques à Linux. _GNU_SOURCE doit être définie pour obtenir leurs définitions.
Les attributs O_CLOEXEC, O_DIRECTORY et O_NOFOLLOW ne sont pas spécifiés dans POSIX.1-2001, mais le sont dans POSIX.1-2008. Depuis glibc 2.12, leurs définitions peuvent être obtenues en définissant soit _POSIX_C_SOURCE avec une valeur supérieure ou égale à 200809L, soit _XOPEN_SOURCE avec une valeur supérieure ou égale à 700. Dans glibc 2.11 et les versions précédentes, les définitions peuvent être obtenues en définissant _GNU_SOURCE.
Comme indiqué dans feature_test_macros(7), les macros de test de fonctionnalités comme _POSIX_C_SOURCE, _XOPEN_SOURCE et _GNU_SOURCE doivent être définies avant d'inclure n’importe quel fichier d'en-tête.
Sous Linux, l'attribut O_NONBLOCK indique que l'on veut ouvrir mais pas nécessairement dans l'intention de lire ou d'écrire. Il est typiquement utilisé pour ouvrir des périphériques dans le but de récupérer un descripteur de fichier pour l'utiliser avec ioctl(2).
L'effet (indéfini) de O_RDONLY | O_TRUNC varie selon l'implémentation. Sur de nombreux systèmes, le fichier est effectivement tronqué.
Notez que open() peut ouvrir des fichiers spéciaux mais creat() ne peut pas en créer, il faut utiliser mknod(2) à la place.
Si un fichier est créé, ses horodatages st_atime, st_ctime, st_mtime (respectivement heure de dernier accès, de dernière modification d'état, et de dernière modification ; consultez stat(2)) sont définis à l'heure actuelle, ainsi que les champs st_ctime et st_mtime du répertoire parent. Sinon, si le fichier est modifié à cause de l'attribut O_TRUNC, ses champs st_ctime et st_mtime sont remplis avec l'heure actuelle.
L'option POSIX-1.2008 « E/S synchrones » décrit des variantes des E/S synchrones, ainsi que plusieurs attributs de open() permettant d'en contrôler le comportement : O_SYNC, O_DSYNC et O_RSYNC. Sans chercher à savoir si une implémentation accepte cette option, elle doit au moins prendre en charge l'utilisation de O_SYNC pour les fichiers normaux.
Linux met en oeuvre O_SYNC et O_DSYNC, mais pas O_RSYNC. (De façon plus ou moins correcte, glibc définit O_RSYNC de façon à avoir la même valeur que O_SYNC.)
O_SYNC fournit l'exécution d'E/S synchrones avec garantie d'intégrité des fichiers, ce qui signifie que les opérations d'écriture envoient les données et les métadonnées associées au matériel. O_DSYNC fournit l'exécution d'E/S synchrones avec garantie d'intégrité des données, ce qui signifie que les opérations d'écriture envoient les données et les métadonnées associées au matériel, mais en envoyant seulement les mises à jour des metadonnées qui permettent d'assurer le bon déroulement d'une opération de lecture ultérieure. L'exécution avec garantie d'intégrité des données peut réduire le nombre d'accès au disque demandés par une application qui ne nécessite pas l'exécution avec garantie d'intégrité des fichiers.
Pour comprendre la différence entre ces deux types d'exécution, imaginez deux extraits de metadonnées d'un fichier : l'horodatage de la dernière modification (st_mtime) et la longueur du fichier. Toutes les opérations d'écriture modifieront l'horodatage de la dernière modification, mais seules les écritures en fin de fichier modifieront la longueur. L'horodatage de dernière modification n'est pas nécessaire pour garantir une lecture correcte du fichier, contrairement à la longueur. Ainsi, O_DSYNC transmettrait seulement la métadonnée relative à la longueur du fichier (quand O_SYNC y ajouterait l'horodatage de dernière modification).
Avant Linux 2.6.33, Linux mettait seulement en oeuvre l'attribut O_SYNC de open(). Cependant, lorsque cet attribut était indiqué, la plupart des systèmes de fichiers fournissait des fonctionnalités équivalentes à l'exécution des E/S synchrones avec garantie de l'intégrité des données (autrement dit, O_SYNC était de fait mis en oeuvre comme O_DSYNC).
A partir de Linux 2.6.33, une véritable prise de charge de O_SYNC est fournie. Cependant, pour assurer la compatibilité ascendante binaire, O_DSYNC a été défini avec la même valeur que le O_SYNC « historique », et O_SYNC a été défini comme un nouvel attribut (de deux bits) qui comprend l'attribut O_DSYNC. Ceci permet d'assurer que les applications compilées avec les nouveaux en-têtes auront au moins la sémantique de O_DSYNC sur les noyaux antérieurs à 2.6.33.
Plusieurs problèmes se posent avec le protocole NFS, concernant entre autres O_SYNC, et O_NDELAY.
Sur les systèmes de fichiers NFS, où la correspondance d'UID est activée, open() peut renvoyer un descripteur de fichier alors qu'une requête read(2) par exemple sera refusée avec le code d'erreur EACCES. En effet, le client a effectué open() en vérifiant les autorisations d'accès, mais la correspondance d'UID est calculée par le serveur au moment des requêtes de lecture ou d'écriture.
Contrairement aux autres valeurs qui peuvent être indiquées dans flags, les valeurs du mode d'accès O_RDONLY, O_WRONLY et O_RDWR ne sont pas des bits individuels. Ils définissent l'ordre des deux bits de poids faible de flags, et ont pour valeur respective 0, 1 et 2. En d'autres termes, l'association O_RDONLY | O_WRONLY est une erreur logique et n'a certainement pas la même signification que O_RDWR.
Linux réserve le sens suivant au mode d'accès spécial et non-standard 3 (en binaire, 11) de l'attribut : vérification des droits en lecture et écriture du fichier, et renvoi d'un descripteur qui ne peut être utilisé ni en lecture, ni en écriture. Ce mode d'accès non-standard est utilisé par certains pilotes Linux afin de renvoyer un descripteur qui n'est destinée qu'à des opérations ioctl(2) propres aux périphériques.
openat() et les autres appels système similaires, ainsi que les fonctions de bibliothèques qui reçoivent pour argument un descripteur de fichier de répertoire (c'est-à-dire, faccessat(2), fanotify_mark(2), fchmodat(2), fchownat(2), fstatat(2), futimesat(2), linkat(2), mkdirat(2), mknodat(2), name_to_handle_at(2), readlinkat(2), renameat(2), symlinkat(2), unlinkat(2), utimensat(2), mkfifoat(3) et scandirat(3)) sont pris en charge pour deux raisons. L'explication est ici donnée dans le contexte de l'appel openat(), mais des arguments analogues sont valables pour les autres interfaces.
Tout d'abord, openat() permet à une application d'éviter les problèmes d'accès concurrents lors de l'utilisation de open() pour ouvrir des fichiers dans des répertoires autres que le répertoire courant. Ces problèmes sont dus au fait que l'un des composants du chemin donné à open() peut être modifié parallèlement à l'appel open(). De tels problèmes peuvent être évités en ouvrant un descripteur de fichier sur le répertoire cible, puis en fournissant ce descripteur comme argument dirfd de openat().
Enfin, openat() permet d'implémenter un « répertoire courant » par thread, grâce à des descripteurs de fichier maintenus par l'application. Cette fonctionnalité peut également être obtenue en jouant avec /proc/self/fd/dirfd, mais de façon moins efficace.
L'attribut O_DIRECT peut imposer, pour des raisons d'alignement, des restrictions sur la longueur et l'adresse des tampons de l'espace utilisateur et des déplacements dans les entrées-sorties de fichiers. Sous Linux, les restrictions d'alignement varient en fonction du système de fichiers et de la version du noyau, et il peut aussi ne pas y en avoir. Cependant, il n'y a pas actuellement d'interface indépendante du système de fichiers qui permette aux applications de découvrir ces restrictions pour un fichier ou système de fichiers donné. Certains systèmes de fichiers fournissent leur propre interface pour faire cela, comme par exemple l'opération XFS_IOC_DIOINFO de xfsctl(3).
Sous Linux 2.4, la taille des transferts, l'alignement du tampon et la position dans le fichier doivent être des multiples de la taille de blocs logiques du système de fichiers. Sous Linux 2.6, un alignement sur des multiples de 512 octets est suffisant.
Les E/S O_DIRECT ne devraient jamais être exécutées en même temps que l'appel système fork(2), si le tampon mémoire est une projection privée (c'est-à-dire n'importe quelle projection en mémoire créée avec l'attribut MAP_PRIVATE de mmap(2), y compris la mémoire allouée sur le tas et les tampons alloués de façon statique). Toutes ces E/S, qu'elles soient soumises par l'intermédiaire d'une interface d'E/S asynchrone ou depuis un autre thread du processus, devraient être achevées avant l'appel de fork(2). En cas d'échec, les conséquences pourraient être une corruption de mémoire ou un comportement imprévisible dans les processus père et fils. Cette restriction ne s'applique pas quand le tampon mémoire pour les E/S O_DIRECT a été créé en utilisant shmat(2) ou mmap(2) avec l'attribut MAP_SHARED. Cette restriction ne s'applique pas non plus quand le tampon mémoire a été configuré comme MADV_DONTFORK avec madvise(2), en s'assurant qu'il ne sera pas disponible au fils après fork(2).
L'attribut O_DIRECT a été introduit par SGI IRIX, qui a des restrictions d'alignement identiques à Linux 2.4. IRIX a aussi un appel fcntl(2) pour obtenir les alignements et tailles appropriés. FreeBSD 4.x a introduit un attribut du même nom, mais sans les restrictions d'alignement.
La gestion de O_DIRECT a été ajouté dans Linux 2.4.10. Les noyaux plus anciens ignorent simplement cet attribut. Certains système de fichiers peuvent ne pas supporter cet attribut et open() échouera avec l'erreur EINVAL s'il a été utilisé.
Les applications devraient éviter de mélanger des entrées-sorties O_DIRECT et normales pour le même fichier, en particulier sur des régions d'un même fichier qui se recouvrent. Même si le système de fichiers gère les problèmes de cohérence dans cette situation, le débit global d'entrées-sorties sera moindre que si un seul mode était utilisé. De la même façon, les applications devraient éviter de mélanger l'utilisation de mmap(2) et d'entrées-sorties directes pour les mêmes fichiers.
Le comportement de O_DIRECT avec NFS diffère des systèmes de fichiers locaux. Les anciens noyaux, ou les noyaux configurés d'une certaine façon, peuvent ne pas gérer cette combinaison. Le protocole NFS ne gère pas le passage de l'attribut au serveur, les entrées-sorties O_DIRECT ne font donc que le cache des pages du client ; le serveur pourra toujours utiliser un cache pour les entrées-sorties. Le client demande au serveur de rendre les entrées-sorties synchrones pour préserver la sémantique synchrone de O_DIRECT. Certains serveurs fonctionnent mal dans ces circonstances, tout particulièrement si les entrées-sorties sont de petite taille. Certains serveurs peuvent aussi être configurés pour mentir aux clients et indiquer que les entrées-sorties ont atteint un espace de stockage stable ; ceci évitera la perte de performance en augmentant les risques pour l'intégrité des données en cas de problème d'alimentation du serveur. Le client NFS Linux n'a pas de restriction d'alignement pour les entrées-sorties O_DIRECT.
En résumé, O_DIRECT est un outil potentiellement puissant qui doit être utilisé avec précaution. Les applications devraient utiliser O_DIRECT comme une option pour améliorer les performances, qui devrait être désactivée par défaut.
Actuellement, il n'est pas possible d'activer les entrées-sorties contrôlées par les signaux en indiquant O_ASYNC lors de l'appel open() ; il faut utiliser fcntl(2) pour activer cet attribut.
Deux codes d’erreur différents – EISDIR et ENOENT — doivent être vérifiés pour essayer de déterminer si le noyau prend en charge la fonctionnalité O_TMPFILE.
chmod(2), chown(2), close(2), dup(2), fcntl(2), link(2), lseek(2), mknod(2), mmap(2), mount(2), open_by_name_at(2), read(2), socket(2), stat(2), umask(2), unlink(2), write(2), fopen(3), fifo(7), path_resolution(7), symlink(7)
Cette page fait partie de la publication 3.65 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/.
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/>.
Christophe Blaess <http://www.blaess.fr/christophe/> (1996-2003), Alain Portal <http://manpagesfr.free.fr/> (2003-2006). Julien Cristau 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> ».