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