/***************************************************************************** * Read commands. *****************************************************************************/ static int libc_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) { off_t i_size, i_ret, i_ret_blocks; i_size = (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE; i_ret = 0; while (i_ret < i_size) { off_t i_r; i_r = read(dvdcss->i_fd, ((char*)p_buffer) + i_ret, i_size - i_ret); if (i_r < 0) { print_error(dvdcss, "read error"); dvdcss->i_pos = -1; return i_r; } if (i_r == 0) break; i_ret += i_r; } i_ret_blocks = i_ret / DVDCSS_BLOCK_SIZE; /* Handle partial reads */ if( i_ret != i_size ) { int i_seek, i_set_pos; i_set_pos = dvdcss->i_pos + i_ret_blocks; dvdcss->i_pos = -1; i_seek = libc_seek( dvdcss, i_set_pos ); if( i_seek < 0 ) { return i_seek; } /* We have to return now so that i_pos isn't clobbered */ return i_ret_blocks; } dvdcss->i_pos += i_ret_blocks; return i_ret_blocks; }
/***************************************************************************** * Readv commands. *****************************************************************************/ static int libc_readv ( dvdcss_t dvdcss, const struct iovec *p_iovec, int i_blocks ) { #if defined( _WIN32 ) int i_index, i_len, i_total = 0; unsigned char *p_base; int i_bytes; for( i_index = i_blocks; i_index; i_index--, p_iovec++ ) { i_len = p_iovec->iov_len; p_base = p_iovec->iov_base; if( i_len <= 0 ) { continue; } i_bytes = read( dvdcss->i_fd, p_base, i_len ); if( i_bytes < 0 ) { /* One of the reads failed, too bad. * We won't even bother returning the reads that went OK, * and as in the POSIX spec the file position is left * unspecified after a failure */ dvdcss->i_pos = -1; return -1; } i_total += i_bytes; i_total /= DVDCSS_BLOCK_SIZE; if( i_bytes != i_len ) { /* We reached the end of the file or a signal interrupted * the read. Return a partial read. */ int i_seek; dvdcss->i_pos = -1; i_seek = libc_seek( dvdcss, i_total ); if( i_seek < 0 ) { return i_seek; } /* We have to return now so that i_pos isn't clobbered */ return i_total; } } dvdcss->i_pos += i_total; return i_total; #else int i_read = readv( dvdcss->i_fd, p_iovec, i_blocks ); if( i_read < 0 ) { dvdcss->i_pos = -1; return i_read; } i_read /= DVDCSS_BLOCK_SIZE; dvdcss->i_pos += i_read; return i_read; #endif }