Home | History | Annotate | Line # | Download | only in import
      1 /* dirfd.c -- return the file descriptor associated with an open DIR*
      2 
      3    Copyright (C) 2001, 2006, 2008-2022 Free Software Foundation, Inc.
      4 
      5    This file is free software: you can redistribute it and/or modify
      6    it under the terms of the GNU Lesser General Public License as
      7    published by the Free Software Foundation; either version 2.1 of the
      8    License, or (at your option) any later version.
      9 
     10    This file is distributed in the hope that it will be useful,
     11    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU Lesser General Public License for more details.
     14 
     15    You should have received a copy of the GNU Lesser General Public License
     16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
     17 
     18 /* Written by Jim Meyering. */
     19 
     20 #include <config.h>
     21 
     22 #include <dirent.h>
     23 #include <errno.h>
     24 
     25 #ifdef __KLIBC__
     26 # include <stdlib.h>
     27 # include <io.h>
     28 
     29 static struct dirp_fd_list
     30 {
     31   DIR *dirp;
     32   int fd;
     33   struct dirp_fd_list *next;
     34 } *dirp_fd_start = NULL;
     35 
     36 /* Register fd associated with dirp to dirp_fd_list. */
     37 int
     38 _gl_register_dirp_fd (int fd, DIR *dirp)
     39 {
     40   struct dirp_fd_list *new_dirp_fd = malloc (sizeof *new_dirp_fd);
     41   if (!new_dirp_fd)
     42     return -1;
     43 
     44   new_dirp_fd->dirp = dirp;
     45   new_dirp_fd->fd = fd;
     46   new_dirp_fd->next = dirp_fd_start;
     47 
     48   dirp_fd_start = new_dirp_fd;
     49 
     50   return 0;
     51 }
     52 
     53 /* Unregister fd from dirp_fd_list with closing it */
     54 void
     55 _gl_unregister_dirp_fd (int fd)
     56 {
     57   struct dirp_fd_list *dirp_fd;
     58   struct dirp_fd_list *dirp_fd_prev;
     59 
     60   for (dirp_fd_prev = NULL, dirp_fd = dirp_fd_start; dirp_fd;
     61        dirp_fd_prev = dirp_fd, dirp_fd = dirp_fd->next)
     62     {
     63       if (dirp_fd->fd == fd)
     64         {
     65           if (dirp_fd_prev)
     66             dirp_fd_prev->next = dirp_fd->next;
     67           else  /* dirp_fd == dirp_fd_start */
     68             dirp_fd_start = dirp_fd_start->next;
     69 
     70           close (fd);
     71           free (dirp_fd);
     72           break;
     73         }
     74     }
     75 }
     76 #endif
     77 
     78 int
     79 dirfd (DIR *dir_p)
     80 {
     81   int fd = DIR_TO_FD (dir_p);
     82   if (fd == -1)
     83 #ifndef __KLIBC__
     84     errno = ENOTSUP;
     85 #else
     86     {
     87       struct dirp_fd_list *dirp_fd;
     88 
     89       for (dirp_fd = dirp_fd_start; dirp_fd; dirp_fd = dirp_fd->next)
     90         if (dirp_fd->dirp == dir_p)
     91           return dirp_fd->fd;
     92 
     93       errno = EINVAL;
     94     }
     95 #endif
     96 
     97   return fd;
     98 }
     99