From d74928b2180e1843f417e15eabc2b31a86483e34 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Tue, 10 May 2011 19:29:15 +0200 Subject: [PATCH] Moves specific MingW code to mingw.c/h. --- Makefile.am | 9 +- mingw.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++ mingw.h | 76 ++++++++++++++++ portable.h | 252 +--------------------------------------------------- 4 files changed, 320 insertions(+), 253 deletions(-) create mode 100644 mingw.c create mode 100644 mingw.h diff --git a/Makefile.am b/Makefile.am index a3e89f0f..1c944f58 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,7 +16,8 @@ snapraid_SOURCES = \ fnmatch.c \ raid.c \ selftest.c \ - speed.c + speed.c \ + mingw.c noinst_HEADERS = \ portable.h \ @@ -42,10 +43,12 @@ noinst_HEADERS = \ fnmatch.h \ cpu.h \ raid.h \ - tables.h + tables.h \ + mingw.h mktest_SOURCES = \ - mktest.c + mktest.c \ + mingw.c EXTRA_DIST = \ autogen.sh \ diff --git a/mingw.c b/mingw.c new file mode 100644 index 00000000..13856a6f --- /dev/null +++ b/mingw.c @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "portable.h" + +#include "mingw.h" + +#ifdef __MINGW32__ /* Only for MingW */ + +/** + * Converts Windows info to the Unix stat format. + */ +static void windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, struct windows_stat* st) +{ + /* Convert special attributes to a char device */ + if ((info->dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0) { + st->st_mode = S_IFCHR; + } else if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + st->st_mode = S_IFDIR; + } else { + st->st_mode = S_IFREG; + } + + st->st_size = info->nFileSizeHigh; + st->st_size <<= 32; + st->st_size |= info->nFileSizeLow; + + st->st_mtime = info->ftLastWriteTime.dwHighDateTime; + st->st_mtime <<= 32; + st->st_mtime |= info->ftLastWriteTime.dwLowDateTime; + + /* + * Convert to unix time + * + * How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME + * http://support.microsoft.com/kb/167296 + */ + st->st_mtime = (st->st_mtime - 116444736000000000LL) / 10000000; + + st->st_ino = info->nFileIndexHigh; + st->st_ino <<= 32; + st->st_ino |= info->nFileIndexLow; + + st->st_nlink = info->nNumberOfLinks; +} + +/** + * Converts Windows findfirst info to the Unix stat format. + */ +static void windows_finddata2stat(const WIN32_FIND_DATA* info, struct windows_stat* st) +{ + /* Convert special attributes to a char device */ + if ((info->dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0) { + st->st_mode = S_IFCHR; + } else if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + st->st_mode = S_IFDIR; + } else { + st->st_mode = S_IFREG; + } + + st->st_size = info->nFileSizeHigh; + st->st_size <<= 32; + st->st_size |= info->nFileSizeLow; + + st->st_mtime = info->ftLastWriteTime.dwHighDateTime; + st->st_mtime <<= 32; + st->st_mtime |= info->ftLastWriteTime.dwLowDateTime; + + /* + * Convert to unix time + * + * How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME + * http://support.microsoft.com/kb/167296 + */ + st->st_mtime = (st->st_mtime - 116444736000000000LL) / 10000000; + + /* No inode information available */ + st->st_ino = 0; + + /* No link information available */ + st->st_nlink = 0; +} + +/** + * Converts Windows error to errno. + */ +static void windows_errno(DWORD error) +{ + switch (error) { + case ERROR_INVALID_HANDLE : + errno = EBADF; + break; + case ERROR_FILE_NOT_FOUND : + errno = ENOENT; + break; + case ERROR_ACCESS_DENIED : + errno = EACCES; + break; + default: + errno = EIO; + break; + } +} + +int windows_fstat(int fd, struct windows_stat* st) +{ + BY_HANDLE_FILE_INFORMATION info; + HANDLE h; + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + if (!GetFileInformationByHandle(h, &info)) { + windows_errno(GetLastError()); + return -1; + } + + windows_info2stat(&info, st); + + return 0; +} + +int windows_stat(const char* file, struct windows_stat* st) +{ + HANDLE h; + WIN32_FIND_DATA data; + + h = FindFirstFile(file, &data); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + if (!FindClose(h)) { + windows_errno(GetLastError()); + return -1; + } + + windows_finddata2stat(&data, st); + + return 0; +} + +int stat_inode(const char* file, struct windows_stat* st) +{ + BY_HANDLE_FILE_INFORMATION info; + HANDLE h; + + h = CreateFile(file, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + if (!GetFileInformationByHandle(h, &info)) { + DWORD error = GetLastError(); + CloseHandle(h); + windows_errno(error); + return -1; + } + + if (!CloseHandle(h)) { + windows_errno(GetLastError()); + return -1; + } + + windows_info2stat(&info, st); + + return 0; +} + +int windows_ftruncate(int fd, off64_t off) +{ + HANDLE h; + LARGE_INTEGER pos; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + pos.QuadPart = off; + if (!SetFilePointerEx(h, pos, 0, FILE_BEGIN)) { + windows_errno(GetLastError()); + return -1; + } + + if (!SetEndOfFile(h)) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +int windows_rename(const char* a, const char* b) +{ + /* + * Implements an atomic rename in Windows. + * Not really atomic at now to support XP. + * + * Is an atomic file rename (with overwrite) possible on Windows? + * http://stackoverflow.com/questions/167414/is-an-atomic-file-rename-with-overwrite-possible-on-windows + */ + if (!MoveFileEx(a, b, MOVEFILE_REPLACE_EXISTING)) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +#endif diff --git a/mingw.h b/mingw.h new file mode 100644 index 00000000..b3ad361d --- /dev/null +++ b/mingw.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __PORTABLE_MINGW_H +#define __PORTABLE_MINGW_H + +#ifdef __MINGW32__ /* Only for MingW */ + +/* Remap functions and types for 64 bit support */ +#define stat windows_stat +#define off_t off64_t +#define lseek lseek64 +#define fstat windows_fstat +#define HAVE_FTRUNCATE 1 +#define ftruncate windows_ftruncate +#define HAVE_FSYNC 1 +#define fsync _commit +#define rename windows_rename +#define mkdir(a, b) mkdir(a) + +/** + * Generic stat information. + */ +struct windows_stat { + uint64_t st_ino; + int64_t st_size; + int64_t st_mtime; + uint32_t st_mode; + uint32_t st_nlink; +}; + +/** + * Like the C fstat() but without inode information. + */ +int windows_fstat(int fd, struct windows_stat* st); + +/** + * Like the C stat() but without inode information. + */ +int windows_stat(const char* file, struct windows_stat* st); + +#define HAVE_STAT_INODE 1 + +/** + * Like the C stat() with inode information. + * It doesn't work for all kind of files and directories. For example "\System Volume Information" cannot be opened. + */ +int stat_inode(const char* file, struct windows_stat* st); + +/** + * Like the C ftruncate(). + */ +int windows_ftruncate(int fd, off64_t off); + +/** + * Like the C rename(). + */ +int windows_rename(const char* a, const char* b); + +#endif +#endif + diff --git a/portable.h b/portable.h index caddfdce..f60cf95d 100644 --- a/portable.h +++ b/portable.h @@ -115,256 +115,8 @@ #define O_SEQUENTIAL 0 #endif -#ifdef __MINGW32__ /* Specific for Windows MINGW */ - -/* Remap functions and types for 64 bit support */ -#define stat windows_stat -#define off_t off64_t -#define lseek lseek64 -#define fstat windows_fstat -#define HAVE_FTRUNCATE 1 -#define ftruncate windows_ftruncate -#define HAVE_FSYNC 1 -#define fsync _commit -#define rename windows_rename -#define mkdir(a, b) mkdir(a) - -/** - * Generic stat information. - */ -struct windows_stat { - uint64_t st_ino; - int64_t st_size; - int64_t st_mtime; - uint32_t st_mode; - uint32_t st_nlink; -}; - -/** - * Converts Windows info to the Unix stat format. - */ -static inline void windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, struct windows_stat* st) -{ - /* Convert special attributes to a char device */ - if ((info->dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0) { - st->st_mode = S_IFCHR; - } else if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { - st->st_mode = S_IFDIR; - } else { - st->st_mode = S_IFREG; - } - - st->st_size = info->nFileSizeHigh; - st->st_size <<= 32; - st->st_size |= info->nFileSizeLow; - - st->st_mtime = info->ftLastWriteTime.dwHighDateTime; - st->st_mtime <<= 32; - st->st_mtime |= info->ftLastWriteTime.dwLowDateTime; - - /* - * Convert to unix time - * - * How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME - * http://support.microsoft.com/kb/167296 - */ - st->st_mtime = (st->st_mtime - 116444736000000000LL) / 10000000; - - st->st_ino = info->nFileIndexHigh; - st->st_ino <<= 32; - st->st_ino |= info->nFileIndexLow; - - st->st_nlink = info->nNumberOfLinks; -} - -/** - * Converts Windows findfirst info to the Unix stat format. - */ -static inline void windows_finddata2stat(const WIN32_FIND_DATA* info, struct windows_stat* st) -{ - /* Convert special attributes to a char device */ - if ((info->dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0) { - st->st_mode = S_IFCHR; - } else if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { - st->st_mode = S_IFDIR; - } else { - st->st_mode = S_IFREG; - } - - st->st_size = info->nFileSizeHigh; - st->st_size <<= 32; - st->st_size |= info->nFileSizeLow; - - st->st_mtime = info->ftLastWriteTime.dwHighDateTime; - st->st_mtime <<= 32; - st->st_mtime |= info->ftLastWriteTime.dwLowDateTime; - - /* - * Convert to unix time - * - * How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME - * http://support.microsoft.com/kb/167296 - */ - st->st_mtime = (st->st_mtime - 116444736000000000LL) / 10000000; - - /* No inode information available */ - st->st_ino = 0; - - /* No link information available */ - st->st_nlink = 0; -} - -/** - * Converts Windows error to errno. - */ -static inline void windows_errno(DWORD error) -{ - switch (error) { - case ERROR_INVALID_HANDLE : - errno = EBADF; - break; - case ERROR_FILE_NOT_FOUND : - errno = ENOENT; - break; - case ERROR_ACCESS_DENIED : - errno = EACCES; - break; - default: - errno = EIO; - break; - } -} - -static inline int windows_fstat(int fd, struct windows_stat* st) -{ - BY_HANDLE_FILE_INFORMATION info; - HANDLE h; - - h = (HANDLE)_get_osfhandle(fd); - if (h == INVALID_HANDLE_VALUE) { - errno = EBADF; - return -1; - } - - if (!GetFileInformationByHandle(h, &info)) { - windows_errno(GetLastError()); - return -1; - } - - windows_info2stat(&info, st); - - return 0; -} - -/** - * Like the C stat() but without inode information. - */ -static inline int windows_stat(const char* file, struct windows_stat* st) -{ - HANDLE h; - WIN32_FIND_DATA data; - - h = FindFirstFile(file, &data); - if (h == INVALID_HANDLE_VALUE) { - windows_errno(GetLastError()); - return -1; - } - - if (!FindClose(h)) { - windows_errno(GetLastError()); - return -1; - } - - windows_finddata2stat(&data, st); - - return 0; -} - -#define HAVE_STAT_INODE 1 -/** - * Like the C stat() with inode information. - * It doesn't work for all kind of files and directories. For example "\System Volume Information" cannot be opened. - */ -static inline int stat_inode(const char* file, struct windows_stat* st) -{ - BY_HANDLE_FILE_INFORMATION info; - HANDLE h; - - h = CreateFile(file, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); - if (h == INVALID_HANDLE_VALUE) { - windows_errno(GetLastError()); - return -1; - } - - if (!GetFileInformationByHandle(h, &info)) { - DWORD error = GetLastError(); - CloseHandle(h); - windows_errno(error); - return -1; - } - - if (!CloseHandle(h)) { - windows_errno(GetLastError()); - return -1; - } - - windows_info2stat(&info, st); - - return 0; -} - -/** - * Like the C ftruncate(). - */ -static inline int windows_ftruncate(int fd, off64_t off) -{ - HANDLE h; - LARGE_INTEGER pos; - - if (fd == -1) { - errno = EBADF; - return -1; - } - - h = (HANDLE)_get_osfhandle(fd); - if (h == INVALID_HANDLE_VALUE) { - errno = EBADF; - return -1; - } - - pos.QuadPart = off; - if (!SetFilePointerEx(h, pos, 0, FILE_BEGIN)) { - windows_errno(GetLastError()); - return -1; - } - - if (!SetEndOfFile(h)) { - windows_errno(GetLastError()); - return -1; - } - - return 0; -} - -/** - * Like the C rename(). - */ -static inline int windows_rename(const char* a, const char* b) -{ - /* - * Implements an atomic rename in Windows. - * Not really atomic at now to support XP. - * - * Is an atomic file rename (with overwrite) possible on Windows? - * http://stackoverflow.com/questions/167414/is-an-atomic-file-rename-with-overwrite-possible-on-windows - */ - if (!MoveFileEx(a, b, MOVEFILE_REPLACE_EXISTING)) { - windows_errno(GetLastError()); - return -1; - } - - return 0; -} +#ifdef __MINGW32__ /* Specific for MingW */ +#include "mingw.h" #endif #endif