Provided by: manpages-fr-dev_4.26.0-1_all bug

NOM

       name_to_handle_at,  open_by_handle_at  -  Récupérer  le  gestionnaire d'un chemin et ouvrir le fichier au
       moyen d'un gestionnaire

BIBLIOTHÈQUE

       Bibliothèque C standard (libc, -lc)

SYNOPSIS

       #define _GNU_SOURCE         /* Consultez feature_test_macros(7) */
       #include <fcntl.h>

       int name_to_handle_at(int dirfd, const char *pathname,
                             struct file_handle *handle,
                             int *mount_id, int flags);
       int open_by_handle_at(int mount_fd, struct file_handle *handle,
                             int flags);

DESCRIPTION

       Les appels système name_to_handle_at() et open_by_handle_at() scindent la fonction de openat(2)  en  deux
       parties  :  name_to_handle_at()  renvoie  un  gestionnaire  opaque  qui correspond à un fichier indiqué ;
       open_by_handle_at() ouvre le fichier correspondant à un gestionnaire renvoyé par  un  appel  antérieur  à
       name_to_handle_at() et renvoie le descripteur d'un fichier ouvert.

   name_to_handle_at()
       L'appel  système  name_to_handle_at()  renvoie  un  gestionnaire  de fichier et un identifiant de montage
       (« mount ID ») correspondant au fichier désigné par les arguments dirfd et pathname. Le  gestionnaire  de
       fichier  est  renvoyé  au moyen de l'argument handle. Cet argument est un pointeur vers une structure qui
       présente la forme suivante :

           struct file_handle {
               unsigned int  handle_bytes;   /* taille de f_handle [in, out] */
               int           handle_type;    /* type du gestionnaire [out] */
               unsigned char f_handle[0];    /* identifiant du fichier (taille
                                                définie par l’appelant) [out] */
           };

       L'appelant à l'origine de l'appel doit s'assurer que la structure est créée avec  une  taille  suffisante
       pour  contenir  le  gestionnaire renvoyé dans f_handle. Avant l'appel, le champ handle_bytes devrait être
       initialisé de sorte que l'espace alloué puisse recevoir f_handle. (La  constante  MAX_HANDLE_SZ,  définie
       dans  <fcntl.h>,  précise  la  taille  maximale  autorisée  pour  un  gestionnaire  de fichier. La limite
       supérieure n'est pas garantie car de futurs systèmes de fichiers pourraient  avoir  besoin  de  davantage
       d'espace).  Lorsque  l'appel  réussit,  le  champ  handle_bytes est mis à jour afin de contenir le nombre
       d'octets effectivement écrits dans f_handle.

       L'appelant peut prendre connaissance de l'espace nécessaire à la structure file_handle en  effectuant  un
       appel  dans  lequel  handle->handle_bytes  vaut  zéro ; dans ce cas, l'appel échoue en renvoyant l'erreur
       EOVERFLOW et handle->handle_bytes prend pour valeur la taille requise ; l'appelant  peut  alors  utiliser
       cette  information pour allouer une structure ayant la taille convenable (consultez EXEMPLES ci-dessous).
       Il faut faire attention ici car EOVERFLOW peut indiquer qu'aucun gestionnaire de fichier n'est disponible
       pour ce nom particulier dans un système de fichiers qui prend  normalement  en  charge  la  recherche  de
       gestionnaire  de  fichiers.  Ce  cas  peut  se  détecter  quand  l'erreur EOVERFLOW est renvoyée sans que
       handle_bytes ne soit augmenté.

       Other than the use of the handle_bytes field, the caller should treat the  file_handle  structure  as  an
       opaque   data  type:  the  handle_type  and  f_handle  fields  can  be  used  in  a  subsequent  call  to
       open_by_handle_at(). The caller can also use the opaque file_handle to compare the identity of filesystem
       objects that were queried at different times and possibly at different paths. The fanotify(7)   subsystem
       can report events with an information record containing a file_handle to identify the filesystem object.

       L'argument  flags  est  un masque de bits construit par OU binaire entre zéro ou plus de AT_EMPTY_PATH et
       AT_SYMLINK_FOLLOW, décrits plus bas.

       When flags contain the AT_HANDLE_FID (since Linux 6.5)  flag, the  caller  indicates  that  the  returned
       file_handle is needed to identify the filesystem object, and not for opening the file later, so it should
       be expected that a subsequent call to open_by_handle_at()  with the returned file_handle may fail.

       Ensemble,  les  arguments  pathname  et  dirfd  désignent  le  fichier pour lequel on souhaite obtenir un
       gestionnaire. On distingue quatre cas :

       -  Si pathname est une chaîne non vide contenant un chemin d'accès  absolu,  alors  un  gestionnaire  est
          renvoyé pour le fichier indiqué par ce chemin. Dans ce cas, dirfd est ignoré.

       -  Si  pathname  est  une  chaîne  non vide contenant 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, et un
          gestionnaire est renvoyé pour le fichier indiqué par le chemin.

       -  Si pathname est une chaîne non vide contenant un chemin d'accès relatif et si dirfd est le descripteur
          de fichier d'un répertoire, alors pathname est interprété par rapport au répertoire désigné par dirfd,
          et un gestionnaire est renvoyé pour le fichier indiqué par le chemin.  (Consultez  openat(3)  si  vous
          souhaitez comprendre à quoi servent les « descripteurs de fichier de répertoires »).

       -  Si pathname est une chaîne vide, et si flags précise la valeur de AT_EMPTY_PATH, alors dirfd peut être
          un  descripteur  de  fichiers  ouvert faisant référence à n'importe quel type de fichier ou à AT_FDCWD
          (répertoire de travail courant), et un gestionnaire  est  renvoyé  pour  le  fichier  auquel  il  fait
          référence.

       L'argument  mount_id renvoie un identifiant pour le point de montage du système de fichiers correspondant
       à pathname. Cet identifiant correspond au premier champ des entrées de /proc/self/mountinfo.  L'ouverture
       du chemin indiqué dans le cinquième champ délivre un descripteur de fichier pour le point de montage ; ce
       descripteur de fichier peut être utilisé par la suite lors d'un appel à open_by_handle_at(). mount_id est
       renvoyé tant en cas de succès qu'en cas d'erreur EOVERFLOW de l'appel.

       Par  défaut,  name_to_handle_at()  ne  déréférence pas pathname s'il s'agit d'un lien symbolique, et donc
       renvoie un gestionnaire pour le lien lui-même. Si AT_SYMLINK_FOLLOW est précisé dans flags, pathname  est
       déréférencé  s'il s'agit d'un lien symbolique (de sorte que l'appel renvoie un indicateur pour le fichier
       vers lequel pointe le lien symbolique).

       name_to_handle_at() ne récupère pas un montage quand le composant final du chemin est un point de montage
       automatique. Quand un système de fichiers gère à la fois les gestionnaires de fichier et  les  points  de
       montage automatique, un appel name_to_handle_at() sur un point de montage automatique renverra une erreur
       EOVERFLOW  sans augmenter handle_bytes. Cela peut arriver depuis Linux 4.13 avec NFS lors d'un accès à un
       répertoire sur un système de fichiers séparé du serveur. Dans ce cas, le montage  automatique  peut  être
       provoqué en ajoutant un « / » à la fin du chemin.

   open_by_handle_at()
       L'appel  système  open_by_handle_at() ouvre le fichier auquel handle fait référence, via un indicateur de
       fichier renvoyé lors d'un précédent appel à name_to_handle_at().

       L'argument mount_fd est un descripteur de fichier pour n'importe quel type d'objet (fichier,  répertoire,
       etc.)  du  système de fichiers monté qui permet d'interpréter l'indicateur de fichier (handle). La valeur
       spéciale AT_FDCWD peut être précisée, et indique le répertoire courant du processus appelant.

       L'argument flags a la même fonction que pour open(2). Si l'indicateur handle fait  référence  à  un  lien
       symbolique,  le  processus  appelant  doit  préciser  l'attribut  O_PATH  et le lien symbolique n'est pas
       déréférencé. L'attribut O_NOFOLLOW est ignoré.

       L'appelant doit avoir la capacité CAP_DAC_READ_SEARCH pour utiliser open_by_handle_at().

