1 /***********************************************************************
2 * Copyright (c) 2009, Secure Endpoints Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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 **********************************************************************/
41 #error Only implemented for Win32
44 struct _dirent_dirinfo
{
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
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.
63 filespec_from_dir_path(const char * path
, char * buffer
, size_t cch_buffer
)
69 if (strcpy_s(buffer
, cch_buffer
, path
) != 0)
72 comp
= strrchr(buffer
, '\\');
78 t
= strrchr(comp
, '/');
87 pos
= strcspn(comp
, "*?");
88 if (comp
[pos
] != '\0')
91 /* We don't append a slash if pos == 0 because that changes the
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
), "*.*");
107 ROKEN_LIB_FUNCTION
DIR * ROKEN_LIB_CALL
108 opendir(const char * path
)
111 struct _finddata_t fd
;
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
)
122 fd_handle
= _findfirst(filespec
, &fd
);
127 dp
= malloc(sizeof(*dp
));
131 memset(dp
, 0, sizeof(*dp
));
132 dp
->magic
= DIRINFO_MAGIC
;
135 dp
->nc_entries
= INITIAL_ENTRIES
;
136 dp
->entries
= calloc(dp
->nc_entries
, sizeof(dp
->entries
[0]));
138 if (dp
->entries
== NULL
) {
145 size_t len
= strlen(fd
.name
);
148 if (dp
->n_entries
== dp
->nc_entries
) {
152 ne
= realloc(dp
->entries
, sizeof(dp
->entries
[0]) * dp
->nc_entries
);
163 e
= malloc(sizeof(*e
) + len
* sizeof(char));
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);
179 _findclose(fd_handle
);
184 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
193 for (i
=0; i
< dp
->n_entries
; i
++) {
194 free(dp
->entries
[i
]);
205 ROKEN_LIB_FUNCTION
struct dirent
* ROKEN_LIB_CALL
210 dp
->cursor
>= dp
->n_entries
)
214 return dp
->entries
[dp
->cursor
++];
217 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
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
)
231 ROKEN_LIB_FUNCTION
long ROKEN_LIB_CALL