/** * Internal, but used from dvd_udf.c * * @param device A read handle. * @param lb_number Logical block number to start read from. * @param block_count Number of logical blocks to read. * @param data Pointer to buffer where read data should be stored. * This buffer must be large enough to hold lb_number*2048 bytes. * The pointer must be aligned to the logical block size when * reading from a raw/O_DIRECT device. * @param encrypted 0 if no decryption shall be performed, * 1 if decryption shall be performed * @param return Returns number of blocks read on success, negative on error */ int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) { int ret; if( !device->dev ) { if(device->verbose >= 1) { fprintf( stderr, "libdvdread: Fatal error in block read.\n" ); } return 0; } ret = dvdinput_seek( device->dev, (int) lb_number ); if( ret != (int) lb_number ) { if(device->verbose >= 1) { fprintf( stderr, "libdvdread: UDFReadBlocksRaw: Can't seek to block %u\n", lb_number ); } return 0; } return dvdinput_read( device->dev, (char *) data, (int) block_count, encrypted ); }
/* Internal, but used from dvd_udf.c */ int InternalUDFReadBlocksRaw( const dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) { int ret; if( !device->dev ) { fprintf( stderr, "libdvdread: Fatal error in block read.\n" ); return 0; } ret = dvdinput_seek( device->dev, (int) lb_number, encrypted & DVDCSS_SEEK_KEY ); if( ret != (int) lb_number ) { fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number ); return 0; } ret = dvdinput_read( device->dev, (char *) data, (int) block_count, encrypted & DVDINPUT_READ_DECRYPT ); return ret; }
/* This is using possibly several inputs and starting from an offset of '0'. * * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' * into the buffer located at 'data' and if 'encrypted' is set * descramble the data if it's encrypted. Returning either an * negative error or the number of blocks read. */ static int DVDReadBlocksPath( const dvd_file_t *dvd_file, unsigned int offset, size_t block_count, unsigned char *data, int encrypted ) { int i; int ret, ret2, off; ret = 0; ret2 = 0; for( i = 0; i < TITLES_MAX; ++i ) { if( !dvd_file->title_sizes[ i ] ) return 0; /* Past end of file */ if( offset < dvd_file->title_sizes[ i ] ) { if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) { off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset, DVDINPUT_NOFLAGS ); if( off < 0 || off != (int)offset ) { fprintf( stderr, "libdvdread: Can't seek to block %u\n", offset ); return off < 0 ? off : 0; } ret = dvdinput_read( dvd_file->title_devs[ i ], data, (int)block_count, encrypted ); break; } else { size_t part1_size = dvd_file->title_sizes[ i ] - offset; /* FIXME: Really needs to be a while loop. * (This is only true if you try and read >1GB at a time) */ /* Read part 1 */ off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset, DVDINPUT_NOFLAGS ); if( off < 0 || off != (int)offset ) { fprintf( stderr, "libdvdread: Can't seek to block %u\n", offset ); return off < 0 ? off : 0; } ret = dvdinput_read( dvd_file->title_devs[ i ], data, (int)part1_size, encrypted ); if( ret < 0 ) return ret; /* FIXME: This is wrong if i is the last file in the set. * also error from this read will not show in ret. */ /* Does the next part exist? If not then return now. */ if( i + 1 >= TITLES_MAX || !dvd_file->title_devs[ i + 1 ] ) return ret; /* Read part 2 */ off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0, DVDINPUT_NOFLAGS ); if( off < 0 || off != 0 ) { fprintf( stderr, "libdvdread: Can't seek to block %d\n", 0 ); return off < 0 ? off : 0; } ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ], data + ( part1_size * (int64_t)DVD_VIDEO_LB_LEN ), (int)(block_count - part1_size), encrypted ); if( ret2 < 0 ) return ret2; break; } } else { offset -= dvd_file->title_sizes[ i ]; } } return ret + ret2; }