Repository: lucy Updated Branches: refs/heads/master d14281228 -> 5f15a92bd
Make FSFileHandle always use Windows handles Switch FSFileHandle over to WinAPI for open/close/write. Add sanity checks to FileHandle_do_open. Fix minor bug in Unix Write method (-1 return value was added to file length). Make Windows Read method use synchronous API and add an extra check for unexpected EOF. Fixes LUCY-321. Project: http://git-wip-us.apache.org/repos/asf/lucy/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/5f15a92b Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/5f15a92b Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/5f15a92b Branch: refs/heads/master Commit: 5f15a92bde4c63e2b0d1c3d8b74a294ed8a3d1f0 Parents: d142812 Author: Nick Wellnhofer <wellnho...@aevum.de> Authored: Sun Feb 19 22:43:03 2017 +0100 Committer: Nick Wellnhofer <wellnho...@aevum.de> Committed: Mon Feb 20 16:10:18 2017 +0100 ---------------------------------------------------------------------- core/Lucy/Store/FSFileHandle.c | 450 +++++++++++++-------------- core/Lucy/Store/FileHandle.c | 28 +- core/Lucy/Store/RAMFileHandle.c | 6 +- test/Lucy/Test/Store/MockFileHandle.c | 2 +- test/Lucy/Test/Store/TestFSFileHandle.c | 20 +- test/Lucy/Test/Store/TestFileHandle.c | 2 +- 6 files changed, 250 insertions(+), 258 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy/blob/5f15a92b/core/Lucy/Store/FSFileHandle.c ---------------------------------------------------------------------- diff --git a/core/Lucy/Store/FSFileHandle.c b/core/Lucy/Store/FSFileHandle.c index 494d661..fff9175 100644 --- a/core/Lucy/Store/FSFileHandle.c +++ b/core/Lucy/Store/FSFileHandle.c @@ -19,45 +19,20 @@ #include "charmony.h" -#include <stdio.h> -#include <fcntl.h> // open, POSIX flags - -#ifdef CHY_HAS_UNISTD_H - #include <unistd.h> // close -#endif - -#ifdef CHY_HAS_SYS_MMAN_H - #include <sys/mman.h> -#elif defined(CHY_HAS_WINDOWS_H) - #include <windows.h> - #include <io.h> -#else - #error "No support for memory mapped files" -#endif - #include "Lucy/Store/ErrorMessage.h" #include "Lucy/Store/FSFileHandle.h" #include "Lucy/Store/FileWindow.h" -// Convert FileHandle flags to POSIX flags. -static CFISH_INLINE int -SI_posix_flags(uint32_t fh_flags) { - int posix_flags = 0; - if (fh_flags & FH_WRITE_ONLY) { posix_flags |= O_WRONLY; } - if (fh_flags & FH_READ_ONLY) { posix_flags |= O_RDONLY; } - if (fh_flags & FH_CREATE) { posix_flags |= O_CREAT; } - if (fh_flags & FH_EXCLUSIVE) { posix_flags |= O_EXCL; } -#ifdef O_LARGEFILE - posix_flags |= O_LARGEFILE; -#endif -#ifdef _O_BINARY - posix_flags |= _O_BINARY; -#endif - return posix_flags; -} - #define IS_64_BIT (CHY_SIZEOF_PTR == 8 ? 1 : 0) +// Architecture- and OS- specific initialization. +static bool +S_init(FSFileHandleIVARS *ivars, String *path, uint32_t flags); + +// Close file in an OS-specific way. +static bool +S_close(FSFileHandleIVARS *ivars); + // Memory map a region of the file with shared (read-only) permissions. If // the requested length is 0, return NULL. If an error occurs, return NULL // and set the global error object. @@ -74,16 +49,6 @@ static CFISH_INLINE bool SI_window(FSFileHandle *self, FSFileHandleIVARS *ivars, FileWindow *window, int64_t offset, int64_t len); -// Architecture- and OS- specific initialization for a read-only FSFileHandle. -static CFISH_INLINE bool -SI_init_read_only(FSFileHandle *self, FSFileHandleIVARS *ivars); - -// Windows-specific routine needed for closing read-only handles. -#ifdef CHY_HAS_WINDOWS_H -static CFISH_INLINE bool -SI_close_win_handles(FSFileHandle *self); -#endif - FSFileHandle* FSFH_open(String *path, uint32_t flags) { FSFileHandle *self = (FSFileHandle*)Class_Make_Obj(FSFILEHANDLE); @@ -92,71 +57,31 @@ FSFH_open(String *path, uint32_t flags) { FSFileHandle* FSFH_do_open(FSFileHandle *self, String *path, uint32_t flags) { - FH_do_open((FileHandle*)self, path, flags); + if (!FH_do_open((FileHandle*)self, path, flags)) { return NULL; } FSFileHandleIVARS *const ivars = FSFH_IVARS(self); + if (!path || !Str_Get_Size(path)) { ErrMsg_set("Missing required param 'path'"); - CFISH_DECREF(self); + DECREF(self); return NULL; } // Attempt to open file. - if (flags & FH_WRITE_ONLY) { - char *path_ptr = Str_To_Utf8(path); - ivars->fd = open(path_ptr, SI_posix_flags(flags), 0666); - FREEMEM(path_ptr); - if (ivars->fd == -1) { - ivars->fd = 0; - ErrMsg_set_with_errno("Attempt to open '%o' failed", path); - CFISH_DECREF(self); - return NULL; - } - if (flags & FH_EXCLUSIVE) { - ivars->len = 0; - } - else { - // Derive length. - ivars->len = chy_lseek64(ivars->fd, INT64_C(0), SEEK_END); - if (ivars->len == -1) { - ErrMsg_set_with_errno("lseek64 on %o failed", path); - CFISH_DECREF(self); - return NULL; - } - else { - int64_t check_val - = chy_lseek64(ivars->fd, INT64_C(0), SEEK_SET); - if (check_val == -1) { - ErrMsg_set_with_errno("lseek64 on %o failed", path); - CFISH_DECREF(self); - return NULL; - } - } - } + if (!S_init(ivars, path, flags)) { + DECREF(self); + return NULL; } - else if (flags & FH_READ_ONLY) { - if (SI_init_read_only(self, ivars)) { - // On 64-bit systems, map the whole file up-front. - if (IS_64_BIT && ivars->len) { - ivars->buf = (char*)SI_map(self, ivars, 0, ivars->len); - if (!ivars->buf) { - // An error occurred during SI_map, which has set - // the global error object for us already. - CFISH_DECREF(self); - return NULL; - } - } - } - else { - CFISH_DECREF(self); + + // On 64-bit systems, map the whole file up-front. + if (IS_64_BIT && (flags & FH_READ_ONLY) && ivars->len) { + ivars->buf = (char*)SI_map(self, ivars, 0, ivars->len); + if (!ivars->buf) { + // An error occurred during SI_map, which has set + // the global error object for us already. + DECREF(self); return NULL; } } - else { - ErrMsg_set("Must specify FH_READ_ONLY or FH_WRITE_ONLY to open '%o'", - path); - CFISH_DECREF(self); - return NULL; - } return self; } @@ -171,45 +96,7 @@ FSFH_Close_IMP(FSFileHandle *self) { ivars->buf = NULL; } - // Close system-specific handles. - if (ivars->fd) { - if (close(ivars->fd)) { - ErrMsg_set_with_errno("Failed to close file"); - return false; - } - ivars->fd = 0; - } - #if (defined(CHY_HAS_WINDOWS_H) && !defined(CHY_HAS_SYS_MMAN_H)) - if (ivars->win_fhandle) { - if (!SI_close_win_handles(self)) { return false; } - } - #endif - - return true; -} - -bool -FSFH_Write_IMP(FSFileHandle *self, const void *data, size_t len) { - FSFileHandleIVARS *const ivars = FSFH_IVARS(self); - - if (len) { - // Write data, track file length, check for errors. - int64_t check_val = write(ivars->fd, data, len); - ivars->len += check_val; - if ((size_t)check_val != len) { - if (check_val == -1) { - ErrMsg_set_with_errno("Error when writing %u64 bytes", - (uint64_t)len); - } - else { - ErrMsg_set("Attempted to write %u64 bytes, but wrote %i64", - (uint64_t)len, check_val); - } - return false; - } - } - - return true; + return S_close(ivars); } int64_t @@ -335,42 +222,95 @@ FSFH_Release_Window_IMP(FSFileHandle *self, FileWindow *window) { #ifdef CHY_HAS_SYS_MMAN_H -static CFISH_INLINE bool -SI_init_read_only(FSFileHandle *self, FSFileHandleIVARS *ivars) { - UNUSED_VAR(self); +#include <fcntl.h> // open, POSIX flags +#include <sys/mman.h> +#include <unistd.h> // close + +static bool +S_init(FSFileHandleIVARS *ivars, String *path, uint32_t flags) { + int posix_flags = 0; + if (flags & FH_WRITE_ONLY) { posix_flags |= O_WRONLY; } + if (flags & FH_READ_ONLY) { posix_flags |= O_RDONLY; } + if (flags & FH_CREATE) { posix_flags |= O_CREAT; } + if (flags & FH_EXCLUSIVE) { posix_flags |= O_EXCL; } +#ifdef O_LARGEFILE + posix_flags |= O_LARGEFILE; +#endif - // Open. - char *path_ptr = Str_To_Utf8(ivars->path); - ivars->fd = open(path_ptr, SI_posix_flags(ivars->flags), 0666); + char *path_ptr = Str_To_Utf8(path); + int fd = open(path_ptr, posix_flags, 0666); FREEMEM(path_ptr); - if (ivars->fd == -1) { - ivars->fd = 0; - ErrMsg_set_with_errno("Can't open '%o'", ivars->path); + if (fd == -1) { + ErrMsg_set_with_errno("Attempt to open '%o' failed", path); return false; } - // Derive len. - ivars->len = chy_lseek64(ivars->fd, INT64_C(0), SEEK_END); - if (ivars->len == -1) { - ErrMsg_set_with_errno("lseek64 on %o failed", ivars->path); - return false; + if (flags & FH_EXCLUSIVE) { + ivars->len = 0; } else { - int64_t check_val = chy_lseek64(ivars->fd, INT64_C(0), SEEK_SET); + // Derive length. + ivars->len = chy_lseek64(fd, INT64_C(0), SEEK_END); + if (ivars->len == -1) { + ErrMsg_set_with_errno("lseek64 on %o failed", path); + return false; + } + int64_t check_val = chy_lseek64(fd, INT64_C(0), SEEK_SET); if (check_val == -1) { - ErrMsg_set_with_errno("lseek64 on %o failed", ivars->path); + ErrMsg_set_with_errno("lseek64 on %o failed", path); return false; } } - // Get system page size. + if (flags & FH_READ_ONLY) { + // Get system page size. #if defined(_SC_PAGESIZE) - ivars->page_size = sysconf(_SC_PAGESIZE); + ivars->page_size = sysconf(_SC_PAGESIZE); #elif defined(_SC_PAGE_SIZE) - ivars->page_size = sysconf(_SC_PAGE_SIZE); + ivars->page_size = sysconf(_SC_PAGE_SIZE); #else - #error "Can't determine system memory page size" + #error "Can't determine system memory page size" #endif + } + + ivars->fd = fd; + + return true; +} + +static bool +S_close(FSFileHandleIVARS *ivars) { + // Close system-specific handles. + if (ivars->fd) { + if (close(ivars->fd)) { + ErrMsg_set_with_errno("Failed to close file '%o'", ivars->path); + return false; + } + ivars->fd = 0; + } + return true; +} + +bool +FSFH_Write_IMP(FSFileHandle *self, const void *data, size_t len) { + FSFileHandleIVARS *const ivars = FSFH_IVARS(self); + + if (len) { + // Write data, track file length, check for errors. + int64_t check_val = write(ivars->fd, data, len); + if (check_val == -1) { + ErrMsg_set_with_errno("Error when writing %u64 bytes", + (uint64_t)len); + return false; + } + + ivars->len += check_val; + if ((size_t)check_val != len) { + ErrMsg_set("Attempted to write %u64 bytes, but wrote %i64", + (uint64_t)len, check_val); + return false; + } + } return true; } @@ -441,51 +381,112 @@ FSFH_Read_IMP(FSFileHandle *self, char *dest, int64_t offset, size_t len) { #elif defined(CHY_HAS_WINDOWS_H) -static CFISH_INLINE bool -SI_init_read_only(FSFileHandle *self, FSFileHandleIVARS *ivars) { - UNUSED_VAR(self); - char *filepath = Str_To_Utf8(ivars->path); - SYSTEM_INFO sys_info; - - // Get system page size. - GetSystemInfo(&sys_info); - ivars->page_size = sys_info.dwAllocationGranularity; - - // Open. - ivars->win_fhandle = CreateFile( - filepath, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_READONLY | FILE_FLAG_OVERLAPPED, - NULL - ); - FREEMEM(filepath); - if (ivars->win_fhandle == INVALID_HANDLE_VALUE) { - ErrMsg_set_with_win_error("CreateFile for %o failed", ivars->path); +#include <windows.h> + +static bool +S_init(FSFileHandleIVARS *ivars, String *path, uint32_t flags) { + DWORD desired_access = flags & FH_READ_ONLY + ? GENERIC_READ + : GENERIC_WRITE; + DWORD creation_disposition = flags & FH_CREATE + ? flags & FH_EXCLUSIVE + ? CREATE_NEW + : OPEN_ALWAYS + : OPEN_EXISTING; + + char *path_ptr = Str_To_Utf8(path); + HANDLE handle + = CreateFileA(path_ptr, desired_access, FILE_SHARE_READ, NULL, + creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); + FREEMEM(path_ptr); + + if (handle == INVALID_HANDLE_VALUE) { + ErrMsg_set_with_win_error("CreateFile for '%o' failed", path); return false; } - // Derive len. - DWORD file_size_hi; - DWORD file_size_lo = GetFileSize(ivars->win_fhandle, &file_size_hi); - if (file_size_lo == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) { - ErrMsg_set_with_win_error("GetFileSize for %o failed", ivars->path); - return false; + if (flags & FH_EXCLUSIVE) { + ivars->len = 0; + } + else { + // Derive len. + DWORD file_size_hi; + DWORD file_size_lo = GetFileSize(handle, &file_size_hi); + if (file_size_lo == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) { + ErrMsg_set_with_win_error("GetFileSize for '%o' failed", path); + return false; + } + ivars->len = ((uint64_t)file_size_hi << 32) | file_size_lo; + } + + if (flags & FH_READ_ONLY) { + // Get system page size. + SYSTEM_INFO sys_info; + GetSystemInfo(&sys_info); + ivars->page_size = sys_info.dwAllocationGranularity; + + // Init mapping handle. + if (ivars->len) { + ivars->win_maphandle + = CreateFileMapping(handle, NULL, PAGE_READONLY, 0, 0, NULL); + if (ivars->win_maphandle == NULL) { + ErrMsg_set_with_win_error("CreateFileMapping for '%o' failed", + path); + return false; + } + } + } + + ivars->win_fhandle = handle; + return true; +} + +static bool +S_close(FSFileHandleIVARS *ivars) { + if (ivars->win_fhandle) { + // Close both standard handle and mapping handle. + if (ivars->win_maphandle) { + if (CloseHandle(ivars->win_maphandle) == 0) { + ErrMsg_set_with_win_error("CloseHandle for '%o' mapping" + " failed", ivars->path); + return false; + } + ivars->win_maphandle = NULL; + } + + if (CloseHandle(ivars->win_fhandle) == 0) { + ErrMsg_set_with_win_error("CloseHandle for '%o' failed", + ivars->path); + return false; + } + ivars->win_fhandle = NULL; } - ivars->len = ((uint64_t)file_size_hi << 32) | file_size_lo; - // Init mapping handle. - ivars->buf = NULL; - if (ivars->len) { - ivars->win_maphandle = CreateFileMapping(ivars->win_fhandle, NULL, - PAGE_READONLY, 0, 0, NULL); - if (ivars->win_maphandle == NULL) { - ErrMsg_set_with_win_error("CreateFileMapping for %o failed", + return true; +} + +bool +FSFH_Write_IMP(FSFileHandle *self, const void *vdata, size_t len) { + FSFileHandleIVARS *const ivars = FSFH_IVARS(self); + const char *data = (const char*)vdata; + + while (len) { + // Write in 2GB chunks. + DWORD to_write = len > 0x80000000 ? 0x80000000 : len; + DWORD written = 0; + + // Write data, track file length, check for errors. + BOOL result + = WriteFile(ivars->win_fhandle, data, to_write, &written, NULL); + ivars->len += written; + if (result == 0) { + ErrMsg_set_with_win_error("WriteFile for '%o' failed", ivars->path); return false; } + + data += to_write; + len -= to_write; } return true; @@ -517,6 +518,7 @@ SI_map(FSFileHandle *self, FSFileHandleIVARS *ivars, int64_t offset, static CFISH_INLINE bool SI_unmap(FSFileHandle *self, char *buf, int64_t len) { UNUSED_VAR(self); + UNUSED_VAR(len); if (buf != NULL) { if (!UnmapViewOfFile(buf)) { ErrMsg_set_with_win_error("Failed to unmap '%o'", @@ -527,40 +529,10 @@ SI_unmap(FSFileHandle *self, char *buf, int64_t len) { return true; } -static CFISH_INLINE bool -SI_close_win_handles(FSFileHandle *self) { - FSFileHandleIVARS *ivars = FSFH_IVARS(self); - // Close both standard handle and mapping handle. - if (ivars->win_maphandle) { - if (!CloseHandle(ivars->win_maphandle)) { - ErrMsg_set_with_win_error("Failed to close file mapping handle"); - return false; - } - ivars->win_maphandle = NULL; - } - if (ivars->win_fhandle) { - if (!CloseHandle(ivars->win_fhandle)) { - ErrMsg_set_with_win_error("Failed to close file handle"); - return false; - } - ivars->win_fhandle = NULL; - } - - return true; -} - #if !IS_64_BIT bool FSFH_Read_IMP(FSFileHandle *self, char *dest, int64_t offset, size_t len) { FSFileHandleIVARS *const ivars = FSFH_IVARS(self); - BOOL check_val; - DWORD got; - OVERLAPPED read_op_state; - uint64_t offs = (uint64_t)offset; - - read_op_state.hEvent = NULL; - read_op_state.OffsetHigh = offs >> 32; - read_op_state.Offset = offs & 0xFFFFFFFF; // Sanity check. if (offset < 0) { @@ -568,33 +540,29 @@ FSFH_Read_IMP(FSFileHandle *self, char *dest, int64_t offset, size_t len) { return false; } - // ReadFile() takes a DWORD (unsigned 32-bit integer) as a length - // argument, so throw a sensible error rather than wrap around. - if (len > UINT32_MAX) { - ErrMsg_set("Can't read more than 4 GB (%u64)", (uint64_t)len); - return false; - } - - // Read. - check_val = ReadFile(ivars->win_fhandle, dest, len, &got, &read_op_state); - if (!check_val && GetLastError() == ERROR_IO_PENDING) { - // Read has been queued by the OS and will soon complete. Wait for - // it, since this is a blocking IO call from the point of the rest of - // the library. - check_val = GetOverlappedResult(ivars->win_fhandle, &read_op_state, - &got, TRUE); - } + DWORD got; + OVERLAPPED overlapped; + overlapped.hEvent = NULL; + overlapped.OffsetHigh = offset >> 32; + overlapped.Offset = offset & 0xFFFFFFFF; - // Verify that the read has succeeded by now. - if (!check_val) { + if (ReadFile(ivars->win_fhandle, dest, len, &got, &overlapped) == 0) { ErrMsg_set_with_win_error("Failed to read %u64 bytes", (uint64_t)len); return false; } + if (got < len) { + ErrMsg_set("Tried to read %u64 bytes, got %u32", (uint64_t)len, got); + return false; + } return true; } #endif // !IS_64_BIT +#else // CHY_HAS_SYS_MMAN_H vs. CHY_HAS_WINDOWS_H + +#error "No support for memory mapped files" + #endif // CHY_HAS_SYS_MMAN_H vs. CHY_HAS_WINDOWS_H http://git-wip-us.apache.org/repos/asf/lucy/blob/5f15a92b/core/Lucy/Store/FileHandle.c ---------------------------------------------------------------------- diff --git a/core/Lucy/Store/FileHandle.c b/core/Lucy/Store/FileHandle.c index 276987e..017989e 100644 --- a/core/Lucy/Store/FileHandle.c +++ b/core/Lucy/Store/FileHandle.c @@ -18,18 +18,40 @@ #include "Lucy/Util/ToolSet.h" #include "Lucy/Store/FileHandle.h" +#include "Lucy/Store/ErrorMessage.h" int32_t FH_object_count = 0; FileHandle* FH_do_open(FileHandle *self, String *path, uint32_t flags) { + // Track number of live FileHandles released into the wild. + FH_object_count++; + + // Check flags. + uint32_t rw_flags = flags & (FH_READ_ONLY | FH_WRITE_ONLY); + if (rw_flags == 0) { + ErrMsg_set("Must specify FH_READ_ONLY or FH_WRITE_ONLY to open '%o'", + path); + DECREF(self); + return NULL; + } + else if (rw_flags == (FH_READ_ONLY | FH_WRITE_ONLY)) { + ErrMsg_set("Can't specify both FH_READ_ONLY and FH_WRITE_ONLY to" + " open '%o'", path); + DECREF(self); + return NULL; + } + if ((flags & (FH_CREATE | FH_EXCLUSIVE)) == FH_EXCLUSIVE) { + ErrMsg_set("Can't specify FH_EXCLUSIVE without FH_CREATE to" + " open '%o' ", path); + DECREF(self); + return NULL; + } + FileHandleIVARS *const ivars = FH_IVARS(self); ivars->path = path ? Str_Clone(path) : Str_new_from_trusted_utf8("", 0); ivars->flags = flags; - // Track number of live FileHandles released into the wild. - FH_object_count++; - ABSTRACT_CLASS_CHECK(self, FILEHANDLE); return self; } http://git-wip-us.apache.org/repos/asf/lucy/blob/5f15a92b/core/Lucy/Store/RAMFileHandle.c ---------------------------------------------------------------------- diff --git a/core/Lucy/Store/RAMFileHandle.c b/core/Lucy/Store/RAMFileHandle.c index c87c606..0768807 100644 --- a/core/Lucy/Store/RAMFileHandle.c +++ b/core/Lucy/Store/RAMFileHandle.c @@ -30,6 +30,9 @@ RAMFH_open(String *path, uint32_t flags, RAMFile *file) { RAMFileHandle* RAMFH_do_open(RAMFileHandle *self, String *path, uint32_t flags, RAMFile *file) { + if (!FH_do_open((FileHandle*)self, path, flags)) { return NULL; } + RAMFileHandleIVARS *const ivars = RAMFH_IVARS(self); + bool must_create = (flags & (FH_CREATE | FH_EXCLUSIVE)) == (FH_CREATE | FH_EXCLUSIVE) ? true : false; @@ -37,9 +40,6 @@ RAMFH_do_open(RAMFileHandle *self, String *path, uint32_t flags, = (flags & (FH_CREATE | FH_WRITE_ONLY)) == (FH_CREATE | FH_WRITE_ONLY) ? true : false; - FH_do_open((FileHandle*)self, path, flags); - RAMFileHandleIVARS *const ivars = RAMFH_IVARS(self); - // Obtain a RAMFile. if (file) { if (must_create) { http://git-wip-us.apache.org/repos/asf/lucy/blob/5f15a92b/test/Lucy/Test/Store/MockFileHandle.c ---------------------------------------------------------------------- diff --git a/test/Lucy/Test/Store/MockFileHandle.c b/test/Lucy/Test/Store/MockFileHandle.c index 029eb5f..2762afd 100644 --- a/test/Lucy/Test/Store/MockFileHandle.c +++ b/test/Lucy/Test/Store/MockFileHandle.c @@ -31,7 +31,7 @@ MockFileHandle_new(String *path, int64_t length) { MockFileHandle* MockFileHandle_init(MockFileHandle *self, String *path, int64_t length) { - FH_do_open((FileHandle*)self, path, 0); + if (!FH_do_open((FileHandle*)self, path, FH_READ_ONLY)) { return NULL; } MockFileHandleIVARS *const ivars = MockFileHandle_IVARS(self); ivars->len = length; return self; http://git-wip-us.apache.org/repos/asf/lucy/blob/5f15a92b/test/Lucy/Test/Store/TestFSFileHandle.c ---------------------------------------------------------------------- diff --git a/test/Lucy/Test/Store/TestFSFileHandle.c b/test/Lucy/Test/Store/TestFSFileHandle.c index 518b71c..5e1c651 100644 --- a/test/Lucy/Test/Store/TestFSFileHandle.c +++ b/test/Lucy/Test/Store/TestFSFileHandle.c @@ -22,11 +22,7 @@ #define TESTLUCY_USE_SHORT_NAMES #include "Lucy/Util/ToolSet.h" -#ifdef CHY_HAS_UNISTD_H - #include <unistd.h> // close -#elif defined(CHY_HAS_IO_H) - #include <io.h> // close -#endif +#include "charmony.h" #include "Clownfish/TestHarness/TestBatchRunner.h" #include "Lucy/Test.h" @@ -159,6 +155,12 @@ test_Read_Write(TestBatchRunner *runner) { "Read() past EOF sets error"); Err_set_error(NULL); + TEST_FALSE(runner, FSFH_Read(fh, buf, 4, 3), + "Read() across EOF returns false"); + TEST_TRUE(runner, Err_get_error() != NULL, + "Read() across EOF sets error"); + + Err_set_error(NULL); TEST_FALSE(runner, FSFH_Write(fh, foo, 3), "Writing to a read-only handle returns false"); TEST_TRUE(runner, Err_get_error() != NULL, @@ -184,8 +186,8 @@ test_Close(TestBatchRunner *runner) { S_remove(test_filename); fh = FSFH_open(test_filename, FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE); -#ifdef _MSC_VER - SKIP(runner, 2, "LUCY-155"); +#if defined(CHY_HAS_WINDOWS_H) && !defined(CHY_HAS_SYS_MMAN_H) + SKIP(runner, 2, "Can't test invalid file handles on Windows"); #else int saved_fd = FSFH_Set_FD(fh, -1); Err_set_error(NULL); @@ -194,7 +196,7 @@ test_Close(TestBatchRunner *runner) { TEST_TRUE(runner, Err_get_error() != NULL, "Failed Close() sets global error"); FSFH_Set_FD(fh, saved_fd); -#endif /* _MSC_VER */ +#endif // Windows check. DECREF(fh); fh = FSFH_open(test_filename, FH_READ_ONLY); @@ -260,7 +262,7 @@ test_Window(TestBatchRunner *runner) { void TestFSFH_Run_IMP(TestFSFileHandle *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 46); + TestBatchRunner_Plan(runner, (TestBatch*)self, 48); test_open(runner); test_Read_Write(runner); test_Close(runner); http://git-wip-us.apache.org/repos/asf/lucy/blob/5f15a92b/test/Lucy/Test/Store/TestFileHandle.c ---------------------------------------------------------------------- diff --git a/test/Lucy/Test/Store/TestFileHandle.c b/test/Lucy/Test/Store/TestFileHandle.c index 2e9850f..739f856 100644 --- a/test/Lucy/Test/Store/TestFileHandle.c +++ b/test/Lucy/Test/Store/TestFileHandle.c @@ -46,7 +46,7 @@ S_new_filehandle() { } Class_Override(klass, S_no_op_method, LUCY_FH_Close_OFFSET); fh = (FileHandle*)Class_Make_Obj(klass); - return FH_do_open(fh, NULL, 0); + return FH_do_open(fh, NULL, FH_READ_ONLY); } void