VALEUR RENVOYÉE

       Lorsqu'il réussit, l'appel name_to_handle_at() renvoie 0 et open_by_handle_at() renvoie un descripteur de
       fichier (un entier non négatif).

       En cas d'échec, les deux appels renvoient -1 et définissent errno pour indiquer l'erreur.

ERREURS

       Les appels name_to_handle_at()  et  open_by_handle_at()  peuvent  échouer  pour  les  mêmes  raisons  que
       openat(2). En outre, ils peuvent également échouer pour les motifs décrits plus bas.

       name_to_handle_at() peut échouer avec les erreurs suivantes :

       EFAULT pathname, mount_id ou handle pointe en dehors de l'espace d'adressage accessible.

       EINVAL flags comprend un bit incorrect.

       EINVAL handle->handle_bytes est supérieur à MAX_HANDLE_SZ.

       ENOENT pathname est une chaîne vide et AT_EMPTY_PATH n’était pas indiqué dans flags.

       ENOTDIR
              Le  descripteur  de  fichiers  fourni  dans  dirfd ne fait pas référence à un répertoire, et il ne
              s'agit pas du cas où flags comprend AT_EMPTY_PATH et pathname est une chaîne vide.

       EOPNOTSUPP
              Le système de fichiers ne permet pas la transcription  du  chemin  de  fichier  en  indicateur  de
              fichier.

       EOVERFLOW
              La  valeur  handle->handle_bytes  transmise  dans l'appel est trop faible. Lorsque cette erreur se
              produit, handle->handle_bytes est modifié afin d'indiquer la taille requise pour cet indicateur.

       open_by_handle_at() peut échouer avec les erreurs suivantes :

       EBADF  mount_fd n'est pas un descripteur de fichier ouvert.

       EBADF  pathname est relatif mais dirfd n'est ni AT_FDWCD ni un descripteur de fichier valable.

       EFAULT handle pointe en dehors de l'espace d'adressage accessible.

       EINVAL handle->handle_bytes est supérieur à MAX_HANDLE_SZ ou égal à zéro.

       ELOOP  handle correspond à un lien symbolique et O_PATH n’était pas indiqué dans flags.

       EPERM  L'appelant n'a pas la capacité CAP_DAC_READ_SEARCH.

       ESTALE The specified handle is not valid for opening a file. This error will occur if, for  example,  the
              file  has  been  deleted.  This  error  can  also  occur  if  the  handle  was  acquired using the
              AT_HANDLE_FID flag and the filesystem does not support open_by_handle_at().

