mescc: Mes C Library: Add closedir, opendir, readdir.
[mes.git] / lib / dirent / opendir.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * GNU Mes --- Maxwell Equations of Software
3  * Copyright (C) 1991-1996,98,2000,2001 Free Software Foundation, Inc.
4  * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
5  *
6  * This file is part of GNU Mes.
7  *
8  * GNU Mes is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or (at
11  * your option) any later version.
12  *
13  * GNU Mes is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with GNU Mes.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 // Taken from GNU C Library 2.2.5
23
24 #include <errno.h>
25 #include <limits.h>
26 #include <stddef.h>
27 #include <stdlib.h>
28 #include <dirent.h>
29 #include <fcntl.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <stdio.h>
34
35 #include <dirstream.h>
36
37 /* Open a directory stream on NAME.  */
38 DIR *
39 opendir (char const *name)
40 {
41   DIR *dirp;
42   struct stat statbuf;
43   int fd;
44   size_t allocation;
45   int save_errno;
46
47   if (name[0] == '\0')
48     {
49       /* POSIX.1-1990 says an empty name gets ENOENT;
50          but `open' might like it fine.  */
51       errno = ENOENT;
52       return 0;
53     }
54
55   fd = open (name, O_RDONLY|O_DIRECTORY);
56   if (fd < 0)
57     return 0;
58
59   if (fstat (fd, &statbuf) < 0)
60     goto lose;
61
62   if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
63     goto lose;
64
65   allocation = statbuf.st_blksize;
66
67   dirp = (DIR *) calloc (1, sizeof (DIR) + allocation);
68   if (!dirp)
69   lose:
70     {
71       save_errno = errno;
72       close (fd);
73       errno = save_errno;
74       return 0;
75     }
76   dirp->data = (char *) (dirp + 1);
77   dirp->allocation = allocation;
78   dirp->fd = fd;
79
80   return dirp;
81 }