1 /* @(#)dirent.c 1.4 17/02/02 Copyright 2011-2017 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)dirent.c 1.4 17/02/02 Copyright 2011-2017 J. Schilling";
6 #endif
7 /*
8 * Copyright (c) 2011-2017 J. Schilling
9 */
10 /*
11 * The contents of this file are subject to the terms of the
12 * Common Development and Distribution License, Version 1.0 only
13 * (the "License"). You may not use this file except in compliance
14 * with the License.
15 *
16 * See the file CDDL.Schily.txt in this distribution for details.
17 * A copy of the CDDL is also available via the Internet at
18 * http://www.opensource.org/licenses/cddl1.txt
19 *
20 * When distributing Covered Code, include this CDDL HEADER in each
21 * file and include the License file CDDL.Schily.txt from this distribution.
22 */
23
24 #include <schily/dirent.h>
25 #include <schily/maxpath.h>
26 #include <schily/string.h>
27 #include <schily/errno.h>
28
29 #ifdef NEED_READDIR
30
31 #if defined(__MINGW32__) || defined(_MSC_VER)
32
33 #include <schily/windows.h>
34 #include <schily/utypes.h>
35 #include <schily/schily.h>
36
37 EXPORT DIR *opendir __PR((const char *));
38 EXPORT int closedir __PR((DIR *));
39 EXPORT struct dirent *readdir __PR((DIR *));
40
41 EXPORT DIR *
opendir(dname)42 opendir(dname)
43 const char *dname;
44 {
45 char path[PATH_MAX];
46 size_t len;
47 uint32_t attr;
48 DIR *dp;
49
50 if (dname == NULL) {
51 seterrno(EFAULT);
52 return ((DIR *)0);
53 }
54 len = strlen(dname);
55 if (len > PATH_MAX) {
56 seterrno(ENAMETOOLONG);
57 return ((DIR *)0);
58 }
59 if (len == 0) {
60 seterrno(ENOENT);
61 return ((DIR *)0);
62 }
63
64 attr = GetFileAttributes(dname);
65 if (attr == INVALID_FILE_ATTRIBUTES ||
66 (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
67 seterrno(ENOTDIR);
68 return ((DIR *)0);
69 }
70 path[0] = '\0';
71 _fullpath(path, dname, PATH_MAX);
72 len = strlen(path);
73 if (len == 0) {
74 seterrno(ENOENT);
75 return ((DIR *)0);
76 }
77
78 dp = malloc(sizeof (*dp) + len + 2); /* Add 2 for "/ *" */
79 if (dp == NULL) {
80 seterrno(ENOMEM);
81 return ((DIR *)0);
82 }
83 strcpy(dp->dd_dirname, path);
84 if (dp->dd_dirname[len-1] != '/' &&
85 dp->dd_dirname[len-1] != '\\') {
86 dp->dd_dirname[len] = '\\';
87 len++;
88 }
89 dp->dd_dirname[len++] = '*';
90 dp->dd_dirname[len] = '\0';
91 dp->dd_handle = -1;
92 dp->dd_state = 0;
93
94 dp->dd_dir.d_ino = 0;
95 dp->dd_dir.d_reclen = 0;
96 dp->dd_dir.d_namlen = 0;
97 zerobytes(dp->dd_dir.d_name, sizeof (dp->dd_dir.d_name));
98
99 return (dp);
100 }
101
102 EXPORT int
closedir(dp)103 closedir(dp)
104 DIR *dp;
105 {
106 int ret = 0;
107
108 if (dp == NULL) {
109 seterrno(EFAULT);
110 return (-1);
111 }
112 if (dp->dd_handle != -1) {
113 ret = _findclose(dp->dd_handle);
114 }
115 free(dp);
116
117 return (ret);
118 }
119
120 EXPORT struct dirent *
readdir(dp)121 readdir(dp)
122 DIR *dp;
123 {
124 if (dp == NULL) {
125 seterrno(EFAULT);
126 return ((struct dirent *)0);
127 }
128 if (dp->dd_state == (char)-1) {
129 return ((struct dirent *)0);
130 } else if (dp->dd_state == (char)0) {
131 dp->dd_handle = _findfirst(dp->dd_dirname, &(dp->dd_data));
132 if (dp->dd_handle != -1)
133 dp->dd_state = 1;
134 else
135 dp->dd_state = -1;
136 } else {
137 if (_findnext(dp->dd_handle, &(dp->dd_data))) {
138 uint32_t werrno = GetLastError();
139
140 if (werrno == ERROR_NO_MORE_FILES)
141 seterrno(0);
142 _findclose(dp->dd_handle);
143 dp->dd_handle = -1;
144 dp->dd_state = -1;
145 } else {
146 dp->dd_state = 1; /* state++ to support seekdir */
147 }
148 }
149 if (dp->dd_state > 0) {
150 strlcpy(dp->dd_dir.d_name, dp->dd_data.name,
151 sizeof (dp->dd_dir.d_name));
152
153 return (&dp->dd_dir);
154 }
155 return ((struct dirent *)0);
156 }
157
158 #endif /* defined(__MINGW32__) || defined(_MSC_VER) */
159
160 #endif /* NEED_READDIR */
161