784 lines
18 KiB
C
784 lines
18 KiB
C
|
/*
|
||
|
* dirent.h - dirent API for Microsoft Visual Studio
|
||
|
*
|
||
|
* Copyright (C) 2006-2012 Toni Ronkko
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||
|
* a copy of this software and associated documentation files (the
|
||
|
* ``Software''), to deal in the Software without restriction, including
|
||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||
|
* the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included
|
||
|
* in all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||
|
* IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||
|
*
|
||
|
*/
|
||
|
#ifndef _GAZEBO_WIN_DIRENT_H_
|
||
|
#define _GAZEBO_WIN_DIRENT_H_
|
||
|
|
||
|
// Define architecture flags so we don't need to include windows.h.
|
||
|
// Avoiding windows.h makes it simpler to use windows sockets in conjunction
|
||
|
// with dirent.h.
|
||
|
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && \
|
||
|
!defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
|
||
|
# define _X86_
|
||
|
#endif
|
||
|
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && \
|
||
|
!defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
|
||
|
#define _AMD64_
|
||
|
#endif
|
||
|
|
||
|
#include <cstdint>
|
||
|
#include <stdio.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <windef.h>
|
||
|
#include <winbase.h>
|
||
|
#include <wchar.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <malloc.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <errno.h>
|
||
|
|
||
|
// Indicates that d_type field is available in dirent structure
|
||
|
#define _DIRENT_HAVE_D_TYPE
|
||
|
|
||
|
// Indicates that d_namlen field is available in dirent structure
|
||
|
#define _DIRENT_HAVE_D_NAMLEN
|
||
|
|
||
|
// Entries missing from MSVC 6.0
|
||
|
#if !defined(FILE_ATTRIBUTE_DEVICE)
|
||
|
# define FILE_ATTRIBUTE_DEVICE 0x40
|
||
|
#endif
|
||
|
|
||
|
// File type and permission flags for stat()
|
||
|
#if !defined(S_IFMT)
|
||
|
// File type mask
|
||
|
# define S_IFMT _S_IFMT
|
||
|
#endif
|
||
|
#if !defined(S_IFDIR)
|
||
|
// Directory
|
||
|
# define S_IFDIR _S_IFDIR
|
||
|
#endif
|
||
|
#if !defined(S_IFCHR)
|
||
|
// Character device
|
||
|
# define S_IFCHR _S_IFCHR
|
||
|
#endif
|
||
|
#if !defined(S_IFFIFO)
|
||
|
// Pipe
|
||
|
# define S_IFFIFO _S_IFFIFO
|
||
|
#endif
|
||
|
#if !defined(S_IFREG)
|
||
|
// Regular file
|
||
|
# define S_IFREG _S_IFREG
|
||
|
#endif
|
||
|
#if !defined(S_IREAD)
|
||
|
// Read permission
|
||
|
# define S_IREAD _S_IREAD
|
||
|
#endif
|
||
|
#if !defined(S_IWRITE)
|
||
|
// Write permission
|
||
|
# define S_IWRITE _S_IWRITE
|
||
|
#endif
|
||
|
#if !defined(S_IEXEC)
|
||
|
// Execute permission
|
||
|
# define S_IEXEC _S_IEXEC
|
||
|
#endif
|
||
|
#if !defined(S_IFIFO)
|
||
|
// Pipe
|
||
|
# define S_IFIFO _S_IFIFO
|
||
|
#endif
|
||
|
#if !defined(S_IFBLK)
|
||
|
// Block device
|
||
|
# define S_IFBLK 0
|
||
|
#endif
|
||
|
#if !defined(S_IFLNK)
|
||
|
// Link
|
||
|
# define S_IFLNK 0
|
||
|
#endif
|
||
|
#if !defined(S_IFSOCK)
|
||
|
// Socket
|
||
|
# define S_IFSOCK 0
|
||
|
#endif
|
||
|
|
||
|
#if defined(_MSC_VER)
|
||
|
// Read user
|
||
|
# define S_IRUSR S_IREAD
|
||
|
// Write user
|
||
|
# define S_IWUSR S_IWRITE
|
||
|
// Execute user
|
||
|
# define S_IXUSR 0
|
||
|
// Read group
|
||
|
# define S_IRGRP 0
|
||
|
// Write group
|
||
|
# define S_IWGRP 0
|
||
|
// Execute group
|
||
|
# define S_IXGRP 0
|
||
|
// Read others
|
||
|
# define S_IROTH 0
|
||
|
// Write others
|
||
|
# define S_IWOTH 0
|
||
|
// Execute others
|
||
|
# define S_IXOTH 0
|
||
|
#endif
|
||
|
|
||
|
// Maximum length of file name
|
||
|
#if !defined(PATH_MAX)
|
||
|
# define PATH_MAX MAX_PATH
|
||
|
#endif
|
||
|
#if !defined(FILENAME_MAX)
|
||
|
# define FILENAME_MAX MAX_PATH
|
||
|
#endif
|
||
|
#if !defined(NAME_MAX)
|
||
|
# define NAME_MAX FILENAME_MAX
|
||
|
#endif
|
||
|
|
||
|
// File type flags for d_type
|
||
|
#define DT_UNKNOWN 0
|
||
|
#define DT_REG S_IFREG
|
||
|
#define DT_DIR S_IFDIR
|
||
|
#define DT_FIFO S_IFIFO
|
||
|
#define DT_SOCK S_IFSOCK
|
||
|
#define DT_CHR S_IFCHR
|
||
|
#define DT_BLK S_IFBLK
|
||
|
#define DT_LNK S_IFLNK
|
||
|
|
||
|
// Macros for converting between st_mode and d_type
|
||
|
#define IFTODT(mode) ((mode) & S_IFMT)
|
||
|
#define DTTOIF(type) (type)
|
||
|
|
||
|
// File type macros. Note that block devices, sockets and links cannot be
|
||
|
// distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
|
||
|
// only defined for compatibility. These macros should always return false
|
||
|
// on Windows.
|
||
|
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
|
||
|
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||
|
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||
|
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
||
|
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
||
|
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
||
|
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
|
||
|
|
||
|
// Return the exact length of d_namlen without zero terminator
|
||
|
#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
|
||
|
|
||
|
// Return number of bytes needed to store d_namlen
|
||
|
#define _D_ALLOC_NAMLEN(p) (PATH_MAX)
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C"
|
||
|
{
|
||
|
#endif
|
||
|
// Wide-character version
|
||
|
struct _wdirent
|
||
|
{
|
||
|
// Always zero
|
||
|
int64_t d_ino;
|
||
|
|
||
|
// Structure size
|
||
|
uint16_t d_reclen;
|
||
|
|
||
|
// Length of name without \0
|
||
|
size_t d_namlen;
|
||
|
|
||
|
// File type
|
||
|
int d_type;
|
||
|
|
||
|
// File name
|
||
|
wchar_t d_name[PATH_MAX];
|
||
|
};
|
||
|
typedef struct _wdirent _wdirent;
|
||
|
|
||
|
struct _WDIR
|
||
|
{
|
||
|
// Current directory entry
|
||
|
struct _wdirent ent;
|
||
|
|
||
|
// Private file data
|
||
|
WIN32_FIND_DATAW data;
|
||
|
|
||
|
// True if data is valid
|
||
|
int cached;
|
||
|
|
||
|
// Win32 search handle
|
||
|
HANDLE handle;
|
||
|
|
||
|
// Initial directory name
|
||
|
wchar_t *patt;
|
||
|
};
|
||
|
typedef struct _WDIR _WDIR;
|
||
|
|
||
|
static _WDIR *_wopendir(const wchar_t *dirname);
|
||
|
static struct _wdirent *_wreaddir(_WDIR *dirp);
|
||
|
static int _wclosedir(_WDIR *dirp);
|
||
|
static void _wrewinddir(_WDIR* dirp);
|
||
|
|
||
|
// For compatibility with Symbian
|
||
|
# define wdirent _wdirent
|
||
|
# define WDIR _WDIR
|
||
|
# define wopendir _wopendir
|
||
|
# define wreaddir _wreaddir
|
||
|
# define wclosedir _wclosedir
|
||
|
# define wrewinddir _wrewinddir
|
||
|
|
||
|
|
||
|
// Multi-byte character versions
|
||
|
struct dirent
|
||
|
{
|
||
|
// Always zero
|
||
|
int64_t d_ino;
|
||
|
|
||
|
// Structure size
|
||
|
uint16_t d_reclen;
|
||
|
|
||
|
// Length of name without \0
|
||
|
size_t d_namlen;
|
||
|
|
||
|
// File type
|
||
|
int d_type;
|
||
|
|
||
|
// File name
|
||
|
char d_name[PATH_MAX];
|
||
|
};
|
||
|
typedef struct dirent dirent;
|
||
|
|
||
|
struct DIR
|
||
|
{
|
||
|
struct dirent ent;
|
||
|
struct _WDIR *wdirp;
|
||
|
};
|
||
|
typedef struct DIR DIR;
|
||
|
|
||
|
static DIR *opendir(const char *dirname);
|
||
|
static int closedir(DIR *dirp);
|
||
|
static void rewinddir(DIR* dirp);
|
||
|
|
||
|
|
||
|
// Internal utility functions
|
||
|
static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp);
|
||
|
static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp);
|
||
|
|
||
|
static int dirent_mbstowcs_s(
|
||
|
size_t *pReturnValue,
|
||
|
wchar_t *wcstr,
|
||
|
size_t sizeInWords,
|
||
|
const char *mbstr,
|
||
|
size_t count);
|
||
|
|
||
|
static int dirent_wcstombs_s(
|
||
|
size_t *pReturnValue,
|
||
|
char *mbstr,
|
||
|
size_t sizeInBytes,
|
||
|
const wchar_t *wcstr,
|
||
|
size_t count);
|
||
|
|
||
|
static void dirent_set_errno(int error);
|
||
|
|
||
|
// Open directory stream DIRNAME for read and return a pointer to the
|
||
|
// internal working area that is used to retrieve individual directory
|
||
|
// entries.
|
||
|
static _WDIR* _wopendir(const wchar_t *dirname)
|
||
|
{
|
||
|
_WDIR *dirp = NULL;
|
||
|
int error;
|
||
|
|
||
|
// Must have directory name
|
||
|
if (dirname == NULL || dirname[0] == '\0')
|
||
|
{
|
||
|
dirent_set_errno(ENOENT);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// Allocate new _WDIR structure
|
||
|
dirp = static_cast<_WDIR*>(malloc(sizeof(struct _WDIR)));
|
||
|
if (dirp != NULL)
|
||
|
{
|
||
|
DWORD n;
|
||
|
|
||
|
// Reset _WDIR structure
|
||
|
dirp->handle = INVALID_HANDLE_VALUE;
|
||
|
dirp->patt = NULL;
|
||
|
dirp->cached = 0;
|
||
|
|
||
|
// Compute the length of full path plus zero terminator
|
||
|
n = GetFullPathNameW(dirname, 0, NULL, NULL);
|
||
|
|
||
|
// Allocate room for absolute directory name and search pattern
|
||
|
dirp->patt = static_cast<wchar_t*>(malloc(sizeof(wchar_t) * n + 16));
|
||
|
if (dirp->patt)
|
||
|
{
|
||
|
// Convert relative directory name to an absolute one. This
|
||
|
// allows rewinddir() to function correctly even when current
|
||
|
// working directory is changed between opendir() and rewinddir().
|
||
|
n = GetFullPathNameW(dirname, n, dirp->patt, NULL);
|
||
|
|
||
|
if (n > 0)
|
||
|
{
|
||
|
wchar_t *p;
|
||
|
|
||
|
// Append search pattern \* to the directory name
|
||
|
p = dirp->patt + n;
|
||
|
if (dirp->patt < p)
|
||
|
{
|
||
|
switch (p[-1])
|
||
|
{
|
||
|
case '\\':
|
||
|
case '/':
|
||
|
case ':':
|
||
|
// Directory ends in path separator, e.g. c:\temp\
|
||
|
// NOP
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
// Directory name doesn't end in path separator
|
||
|
*p++ = '\\';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*p++ = '*';
|
||
|
*p = '\0';
|
||
|
|
||
|
// Open directory stream and retrieve the first entry
|
||
|
if (dirent_first(dirp))
|
||
|
{
|
||
|
// Directory stream opened successfully
|
||
|
error = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Cannot retrieve first entry
|
||
|
error = 1;
|
||
|
dirent_set_errno(ENOENT);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Cannot retrieve full path name
|
||
|
dirent_set_errno(ENOENT);
|
||
|
error = 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Cannot allocate memory for search pattern
|
||
|
error = 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Cannot allocate _WDIR structure
|
||
|
error = 1;
|
||
|
}
|
||
|
|
||
|
// Clean up in case of error
|
||
|
if (error && dirp)
|
||
|
{
|
||
|
_wclosedir(dirp);
|
||
|
dirp = NULL;
|
||
|
}
|
||
|
|
||
|
return dirp;
|
||
|
}
|
||
|
|
||
|
// Read next directory entry. The directory entry is returned in dirent
|
||
|
// structure in the d_name field. Individual directory entries returned by
|
||
|
// this function include regular files, sub-directories, pseudo-directories
|
||
|
// "." and ".." as well as volume labels, hidden files and system files.
|
||
|
static struct _wdirent* _wreaddir(_WDIR *dirp)
|
||
|
{
|
||
|
WIN32_FIND_DATAW *datap;
|
||
|
struct _wdirent *entp;
|
||
|
|
||
|
// Read next directory entry
|
||
|
datap = dirent_next(dirp);
|
||
|
if (datap)
|
||
|
{
|
||
|
size_t n;
|
||
|
DWORD attr;
|
||
|
|
||
|
// Pointer to directory entry to return
|
||
|
entp = &dirp->ent;
|
||
|
|
||
|
// Copy file name as wide-character string. If the file name is too
|
||
|
// long to fit in to the destination buffer, then truncate file name
|
||
|
// to PATH_MAX characters and zero-terminate the buffer.
|
||
|
n = 0;
|
||
|
while (n + 1 < PATH_MAX && datap->cFileName[n] != 0)
|
||
|
{
|
||
|
entp->d_name[n] = datap->cFileName[n];
|
||
|
n++;
|
||
|
}
|
||
|
dirp->ent.d_name[n] = 0;
|
||
|
|
||
|
// Length of file name excluding zero terminator
|
||
|
entp->d_namlen = n;
|
||
|
|
||
|
// File type
|
||
|
attr = datap->dwFileAttributes;
|
||
|
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0)
|
||
|
{
|
||
|
entp->d_type = DT_CHR;
|
||
|
}
|
||
|
else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||
|
{
|
||
|
entp->d_type = DT_DIR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
entp->d_type = DT_REG;
|
||
|
}
|
||
|
|
||
|
// Reset dummy fields
|
||
|
entp->d_ino = 0;
|
||
|
entp->d_reclen = sizeof(struct _wdirent);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Last directory entry read
|
||
|
entp = NULL;
|
||
|
}
|
||
|
|
||
|
return entp;
|
||
|
}
|
||
|
|
||
|
// Close directory stream opened by opendir() function. This invalidates the
|
||
|
// DIR structure as well as any directory entry read previously by
|
||
|
// _wreaddir().
|
||
|
static int _wclosedir(_WDIR *dirp)
|
||
|
{
|
||
|
int ok;
|
||
|
if (dirp)
|
||
|
{
|
||
|
// Release search handle
|
||
|
if (dirp->handle != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
FindClose(dirp->handle);
|
||
|
dirp->handle = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
// Release search pattern
|
||
|
if (dirp->patt)
|
||
|
{
|
||
|
free(dirp->patt);
|
||
|
dirp->patt = NULL;
|
||
|
}
|
||
|
|
||
|
// Release directory structure
|
||
|
free(dirp);
|
||
|
|
||
|
// success
|
||
|
ok = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Invalid directory stream
|
||
|
dirent_set_errno(EBADF);
|
||
|
|
||
|
// failure
|
||
|
ok = -1;
|
||
|
}
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
// Rewind directory stream such that _wreaddir() returns the very first
|
||
|
// file name again.
|
||
|
static void _wrewinddir(_WDIR* dirp)
|
||
|
{
|
||
|
if (dirp)
|
||
|
{
|
||
|
// Release existing search handle
|
||
|
if (dirp->handle != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
FindClose(dirp->handle);
|
||
|
}
|
||
|
|
||
|
// Open new search handle
|
||
|
dirent_first(dirp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Get first directory entry (internal)
|
||
|
static WIN32_FIND_DATAW* dirent_first(_WDIR *dirp)
|
||
|
{
|
||
|
WIN32_FIND_DATAW *datap;
|
||
|
|
||
|
// Open directory and retrieve the first entry
|
||
|
dirp->handle = FindFirstFileW(dirp->patt, &dirp->data);
|
||
|
if (dirp->handle != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
// a directory entry is now waiting in memory
|
||
|
datap = &dirp->data;
|
||
|
dirp->cached = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Failed to re-open directory: no directory entry in memory
|
||
|
dirp->cached = 0;
|
||
|
datap = NULL;
|
||
|
}
|
||
|
return datap;
|
||
|
}
|
||
|
|
||
|
// Get next directory entry (internal)
|
||
|
static WIN32_FIND_DATAW* dirent_next(_WDIR *dirp)
|
||
|
{
|
||
|
WIN32_FIND_DATAW *p;
|
||
|
|
||
|
// Get next directory entry
|
||
|
if (dirp->cached != 0)
|
||
|
{
|
||
|
// A valid directory entry already in memory
|
||
|
p = &dirp->data;
|
||
|
dirp->cached = 0;
|
||
|
}
|
||
|
else if (dirp->handle != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
// Get the next directory entry from stream
|
||
|
if (FindNextFileW (dirp->handle, &dirp->data) != FALSE)
|
||
|
{
|
||
|
// Got a file
|
||
|
p = &dirp->data;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// The very last entry has been processed or an error occured
|
||
|
FindClose(dirp->handle);
|
||
|
dirp->handle = INVALID_HANDLE_VALUE;
|
||
|
p = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// End of directory stream reached
|
||
|
p = NULL;
|
||
|
}
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
// Open directory stream using plain old C-string.
|
||
|
static DIR* opendir(const char *dirname)
|
||
|
{
|
||
|
struct DIR *dirp;
|
||
|
int error;
|
||
|
|
||
|
// Must have directory name
|
||
|
if (dirname == NULL || dirname[0] == '\0')
|
||
|
{
|
||
|
dirent_set_errno(ENOENT);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// Allocate memory for DIR structure
|
||
|
dirp = static_cast<DIR*>(malloc(sizeof(struct DIR)));
|
||
|
if (dirp)
|
||
|
{
|
||
|
wchar_t wname[PATH_MAX];
|
||
|
size_t n;
|
||
|
|
||
|
// Convert directory name to wide-character string
|
||
|
error = dirent_mbstowcs_s(&n, wname, PATH_MAX, dirname, PATH_MAX);
|
||
|
if (!error)
|
||
|
{
|
||
|
// Open directory stream using wide-character name
|
||
|
dirp->wdirp = _wopendir(wname);
|
||
|
if (dirp->wdirp)
|
||
|
{
|
||
|
// Directory stream opened
|
||
|
error = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Failed to open directory stream
|
||
|
error = 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Cannot convert file name to wide-character string. This
|
||
|
// occurs if the string contains invalid multi-byte sequences or
|
||
|
// the output buffer is too small to contain the resulting
|
||
|
// string.
|
||
|
error = 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Cannot allocate DIR structure
|
||
|
error = 1;
|
||
|
}
|
||
|
|
||
|
// Clean up in case of error
|
||
|
if (error && dirp)
|
||
|
{
|
||
|
free(dirp);
|
||
|
dirp = NULL;
|
||
|
}
|
||
|
return dirp;
|
||
|
}
|
||
|
|
||
|
// Close directory stream.
|
||
|
static int closedir(DIR *dirp)
|
||
|
{
|
||
|
int ok;
|
||
|
if (dirp)
|
||
|
{
|
||
|
// Close wide-character directory stream
|
||
|
ok = _wclosedir(dirp->wdirp);
|
||
|
dirp->wdirp = NULL;
|
||
|
|
||
|
// Release multi-byte character version
|
||
|
free(dirp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Invalid directory stream
|
||
|
dirent_set_errno(EBADF);
|
||
|
|
||
|
// failure
|
||
|
ok = -1;
|
||
|
}
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
// Rewind directory stream to beginning.
|
||
|
static void rewinddir(DIR* dirp)
|
||
|
{
|
||
|
// Rewind wide-character string directory stream
|
||
|
_wrewinddir(dirp->wdirp);
|
||
|
}
|
||
|
|
||
|
// Convert multi-byte string to wide character string
|
||
|
static int dirent_mbstowcs_s(
|
||
|
size_t *pReturnValue,
|
||
|
wchar_t *wcstr,
|
||
|
size_t sizeInWords,
|
||
|
const char *mbstr,
|
||
|
size_t count)
|
||
|
{
|
||
|
int error;
|
||
|
|
||
|
# if defined(_MSC_VER) && _MSC_VER >= 1400
|
||
|
// Microsoft Visual Studio 2005 or later
|
||
|
error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count);
|
||
|
|
||
|
# else
|
||
|
|
||
|
// Older Visual Studio or non-Microsoft compiler
|
||
|
size_t n;
|
||
|
|
||
|
// Convert to wide-character string (or count characters)
|
||
|
n = mbstowcs(wcstr, mbstr, sizeInWords);
|
||
|
if (!wcstr || n < count)
|
||
|
{
|
||
|
// Zero-terminate output buffer
|
||
|
if (wcstr && sizeInWords)
|
||
|
{
|
||
|
if (n >= sizeInWords)
|
||
|
{
|
||
|
n = sizeInWords - 1;
|
||
|
}
|
||
|
wcstr[n] = 0;
|
||
|
}
|
||
|
|
||
|
// Length of resuting multi-byte string WITH zero terminator
|
||
|
if (pReturnValue)
|
||
|
{
|
||
|
*pReturnValue = n + 1;
|
||
|
}
|
||
|
|
||
|
// Success
|
||
|
error = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Could not convert string
|
||
|
error = 1;
|
||
|
}
|
||
|
#endif
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
// Convert wide-character string to multi-byte string
|
||
|
static int dirent_wcstombs_s(
|
||
|
size_t *pReturnValue,
|
||
|
char *mbstr,
|
||
|
// max size of mbstr
|
||
|
size_t sizeInBytes,
|
||
|
const wchar_t *wcstr,
|
||
|
size_t count)
|
||
|
{
|
||
|
int error;
|
||
|
|
||
|
# if defined(_MSC_VER) && _MSC_VER >= 1400
|
||
|
|
||
|
// Microsoft Visual Studio 2005 or later
|
||
|
error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count);
|
||
|
|
||
|
#else
|
||
|
|
||
|
// Older Visual Studio or non-Microsoft compiler
|
||
|
size_t n;
|
||
|
|
||
|
// Convert to multi-byte string (or count the number of bytes needed)
|
||
|
n = wcstombs(mbstr, wcstr, sizeInBytes);
|
||
|
if (!mbstr || n < count)
|
||
|
{
|
||
|
// Zero-terminate output buffer
|
||
|
if (mbstr && sizeInBytes)
|
||
|
{
|
||
|
if (n >= sizeInBytes)
|
||
|
{
|
||
|
n = sizeInBytes - 1;
|
||
|
}
|
||
|
mbstr[n] = '\0';
|
||
|
}
|
||
|
|
||
|
// Lenght of resulting multi-bytes string WITH zero-terminator
|
||
|
if (pReturnValue)
|
||
|
{
|
||
|
*pReturnValue = n + 1;
|
||
|
}
|
||
|
|
||
|
// Success
|
||
|
error = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Cannot convert string
|
||
|
error = 1;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
// Set errno variable
|
||
|
static void dirent_set_errno(int error)
|
||
|
{
|
||
|
# if defined(_MSC_VER) && _MSC_VER >= 1400
|
||
|
// Microsoft Visual Studio 2005 and later
|
||
|
_set_errno(error);
|
||
|
#else
|
||
|
// Non-Microsoft compiler or older Microsoft compiler
|
||
|
errno = error;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// _GAZEBO_WIN_DIRENT_H_
|
||
|
#endif
|