fcntl(2) System Calls Manual fcntl(2) NOM fcntl - Manipuler un descripteur de fichier BIBLIOTHEQUE Bibliotheque C standard (libc, -lc) SYNOPSIS #include int fcntl(int fd, int cmd, ... /* arg */ ); DESCRIPTION fcntl() permet de se livrer a diverses operations sur le descripteur de fichier fd. L'operation en question est determinee par la valeur de l'argument cmd. fcntl() accepte un troisieme parametre optionnel. La necessite de fournir, ou pas, ce parametre depend de cmd. Le parametre doit etre du type indique entre parentheses apres chaque nom de commande cmd (dans la plupart des cas, le type requis est un int, et le parametre est identifie en utilisant le nom arg), ou void est indique si le parametre n'est pas necessaire. Certaines des operations suivantes ne sont prises en charge qu'a partir d'une version donnee du noyau Linux. La methode preferee pour verifier si le noyau hote prend en charge une certaine operation est d'invoquer fcntl() avec la valeur de cmd voulue et ensuite de tester si l'appel a echoue avec EINVAL, indiquant que le noyau ne reconnait pas cette valeur. Dupliquer un descripteur de fichier F_DUPFD (int) Dupliquer le descripteur de fichier fd en utilisant le plus petit numero de descripteur de fichier libre superieur ou egal a arg. Cela est different de dup2(2), qui utilise exactement le descripteur de fichier transmis. En cas de reussite, le nouveau descripteur de fichier est renvoye. Consultez dup(2) pour plus d'informations. F_DUPFD_CLOEXEC (int ; depuis Linux 2.6.24) Comme pour F_DUPFD, mais positionner en plus l'attribut << close-on-exec >> pour le descripteur de fichier duplique. Indiquer cet attribut permet a un programme d'eviter une operation F_SETFD de fcntl() supplementaire pour positionner l'attribut FD_CLOEXEC. Pour une explication sur ce en quoi cet attribut est utile, consultez la description de O_CLOEXEC dans open(2). Attributs du descripteur de fichier Les commandes suivantes manipulent les attributs associes a un descripteur de fichier. Actuellement, un seul attribut est defini : il s'agit de FD_CLOEXEC, l'attribut << close-on-exec >>. Si le bit FD_CLOEXEC est positionne, le descripteur de fichier sera automatiquement ferme lors d'un execve(2) reussi (si execve(2) echoue, le descripteur de fichier reste ouvert). Si le bit FD_CLOEXEC n'est pas positionne, le descripteur de fichier restera ouvert a la fin d'un execve(2). F_GETFD (void) Renvoyer (en tant que resultat de la fonction) les attributs du descripteur de fichier ; arg est ignore. F_SETFD (int) Positionner les attributs du descripteur de fichier avec la valeur precisee par arg. Dans un programme multithreade, l'utilisation simultanee dans un thread de fcntl() avec F_SETFD afin de definir l'attribut << close-on-exec >> (FD_CLOEXEC), et de fork(2) suivi de execve(2) dans un autre thread rend le programme vulnerable a une condition de concurrence pouvant provoquer la divulgation du descripteur de fichier dans le programme execute dans le processus enfant. Consultez les details de l'attribut O_CLOEXEC dans open(2) qui decrivent une solution a ce probleme. Attribut d'etat du fichier Un descripteur de fichier dispose de certains attributs d'etat, initialises par open(2) et eventuellement modifies par fcntl(). Les descripteurs de fichier dupliques (obtenus avec dup(2), fcntl(F_DUPFD), fork(2), etc.) concernent la meme description de fichier ouvert, et par consequent partagent les memes attributs d'etat de fichier. Les attributs et leurs semantiques sont decrits dans la page open(2). F_GETFL (void) Renvoyer (en tant que resultat de la fonction) les droits d'acces du fichier et les drapeaux d'etat du fichier ; arg est ignore. F_SETFL (int) Positionner les drapeaux d'etat du fichier a la valeur indiquee par arg. Les drapeaux des droits d'acces au fichier (O_RDONLY, O_WRONLY, O_RDWR) et les attributs de creation du fichier (O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) de arg sont ignores. Sous Linux, cette commande ne peut changer que les attributs O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME et O_NONBLOCK. Modifier les attributs O_DSYNC et O_SYNC est impossible, consultez BOGUES ci-dessous. Verrouillages d'enregistrements cooperatifs Linux implemente les verrouillages d'enregistrements UNIX traditionnels (<< associes au processus >>), tels que normalises par POSIX. Pour une alternative specifique a Linux avec de meilleures semantiques, consultez la discussion suivante sur les verrouillages de description de fichier ouvert. F_SETLK, F_SETLKW et F_GETLK servent a gerer les verrouillages d'enregistrements (d'intervalle d'octets, de segments de fichiers ou de zones de fichiers). Le troisieme argument, lock, est un pointeur sur une structure qui a au moins les champs suivants (dans un ordre non indique). struct flock { ... short l_type; /* Type de verrouillage : F_RDLCK, F_WRLCK, F_UNLCK */ short l_whence; /* Interpretation de l_start: SEEK_SET, SEEK_CUR, SEEK_END */ off_t l_start; /* Decalage de debut du verrouillage */ off_t l_len; /* Nombre d'octets du verrouillage */ pid_t l_pid; /* PID du processus bloquant notre verrou (mis par F_GETLK et F_OFD_GETLK seulement) */ ... }; Les champs l_whence, l_start et l_len de cette structure indiquent l'intervalle d'octets a verrouiller. Des octets apres la fin du fichier peuvent etre verrouilles, mais pas des octets avant le debut du fichier. l_start est la position de debut du verrou, et est interprete de facon relative : au debut du fichier (si l_whence vaut SEEK_SET) ; a la position actuelle dans le fichier (si l_whence vaut SEEK_CUR) ; a la fin du fichier (si l_whence vaut SEEK_END). Dans les deux derniers cas, l_start peut etre un nombre negatif, a partir du moment ou la position fournie ne pointe pas avant le debut du fichier. l_len indique le nombre d'octets a verrouiller. Si l_len est positif, alors l'intervalle a verrouiller couvre les octets a partir de l_start jusqu'a l_start+l_len-1 (inclus). Indiquer 0 dans l_len a une signification particuliere : cela verrouille tous les octets a partir de la position indiquee par l_whence et l_start jusqu'a la fin du fichier, quelle que soit la taille que prendra le fichier. POSIX.1-2001 permet (mais n'impose pas) a une implementation de prendre en charge des valeurs de l_len negatives ; si l_len est negatif, l'intervalle decrivant le verrou lock couvre les octets l_start+l_len jusqu'a l_start-1 inclus. Cela est gere par Linux 2.4.21 et Linux 2.5.49. Le champ l_type peut servir a placer un verrou en lecture (F_RDLCK) ou en ecriture (F_WRLCK) sur un fichier. Un nombre quelconque de processus peuvent tenir un verrou en lecture (partage), sur une zone d'un fichier, mais un seul peut avoir un verrou en ecriture (exclusif). Un verrou en ecriture exclut tous les autres verrous, aussi bien en lecture qu'en ecriture. Un processus donne ne peut tenir qu'un seul verrou sur une zone d'un fichier ; si un nouveau verrou est applique sur une zone deja verrouillee, alors le verrou precedent est converti suivant le nouveau type. Ces conversions pourraient entrainer le decoupage, la reduction ou l'extension du verrou existant si le nombre d'octets du nouveau verrou ne coincide pas exactement avec celui de l'ancien. F_SETLK (struct flock *) Acquerir (si l_type vaut F_RDLCK ou F_WRLCK) ou liberer (si l_type vaut F_UNLCK) le verrou sur les octets indiques par les champs l_whence, l_start, et l_len de lock. Si un conflit avec un verrou tenu par un autre processus existe, cet appel renvoie -1 et positionne errno aux valeurs EACCES ou EAGAIN (l'erreur renvoyee dans ce cas depend des implementations, donc POSIX impose aux applications portables de verifier les deux erreurs). F_SETLKW (struct flock *) Comme F_SETLK, mais attendre la liberation du verrou au lieu de renvoyer une erreur si un verrou en conflit est utilise sur le fichier. Si un signal est recu pendant l'attente, l'appel est interrompu et renverra immediatement (apres le retour du gestionnaire de signaux) la valeur -1. errno sera remplie avec la valeur EINTR ; consultez signal(7). F_GETLK (struct flock *) En entree dans cette routine, lock decrit un verrou que nous aimerions placer sur le fichier. Si le verrouillage est possible, fcntl() ne le fait pas, mais renvoie F_UNLCK dans le champ l_type de lock et laisse les autres champs de la structure inchanges. Si un ou plusieurs verrouillages incompatibles empechaient l'action, alors fcntl() renvoie des informations sur l'un de ces verrous dans les champs l_type, l_whence, l_start, et l_len de lock. Si le verrouillage en conflit est un verrouillage d'enregistrements UNIX traditionnels (<< associe au processus >>), alors le champ l_pid est defini avec le PID du processus detenant ce verrou. Si le verrouillage en conflit est un verrouillage de description de fichier ouvert, alors l_pid est defini a -1. Remarquez que les renseignements renvoyes pourraient deja etre perimes au moment ou l'appelant les inspecte. Pour pouvoir placer un verrou en lecture, fd doit etre ouvert au moins en lecture. Pour placer un verrou en ecriture, fd doit etre ouvert en ecriture. Pour placer les deux types de verrous, il faut une ouverture en lecture/ecriture. Lors du placement de verrous avec F_SETLKW, le noyau detecte les interblocages (deadlocks), au moyen desquels au moins deux processus ont leurs demandes de verrouillage reciproquement bloquees par des verrous detenus par d'autres processus. Par exemple, supposons qu'un processus A detient un verrou d'ecriture sur l'octet 100 d'un fichier et qu'un processus B detient un verrou d'ecriture sur l'octet 200. Si les deux processus tentent alors de verrouiller l'octet deja verrouille par l'autre processus en utilisant F_SETLKW, alors, sans detection d'interblocage, les deux processus resteront bloques indefiniment. Quand le noyau detecte ce type d'interblocages, il force l'une des demandes bloquantes de verrouillage a echouer immediatement avec l'erreur EDEADLK ; une application qui rencontre ce type d'erreur devrait liberer certains de ses verrous pour permettre a d'autres applications de continuer avant de tenter d'obtenir de nouveau les verrous dont elle a besoin. Les interblocages circulaires, impliquant plus de deux processus, sont egalement detectes. Remarquez, cependant, que l'algorithme de detection d'interblocages du noyau a ses limites, consultez BOGUES. Outre la suppression par un F_UNLCK explicite, les verrous sont automatiquement liberes lorsque le processus se termine. Les verrouillages d'enregistrements ne sont pas herites par les enfants lors d'un fork(2), mais sont conserves a la fin d'un execve(2). A cause des tampons geres par la bibliotheque stdio(3), l'utilisation des verrous d'enregistrements avec les routines de celle-ci est deconseillee. Utilisez plutot read(2) et write(2). Les verrouillages d'enregistrements decrits precedemment sont associes au processus (contrairement aux verrouillages de description de fichier ouvert decrits ci-dessous). Cela a quelques consequences malheureuses. - Si le processus ferme l'un des descripteurs se referant a un fichier, alors tous les verrous du processus sur ce fichier sont liberes, quels que soient le ou les descripteurs de fichier sur lesquels les verrous avaient ete obtenus. C'est dangereux : cela signifie qu'un processus peut perdre ses verrous sur un fichier comme /etc/passwd ou /etc/mtab si, pour une raison quelconque, une fonction de bibliotheque decide d'ouvrir, lire, puis refermer le meme fichier. - Les threads d'un processus partagent les verrous. Autrement dit, un programme multithreade ne pas pas utiliser de verrouillage d'enregistrement pour s'assurer que les threads ne vont pas acceder simultanement a la meme zone d'un fichier. Les verrouillages de description de fichier ouvert apportent une solution a ces deux problemes. Verrouillages de description de fichier ouvert (non POSIX) Les verrouillages de description de fichier ouvert sont des verrouillages d'intervalle d'octets cooperatifs dont le fonctionnement est identique en presque tout point aux verrouillages d'enregistrements traditionnels decrits precedemment. Ce type de verrouillage est specifique a Linux et disponible depuis la version 3.15. Pour une explication des descriptions de fichier ouvert, consultez open(2). La principale difference entre les deux types de verrouillage est que les verrouillages d'enregistrements traditionnels sont associes a un processus, alors que les verrouillages de description de fichier ouvert sont associes a la description de fichier ouvert sur laquelle ils sont obtenus, tout comme les verrous obtenus avec flock(2). Par consequent (et contrairement aux verrouillages d'enregistrements cooperatifs traditionnels), les verrouillages de description de fichier ouvert sont herites entre fork(2) (et clone(2) avec CLONE_FILES) et ne sont automatiquement liberes que lors de la derniere fermeture de la description de fichier ouvert, au lieu d'etre liberes lors de n'importe quelle fermeture du fichier. Les combinaisons de verrouillage de conflit (a savoir un verrouillage en lecture et en ecriture, ou deux verrouillages en ecriture), ou l'un est un verrouillage de description de fichier ouvert, et l'autre un verrouillage traditionnel d'enregistrement sont toujours en conflit meme lorsqu'ils sont acquis par le meme processus sur le meme descripteur de fichier. Les verrouillages de description de fichier ouvert places a l'aide de la meme description de fichier ouvert (c'est-a-dire a l'aide du meme descripteur de fichier ou a l'aide d'un descripteur de fichier duplique par fork(2), dup(2), fcntl(2) F_DUPFD, etc.) sont toujours compatibles : si un nouveau verrou est place sur une zone deja verrouillee, alors le verrou existant est converti suivant le nouveau (ces conversions pourraient avoir pour consequence le decoupage, la reduction ou l'extension du verrou existant comme evoque precedemment). En revanche, les verrouillages de description de fichier ouvert peuvent etre en conflit entre eux quand ils sont obtenus a l'aide de descriptions de fichier ouvert differentes. Ainsi, les threads dans un programme multithreade peuvent utiliser des verrouillages de description de fichier ouvert pour synchroniser l'acces a une zone de fichier si tous les threads realisent leur propre appel d'open(2) sur le fichier et utilisent les verrouillages a l'aide du descripteur de fichier qui en resulte. Comme avec les verrouillages cooperatifs traditionnels, le troisieme argument de fcntl(), lock, est un pointeur vers une structure flock. Contrairement aux verrouillages d'enregistrements traditionnels, le champ l_pid de cette structure doit etre mis a zero lors de l'utilisation des commandes decrites ci-dessous. Les commandes permettant d'interagir avec les verrouillages de description de fichier ouvert sont similaires a celles utilisees avec les verrouillages traditionnels. F_OFD_SETLK (struct flock *) Acquerir (si l_type vaut F_RDLCK ou F_WRLCK) ou liberer (si l_type vaut F_UNLCK) un verrou de description de fichier ouvert sur les octets indiques par les champs l_whence, l_start et l_len de lock. Si un conflit avec un verrou detenu par un autre processus existe, cet appel renvoie -1 et definit errno a EAGAIN. F_OFD_SETLKW (struct flock *) Comme F_OFD_SETLK, mais si un verrou en conflit existe sur le fichier attendre la liberation du verrou. Si un signal a intercepter est recu pendant l'attente, l'appel est interrompu et renverra immediatement (apres renvoi du gestionnaire de signaux) la valeur -1 et errno sera definie a EINTR ; consultez signal(7). F_OFD_GETLK (struct flock *) En entree dans cette routine, lock decrit un verrou de description de fichier ouvert que nous aimerions placer sur le fichier. Si le verrouillage est possible, fcntl() ne le fait pas, mais renvoie F_UNLCK dans le champ l_type de lock et laisse les autres champs de la structure inchanges. Si un ou plusieurs verrouillages incompatibles empechaient l'action, alors des informations sur l'un de ces verrous sont renvoyes a l'aide de lock, comme decrit precedemment pour F_GETLK. Dans l'implementation actuelle, aucune detection d'interblocage n'est realisee pour les verrouillages de description de fichier ouvert (contrairement aux verrouillages d'enregistrements associes au processus, pour lesquels le noyau realise une detection d'interblocage). Verrouillage imperatif Attention : l'implementation Linux du verrouillage obligatoire n'est pas fiable. Voir BOGUES ci-dessous. A cause de ces bogues et du fait que cette fonction soit vue comme peu utilisee, depuis Linux 4.5, le verrouillage obligatoire est devenu une fonction facultative geree par une option de configuration (CONFIG_MANDATORY_FILE_LOCKING). Cette fonctionnalite n'est plus prise en charge depuis Linux 5.15 et superieur. Par defaut, a la fois les verrouillages d'enregistrements traditionnels (associes au processus) et ceux de description de fichier ouvert sont cooperatifs. Les verrouillages cooperatifs ne sont pas imposes, donc ils ne fonctionnent qu'entre processus qui les utilisent. Les deux types de verrouillages peuvent aussi etre imperatifs. Les verrous imperatifs sont appliques a tous les processus. Si un processus tente d'effectuer un acces incompatible (par exemple read(2) ou write(2)) sur une zone d'un fichier qui a un verrou imperatif, le resultat depend de l'attribut O_NONBLOCK du descripteur de fichier. S'il n'est pas active, l'appel systeme est bloque jusqu'a ce que le verrou soit enleve ou converti en un mode compatible avec l'acces demande. Si l'attribut O_NONBLOCK est active, l'appel systeme echoue avec l'erreur EAGAIN. Pour utiliser des verrous imperatifs, ce type de verrouillage doit etre active sur le systeme de fichiers contenant le fichier a verrouiller (en utilisant l'option << -o mand >> de mount(8)), ou l'attribut MS_MANDLOCK de mount(2). Le verrouillage imperatif est active pour un fichier en desactivant la permission d'execution du groupe et en activant le bit de permission Set-GID (consultez chmod(1) et chmod(2)). Le verrouillage imperatif n'est pas defini par POSIX. Certains autres systemes permettent egalement d'utiliser le verrouillage imperatif, mais la facon de l'activer depend des systemes. Verrouillages perdus Quand un verrou d'observation est obtenu sur un systeme de fichiers en reseau comme NFS, il est possible que le verrou soit perdu. Cela peut arriver suite a une action d'administration sur le serveur ou a une partition du reseau (a savoir une perte de la connexion reseau avec le serveur) qui dure assez pour que le serveur pense que le client ne fonctionne plus. Quand un systeme de fichiers determine qu'un verrou est perdu, les futures requetes read(2) ou write(2) peuvent echouer avec l'erreur EIO. Cette erreur persistera jusqu'a la suppression du verrou ou la fermeture du descripteur de fichier. Depuis Linux 3.12, cela se produit au moins sur NFSv4 (y compris toutes les versions mineures). Certaines versions d'UNIX envoient un signal (SIGLOST) dans ce cas. Linux ne definit pas ce signal et il ne fournit pas de notification asynchrone de perte de verrous. Gestion des signaux F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG et F_SETSIG servent a gerer les signaux de disponibilite d'entree-sortie : F_GETOWN (void) Renvoyer (comme resultat de la fonction) le PID ou l'ID de processus qui recoit les signaux SIGIO et SIGURG pour les evenements concernant le descripteur de fichier fd. Les ID de processus sont renvoyes sous forme de valeurs positives ; les ID de groupe de processus sont renvoyes sous forme de valeurs negatives (mais consultez la section BOGUES ci-dessous). arg est ignore. F_SETOWN (int) Definir le PID ou l'identifiant de processus qui recevront les signaux SIGIO et SIGURG pour les evenements concernant le descripteur fd. L'ID de processus ou de groupe de processus cible est indique dans arg. L'ID d'un processus est indique sous forme d'une valeur positive ; l'ID d'un groupe de processus est formule en tant que valeur negative. En general, le processus appelant indique son propre PID comme argument (arg est donc getpid(2)). Outre la definition du proprietaire du descripteur de fichier, vous pourriez aussi activer la generation de signaux sur le descripteur de fichier. Cela se fait en utilisant la commande F_SETFL de fcntl() pour positionner le drapeau d'etat du fichier O_ASYNC sur le descripteur de fichier. Par consequent, un signal SIGIO est envoye des que l'entree ou la sortie sont possibles sur ce descripteur. La commande F_SETSIG de fcntl() peut etre utilisee pour recevoir un autre signal que SIGIO. L'envoi d'un signal au processus (ou groupe de processus) proprietaire indique par F_SETOWN est conditionne par les memes verifications de permissions que l'envoi d'un signal par kill(2), ou le processus envoyant le signal est celui qui utilise F_SETOWN (mais consultez la section BOGUES ci-dessous). Si cette verification echoue, le signal est ignore silencieusement. Note : l'operation F_SETOWN enregistre les droits de l'appelant utilises lors de l'appel fcntl() pour les verifications de permissions. Si le descripteur fd est un socket, F_SETOWN permet egalement la reception de signaux SIGURG lorsque des donnees hors-bande arrivent sur le socket. (SIGURG est emis dans toutes les situations ou l'appel select(2) aurait indique que le socket est dans une << situation exceptionnelle >>.) Le paragraphe ci-dessous etait pertinent Linux 2.6.x, jusqu'a Linux 2.6.11 inclus : Si une valeur non nulle est passee a F_SETSIG dans un processus multithreade utilisant une bibliotheque de threads gerant les groupes de threads (par exemple NPTL), une valeur positive passee a F_SETOWN a une signification differente : au lieu d'etre un PID identifiant tout un processus, il s'agit d'un identifiant de thread, referant a un thread specifique dans un processus. Par consequent, il peut etre necessaire de passer a F_SETOWN la valeur renvoyee par gettid(2) plutot que celle renvoyee par getpid(2) pour obtenir les resultats souhaites si F_SETSIG est utilise. (Dans les implementations actuelles des threads sous Linux, l'identifiant de thread (TID) du thread principal est son identifiant de processus. Cela signifie qu'un processus avec un seul thread peut utiliser indifferemment gettid(2) ou getpid(2).) Veuillez toutefois noter que les remarques de ce paragraphe ne s'appliquent pas au signal SIGURG genere lorsque des donnees hors-bande sont disponibles sur un socket : ce signal est toujours envoye soit a un processus, soit a un groupe de processus, selon la valeur donnee a F_SETOWN. Le comportement ci-dessus a ete supprime par accident dans Linux 2.6.12, et ne sera pas remis. A partir de Linux 2.6.32, utilisez F_SETOWN_EX pour envoyer les signaux SIGIO et SIGURG a un thread en particulier. F_GETOWN_EX (struct f_owner_ex *) (depuis Linux 2.6.32) Renvoyer les parametres du proprietaire du descripteur de fichier actuel, tels que definis par une utilisation anterieure de F_SETOWN_EX. L'information est renvoyee dans la structure pointee par arg, qui a la forme suivante : struct f_owner_ex { int type; pid_t pid; }; Le champ type aura l'une des valeurs F_OWNER_TID, F_OWNER_PID ou F_OWNER_PGRP. Le champ pid est un entier positif representant un identifiant de thread, de processus ou de groupe de processus. Consultez F_SETOWN_EX pour plus de details. F_SETOWN_EX (struct f_owner_ex *) (depuis Linux 2.6.32) Cette operation effectue une tache similaire a F_SETOWN. Elle autorise l'appelant a diriger les signaux de disponibilite d'entrees-sorties vers un thread, un processus ou un groupe de processus specifiques. L'appellant indique le destinataire des signaux avec arg, qui est un pointeur vers une structure f_owner_ex. Le champ type possede l'une des valeurs suivantes, qui definit comment pid est interprete : F_OWNER_TID Envoyer le signal au thread dont l'identifiant (la valeur renvoyee par un appel a clone(2) ou gettid(2)) est indique par pid. F_OWNER_PID Envoyer le signal au processus dont l'identifiant est indique par pid. F_OWNER_PGRP Envoyer le signal au groupe de processus dont l'identifiant est indique par pid. Notez que, a la difference de F_SETOWN, un identifiant de groupe de processus est indique ici avec une valeur positive. F_GETSIG (void) Renvoyer (comme resultat de la fonction) le numero du signal emis lorsque l'entree ou la sortie deviennent possibles. Une valeur nulle signifie l'emission de SIGIO. Toute autre valeur (y compris SIGIO) precise le signal emis, et des informations supplementaires seront disponibles pour le gestionnaire s'il est installe avec SA_SIGINFO. arg est ignore. F_SETSIG (int) Definir le signal a emettre lorsque l'entree ou la sortie deviennent possibles a la valeur fournie par arg. Une valeur nulle signifie l'emission de SIGIO. Toute autre valeur (y compris SIGIO) precise le signal a emettre, et des informations supplementaires seront disponibles pour le gestionnaire s'il est installe avec SA_SIGINFO. En utilisant F_SETSIG avec une valeur non nulle, et en configurant SA_SIGINFO pour le gestionnaire (consultez sigaction(2)), des informations supplementaires sur les evenements d'entrees-sorties sont fournies au gestionnaire a travers une structure siginfo_t. Si le champ si_code indique que la source est SI_SIGIO, le champ si_fd fournit le descripteur du fichier concerne par l'evenement. Sinon, il n'y a pas d'indication de descripteurs de fichier en attente, et il faut utiliser les mecanismes habituels (select(2), poll(2), read(2) avec O_NONBLOCK configure, etc.) pour determiner quels descripteurs de fichier sont disponibles pour les entrees-sorties. Remarquez que le descripteur de fichier fourni dans si_fd est celui indique lors de l'operation F_SETSIG. Cela peut provoquer un effet de bord inhabituel. Si le descripteur de fichier est duplique (dup(2) ou equivalent), et si le descripteur de fichier d'origine est ferme, alors des evenements E/S continueront a etre emis mais le champ si_fd contiendra le numero du descripteur de fichier a present ferme. En selectionnant un signal temps reel (valeur >= SIGRTMIN), de multiples evenements d'entrees-sorties peuvent etre memorises avec le meme numero (la memorisation depend de la memoire disponible). Des informations supplementaires sont disponibles, comme ci-dessus, si SA_SIGINFO est configure pour le gestionnaire. Notez que Linux impose une limite sur le nombre de signaux temps reel qui peuvent etre mis en attente pour un processus (consultez getrlimit(2) et signal(7)), et si cette limite est atteinte, le noyau change de comportement et envoie SIGIO, et ce signal est delivre au processus entier plutot qu'au thread specifique. En utilisant ces mecanismes, un programme peut implementer des entrees-sorties totalement asynchrones, la plupart du temps sans avoir besoin d'invoquer select(2) ou poll(2). L'utilisation de O_ASYNC est specifique a BSD et Linux. La seule utilisation de F_GETOWN et F_SETOWN specifiee dans POSIX.1 est en conjonction avec l'utilisation du signal SIGURG sur les sockets (POSIX ne specifie pas le signal SIGIO). F_GETOWN_EX, F_SETOWN_EX, F_GETSIG et F_SETSIG sont specifiques a Linux. POSIX dispose d'entrees-sorties asynchrones et de la structure aio_sigevent pour effectuer la meme chose. Cela est egalement disponible sous Linux dans la bibliotheque GNU C (glibc). Baux F_SETLEASE et F_GETLEASE (depuis Linux 2.4) servent respectivement a etablir un nouveau bail et a consulter le bail actuel sur le descripteur de fichier indique par fd. (NdT : je traduis << lease >> par << bail >>, faute de terme plus technique.) Le bail sur un fichier fournit un mecanisme par lequel un processus detenteur du bail est averti (par delivrance d'un signal) lorsqu'un autre processus (le << casseur de bail >>) essaie d'appeler open(2) ou truncate(2) sur le fichier vers lequel pointe ce descripteur de fichier. F_SETLEASE (int) Definir ou supprimer un bail de fichier en fonction de la valeur fournie dans l'entier arg : F_RDLCK Prendre un bail en lecture. Le processus appelant sera prevenu lorsqu'un autre processus ouvrira le fichier en ecriture ou le tronquera. Un bail en lecture ne peut etre place que sur un descripteur de fichier ouvert en lecture seule. F_WRLCK Prendre un bail en ecriture. Le processus appelant sera prevenu lorsqu'un autre processus ouvrira le fichier (en lecture ou ecriture) ou le tronquera. Un bail en ecriture ne peut etre pris sur le fichier que s'il n'y a aucun autre descripteur de fichier ouvert pour le fichier. F_UNLCK Supprimer le bail sur un fichier. Les baux sont associes a une description de fichier ouvert (consultez open(2)). Cela signifie que les descripteurs de fichier dupliques (crees par, par exemple, fork(2) ou dup(2)) font reference au meme bail, et que ce bail peut etre modifie ou resilie par n'importe lequel de ces descripteurs. De plus, le bail est resilie soit par une operation F_UNLCK explicite sur n'importe lequel de ces descripteurs dupliques, soit lorsque tous ces descripteurs ont ete fermes. Les baux ne peuvent etre pris que sur des fichiers normaux. Un processus non privilegie ne peut prendre un bail que sur un fichier dont l'UID (le proprietaire) correspond au FS-UID du processus. Un processus possedant la capacite CAP_LEASE peut prendre un bail sur n'importe quel fichier. F_GETLEASE (void) Indiquer le type de bail possede sur le descripteur de fichier fd en renvoyant F_RDLCK, F_WRLCK, ou F_UNLCK, signifiant respectivement que le processus appelant a un bail en lecture, ecriture, ou pas de bail sur le fichier. arg est ignore. Lorsqu'un processus (le << casseur de bail >>) appelle open(2) ou truncate(2) en conflit avec un bail etabli par F_SETLEASE, l'appel systeme est bloque par le noyau et le noyau avertit le processus tenant le bail par l'envoi d'un signal (SIGIO par defaut). Le tenant du bail doit repondre a ce signal en effectuant tout le nettoyage necessaire pour que le fichier soit accessible par un autre processus (par exemple en vidant des tampons internes) et en supprimant ou declassant son bail. Un bail est supprime en appelant la commande F_SETLEASE avec arg valant F_UNLCK. Si le tenant du bail possede un bail en ecriture sur le fichier et que le casseur de bail ouvre le fichier en lecture, il est suffisant que le tenant du bail declasse le bail en un bail en lecture. Cela est effectue en appelant la commande F_SETLEASE avec arg valant F_RDLCK. Si le detenteur du bail n'arrive pas a le declasser ou le supprimer avant le nombre de secondes indique dans /proc/sys/fs/lease-break-time alors le noyau supprimera ou declassera de force le bail du processus qui le detient. Des qu'un cassage de bail a ete commence, F_GETLEASE renvoie le type de bail cible (F_RDLCK ou F_UNLCK, en fonction de ce qui serait compatible avec le casseur de bail) jusqu'a ce que le detenteur du bail ne le declasse ou le supprime volontairement, ou que le noyau ne soit force a le faire apres expiration du delai de cassage de bail. Des que le bail a ete, de gre ou de force, resilie ou declasse et en supposant que le casseur de bail n'a pas debloque son appel systeme, le noyau permet a ce dernier de se derouler. Si l'appel a open(2) ou truncate(2) du casseur de bail est interrompu par un gestionnaire de signal, l'appel systeme echoue avec l'erreur EINTR, mais les autres etapes decrites ci-dessous se deroulent normalement. Si le casseur de bail est tue par un signal pendant que son appel systeme open(2) ou truncate(2) bloque, tout se deroule comme decrit ci-dessus. De meme, si le casseur de bail utilise l'option O_NONBLOCK de open(2), l'appel retourne immediatement avec l'erreur EWOULDBLOCK, mais les autres etapes se deroulent comme decrit ci-dessus. Le signal de notification par defaut pour le tenant du bail est SIGIO, mais on peut le modifier avec la commande F_SETSIG de la fonction fcntl(). Si une commande F_SETSIG est realisee (meme pour SIGIO), et si le gestionnaire de signal est installe avec SA_SIGINFO, alors il recevra une structure siginfo_t en second argument, et le champ si_fd contiendra le descripteur de fichier du bail ou il y a eu une tentative d'acces par un autre processus. (Cela sert si le processus tient des baux sur plusieurs fichiers.) Notification de modification de fichier et de repertoire (dnotify) F_NOTIFY (int) (Depuis Linux 2.4) Fournir un avertissement lorsque le repertoire correspondant a fd ou l'un des fichiers qu'il contient est modifie. Les evenements a notifier sont precises dans arg, sous forme de masque regroupant par un OU binaire zero, une ou plusieurs des constantes suivantes : DN_ACCESS Acces a un fichier (read(2), pread(2), readv(2) et similaires) DN_MODIFY Modification d'un fichier (write(2), pwrite(2), writev(2), truncate(2), ftruncate(2) et similaires). DN_CREATE Creation d'un fichier (open(2), creat(2), mknod(2), mkdir(2), link(2), symlink(2), rename(2) dans ce repertoire). DN_DELETE Suppression d'un fichier (unlink(2), rename(2) dans un autre repertoire, rmdir(2)). DN_RENAME Un fichier a ete renomme dans le meme repertoire (rename(2)). DN_ATTRIB Les attributs d'un fichier ont ete modifies (chown(2), chmod(2), utime(2), utimensat(2) et similaires). (Afin d'obtenir ces definitions, la macro _GNU_SOURCE doit etre definie avant d'inclure tout fichier d'en-tete). Les notifications de repertoire sont habituellement uniques, et l'application doit reenregistrer une demande pour les notifications ulterieures. Inversement, si DN_MULTISHOT est incluse dans arg, les notifications resteront en effet jusqu'a une demande explicite de suppression. Une serie de F_NOTIFY sont cumules, les evenements decrits dans arg etant ajoutes a l'ensemble des evenements deja surveilles. Pour supprimer les notifications de tous les evenements, il faut invoquer F_NOTIFY avec arg valant 0. La notification se produit par l'occurrence d'un signal. Le signal par defaut est SIGIO, mais on peut le changer avec la commande F_SETSIG de fcntl() (remarquez que SIGIO est un des signaux standards sans file d'attente ; basculer vers l'utilisation d'un signal temps reel signifie que plusieurs notifications peuvent etre mises en attente dans le processus). Dans ce cas, le gestionnaire de signal recoit une structure siginfo_t en second argument (si le gestionnaire a ete installe avec SA_SIGINFO) dont le champ si_fd contient le descripteur du fichier qui a declenche la notification (utile pour superviser plusieurs repertoires). En outre, avec DN_MULTISHOT, un signal temps reel devrait etre utilise pour la notification pour pouvoir empiler les notifications successives. Remarque : les nouvelles applications devraient utiliser l'interface inotify (disponible depuis Linux 2.6.13), qui fournit une bien meilleure interface pour obtenir des notifications d'evenements sur le systeme de fichiers. Consultez inotify(7). Changer la capacite d'un tube F_SETPIPE_SZ (int ; depuis Linux 2.6.35) Changer la capacite du tube reference par fd pour contenir au moins arg octets. Un processus non privilegie peut ajuster la capacite d'un tube a toute valeur comprise entre la taille de page du systeme et la limite definie dans /proc/sys/fs/pipe-max-size (consultez proc(5)). Les tentatives pour definir la capacite du tube en dessous de la taille de page sont silencieusement arrondies a la taille de page. Les tentatives d'un processus non privilegie pour definir la capacite du tube au dessus de /proc/sys/fs/pipe-max-size renvoie l'erreur EPERM ; un processus privilegie (CAP_SYS_RESOURCE) peut passer outre cette limite. Lors de l'affectation d'un tampon a un tube, le noyau peut utiliser une capacite superieure a arg, si c'est plus pratique pour l'implementation (dans l'implementation actuelle, l'affectation se fait sur le prochain multiple de la taille de la page superieur a la puissance de deux de la taille indiquee). La capacite actuelle (en octets) definie est renvoyee en tant que resultat de la fonction. Essayer de definir une capacite de tube plus petite que la taille de l'espace du tampon actuellement utilise pour stocker des donnees aboutit a l'erreur EBUSY. Remarquez qu'a cause de la maniere dont les pages du tampon du tube sont utilisees quand des donnees sont ecrites dans le tube, le nombre d'octets qui peuvent etre ecrits peut etre inferieur a la taille nominale, selon la taille des ecritures. F_GETPIPE_SZ (void ; depuis Linux 2.6.35) Renvoyer (comme resultat de la fonction) la capacite du tube reference par fd. Verrouillages de fichier Les verrous de fichier limitent le jeu d'operations autorisees sur un fichier donne. Pour chaque verrou positionne sur un fichier, un ensemble specifique d'operations echouera sur le fichier avec EPERM a partir de maintenant. Le fichier est dit verrouille (sealed). Le jeu de verrous depend du type de fichier et du systeme de fichiers sous-jacents. Pour un apercu du verrouillage de fichiers, un point sur ses objectifs et des exemples de code, voir memfd_create(2). Actuellement, les verrous de fichier ne peuvent etre appliques que sur un descripteur de fichier renvoye par memfd_create(2) (si MFD_ALLOW_SEALING est utilise). Sur d'autres systemes de fichiers, toutes les operations de fcntl() agissant sur les verrous renverront EINVAL. Les verrous constituent une propriete d'un inoeud. Ainsi, tous les descripteurs de fichier ouverts qui se rapportent au meme inoeud partagent le meme jeu de verrous. En outre, les verrous ne peuvent jamais etre supprimes mais uniquement ajoutes. F_ADD_SEALS (int ; depuis Linux 3.17) Ajouter les verrous donnes dans le parametre arg du masque de bit a l'ensemble de verrous de l'inoeud auquel se rapporte le descripteur de fichier fd. Les verrous ne peuvent pas etre supprimes de nouveau. Une fois que cet appel reussit, ils sont renforces immediatement par le noyau. Si le jeu de verrous actuel comprend F_SEAL_SEAL (voir ci-dessous), cet appel sera rejete avec EPERM. L'ajout d'un verrou deja defini n'est pas operationnel, si F_SEAL_SEAL n'est pas deja positionne. Pour positionner un verrou, le descripteur de fichier fd doit etre accessible en ecriture. F_GET_SEALS (void ; depuis Linux 3.17) Renvoyer (en tant que resultat de la fonction) le jeu de verrous actuel de l'inoeud auquel se rapporte fd. Si aucun verrou n'est positionne, 0 est renvoye. Si le fichier ne gere pas les verrous, -1 est renvoye et errno est positionne sur EINVAL. Les verrous suivants sont disponibles : F_SEAL_SEAL Si ce verrou est positionne, tout appel suivant a fcntl() avec F_ADD_SEALS echouera avec l'erreur EPERM. Ce verrou empeche donc toute modification du jeu de verrous lui-meme. Si le jeu de verrous initial du fichier comprend F_SEAL_SEAL, cela le rend en fait constant et verrouille. F_SEAL_SHRINK Si ce verrou est positionne, le fichier en question ne peut pas voir sa taille reduite. Cela concerne open(2) avec le drapeau O_TRUNC ainsi que truncate(2) et ftruncate(2). Ces appels echouent avec EPERM si vous essayez de reduire le fichier en question. Augmenter la taille reste possible. F_SEAL_GROW Si ce verrou est positionne, le fichier en question ne peut pas voir sa taille augmentee. Cela concerne write(2) apres la fin du fichier, truncate(2), ftruncate(2) et fallocate(2). Ces appels echoueront avec EPERM si vous les utilisez pour augmenter la taille du fichier. Si vous la laissez stable ou la reduisez, ces appels fonctionneront comme prevu. F_SEAL_WRITE Si ce verrou est positionne, vous ne pouvez pas modifier le contenu du fichier. Remarquez que la reduction ou l'augmentation de la taille du fichier restent possibles et autorisees. Ainsi, ce verrou s'utilise en principe avec un autre verrou. Il concerne write(2) et fallocate(2) (combine au drapeau FALLOC_FL_PUNCH_HOLE). Ces appels echoueront avec EPERM si ce verrou est positionne. De plus, les tentatives de creer de nouveaux tableaux de memoire (memory-mappings) accessibles en ecriture avec mmap(2) echoueront egalement avec EPERM. L'utilisation de l'operation F_ADD_SEALS pour definir le verrou F_SEAL_WRITE echoue avec EBUSY si un tableau partage accessible en ecriture existe. De tels tableaux doivent etre desassocies avant d'ajouter ce verrou. De plus, s'il existe des operations d'E/S asynchrones (io_submit(2)) en attente sur le fichier, toutes les ecritures posterieures seront ignorees. F_SEAL_FUTURE_WRITE (depuis Linux 5.1) L'effet de ce verrou est identique a F_SEAL_WRITE, mais le contenu du fichier peut encore etre modifie avec des tableaux partages accessibles en ecriture crees avant que le verrou ne soit positionne. Toute tentative de creer de nouveaux tableaux accessibles en ecriture sur le fichier avec mmap(2) echouera avec EPERM. De meme, une tentative d'ecriture dans le fichier avec write(2) echouera avec EPERM. En utilisant ce verrou, un processus peut creer un tampon de memoire qu'il peut continuer a modifier tout en le partageant sur une base de << lecture seule >> avec d'autres processus. Indications de lecture/ecriture de fichiers Les indications (hints) de duree d'ecriture peuvent etre utilisees pour informer le noyau de la duree relative prevue des ecritures sur un inoeud ou a l'aide d'une description de fichier ouvert en particulier (voir open(2) pour une explication sur les descriptions de fichier ouvert). Dans ce contexte, le terme << duree d'ecriture >> (write lifetime) signifie la duree prevue de vie des donnees sur le media avant d'etre remplacees ou ecrasees. Une application peut utiliser les differentes valeurs de reference indiquees ci-dessous pour separer les ecritures en differentes classes, pour que plusieurs utilisateurs ou applications fonctionnant sur un seul dorsal de stockage puissent agreger leurs motifs E/S de maniere coherente. Cependant, il n'existe pas de semantique fonctionnelle impliquee par ces attributs et plusieurs classes E/S peuvent utiliser les valeurs de reference de duree d'ecriture de maniere arbitraire, tant que celles-ci sont utilisees de maniere coherente. Les operations suivantes peuvent etre appliquees au descripteur de fichier, fd : F_GET_RW_HINT (uint64_t * ; depuis Linux 4.13) Renvoie la valeur de reference (<< hint >>) de lecture/ecriture associee a l'inoeud sous-jacent auquel renvoie fd. F_SET_RW_HINT (uint64_t * ; depuis Linux 4.13) Definit la valeur de reference de lecture/ecriture associee a l'inoeud sous-jacent auquel renvoie fd. Cette valeur de reference persiste soit jusqu'a etre explicitement modifiee, soit jusqu'a ce que le systeme de fichiers sous-jacent ne soit demonte. F_GET_FILE_RW_HINT (uint64_t * ; depuis Linux 4.13) Renvoie la valeur de reference << hint >> de lecture/ecriture associee a la description de fichier ouvert a laquelle renvoie fd. F_SET_FILE_RW_HINT (uint64_t * ; depuis Linux 4.13) Definit la valeur de reference de lecture/ecriture associee a la description de fichier ouvert a laquelle se rapporte fd. Si une description de fichier ouvert n'a pas de valeur de reference de lecture/ecriture assignee, elle devra utiliser la valeur affectee a l'inoeud s'il y en a une. Les valeurs de reference de lecture/ecriture suivantes sont applicables depuis Linux 4.13 : RWH_WRITE_LIFE_NOT_SET Aucune valeur de reference en particulier n'a ete definie. Il s'agit de la valeur par defaut. RWH_WRITE_LIFE_NONE Aucune duree de vie specifique a l'ecriture n'a ete associee a ce fichier ou a cet inoeud. RWH_WRITE_LIFE_SHORT Les donnees ecrites dans cet inoeud ou via cette description de fichier ouvert doivent avoir une duree de vie courte. RWH_WRITE_LIFE_MEDIUM Les donnees ecrites dans cet inoeud ou via cette description de fichier ouvert doivent avoir une duree de vie superieure a celle des donnees ecrites avec RWH_WRITE_LIFE_SHORT. RWH_WRITE_LIFE_LONG Les donnees ecrites dans cet inoeud ou via cette description de fichier ouvert doivent avoir une duree de vie superieure a celle des donnees ecrites avec RWH_WRITE_LIFE_MEDIUM. RWH_WRITE_LIFE_EXTREME Les donnees ecrites dans cet inoeud ou via cette description de fichier ouvert doivent avoir une duree de vie superieure a celle des donnees ecrites avec RWH_WRITE_LIFE_LONG. Toutes les valeurs de reference specifiques a l'ecriture sont relatives entre elles et aucun sens absolu individuel ne devrait leur etre attribue. VALEUR RENVOYEE Pour qu'un appel reussisse, le code de retour depend de l'operation : F_DUPFD Le nouveau descripteur de fichier. F_GETFD Valeur des attributs du descripteur de fichier. F_GETFL Valeur des attributs d'etat du fichier. F_GETLEASE Le type de bail tenu sur le descripteur de fichier. F_GETOWN Valeur du proprietaire du descripteur de fichier. F_GETSIG La valeur du signal envoye lorsque la lecture ou l'ecriture deviennent possibles, ou zero pour le comportement SIGIO traditionnel. F_GETPIPE_SZ F_SETPIPE_SZ La capacite du tube. F_GET_SEALS Un masque de bit identifiant les verrous positionnes sur le inoeud auquel renvoie fd. Toutes les autres commandes : Zero. En cas d'erreur, la valeur de retour est -1 et errno est definie pour preciser l'erreur. ERREURS EACCES ou EAGAIN L'operation est interdite en raison de verrous tenus par d'autres processus. EAGAIN L'operation est impossible a cause d'une projection en memoire effectuee par un autre processus. EBADF fd n'est pas un descripteur de fichier ouvert EBADF fd vaut F_SETLK ou F_SETLKW et les droits d'ouverture sur le descripteur de fichier ne correspondent pas au type de verrou demande. EBUSY cmd vaut F_SETPIPE_SZ et la capacite du nouveau tube indique dans arg est inferieure a la taille de l'espace du tampon actuellement utilise pour stocker les donnees dans le tube. EBUSY cmd vaut F_ADD_SEALS, arg inclut F_SEAL_WRITE et il existe un tableau partage accessible en ecriture sur le fichier auquel se rapporte fd. EDEADLK Le verrouillage F_SETLKW conduirait a un interblocage. EFAULT lock se trouve en dehors de l'espace d'adressage. EINTR cmd vaut F_SETLKW ou F_OFD_SETLKW et l'operation a ete interrompue par un signal ; voir signal(7). EINTR cmd vaut F_GETLK, F_SETLK, F_OFD_GETLK ou F_OFD_SETLK et l'operation a ete interrompue par un signal avant la verification ou l'acquisition du verrouillage. Generalement, quand on verrouille un fichier distant (comme un verrou sur NFS), mais cela peut aussi arriver localement. EINVAL La valeur indiquee dans cmd n'est pas reconnue par ce noyau. EINVAL cmd vaut F_ADD_SEALS et arg inclut un bit de verrou non reconnu. EINVAL cmd vaut F_ADD_SEALS ou F_GET_SEALS et le systeme de fichiers contenant l'inoeud auquel se rapporte fd ne prend pas en charge les verrous. EINVAL cmd vaut F_DUPFD et arg est negatif ou superieur a la valeur maximale permise (voir le point sur RLIMIT_NOFILE dans getrlimit(2)). EINVAL cmd vaut F_SETSIG et arg n'est pas un numero de signal autorise. EINVAL cmd est F_OFD_SETLK, F_OFD_SETLKW ou F_OFD_GETLK, et l_pid n'a pas ete defini comme nul. EMFILE cmd vaut F_DUPFD et la limite par processus du nombre de descripteurs de fichier ouverts a ete atteinte. ENOLCK Trop de verrous sont ouverts, ou la table des verrous est pleine, ou le verrouillage distant (par exemple par NFS) a echoue. ENOTDIR F_NOTIFY a ete indique dans cmd, mais fd ne fait pas reference a un repertoire. EPERM cmd vaut F_SETPIPE_SZ et la limite rigide ou souple du tube de l'utilisateur a ete atteinte ; voir pipe(7). EPERM Essai d'effacement de l'attribut O_APPEND sur un fichier, mais il est considere comme en-ajout-seulement. EPERM cmd valait F_ADD_SEALS, mais fd n'etait pas ouvert en ecriture ou le jeu de verrous actuel sur le fichier inclut deja F_SEAL_SEAL. STANDARDS POSIX.1-2008. F_GETOWN_EX, F_SETOWN_EX, F_SETPIPE_SZ, F_GETPIPE_SZ, F_GETSIG, F_SETSIG, F_NOTIFY, F_GETLEASE et F_SETLEASE sont specifiques a Linux. (Definissez la macro _GNU_SOURCE pour avoir ces definitions). F_OFD_SETLK, F_OFD_SETLKW et F_OFD_GETLK sont specifiques a Linux (et il faut definir _GNU_SOURCE pour obtenir leurs definitions), mais le travail est en cours pour les avoir dans la prochaine version de POSIX.1. F_ADD_SEALS et F_GET_SEALS sont specifiques a Linux. HISTORIQUE SVr4, 4.3BSD, POSIX.1-2001. Seules les operations F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK et F_SETLKW sont specifiees dans POSIX.1-2001. F_GETOWN et F_SETOWN sont specifiees dans POSIX.1-2001 (pour activer ces definitions, vous devez definir soit _XOPEN_SOURCE a la valeur superieure ou egale a 500, soit _POSIX_C_SOURCE a la valeur superieure ou egale a 200809L). F_DUPFD_CLOEXEC est specifiee dans POSIX.1-2008 (pour activer cette definition, vous devez definir _POSIX_C_SOURCE avec une valeur superieure ou egale a 200809L, ou _XOPEN_SOURCE avec une valeur superieure ou egale a 700). NOTES Les erreurs renvoyees par dup2(2) ne sont pas les memes que celles renvoyees par F_DUPFD. Verrouillages de fichier L'appel systeme fcntl() originel de Linux n'a pas ete concu pour gerer les positions (dans la structure flock) dans des fichiers de tres grosse taille. En consequence, Linux 2.4 a ajoute l'appel systeme fcntl64(). Ce nouvel appel systeme utilise une structure differente de verrouillage de fichier, flock64, ainsi que les commandes correspondantes F_GETLK64, F_SETLK64 et F_SETLKW64. Cependant, ces details peuvent etre ignores par les applications qui utilisent la glibc, car sa fonction fcntl() encapsule de maniere transparente l'appel systeme le plus recent disponible. Verrouillages d'enregistrements Depuis Linux 2.0, il n'y a pas d'interaction entre les types de verrous places par flock(2) et fcntl(). Plusieurs systemes ont d'autres champs dans struct flock comme, par exemple, l_sysid (pour identifier la machine ou se trouve le verrou). Clairement, l_pid seul ne sera pas tres utile si le processus detenant le verrou s'execute sur une autre machine ; sur Linux, bien que ce champ soit present sur certaines architectures (comme MIPS32), ce champ n'est pas utilise. L'appel systeme fcntl() originel de Linux n'a pas ete concu pour gerer les positions (dans la structure flock) dans des fichiers de tres grosse taille. En consequence, Linux 2.4 a ajoute l'appel systeme fcntl64(). Ce nouvel appel systeme utilise une structure differente de verrouillage de fichier, flock64, ainsi que les commandes correspondantes F_GETLK64, F_SETLK64 et F_SETLKW64. Cependant, ces details peuvent etre ignores par les applications qui utilisent la glibc, car sa fonction fcntl() encapsule de maniere transparente l'appel systeme le plus recent disponible. Verrouillages d'enregistrements et NFS Avant Linux 3.12, si un client NFSv4 perd le contact avec le serveur pendant un certain temps (defini a plus de 90 secondes sans communication), il pourrait perdre puis obtenir un nouveau verrou sans meme en etre informe. (La periode au bout de laquelle le contact est assume perdu est connue sous le nom de periode de bail (<< leasetime >>) NFSv4. Sur un serveur NFS Linux, elle peut etre determinee en regardant /proc/fs/nfsd/nfsv4leasetime, qui exprime la periode en seconde. La valeur par defaut pour ce fichier est 90.) Ce scenario a pour risque potentiel la corruption de donnees, puisqu'un autre processus pourrait obtenir un verrou pendant la periode intermediaire et realiser des entrees et sorties de fichier. Depuis Linux 3.12, si un client NFSv4 perd le contact avec le serveur, toutes les entrees et sorties du fichier par un processus qui << pense >> detenir un verrou echoueront avant que le processus ne ferme et rouvre le fichier. Un parametre du noyau, nfs.recover_lost_locks, peut etre defini a 1 pour obtenir le comportement precedant (avant Linux 3.12), ou le client essayera de recuperer les verrous perdus quand le contact avec le serveur est retabli. A cause du risque associe de corruption de donnees, la valeur par defaut de ce parametre est 0 (desactive). BOGUES F_SETFL Il n'est pas possible d'utiliser F_SETFL pour modifier l'etat des attributs O_DSYNC et O_SYNC. Une tentative de modification de ces attributs sera simplement ignoree. F_GETOWN En raison d'une limitation des conventions d'appels systeme sur certaines architectures (en particulier i386), si F_GETOWN renvoie un identifiant de groupe de processus compris entre -1 et -4095, la valeur de retour est interpretee par glibc comme une erreur ; la valeur de retour de fcntl() sera -1 et errno contiendra l'identifiant du groupe de processus (positif). L'operation specifique a Linux F_SETOWN_EX evite ce probleme. Depuis la glibc 2.11, glibc rend le probleme avec F_GETOWN invisible en implementant F_GETOWN par-dessus F_GETOWN_EX. F_SETOWN Sous Linux 2.4 et precedents, lorsqu'un processus non privilegie utilise F_SETOWN pour indiquer le proprietaire d'un socket, avec un identifiant de (groupe de) processus autre que celui de l'appelant, un bogue peut survenir. Dans ce cas, fcntl() peut renvoyer -1, avec errno positionne a EPERM, meme si l'appelant a le droit d'envoyer un signal a ce (groupe de) processus. En depit de cette erreur, le proprietaire du descripteur de fichier est positionne, et les signaux seront envoyes au proprietaire. Detection d'interblocage L'algorithme de detection d'interblocage utilise par le noyau lors du traitement de demandes F_SETLKW peut produire a la fois des faux negatifs (echec de detection d'interblocages, laissant un ensemble de processus interbloques se bloquer indefiniment) et des faux positifs (erreurs EDEADLK alors qu'aucun interblocage n'existe). Par exemple, le noyau limite la profondeur de verrouillage lors de sa recherche de dependances a dix etapes, ce qui signifie que les chaines d'interblocages circulaires depassant cette taille ne seront pas detectees. De plus, le noyau pourrait faussement indiquer un interblocage lorsqu'au moins deux processus crees en utilisant l'attribut CLONE_FILES de clone(2) placent des verrous qui semblent (au noyau) en conflit. Verrouillage imperatif L'implementation Linux du verrouillage imperatif est sujette a des conditions de concurrence qui la rende non fiable : un appel a write(2) qui chevauche un verrou peut modifier les donnees apres que le verrouillage imperatif a ete acquis ; un appel a read(2) qui chevauche un verrou peut detecter des modifications sur des donnees qui ont ete faites seulement apres qu'un verrou en ecriture a ete acquis. Des conditions de concurrence similaires existent entre les verrous imperatifs et mmap(2). Il est donc deconseille de faire confiance au verrouillage imperatif. VOIR AUSSI dup2(2), flock(2), open(2), socket(2), lockf(3), capabilities(7), feature_test_macros(7), lslocks(8) locks.txt, mandatory-locking.txt et dnotify.txt dans le repertoire Documentation/filesystems/ des sources du noyau Linux. (Sur d'anciens noyaux, ces fichiers se trouvent dans le repertoire Documentation/ et mandatory-locking.txt est appele mandatory.txt.) 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 et Jean-Philippe MENGUAL 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 31 octobre 2023 fcntl(2)