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
)
68 if (strcpy_s(buffer
, cch_buffer
, path
) != 0)
71 comp
= strrchr(buffer
, '\\');
75 t
= strrchr(comp
, '/');
81 pos
= strcspn(comp
, "*?");
82 if (comp
[pos
] != '\0')
85 /* We don't append a slash if pos == 0 because that changes the
88 * "*.*" is all files in the current directory.
89 * "\*.*" is all files in the root directory of the current drive.
91 if (pos
> 0 && comp
[pos
- 1] != '\\' &&
92 comp
[pos
- 1] != '/') {
93 strcat_s(comp
, cch_buffer
- (comp
- buffer
), "\\");
96 strcat_s(comp
, cch_buffer
- (comp
- buffer
), "*.*");
101 ROKEN_LIB_FUNCTION
DIR * ROKEN_LIB_CALL
102 opendir(const char * path
)
105 struct _finddata_t fd
;
107 const char *filespec
;
108 char path_buffer
[1024];
110 memset(&fd
, 0, sizeof(fd
));
112 filespec
= filespec_from_dir_path(path
, path_buffer
, sizeof(path_buffer
)/sizeof(char));
113 if (filespec
== NULL
)
116 fd_handle
= _findfirst(filespec
, &fd
);
121 dp
= malloc(sizeof(*dp
));
125 memset(dp
, 0, sizeof(*dp
));
126 dp
->magic
= DIRINFO_MAGIC
;
129 dp
->nc_entries
= INITIAL_ENTRIES
;
130 dp
->entries
= calloc(dp
->nc_entries
, sizeof(dp
->entries
[0]));
132 if (dp
->entries
== NULL
) {
139 size_t len
= strlen(fd
.name
);
142 if (dp
->n_entries
== dp
->nc_entries
) {
146 ne
= realloc(dp
->entries
, sizeof(dp
->entries
[0]) * dp
->nc_entries
);
157 e
= malloc(sizeof(*e
) + len
* sizeof(char));
164 e
->d_ino
= 0; /* no inodes :( */
165 strcpy_s(e
->d_name
, len
+ 1, fd
.name
);
167 dp
->entries
[dp
->n_entries
++] = e
;
169 } while (_findnext(fd_handle
, &fd
) == 0);
173 _findclose(fd_handle
);
178 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
187 for (i
=0; i
< dp
->n_entries
; i
++) {
188 free(dp
->entries
[i
]);
199 ROKEN_LIB_FUNCTION
struct dirent
* ROKEN_LIB_CALL
204 dp
->cursor
>= dp
->n_entries
)
208 return dp
->entries
[dp
->cursor
++];
211 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
218 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
219 seekdir(DIR * dp
, long offset
)
221 if (IS_DP(dp
) && offset
>= 0 && offset
< dp
->n_entries
)
225 ROKEN_LIB_FUNCTION
long ROKEN_LIB_CALL