dirfd.c 2.3 KB

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