VERSIONS

       FreeBSD has a broadly similar pair of system calls in the form of getfh() and fhopen().

STANDARDS

       Linux.

HISTORIQUE

       Linux 2.6.39, glibc 2.14.

NOTES

       Un indicateur de fichier peut être créé dans un processus au moyen de name_to_handle_at() et utilisé plus
       tard dans un autre processus qui appelle open_by_handle_at().

       Certains systèmes de fichiers ne permettent pas la transcription des chemins en indicateurs  de  fichier,
       par exemple, /proc, /sys, ainsi que divers systèmes de fichiers en réseaux. Certains systèmes de fichiers
       permettent  la  transcription  des  chemins  en  indicateurs  de  fichier, mais ne prennent pas en charge
       l'utilisation de ces indicateurs de fichier dans open_by_handle_at().

       Un indicateur de fichier peut devenir non valable (« stale ») si un fichier est  supprimé,  ou  pour  une
       raison  propre  au système de fichiers. Les indicateurs non autorisés sont signalés par une erreur ESTALE
       provenant de open_by_handle_at().

       Ces appels systèmes sont conçus pour être utilisés par des serveurs de fichiers  en  espace  utilisateur.
       Par  exemple,  un  serveur  NFS  en espace utilisateur produit un indicateur de fichier et le transmet au
       client NFS. Plus tard, lorsque le client souhaite accéder au fichier, il peut  renvoyer  l'indicateur  au
       serveur.  Ce  type  de fonctionnalité permet à un serveur de fichiers en espace utilisateur d'opérer sans
       état vis à vis des fichiers qu'il délivre.

       Si pathname fait référence à un lien symbolique et si  flags  ne  précise  pas  AT_SYMLINK_FOLLOW,  alors
       name_to_handle_at()  renvoie  un  indicateur pour le lien (plutôt que pour le fichier vers lequel le lien
       pointe). Le processus  recevant  l'indicateur  peut  effectuer  plus  tard  une  opération  sur  ce  lien
       symbolique,  en  convertissant  l'indicateur  en  descripteur  de fichier au moyen de open_by_handle_at()
       utilisé avec l'argument O_PATH, et en passant le  descripteur  de  fichier  en  argument  dirfd  d’appels
       système (tels que readlinkat(2) et fchownat(2)).

   Obtenir un identifiant persistant de système de fichier
       Les  identifiants  de montage dans /proc/self/mountinfo peuvent être réutilisés même lorsque les systèmes
       de fichiers sont démontés et remontés. Ainsi, l'identifiant de montage  renvoyé  par  name_to_handle_at()
       (dans  *mount_id)  ne doit pas être considéré comme un identifiant persistant pour le système de fichiers
       considéré. Néanmoins, il  est  possible  pour  une  application  d'utiliser  l'information  fournie  dans
       mountinfo et correspondant à l'identifiant de montage pour en déduire un identifiant persistant.

       Par  exemple,  on  peut utiliser le nom de périphérique présent dans le cinquième champ de mountinfo pour
       retrouver l'UUID du périphérique correspondant au moyen des liens  symboliques  dans  /dev/disks/by-uuid.
       (Un moyen plus simple d'obtenir cet UUID consiste à utiliser la bibliothèque libblkid(3)). Cette façon de
       procéder  peut être inversée, en utilisant l'UUID pour retrouver le nom du périphérique, et ainsi obtenir
       le  point  de  montage  correspondant,   et   enfin   construire   l'argument   de   mount_fd   utile   à
       open_by_handle_at().

EXEMPLES

       Les  deux  programmes suivants illustrent l'utilisation de name_to_handle_at() et de open_by_handle_at().
       Le premier programme (t_name_to_handle_at.c) utilise name_to_handle_at() pour récupérer  l'indicateur  de
       fichier  et  l'identifiant  de  montage  du  fichier  indiqué  dans  les arguments en ligne de commande ;
       l'indicateur et l'identifiant de montage sont écrits sur la sortie standard.

       Le second programme (t_open_by_handle_at.c) lit un identifiant de montage et  un  indicateur  de  fichier
       depuis  l'entrée standard. Le programme utilise ensuite open_by_handle_at() pour lire le fichier au moyen
       de cet indicateur. Si un argument optionnel est fourni  dans  la  ligne  de  commande,  alors  l'argument
       mount_fd  de open_by_handle_at() est obtenu en ouvrant le répertoire précisé en argument. Sinon, mount_fd
       est obtenu en parcourant /proc/self/mountinfo à la recherche d'un identifiant de montage correspondant  à
       celui  fourni  via l'entrée standard, et le répertoire monté qui a été trouvé est ouvert. (Ces programmes
       ne tiennent pas compte du fait que les identifiants de montage ne sont pas persistants.)

       La session shell suivante montre des exemples d'utilisation de ces deux programmes :

           $ echo 'Can you please think about it?' > cecilia.txt
           $ ./t_name_to_handle_at cecilia.txt > fh
           $ ./t_open_by_handle_at < fh
           open_by_handle_at: Operation not permitted
           $ sudo ./t_open_by_handle_at < fh      # Nécessite CAP_SYS_ADMIN
           Read 31 bytes
           $ rm cecilia.txt

       A ce stade, on supprime et recrée (rapidement) le fichier, de sorte qu'il ait le même contenu et (avec un
       peu de chance) le même inœud. Cependant, open_by_handle_at() s'aperçoit que le  fichier  original  auquel
       l'indicateur fait référence n'existe plus.

           $ stat --printf="%i\n" cecilia.txt     # Display inode number
           4072121
           $ rm cecilia.txt
           $ echo 'Can you please think about it?' > cecilia.txt
           $ stat --printf="%i\n" cecilia.txt     # Check inode number
           4072121
           $ sudo ./t_open_by_handle_at < fh
           open_by_handle_at: Stale NFS file handle

   Source du programme : t_name_to_handle_at.c

       #define _GNU_SOURCE
       #include <err.h>
       #include <errno.h>
       #include <fcntl.h>
       #include <stdio.h>
       #include <stdlib.h>

       int
       main(int argc, char *argv[])
       {
           int                 mount_id, fhsize, flags, dirfd;
           char                *pathname;
           struct file_handle  *fhp;

           if (argc != 2) {
               fprintf(stderr, "Usage: %s pathname\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           pathname = argv[1];

           /* Allocate file_handle structure. */

           fhsize = sizeof(*fhp);
           fhp = malloc(fhsize);
           if (fhp == NULL)
               err(EXIT_FAILURE, "malloc");

           /* Make an initial call to name_to_handle_at() to discover
              the size required for file handle. */

           dirfd = AT_FDCWD;           /* For name_to_handle_at() calls */
           flags = 0;                  /* For name_to_handle_at() calls */
           fhp->handle_bytes = 0;
           if (name_to_handle_at(dirfd, pathname, fhp,
                                 &mount_id, flags) != -1
               || errno != EOVERFLOW)
           {
               fprintf(stderr, "Unexpected result from name_to_handle_at()\n");
               exit(EXIT_FAILURE);
           }

           /* Reallocate file_handle structure with correct size. */

           fhsize = sizeof(*fhp) + fhp->handle_bytes;
           fhp = realloc(fhp, fhsize);         /* Copies fhp->handle_bytes */
           if (fhp == NULL)
               err(EXIT_FAILURE, "realloc");

           /* Get file handle from pathname supplied on command line. */

           if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == -1)
               err(EXIT_FAILURE, "name_to_handle_at");

           /* Write mount ID, file handle size, and file handle to stdout,
              for later reuse by t_open_by_handle_at.c. */

           printf("%d\n", mount_id);
           printf("%u %d   ", fhp->handle_bytes, fhp->handle_type);
           for (size_t j = 0; j < fhp->handle_bytes; j++)
               printf(" %02x", fhp->f_handle[j]);
           printf("\n");

           exit(EXIT_SUCCESS);
       }

   Source du programme : t_open_by_handle_at.c

       #define _GNU_SOURCE
       #include <err.h>
       #include <fcntl.h>
       #include <limits.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/types.h>
       #include <unistd.h>

       /* Scan /proc/self/mountinfo to find the line whose mount ID matches
          'mount_id'. (An easier way to do this is to install and use the
          'libmount' library provided by the 'util-linux' project.)
          Open the corresponding mount path and return the resulting file
          descriptor. */

       static int
       open_mount_path_by_id(int mount_id)
       {
           int      mi_mount_id, found;
           char     mount_path[PATH_MAX];
           char     *linep;
           FILE     *fp;
           size_t   lsize;
           ssize_t  nread;

           fp = fopen("/proc/self/mountinfo", "r");
           if (fp == NULL)
               err(EXIT_FAILURE, "fopen");

           found = 0;
           linep = NULL;
           while (!found) {
               nread = getline(&linep, &lsize, fp);
               if (nread == -1)
                   break;

               nread = sscanf(linep, "%d %*d %*s %*s %s",
                              &mi_mount_id, mount_path);
               if (nread != 2) {
                   fprintf(stderr, "Bad sscanf()\n");
                   exit(EXIT_FAILURE);
               }

               if (mi_mount_id == mount_id)
                   found = 1;
           }
           free(linep);

           fclose(fp);

           if (!found) {
               fprintf(stderr, "Could not find mount point\n");
               exit(EXIT_FAILURE);
           }

           return open(mount_path, O_RDONLY);
       }

       int
       main(int argc, char *argv[])
       {
           int                 mount_id, fd, mount_fd, handle_bytes;
           char                buf[1000];
       #define LINE_SIZE 100
           char                line1[LINE_SIZE], line2[LINE_SIZE];
           char                *nextp;
           ssize_t             nread;
           struct file_handle  *fhp;

           if ((argc > 1 && strcmp(argv[1], "--help") == 0) || argc > 2) {
               fprintf(stderr, "Usage: %s [mount-path]\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           /* Standard input contains mount ID and file handle information:

                Line 1: <mount_id>
                Line 2: <handle_bytes> <handle_type>   <bytes of handle in hex>
           */

           if (fgets(line1, sizeof(line1), stdin) == NULL ||
               fgets(line2, sizeof(line2), stdin) == NULL)
           {
               fprintf(stderr, "Missing mount_id / file handle\n");
               exit(EXIT_FAILURE);
           }

           mount_id = atoi(line1);

           handle_bytes = strtoul(line2, &nextp, 0);

           /* Given handle_bytes, we can now allocate file_handle structure. */

           fhp = malloc(sizeof(*fhp) + handle_bytes);
           if (fhp == NULL)
               err(EXIT_FAILURE, "malloc");

           fhp->handle_bytes = handle_bytes;

           fhp->handle_type = strtoul(nextp, &nextp, 0);

           for (size_t j = 0; j < fhp->handle_bytes; j++)
               fhp->f_handle[j] = strtoul(nextp, &nextp, 16);

           /* Obtain file descriptor for mount point, either by opening
              the pathname specified on the command line, or by scanning
              /proc/self/mounts to find a mount that matches the 'mount_id'
              that we received from stdin. */

           if (argc > 1)
               mount_fd = open(argv[1], O_RDONLY);
           else
               mount_fd = open_mount_path_by_id(mount_id);

           if (mount_fd == -1)
               err(EXIT_FAILURE, "opening mount fd");

           /* Open file using handle and mount point. */

           fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
           if (fd == -1)
               err(EXIT_FAILURE, "open_by_handle_at");

           /* Try reading a few bytes from the file. */

           nread = read(fd, buf, sizeof(buf));
           if (nread == -1)
               err(EXIT_FAILURE, "read");

           printf("Read %zd bytes\n", nread);

           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

       open(2), libblkid(3), blkid(8), findfs(8), mount(8)

       La  documentation  relative  à  libblkid  et  à  libmount  de  la  dernière  publication  de util-linux à
       https://www.kernel.org/pub/linux/utils/util-linux/

TRADUCTION

       La  traduction  française   de   cette   page   de   manuel   a   été   créée   par   Christophe   Blaess
       <https://www.blaess.fr/christophe/>,   Stéphan   Rafin   <stephan.rafin@laposte.net>,   Thierry   Vignaud
       <tvignaud@mandriva.com>, François Micaux, Alain Portal  <aportal@univ-montp2.fr>,  Jean-Philippe  Guérard
       <fevrier@tigreraye.org>,   Jean-Luc   Coulon   (f5ibh)   <jean-luc.coulon@wanadoo.fr>,   Julien   Cristau
       <jcristau@debian.org>,     Thomas     Huriaux      <thomas.huriaux@gmail.com>,      Nicolas      François
       <nicolas.francois@centraliens.net>,     Florentin     Duneau    <fduneau@gmail.com>,    Simon    Paillard
       <simon.paillard@resel.enst-bretagne.fr>,    Denis    Barbier    <barbier@debian.org>,    David     Prévot
       <david@tilapin.org>,     Frédéric     Hantrais    <fhantrais@gmail.com>    et    Jean-Philippe    MENGUAL
       <jpmengual@debian.org>

       Cette traduction est une documentation libre ; veuillez vous  reporter  à  la  GNU General Public License
       version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si  vous  découvrez  un  bogue  dans la traduction de cette page de manuel, veuillez envoyer un message à
       debian-l10n-french@lists.debian.org.

Pages du manuel de Linux 6.9.1                    15 juin 2024                              open_by_handle_at(2)