int DVDISOVolumeInfo( dvd_reader_t *dvd, char *volid, unsigned int volid_size, unsigned char *volsetid, unsigned int volsetid_size ) { unsigned char *buffer, *buffer_base; int ret; /* Check arguments. */ if( dvd == NULL ) return 0; if( dvd->dev == NULL ) { /* No block access, so no ISO... */ return -1; } buffer_base = malloc( DVD_VIDEO_LB_LEN + 2048 ); if( buffer_base == NULL ) { fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " "allocate memory for file read!\n" ); return -1; } buffer = (unsigned char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048); ret = InternalUDFReadBlocksRaw( dvd, 16, 1, buffer, 0 ); if( ret != 1 ) { fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " "read ISO9660 Primary Volume Descriptor!\n" ); free( buffer_base ); return -1; } if( (volid != NULL) && (volid_size > 0) ) { unsigned int n; for(n = 0; n < 32; n++) { if(buffer[40+n] == 0x20) { break; } } if(volid_size > n+1) { volid_size = n+1; } memcpy(volid, &buffer[40], volid_size-1); volid[volid_size-1] = '\0'; } if( (volsetid != NULL) && (volsetid_size > 0) ) { if(volsetid_size > 128) { volsetid_size = 128; } memcpy(volsetid, &buffer[190], volsetid_size); } free( buffer_base ); return 0; }
/** * Open an unencrypted file on a DVD image file. */ static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, const char *filename, int do_cache ) { uint32_t start, len; dvd_file_t *dvd_file; start = UDFFindFile( dvd, filename, &len ); if( !start ) { fprintf( stderr, "libdvdread:DVDOpenFileUDF:UDFFindFile %s failed\n", filename ); return NULL; } dvd_file = calloc( 1, sizeof( dvd_file_t ) ); if( !dvd_file ) { fprintf( stderr, "libdvdread:DVDOpenFileUDF:malloc failed\n" ); return NULL; } dvd_file->dvd = dvd; dvd_file->lb_start = start; dvd_file->filesize = len / DVD_VIDEO_LB_LEN; /* Read the whole file in cache (unencrypted) if asked and if it doesn't * exceed 128KB */ if( do_cache && len < 64 * DVD_VIDEO_LB_LEN ) { int ret; dvd_file->cache = malloc( len ); if( !dvd_file->cache ) return dvd_file; ret = InternalUDFReadBlocksRaw( dvd, dvd_file->lb_start, dvd_file->filesize, dvd_file->cache, DVDINPUT_NOFLAGS ); if( ret != dvd_file->filesize ) { free( dvd_file->cache ); dvd_file->cache = NULL; } } return dvd_file; }
/* It's required to either fail or deliver all the blocks asked for. */ static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) { size_t count = block_count; while(count > 0) { int ret; ret = InternalUDFReadBlocksRaw(device, lb_number, count, data + DVD_VIDEO_LB_LEN * (block_count - count), encrypted); if(ret <= 0) { /* One of the reads failed or nothing more to read, too bad. * We won't even bother returning the reads that went ok. */ return ret; } count -= (size_t)ret; lb_number += (uint32_t)ret; } return block_count; }
/* This is using a single input and starting from 'dvd_file->lb_start' offset. * * 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 DVDReadBlocksUDF( const dvd_file_t *dvd_file, uint32_t offset, size_t block_count, unsigned char *data, int encrypted ) { /* If the cache is present and we don't need to decrypt, use the cache to * feed the data */ if( dvd_file->cache && (encrypted & DVDINPUT_READ_DECRYPT) == 0 ) { /* Check if we don't exceed the cache (or file) size */ if( block_count + offset > (size_t) dvd_file->filesize ) return 0; /* Copy the cache at a specified offset into data. offset and block_count * must be converted into bytes */ memcpy( data, dvd_file->cache + (off_t)offset * (off_t)DVD_VIDEO_LB_LEN, (off_t)block_count * (off_t)DVD_VIDEO_LB_LEN ); /* return the amount of blocks copied */ return block_count; } else { /* use dvdinput access */ return InternalUDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset, block_count, data, encrypted ); } }
//virtual int DVDStream::safe_read(void *data, uint size) { uint32_t lb = size / DVD_VIDEO_LB_LEN; if (lb < 1) { LOG(VB_GENERAL, LOG_ERR, "DVDStream::safe_read too small"); return -1; } if (!m_reader) return -1; int ret = 0; // Are any blocks in the range encrypted? list_t::const_iterator it; it = std::lower_bound(m_list.begin(), m_list.end(), BlockRange(m_pos, lb, -1)); uint32_t b = it == m_list.end() ? lb : m_pos < it->Start() ? it->Start() - m_pos : 0; if (b) { // Read the beginning unencrypted blocks ret = InternalUDFReadBlocksRaw(m_reader, m_pos, b, (unsigned char*)data, DVDINPUT_NOFLAGS); if (ret == -1) { LOG(VB_GENERAL, LOG_ERR, "DVDStream::safe_read DVDReadBlocks error"); return -1; } m_pos += ret; lb -= ret; if (it == m_list.end()) return ret * DVD_VIDEO_LB_LEN; data = (unsigned char*)data + ret * DVD_VIDEO_LB_LEN; } b = it->End() - m_pos; if (b > lb) b = lb; // Request new key if change in title int flags = DVDINPUT_READ_DECRYPT; if (it->Title() != m_title) { m_title = it->Title(); flags |= DVDCSS_SEEK_KEY; } // Read the encrypted blocks int ret2 = InternalUDFReadBlocksRaw(m_reader, m_pos + m_start, b, (unsigned char*)data, flags); if (ret2 == -1) { LOG(VB_GENERAL, LOG_ERR, "DVDStream::safe_read DVDReadBlocks error"); m_title = -1; return -1; } m_pos += ret2; ret += ret2; lb -= ret2; data = (unsigned char*)data + ret2 * DVD_VIDEO_LB_LEN; if (lb > 0 && m_start == 0) { // Read the last unencrypted blocks ret2 = InternalUDFReadBlocksRaw(m_reader, m_pos, lb, (unsigned char*)data, DVDINPUT_NOFLAGS); if (ret2 == -1) { LOG(VB_GENERAL, LOG_ERR, "DVDStream::safe_read DVDReadBlocks error"); return -1; } m_pos += ret2; ret += ret2;; } return ret * DVD_VIDEO_LB_LEN; }