get the prototype right for yyparse, it returns an int
[heimdal.git] / lib / roken / dirent.c
blobdf4c270a6f7344d12ed8053de0a8a469afe9a0a0
1 /***********************************************************************
2 * Copyright (c) 2009, Secure Endpoints Inc.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 **********************************************************************/
32 #include<config.h>
34 #include <stdlib.h>
35 #include <io.h>
36 #include <string.h>
37 #include <errno.h>
38 #include "dirent.h"
40 #ifndef _WIN32
41 #error Only implemented for Win32
42 #endif
44 struct _dirent_dirinfo {
45 int magic;
46 long n_entries;
47 long nc_entries;
48 long cursor;
49 struct dirent **entries;
51 #define DIRINFO_MAGIC 0xf8c0639d
52 #define IS_DP(p) ((p) && ((DIR *)(p))->magic == DIRINFO_MAGIC)
54 #define INITIAL_ENTRIES 16
56 /**
57 * Create a filespec for use with _findfirst() using a path spec
59 * If the last component of the path spec contains wildcards, we let
60 * it be. If the last component doesn't end with a slash, we add one.
62 static const char *
63 filespec_from_dir_path(const char * path, char * buffer, size_t cch_buffer)
65 char *comp, *t;
66 size_t pos;
67 int found_sep = 0;
69 if (strcpy_s(buffer, cch_buffer, path) != 0)
70 return NULL;
72 comp = strrchr(buffer, '\\');
73 if (comp == NULL)
74 comp = buffer;
75 else
76 found_sep = 1;
78 t = strrchr(comp, '/');
79 if (t != NULL) {
80 comp = t;
81 found_sep = 1;
84 if (found_sep)
85 comp++;
87 pos = strcspn(comp, "*?");
88 if (comp[pos] != '\0')
89 return buffer;
91 /* We don't append a slash if pos == 0 because that changes the
92 * meaning:
94 * "*.*" is all files in the current directory.
95 * "\*.*" is all files in the root directory of the current drive.
97 if (pos > 0 && comp[pos - 1] != '\\' &&
98 comp[pos - 1] != '/') {
99 strcat_s(comp, cch_buffer - (comp - buffer), "\\");
102 strcat_s(comp, cch_buffer - (comp - buffer), "*.*");
104 return buffer;
107 ROKEN_LIB_FUNCTION DIR * ROKEN_LIB_CALL
108 opendir(const char * path)
110 DIR * dp;
111 struct _finddata_t fd;
112 intptr_t fd_handle;
113 const char *filespec;
114 char path_buffer[1024];
116 memset(&fd, 0, sizeof(fd));
118 filespec = filespec_from_dir_path(path, path_buffer, sizeof(path_buffer)/sizeof(char));
119 if (filespec == NULL)
120 return NULL;
122 fd_handle = _findfirst(filespec, &fd);
124 if (fd_handle == -1)
125 return NULL;
127 dp = malloc(sizeof(*dp));
128 if (dp == NULL)
129 goto done;
131 memset(dp, 0, sizeof(*dp));
132 dp->magic = DIRINFO_MAGIC;
133 dp->cursor = 0;
134 dp->n_entries = 0;
135 dp->nc_entries = INITIAL_ENTRIES;
136 dp->entries = calloc(dp->nc_entries, sizeof(dp->entries[0]));
138 if (dp->entries == NULL) {
139 closedir(dp);
140 dp = NULL;
141 goto done;
144 do {
145 size_t len = strlen(fd.name);
146 struct dirent * e;
148 if (dp->n_entries == dp->nc_entries) {
149 struct dirent ** ne;
151 dp->nc_entries *= 2;
152 ne = realloc(dp->entries, sizeof(dp->entries[0]) * dp->nc_entries);
154 if (ne == NULL) {
155 closedir(dp);
156 dp = NULL;
157 goto done;
160 dp->entries = ne;
163 e = malloc(sizeof(*e) + len * sizeof(char));
164 if (e == NULL) {
165 closedir(dp);
166 dp = NULL;
167 goto done;
170 e->d_ino = 0; /* no inodes :( */
171 strcpy_s(e->d_name, len + 1, fd.name);
173 dp->entries[dp->n_entries++] = e;
175 } while (_findnext(fd_handle, &fd) == 0);
177 done:
178 if (fd_handle != -1)
179 _findclose(fd_handle);
181 return dp;
184 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
185 closedir(DIR * dp)
187 if (!IS_DP(dp))
188 return EINVAL;
190 if (dp->entries) {
191 long i;
193 for (i=0; i < dp->n_entries; i++) {
194 free(dp->entries[i]);
197 free(dp->entries);
200 free(dp);
202 return 0;
205 ROKEN_LIB_FUNCTION struct dirent * ROKEN_LIB_CALL
206 readdir(DIR * dp)
208 if (!IS_DP(dp) ||
209 dp->cursor < 0 ||
210 dp->cursor >= dp->n_entries)
212 return NULL;
214 return dp->entries[dp->cursor++];
217 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
218 rewinddir(DIR * dp)
220 if (IS_DP(dp))
221 dp->cursor = 0;
224 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
225 seekdir(DIR * dp, long offset)
227 if (IS_DP(dp) && offset >= 0 && offset < dp->n_entries)
228 dp->cursor = offset;
231 ROKEN_LIB_FUNCTION long ROKEN_LIB_CALL
232 telldir(DIR * dp)
234 return dp->cursor;