static Sint64 internal_sync_io(efile_win_t *w, io_op_t operation, SysIOVec *iov, int iovlen, OVERLAPPED *overlapped) { Sint64 bytes_processed = 0; for(;;) { DWORD block_bytes_processed, last_error; BOOL succeeded; if(iovlen < 1) { return bytes_processed; } succeeded = operation(w->handle, iov->iov_base, iov->iov_len, &block_bytes_processed, overlapped); last_error = GetLastError(); if(!succeeded && (last_error != ERROR_HANDLE_EOF)) { w->common.posix_errno = windows_to_posix_errno(last_error); return -1; } else if(block_bytes_processed == 0) { /* EOF */ return bytes_processed; } if(overlapped != NULL) { shift_overlapped(overlapped, block_bytes_processed); } shift_iov(&iov, &iovlen, block_bytes_processed); bytes_processed += block_bytes_processed; } }
Sint64 efile_preadv(efile_data_t *d, Sint64 offset, SysIOVec *iov, int iovlen) { efile_unix_t *u = (efile_unix_t*)d; Uint64 bytes_read; Sint64 result; #if !defined(HAVE_PREADV) && !defined(HAVE_PREAD) /* This function is documented as leaving the file position undefined, but * the old driver always reset it so there's probably code in the wild that * relies on this behavior. */ off_t original_position = lseek(u->fd, 0, SEEK_CUR); if(original_position < 0 || lseek(u->fd, offset, SEEK_SET) < 0) { u->common.posix_errno = errno; return -1; } #endif bytes_read = 0; do { if(iovlen < 1) { result = 0; break; } #if defined(HAVE_PREADV) result = preadv(u->fd, iov, MIN(IOV_MAX, iovlen), offset); #elif defined(HAVE_PREAD) result = pread(u->fd, iov->iov_base, iov->iov_len, offset); #else result = read(u->fd, iov->iov_base, iov->iov_len); #endif if(result > 0) { shift_iov(&iov, &iovlen, result); bytes_read += result; offset += result; } } while(result > 0 || (result < 0 && errno == EINTR)); u->common.posix_errno = errno; #if !defined(HAVE_PREADV) && !defined(HAVE_PREAD) if(result >= 0) { if(lseek(u->fd, original_position, SEEK_SET) < 0) { u->common.posix_errno = errno; return -1; } } #endif if(result == 0 && bytes_read > 0) { return bytes_read; } return result; }
Sint64 efile_pwritev(efile_data_t *d, Sint64 offset, SysIOVec *iov, int iovlen) { efile_unix_t *u = (efile_unix_t*)d; Sint64 bytes_written; ssize_t result; #if !defined(HAVE_PWRITEV) && !defined(HAVE_PWRITE) off_t original_position = lseek(u->fd, 0, SEEK_CUR); if(original_position < 0 || lseek(u->fd, offset, SEEK_SET) < 0) { u->common.posix_errno = errno; return -1; } #endif bytes_written = 0; do { if(iovlen < 1) { result = 0; break; } #if defined(HAVE_PWRITEV) result = pwritev(u->fd, iov, MIN(IOV_MAX, iovlen), offset); #elif defined(HAVE_PWRITE) result = pwrite(u->fd, iov->iov_base, iov->iov_len, offset); #else result = write(u->fd, iov->iov_base, iov->iov_len); #endif if(result > 0) { shift_iov(&iov, &iovlen, result); bytes_written += result; offset += result; } } while(result > 0 || (result < 0 && errno == EINTR)); u->common.posix_errno = errno; #if !defined(HAVE_PWRITEV) && !defined(HAVE_PWRITE) if(result >= 0) { if(lseek(u->fd, original_position, SEEK_SET) < 0) { u->common.posix_errno = errno; return -1; } } #endif if(result == 0 && bytes_written > 0) { return bytes_written; } return result; }
Sint64 efile_readv(efile_data_t *d, SysIOVec *iov, int iovlen) { efile_unix_t *u = (efile_unix_t*)d; Sint64 bytes_read; ssize_t result; bytes_read = 0; do { int use_fallback = 0; if(iovlen < 1) { result = 0; break; } /* writev(2) implies readv(2) */ #ifdef HAVE_WRITEV result = readv(u->fd, iov, MIN(IOV_MAX, iovlen)); /* Fall back to using read(2) if readv(2) reports that the combined * size of iov is greater than SSIZE_T_MAX. */ use_fallback = (result < 0 && errno == EINVAL); #else use_fallback = 1; #endif if(use_fallback) { result = read(u->fd, iov->iov_base, iov->iov_len); } if(result > 0) { shift_iov(&iov, &iovlen, result); bytes_read += result; } } while(result > 0 || (result < 0 && errno == EINTR)); u->common.posix_errno = errno; if(result == 0 && bytes_read > 0) { return bytes_read; } return result; }