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 *
opendirat(int dir_fd,char const * dir,int extra_flags,int * pnew_fd)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