1 /* Test opening a directory stream from a file descriptor.
2    Copyright (C) 2009-2021 Free Software Foundation, Inc.
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16 
17 /* Written by Eric Blake <ebb9@byu.net>, 2009.  */
18 
19 #include <config.h>
20 
21 #include <dirent.h>
22 
23 #include "signature.h"
24 SIGNATURE_CHECK (fdopendir, DIR *, (int));
25 
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 
30 #include "macros.h"
31 
32 int
main(_GL_UNUSED int argc,char * argv[])33 main (_GL_UNUSED int argc, char *argv[])
34 {
35   DIR *d;
36   int fd;
37 
38   /* A non-directory cannot be turned into a directory stream.  */
39   fd = open ("test-fdopendir.tmp", O_RDONLY | O_CREAT, 0600);
40   ASSERT (0 <= fd);
41   errno = 0;
42   ASSERT (fdopendir (fd) == NULL);
43   ASSERT (errno == ENOTDIR);
44   ASSERT (close (fd) == 0);
45   ASSERT (unlink ("test-fdopendir.tmp") == 0);
46 
47   /* A bad fd cannot be turned into a stream.  */
48   {
49     errno = 0;
50     ASSERT (fdopendir (-1) == NULL);
51     ASSERT (errno == EBADF);
52   }
53   {
54     close (99);
55     errno = 0;
56     ASSERT (fdopendir (99) == NULL);
57     ASSERT (errno == EBADF);
58   }
59 
60   /* This should work.  */
61   fd = open (".", O_RDONLY);
62   ASSERT (0 <= fd);
63   d = fdopendir (fd);
64   ASSERT (d);
65   /* fdopendir should not close fd.  */
66   ASSERT (dup2 (fd, fd) == fd);
67 
68   /* Don't test dirfd here.  dirfd (d) must return fd on current POSIX
69      platforms, but on pre-2008 platforms or on non-POSIX platforms
70      dirfd (fd) might return some other descriptor, or -1, and gnulib
71      does not work around this porting problem.  */
72 
73   ASSERT (closedir (d) == 0);
74   /* Now we can guarantee that fd must be closed.  */
75   errno = 0;
76   ASSERT (dup2 (fd, fd) == -1);
77   ASSERT (errno == EBADF);
78 
79   return 0;
80 }
81