mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-06 17:53:27 +00:00
240 lines
4.9 KiB
Plaintext
240 lines
4.9 KiB
Plaintext
/* $Id$ */
|
|
/*
|
|
Copyright (C) 2003 - 2011 by David White <dave@whitevine.net>
|
|
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License version 2
|
|
or at your option any later version.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
|
|
See the COPYING file for more details.
|
|
*/
|
|
|
|
/**
|
|
* @file filesystem_win32.ii
|
|
* Win32 platform-specific filesystem code.
|
|
*/
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* This code swiped from dirent.c in the unixem library, version 1.7.3.
|
|
* See http://synesis.com.au/software/unixem.html for full sources.
|
|
* It's under BSD license.
|
|
*/
|
|
|
|
#include <direct.h>
|
|
#include <io.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <windows.h>
|
|
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Compiler differences
|
|
*/
|
|
|
|
#if defined(__BORLANDC__)
|
|
# define DIRENT_PROVIDED_BY_COMPILER
|
|
#elif defined(__DMC__)
|
|
# define DIRENT_PROVIDED_BY_COMPILER
|
|
#elif defined(__GNUC__)
|
|
# define DIRENT_PROVIDED_BY_COMPILER
|
|
#elif defined(__INTEL_COMPILER)
|
|
#elif defined(_MSC_VER)
|
|
#elif defined(__MWERKS__)
|
|
#elif defined(__WATCOMC__)
|
|
#else
|
|
# error Compiler not discriminated
|
|
#endif /* compiler */
|
|
|
|
#if defined(DIRENT_PROVIDED_BY_COMPILER)
|
|
#include <dirent.h>
|
|
#else
|
|
|
|
/* ////////////////////////////////////////////////////////////////////// */
|
|
|
|
#include <stddef.h>
|
|
|
|
#ifndef NAME_MAX
|
|
# define NAME_MAX (260)
|
|
#endif /* !NAME_MAX */
|
|
|
|
struct dirent
|
|
{
|
|
char d_name[NAME_MAX + 1]; /*!< file name (null-terminated) */
|
|
int d_mode;
|
|
};
|
|
|
|
struct DIR
|
|
{
|
|
char directory[_MAX_DIR+1]; /* . */
|
|
WIN32_FIND_DATAA find_data; /* The Win32 FindFile data. */
|
|
HANDLE hFind; /* The Win32 FindFile handle. */
|
|
struct dirent dirent; /* The handle's entry. */
|
|
};
|
|
|
|
#ifndef FILE_ATTRIBUTE_ERROR
|
|
# define FILE_ATTRIBUTE_ERROR (0xFFFFFFFF)
|
|
#endif /* FILE_ATTRIBUTE_ERROR */
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* Helper functions
|
|
*/
|
|
|
|
static HANDLE dirent__findfile_directory(char const *name, LPWIN32_FIND_DATAA data)
|
|
{
|
|
char search_spec[_MAX_PATH +1];
|
|
|
|
// Simply add the *.*, ensuring the path separator is included.
|
|
(void)lstrcpyA(search_spec, name);
|
|
if( '\\' != search_spec[lstrlenA(search_spec) - 1] &&
|
|
'/' != search_spec[lstrlenA(search_spec) - 1])
|
|
{
|
|
(void)lstrcatA(search_spec, "\\*.*");
|
|
}
|
|
else
|
|
{
|
|
(void)lstrcatA(search_spec, "*.*");
|
|
}
|
|
|
|
return FindFirstFileA(search_spec, data);
|
|
}
|
|
|
|
/* /////////////////////////////////////////////////////////////////////////
|
|
* API functions
|
|
*/
|
|
|
|
DIR *opendir(char const *name)
|
|
{
|
|
DIR *result = NULL;
|
|
DWORD dwAttr;
|
|
|
|
// Must be a valid name
|
|
if( !name ||
|
|
!*name ||
|
|
(dwAttr = GetFileAttributes(name)) == 0xFFFFFFFF)
|
|
{
|
|
errno = ENOENT;
|
|
}
|
|
// Must be a directory
|
|
else if(!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
errno = ENOTDIR;
|
|
}
|
|
else
|
|
{
|
|
result = (DIR*)malloc(sizeof(DIR));
|
|
|
|
if(result == NULL)
|
|
{
|
|
errno = ENOMEM;
|
|
}
|
|
else
|
|
{
|
|
result->hFind=dirent__findfile_directory(name, &result->find_data);
|
|
|
|
if(result->hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
free(result);
|
|
|
|
result = NULL;
|
|
}
|
|
else
|
|
{
|
|
// Save the directory, in case of rewind.
|
|
(void)lstrcpyA(result->directory, name);
|
|
(void)lstrcpyA(result->dirent.d_name, result->find_data.cFileName);
|
|
result->dirent.d_mode = (int)result->find_data.dwFileAttributes;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int closedir(DIR *dir)
|
|
{
|
|
int ret;
|
|
|
|
if(dir == NULL)
|
|
{
|
|
errno = EBADF;
|
|
|
|
ret = -1;
|
|
}
|
|
else
|
|
{
|
|
// Close the search handle, if not already done.
|
|
if(dir->hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
(void)FindClose(dir->hFind);
|
|
}
|
|
|
|
free(dir);
|
|
|
|
ret = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
struct dirent *readdir(DIR *dir)
|
|
{
|
|
// The last find exhausted the matches, so return NULL.
|
|
if(dir->hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
if(FILE_ATTRIBUTE_ERROR == dir->find_data.dwFileAttributes)
|
|
{
|
|
errno = EBADF;
|
|
}
|
|
else
|
|
{
|
|
dir->find_data.dwFileAttributes = FILE_ATTRIBUTE_ERROR;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
// Copy the result of the last successful match to dirent.
|
|
(void)lstrcpyA(dir->dirent.d_name, dir->find_data.cFileName);
|
|
|
|
// Attempt the next match.
|
|
if(!FindNextFileA(dir->hFind, &dir->find_data))
|
|
{
|
|
// Exhausted all matches, so close and null the handle.
|
|
(void)FindClose(dir->hFind);
|
|
dir->hFind = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
return &dir->dirent;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Microsoft C uses _stat instead of stat,
|
|
* for both the function name and the structure name.
|
|
* See <http://svn.ghostscript.com:8080/ghostscript/trunk/gs/src/stat_.h>
|
|
*/
|
|
#ifdef _MSC_VER
|
|
# define stat _stat
|
|
namespace {
|
|
typedef int mode_t;
|
|
}
|
|
#endif
|
|
|
|
#ifndef S_IFMT
|
|
#define S_IFMT (S_IFDIR|S_IFREG)
|
|
#endif
|
|
#ifndef S_ISREG
|
|
#define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
|
|
#endif
|
|
#ifndef S_ISDIR
|
|
#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
|
|
#endif
|
|
|
|
#endif /* !DIRENT_PROVIDED_BY_COMPILER */
|
|
|
|
#define mkdir(a,b) (_mkdir(a))
|