1*09d4459fSDaniel Fojt /* Open a directory relative to another directory. 2*09d4459fSDaniel Fojt 3*09d4459fSDaniel Fojt Copyright 2006-2020 Free Software Foundation, Inc. 4*09d4459fSDaniel Fojt 5*09d4459fSDaniel Fojt This program is free software: you can redistribute it and/or modify 6*09d4459fSDaniel Fojt it under the terms of the GNU General Public License as published by 7*09d4459fSDaniel Fojt the Free Software Foundation; either version 3 of the License, or 8*09d4459fSDaniel Fojt (at your option) any later version. 9*09d4459fSDaniel Fojt 10*09d4459fSDaniel Fojt This program is distributed in the hope that it will be useful, 11*09d4459fSDaniel Fojt but WITHOUT ANY WARRANTY; without even the implied warranty of 12*09d4459fSDaniel Fojt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*09d4459fSDaniel Fojt GNU General Public License for more details. 14*09d4459fSDaniel Fojt 15*09d4459fSDaniel Fojt You should have received a copy of the GNU General Public License 16*09d4459fSDaniel Fojt along with this program. If not, see <https://www.gnu.org/licenses/>. 17*09d4459fSDaniel Fojt 18*09d4459fSDaniel Fojt Written by Jim Meyering and Paul Eggert. */ 19*09d4459fSDaniel Fojt 20*09d4459fSDaniel Fojt #include <config.h> 21*09d4459fSDaniel Fojt 22*09d4459fSDaniel Fojt #include <opendirat.h> 23*09d4459fSDaniel Fojt 24*09d4459fSDaniel Fojt #include <errno.h> 25*09d4459fSDaniel Fojt #include <fcntl--.h> 26*09d4459fSDaniel Fojt #include <unistd.h> 27*09d4459fSDaniel Fojt 28*09d4459fSDaniel Fojt /* Relative to DIR_FD, open the directory DIR, passing EXTRA_FLAGS to 29*09d4459fSDaniel Fojt the underlying openat call. On success, store into *PNEW_FD the 30*09d4459fSDaniel Fojt underlying file descriptor of the newly opened directory and return 31*09d4459fSDaniel Fojt the directory stream. On failure, return NULL and set errno. 32*09d4459fSDaniel Fojt 33*09d4459fSDaniel Fojt On success, *PNEW_FD is at least 3, so this is a "safer" function. */ 34*09d4459fSDaniel Fojt 35*09d4459fSDaniel Fojt DIR * 36*09d4459fSDaniel Fojt opendirat (int dir_fd, char const *dir, int extra_flags, int *pnew_fd) 37*09d4459fSDaniel Fojt { 38*09d4459fSDaniel Fojt int open_flags = (O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_NOCTTY 39*09d4459fSDaniel Fojt | O_NONBLOCK | extra_flags); 40*09d4459fSDaniel Fojt int new_fd = openat (dir_fd, dir, open_flags); 41*09d4459fSDaniel Fojt 42*09d4459fSDaniel Fojt if (new_fd < 0) 43*09d4459fSDaniel Fojt return NULL; 44*09d4459fSDaniel Fojt DIR *dirp = fdopendir (new_fd); 45*09d4459fSDaniel Fojt if (dirp) 46*09d4459fSDaniel Fojt *pnew_fd = new_fd; 47*09d4459fSDaniel Fojt else 48*09d4459fSDaniel Fojt { 49*09d4459fSDaniel Fojt int fdopendir_errno = errno; 50*09d4459fSDaniel Fojt close (new_fd); 51*09d4459fSDaniel Fojt errno = fdopendir_errno; 52*09d4459fSDaniel Fojt } 53*09d4459fSDaniel Fojt return dirp; 54*09d4459fSDaniel Fojt } 55