diff options
author | Adam Borowski <kilobyte@angband.pl> | 2010-09-17 01:53:41 +0200 |
---|---|---|
committer | Adam Borowski <kilobyte@angband.pl> | 2010-09-17 01:56:35 +0200 |
commit | e65b29e9f2a9a79731f38787384f9c877eec430f (patch) | |
tree | df729dca05bd679dccf7cc336974e4795099ce47 /crawl-ref/source/syscalls.cc | |
parent | 0fac9b0ec9f22978b94594373d65c5a70a4441fd (diff) | |
download | crawl-ref-e65b29e9f2a9a79731f38787384f9c877eec430f.tar.gz crawl-ref-e65b29e9f2a9a79731f38787384f9c877eec430f.zip |
Handle filenames with non-ascii characters.
Only iostreams functions are left; on Windows they don't support Unicode
so a workaround will be needed.
Diffstat (limited to 'crawl-ref/source/syscalls.cc')
-rw-r--r-- | crawl-ref/source/syscalls.cc | 153 |
1 files changed, 146 insertions, 7 deletions
diff --git a/crawl-ref/source/syscalls.cc b/crawl-ref/source/syscalls.cc index b507511fb3..615f7b3cf4 100644 --- a/crawl-ref/source/syscalls.cc +++ b/crawl-ref/source/syscalls.cc @@ -5,17 +5,20 @@ */ #include "AppHdr.h" -#include "syscalls.h" +#include <dirent.h> #ifdef TARGET_OS_WINDOWS - -// FIXME! This file doesn't yet use rename() (but we'll redefine it anyway once -// charset handling comes). -#undef rename - -#include <io.h> +# ifdef TARGET_COMPILER_VC +# include <direct.h> +# endif +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# include <io.h> #endif +#include "syscalls.h" +#include "unicode.h" + bool lock_file(int fd, bool write) { #ifdef TARGET_OS_WINDOWS @@ -30,3 +33,139 @@ bool lock_file(int fd, bool write) return !fcntl(fd, F_SETLK, &fl); #endif } + +bool file_exists(const std::string &name) +{ +#ifdef TARGET_OS_WINDOWS + DWORD lAttr = GetFileAttributesW(utf8_to_16(name.c_str()).c_str()); + return (lAttr != INVALID_FILE_ATTRIBUTES + && !(lAttr & FILE_ATTRIBUTE_DIRECTORY)); +#else + struct stat st; + const int err = ::stat(utf8_to_mb(name).c_str(), &st); + return (!err && S_ISREG(st.st_mode)); +#endif +} + +// Low-tech existence check. +bool dir_exists(const std::string &dir) +{ +#ifdef TARGET_OS_WINDOWS + DWORD lAttr = GetFileAttributesW(utf8_to_16(dir.c_str()).c_str()); + return (lAttr != INVALID_FILE_ATTRIBUTES + && (lAttr & FILE_ATTRIBUTE_DIRECTORY)); +#elif defined(HAVE_STAT) + struct stat st; + const int err = ::stat(utf8_to_mb(dir).c_str(), &st); + return (!err && S_ISDIR(st.st_mode)); +#else + DIR *d = opendir(utf8_to_mb(dir).c_str()); + const bool exists = !!d; + if (d) + closedir(d); + + return (exists); +#endif +} + +static inline bool _is_good_filename(const std::string &s) +{ + return (s != "." && s != ".."); +} + +// Returns the names of all files in the given directory. Note that the +// filenames returned are relative to the directory. +std::vector<std::string> get_dir_files(const std::string &dirname) +{ + std::vector<std::string> files; + +#ifdef TARGET_OS_WINDOWS + WIN32_FIND_DATAW lData; + std::string dir = dirname; + if (!dir.empty() && dir[dir.length() - 1] != FILE_SEPARATOR) + dir += FILE_SEPARATOR; + dir += "*"; + HANDLE hFind = FindFirstFileW(utf8_to_16(dir.c_str()).c_str(), &lData); + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + if (_is_good_filename(utf16_to_8(lData.cFileName))) + files.push_back(utf16_to_8(lData.cFileName)); + } while (FindNextFileW(hFind, &lData)); + FindClose(hFind); + } +#else + + DIR *dir = opendir(utf8_to_mb(dirname).c_str()); + if (!dir) + return (files); + + while (dirent *entry = readdir(dir)) + { + std::string name = mb_to_utf8(entry->d_name); + if (_is_good_filename(name)) + files.push_back(name); + } + closedir(dir); +#endif + + return (files); +} + +int rename_u(const char *oldpath, const char *newpath) +{ +#ifdef TARGET_OS_WINDOWS + return !MoveFileExW(utf8_to_16(oldpath).c_str(), + utf8_to_16(newpath).c_str(), + MOVEFILE_REPLACE_EXISTING); +#else + return rename(utf8_to_mb(oldpath).c_str(), utf8_to_mb(newpath).c_str()); +#endif +} + +int unlink_u(const char *pathname) +{ +#ifdef TARGET_OS_WINDOWS + return _wunlink(utf8_to_16(pathname).c_str()); +#else + return unlink(utf8_to_mb(pathname).c_str()); +#endif +} + +int chmod_u(const char *path, mode_t mode) +{ +#ifdef TARGET_OS_WINDOWS + return _wchmod(utf8_to_16(path).c_str(), mode); +#else + return chmod(utf8_to_mb(path).c_str(), mode); +#endif +} + +FILE *fopen_u(const char *path, const char *mode) +{ +#ifdef TARGET_OS_WINDOWS + // Why it wants the mode string as double-byte is beyond me. + return _wfopen(utf8_to_16(path).c_str(), utf8_to_16(mode).c_str()); +#else + return fopen(utf8_to_mb(path).c_str(), mode); +#endif +} + +int mkdir_u(const char *pathname, mode_t mode) +{ +#ifdef TARGET_OS_WINDOWS + return _wmkdir(utf8_to_16(pathname).c_str()); +#else + return mkdir(utf8_to_mb(pathname).c_str(), mode); +#endif +} + +int open_u(const char *pathname, int flags, mode_t mode) +{ +#ifdef TARGET_OS_WINDOWS + return _wopen(utf8_to_16(pathname).c_str(), flags, mode); +#else + return open(utf8_to_mb(pathname).c_str(), flags, mode); +#endif +} |