/** * Allocates aligned memory (for use with reads from raw/O_DIRECT devices). * This memory must be freed with dvdalign_free() * The size of the memory that is allocate is num_lbs*2048 bytes. * The memory will be suitably aligned for use with * block reads from raw/O_DIRECT device. * @param num_lbs Number of logical blocks (2048 bytes) to allocate. * @return Returns pointer to allocated memory, or NULL on failure * This isn't supposed to be fast/efficient, if that is needed * this function should be rewritten to use posix_memalign or similar. * It's just needed for aligning memory for small block reads from * raw/O_DIRECT devices. * We assume that 2048 is enough alignment for all systems at the moment. * Not thread safe. Only use this from one thread. * Depends on sizeof(unsigned long) being at least as large as sizeof(void *) */ static void *dvdalign_lbmalloc(dvd_reader_t *device, uint32_t num_lbs) { void *m; int n; dvdalign_t *a; m = malloc((num_lbs+1)*DVD_VIDEO_LB_LEN); if(m == NULL) { return m; } a = (dvdalign_t *)GetAlignHandle(device); if(a == NULL) { a = malloc(sizeof(dvdalign_t)); if(a == NULL) { return a; } a->ptrs = NULL; a->ptrs_in_use = 0; a->ptrs_max = 0; SetAlignHandle(device, (void *)a); } if(a->ptrs_in_use >= a->ptrs_max) { a->ptrs = realloc(a->ptrs, (a->ptrs_max+10)*sizeof(dvdalign_ptrs_t)); if(a->ptrs == NULL) { free(m); return NULL; } a->ptrs_max+=10; for(n = a->ptrs_in_use; n < a->ptrs_max; n++) { a->ptrs[n].start = NULL; a->ptrs[n].aligned = NULL; } n = a->ptrs_in_use; } else { for(n = 0; n < a->ptrs_max; n++) { if(a->ptrs[n].start == NULL) { break; } } } a->ptrs[n].start = m; a->ptrs[n].aligned = DVD_ALIGN(m); a->ptrs_in_use++; /* If this function starts to be used too much print a warning. Either there is a memory leak somewhere or we need to rewrite this to a more efficient version. */ return a->ptrs[n].aligned; }
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) { unsigned char *secbuf_start; unsigned char *secbuf; //must be aligned to 2048-bytes for raw/O_DIRECT unsigned int numsec, seek_sector, seek_byte; int ret; /* Check arguments. */ if( dvd_file == NULL || data == NULL ) { errno = EINVAL; return -1; } seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN; seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN; numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 ); /* must align to 2048 bytes if we are reading from raw/O_DIRECT */ secbuf_start = (unsigned char *) malloc( (numsec+1) * DVD_VIDEO_LB_LEN ); if( !secbuf_start ) { /* errno will be set to ENOMEM by malloc */ return -1; } secbuf = DVD_ALIGN(secbuf_start); if( dvd_file->dvd->isImageFile ) { ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector, (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); } else { ret = DVDReadBlocksPath( dvd_file, seek_sector, (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); } if( ret != (int) numsec ) { free( secbuf_start ); return ret < 0 ? ret : 0; } memcpy( data, &(secbuf[ seek_byte ]), byte_size ); free( secbuf_start ); dvd_file->seek_pos += byte_size; return byte_size; }
int DVDISOVolumeInfo( dvd_reader_t *dvd, char *volid, unsigned int volid_size, unsigned char *volsetid, unsigned int volsetid_size ) { unsigned char *buffer; /* must be aligned to 2048 for raw/O_DIRECT */ unsigned char *buffer_start; int ret; /* Check arguments. */ if( dvd == NULL ) { errno = EINVAL; return -1; } if( dvd->dev == NULL ) { /* No block access, so no ISO... */ errno = EINVAL; return -1; } buffer_start = malloc( 2 * DVD_VIDEO_LB_LEN ); if( buffer_start == NULL ) { return -1; } buffer = DVD_ALIGN(buffer_start); ret = UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 ); if( ret != 1 ) { if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " "read ISO9660 Primary Volume Descriptor!\n" ); } free(buffer_start); 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_start); return 0; }