Esempio n. 1
0
static INLINE bool_t
SI_close_win_handles(FSFileHandle *self) {
    // Close both standard handle and mapping handle.
    if (self->win_maphandle) {
        if (!CloseHandle(self->win_maphandle)) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf("Failed to close file mapping handle: %s",
                                          win_error)));
            FREEMEM(win_error);
            return false;
        }
        self->win_maphandle = NULL;
    }
    if (self->win_fhandle) {
        if (!CloseHandle(self->win_fhandle)) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf("Failed to close file handle: %s",
                                          win_error)));
            FREEMEM(win_error);
            return false;
        }
        self->win_fhandle = NULL;
    }

    return true;
}
Esempio n. 2
0
static INLINE bool_t 
SI_init_read_only(FSFileHandle *self)
{
    LARGE_INTEGER large_int;
    char *filepath = (char*)CB_Get_Ptr8(self->path);
    SYSTEM_INFO sys_info;

    // Get system page size. 
    GetSystemInfo(&sys_info);
    self->page_size = sys_info.dwAllocationGranularity;

    // Open. 
    self->win_fhandle = CreateFile(
        filepath,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_READONLY | FILE_FLAG_OVERLAPPED,
        NULL
    );
    if (self->win_fhandle == INVALID_HANDLE_VALUE) {
        char *win_error = Err_win_error();
        Err_set_error(Err_new(CB_newf("CreateFile for %o failed: %s", 
            self->path, win_error)));
        FREEMEM(win_error);
        return false;
    }

    // Derive len. 
    GetFileSizeEx(self->win_fhandle, &large_int);
    self->len = large_int.QuadPart;
    if (self->len < 0) {
        Err_set_error(Err_new(CB_newf(
            "GetFileSizeEx for %o returned a negative length: '%i64'", 
            self->path, self->len)));
        return false;
    }

    // Init mapping handle. 
    self->buf = NULL;
    if (self->len) {
        self->win_maphandle = CreateFileMapping(self->win_fhandle, NULL,
            PAGE_READONLY, 0, 0, NULL);
        if (self->win_maphandle == NULL) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf(
                "CreateFileMapping for %o failed: %s", 
                self->path, win_error)));
            FREEMEM(win_error);
            return false;
        }
    }
    
    return true;
}
Esempio n. 3
0
static INLINE bool
SI_init_read_only(FSFileHandle *self, FSFileHandleIVARS *ivars) {
    char *filepath = (char*)CB_Get_Ptr8(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
                        );
    if (ivars->win_fhandle == INVALID_HANDLE_VALUE) {
        char *win_error = Err_win_error();
        Err_set_error(Err_new(CB_newf("CreateFile for %o failed: %s",
                                      ivars->path, win_error)));
        FREEMEM(win_error);
        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) {
        Err_set_error(Err_new(CB_newf("GetFileSize for %o failed",
                                      ivars->path)));
        return false;
    }
    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) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf("CreateFileMapping for %o failed: %s",
                                          ivars->path, win_error)));
            FREEMEM(win_error);
            return false;
        }
    }

    return true;
}
Esempio n. 4
0
static INLINE void*
SI_map(FSFileHandle *self, int64_t offset, int64_t len)
{
    void *buf = NULL;

    if (len) {
        // Read-only memory map. 
        uint64_t offs = (uint64_t)offset;
        DWORD file_offset_hi = offs >> 32;
        DWORD file_offset_lo = offs & 0xFFFFFFFF;
        size_t amount = (size_t)len;
        buf = MapViewOfFile(
            self->win_maphandle, 
            FILE_MAP_READ, 
            file_offset_hi,
            file_offset_lo,
            amount
        );
        if (buf == NULL) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf(
                "MapViewOfFile for %o failed: %s", 
                self->path, win_error)));
            FREEMEM(win_error);
        }
    }

    return buf;
}
Esempio n. 5
0
bool
FSDH_close(FSDirHandle *self) {
    FSDirHandleIVARS *const ivars = FSDH_IVARS(self);
    if (ivars->sys_dirhandle && ivars->sys_dirhandle != INVALID_HANDLE_VALUE) {
        HANDLE dirhandle = (HANDLE)ivars->sys_dirhandle;
        ivars->sys_dirhandle = NULL;
        if (dirhandle != INVALID_HANDLE_VALUE && !FindClose(dirhandle)) {
            if (!ivars->saved_error) {
                char *win_error = Err_win_error();
                ivars->saved_error
                    = Err_new(CB_newf("Error while closing directory: %s",
                                      win_error));
                FREEMEM(win_error);
            }
        }
    }
    if (ivars->sys_dir_entry) {
        FREEMEM(ivars->sys_dir_entry);
        ivars->sys_dir_entry = NULL;
    }

    // If we encountered an error condition previously, report it now.
    if (ivars->saved_error) {
        Err_set_error((Err*)CFISH_INCREF(ivars->saved_error));
        return false;
    }
    else {
        return true;
    }
}
Esempio n. 6
0
static INLINE bool_t
SI_unmap(FSFileHandle *self, char *buf, int64_t len) {
    if (buf != NULL) {
        if (!UnmapViewOfFile(buf)) {
            char *win_error = Err_win_error();
            Err_set_error(Err_new(CB_newf("Failed to unmap '%o': %s",
                                          self->path, win_error)));
            FREEMEM(win_error);
            return false;
        }
    }
    return true;
}
Esempio n. 7
0
static bool
S_hard_link(char *from8, char *to8) {
    if (CreateHardLink(to8, from8, NULL)) {
        return true;
    }
    else {
        char *win_error = Err_win_error();
        Err_set_error(Err_new(Str_newf("CreateHardLink for new file '%s' from '%s' failed: %s",
                                       to8, from8, win_error)));
        FREEMEM(win_error);
        return false;
    }
}
Esempio n. 8
0
bool_t
FSFH_read(FSFileHandle *self, char *dest, int64_t offset, size_t len)
{
    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) {
        Err_set_error(Err_new(CB_newf(
            "Can't read from an offset less than 0 (%i64)", offset)));
        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 > U32_MAX) {
        Err_set_error(Err_new(CB_newf(
            "Can't read more than 4 GB (%u64)", (uint64_t)len))); 
        return false;
    }

    // Read. 
    check_val = ReadFile(self->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(self->win_fhandle, &read_op_state,
           &got, TRUE);
    }

    // Verify that the read has succeeded by now. 
    if (!check_val) {
        char *win_error = Err_win_error();
        Err_set_error(Err_new(CB_newf("Failed to read %u64 bytes: %s",
            (uint64_t)len, win_error)));
        FREEMEM(win_error);
        return false;
    }

    return true;
}
Esempio n. 9
0
void
ErrMsg_set_with_win_error(const char *fmt, ...) {
    char *win_error = Err_win_error();

    CharBuf *buf = CB_new(0);

    va_list args;
    va_start(args, fmt);
    CB_VCatF(buf, fmt, args);
    va_end(args);

    CB_Cat_Trusted_Utf8(buf, ": ", 2);
    CB_Cat_Utf8(buf, win_error, strlen(win_error));

    Err_set_error(Err_new(CB_Yield_String(buf)));
    DECREF(buf);
    FREEMEM(win_error);
}
Esempio n. 10
0
bool
FSDH_next(FSDirHandle *self) {
    FSDirHandleIVARS *const ivars = FSDH_IVARS(self);
    HANDLE           dirhandle = (HANDLE)ivars->sys_dirhandle;
    WIN32_FIND_DATA *find_data = (WIN32_FIND_DATA*)ivars->sys_dir_entry;

    // Attempt to move forward or absorb cached iter.
    if (!dirhandle || dirhandle == INVALID_HANDLE_VALUE) {
        return false;
    }
    else if (ivars->delayed_iter) {
        ivars->delayed_iter = false;
    }
    else if ((FindNextFile(dirhandle, find_data) == 0)) {
        // Iterator exhausted.  Verify that no errors were encountered.
        CB_Set_Size(ivars->entry, 0);
        if (GetLastError() != ERROR_NO_MORE_FILES) {
            char *win_error = Err_win_error();
            ivars->saved_error
                = Err_new(CB_newf("Error while traversing directory: %s",
                                  win_error));
            FREEMEM(win_error);
        }
        return false;
    }

    // Process the results of the iteration.
    size_t len = strlen(find_data->cFileName);
    if (SI_is_updir(find_data->cFileName, len)) {
        return FSDH_Next(self);
    }
    else {
        CB_Mimic_Str(ivars->entry, find_data->cFileName, len);
        return true;
    }
}