/*********************************************************************** * Copyright (c) 2009, Secure Endpoints Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * **********************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "dirent.h" #ifndef _WIN32 #error Only implemented for Win32 #endif struct _dirent_dirinfo { int magic; long n_entries; long nc_entries; long cursor; struct dirent **entries; }; #define DIRINFO_MAGIC 0xf8c0639d #define IS_DP(p) ((p) && ((DIR *)(p))->magic == DIRINFO_MAGIC) #define INITIAL_ENTRIES 16 ROKEN_LIB_FUNCTION DIR * ROKEN_LIB_CALL opendir(const char * filespec) { DIR * dp; struct _finddata_t fd; intptr_t fd_handle; memset(&fd, 0, sizeof(fd)); fd_handle = _findfirst(filespec, &fd); if (fd_handle == -1) return NULL; dp = malloc(sizeof(*dp)); if (dp == NULL) goto done; memset(dp, 0, sizeof(*dp)); dp->magic = DIRINFO_MAGIC; dp->cursor = 0; dp->n_entries = 0; dp->nc_entries = INITIAL_ENTRIES; dp->entries = calloc(dp->nc_entries, sizeof(dp->entries[0])); if (dp->entries == NULL) { closedir(dp); dp = NULL; goto done; } do { long len = strlen(fd.name); struct dirent * e; if (dp->n_entries == dp->nc_entries) { struct dirent ** ne; dp->nc_entries *= 2; ne = realloc(dp->entries, sizeof(dp->entries[0]) * dp->nc_entries); if (ne == NULL) { closedir(dp); dp = NULL; goto done; } dp->entries = ne; } e = malloc(sizeof(*e) + len * sizeof(char)); if (e == NULL) { closedir(dp); dp = NULL; goto done; } e->d_ino = 0; /* no inodes :( */ strcpy_s(e->d_name, len + 1, fd.name); dp->entries[dp->n_entries++] = e; } while (_findnext(fd_handle, &fd) == 0); done: if (fd_handle != -1) _findclose(fd_handle); return dp; } ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL closedir(DIR * dp) { if (!IS_DP(dp)) return EINVAL; if (dp->entries) { long i; for (i=0; i < dp->n_entries; i++) { free(dp->entries[i]); } free(dp->entries); } free(dp); return 0; } ROKEN_LIB_FUNCTION struct dirent * ROKEN_LIB_CALL readdir(DIR * dp) { if (!IS_DP(dp) || dp->cursor < 0 || dp->cursor >= dp->n_entries) return NULL; return dp->entries[dp->cursor++]; } ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL rewinddir(DIR * dp) { if (IS_DP(dp)) dp->cursor = 0; } ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL seekdir(DIR * dp, long offset) { if (IS_DP(dp) && offset >= 0 && offset < dp->n_entries) dp->cursor = offset; } ROKEN_LIB_FUNCTION long ROKEN_LIB_CALL telldir(DIR * dp) { return dp->cursor; }