Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / libcc.ansi / misc / opendir.c
1 /*
2         opendir -- open a directory stream
3
4         last edit:      16-Jun-1987     D A Gwyn
5 */
6
7 #include        <errno.h>
8 #include        <stdlib.h>
9 #include        <sys/errno.h>
10 #include        <sys/types.h>
11 #include        <sys/stat.h>
12 #include        <dirent.h>
13
14 typedef void    *pointer;               /* (void *) if you have it */
15
16 extern int _open(const char *path, int flags, int mode);
17 extern int _close(int d);
18 extern int _fstat(int fd, struct stat *buf);
19
20 #ifndef NULL
21 #define NULL    0
22 #endif
23
24 #ifndef O_RDONLY
25 #define O_RDONLY        0
26 #endif
27
28 #ifndef S_ISDIR                         /* macro to test for directory file */
29 #define S_ISDIR( mode )         (((mode) & S_IFMT) == S_IFDIR)
30 #endif
31
32 DIR *
33 opendir(const char *dirname)            /* name of directory */
34 {
35         register DIR    *dirp;          /* -> malloc'ed storage */
36         register int    fd;             /* file descriptor for read */
37         struct stat     sbuf;           /* result of fstat() */
38
39         if ( (fd = _open( dirname, O_RDONLY, 0 )) < 0 )
40                 return NULL;            /* errno set by open() */
41
42         if ( _fstat( fd, &sbuf ) != 0 || !S_ISDIR( sbuf.st_mode ) )
43                 {
44                 (void)_close( fd );
45                 errno = ENOTDIR;
46                 return NULL;            /* not a directory */
47                 }
48
49         if ( (dirp = (DIR *)malloc( sizeof(DIR) )) == NULL
50           || (dirp->dd_buf = (char *)malloc( (unsigned)DIRBUF )) == NULL
51            )    {
52                 register int    serrno = errno;
53                                         /* errno set to ENOMEM by sbrk() */
54
55                 if ( dirp != NULL )
56                         free( (pointer)dirp );
57
58                 (void)_close( fd );
59                 errno = serrno;
60                 return NULL;            /* not enough memory */
61                 }
62
63         dirp->dd_fd = fd;
64         dirp->dd_loc = dirp->dd_size = 0;       /* refill needed */
65
66         return dirp;
67 }