/*! Set "long" time in format used in ISO 9660 primary volume descriptor from a Unix time structure. timezone is given as an offset correction in minutes. */ void iso9660_set_ltime_with_timezone(const struct tm *p_tm, int time_zone, /*out*/ iso9660_ltime_t *pvd_date) { char *_pvd_date = (char *) pvd_date; memset (_pvd_date, (int) '0', 16); pvd_date->lt_gmtoff = (iso712_t) 0; /* Start out with time zone GMT. */ if (!p_tm) return; snprintf(_pvd_date, 17, "%4.4d%2.2d%2.2d" "%2.2d%2.2d%2.2d" "%2.2d", p_tm->tm_year + 1900, p_tm->tm_mon + 1, p_tm->tm_mday, p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec, 0 /* 1/100 secs */ ); /* Set time zone in 15-minute interval encoding. */ pvd_date->lt_gmtoff -= (time_zone / 15); if (pvd_date->lt_gmtoff < -48 ) { cdio_warn ("Converted ISO 9660 timezone %d is less than -48. Adjusted", (int) pvd_date->lt_gmtoff); pvd_date->lt_gmtoff = -48; } else if (pvd_date->lt_gmtoff > 52) { cdio_warn ("Converted ISO 9660 timezone %d is over 52. Adjusted", (int) pvd_date->lt_gmtoff); pvd_date->lt_gmtoff = 52; } }
/*! Set time in format used in ISO 9660 directory index record from a Unix time structure. */ void iso9660_set_dtime (const struct tm *p_tm, /*out*/ iso9660_dtime_t *p_idr_date) { memset (p_idr_date, 0, 7); if (!p_tm) return; p_idr_date->dt_year = p_tm->tm_year; p_idr_date->dt_month = p_tm->tm_mon + 1; p_idr_date->dt_day = p_tm->tm_mday; p_idr_date->dt_hour = p_tm->tm_hour; p_idr_date->dt_minute = p_tm->tm_min; p_idr_date->dt_second = p_tm->tm_sec; #ifdef HAVE_TM_GMTOFF /* The ISO 9660 timezone is in the range -48..+52 and each unit represents a 15-minute interval. */ p_idr_date->dt_gmtoff = p_tm->tm_gmtoff / (15 * 60); if (p_tm->tm_isdst) p_idr_date->dt_gmtoff -= 4; if (p_idr_date->dt_gmtoff < -48 ) { cdio_warn ("Converted ISO 9660 timezone %d is less than -48. Adjusted", p_idr_date->dt_gmtoff); p_idr_date->dt_gmtoff = -48; } else if (p_idr_date->dt_gmtoff > 52) { cdio_warn ("Converted ISO 9660 timezone %d is over 52. Adjusted", p_idr_date->dt_gmtoff); p_idr_date->dt_gmtoff = 52; } #else p_idr_date->dt_gmtoff = 0; #endif }
/*! Set time in format used in ISO 9660 directory index record from a Unix time structure. timezone is given as an offset correction in minutes. */ void iso9660_set_dtime_with_timezone (const struct tm *p_tm, int time_zone, /*out*/ iso9660_dtime_t *p_idr_date) { memset (p_idr_date, 0, 7); if (!p_tm) return; p_idr_date->dt_year = p_tm->tm_year; p_idr_date->dt_month = p_tm->tm_mon + 1; p_idr_date->dt_day = p_tm->tm_mday; p_idr_date->dt_hour = p_tm->tm_hour; p_idr_date->dt_minute = p_tm->tm_min; p_idr_date->dt_second = p_tm->tm_sec; /* The ISO 9660 timezone is in the range -48..+52 and each unit represents a 15-minute interval. */ p_idr_date->dt_gmtoff = time_zone / 15; if (p_idr_date->dt_gmtoff < -48 ) { cdio_warn ("Converted ISO 9660 timezone %d is less than -48. Adjusted", p_idr_date->dt_gmtoff); p_idr_date->dt_gmtoff = -48; } else if (p_idr_date->dt_gmtoff > 52) { cdio_warn ("Converted ISO 9660 timezone %d is over 52. Adjusted", p_idr_date->dt_gmtoff); p_idr_date->dt_gmtoff = 52; } }
/*! Initialize CD device. */ bool cdio_generic_init (void *user_data, int open_flags) { generic_img_private_t *p_env = user_data; if (p_env->init) { cdio_warn ("init called more than once"); return false; } p_env->fd = open (p_env->source_name, open_flags, 0); if (p_env->fd < 0) { cdio_warn ("open (%s): %s", p_env->source_name, strerror (errno)); return false; } p_env->init = true; p_env->toc_init = false; p_env->cdtext = NULL; p_env->scsi_tuple = NULL; p_env->b_cdtext_error = false; p_env->u_joliet_level = 0; /* Assume no Joliet extensions initally */ return true; }
/** Attempts to read up to count bytes from UDF directory entry p_udf_dirent into the buffer starting at buf. buf should be a multiple of UDF_BLOCKSIZE bytes. Reading continues after the point at which we last read or from the beginning the first time. If count is zero, read() returns zero and has no other results. If count is greater than SSIZE_MAX, the result is unspecified. It is the caller's responsibility to ensure that count is less than the number of blocks recorded via p_udf_dirent. If there is an error, cast the result to driver_return_code_t for the specific error code. */ ssize_t udf_read_block(const udf_dirent_t *p_udf_dirent, void * buf, size_t count) { if (count == 0) return 0; else { driver_return_code_t ret; uint32_t i_max_size=0; udf_t *p_udf = p_udf_dirent->p_udf; lba_t i_lba = offset_to_lba(p_udf_dirent, p_udf->i_position, &i_lba, &i_max_size); if (i_lba != CDIO_INVALID_LBA) { uint32_t i_max_blocks = CEILING(i_max_size, UDF_BLOCKSIZE); if ( i_max_blocks < count ) { cdio_warn("read count %u is larger than %u extent size.", (unsigned int)count, i_max_blocks); cdio_warn("read count truncated to %u", (unsigned int)count); count = i_max_blocks; } ret = udf_read_sectors(p_udf, buf, i_lba, count); if (DRIVER_OP_SUCCESS == ret) { ssize_t i_read_len = MIN(i_max_size, count * UDF_BLOCKSIZE); p_udf->i_position += i_read_len; return i_read_len; } return ret; } else { return DRIVER_OP_ERROR; } } }
bool init_freebsd_cam (_img_private_t *p_env) { char pass[100]; p_env->cam=NULL; memset (&p_env->ccb, 0, sizeof(p_env->ccb)); p_env->ccb.ccb_h.func_code = XPT_GDEVLIST; if (-1 == p_env->gen.fd) p_env->gen.fd = open (p_env->device, O_RDONLY, 0); if (p_env->gen.fd < 0) { cdio_warn ("open (%s): %s", p_env->device, strerror (errno)); return false; } (void)ioctl(p_env->gen.fd, CDIOCALLOW); if (ioctl (p_env->gen.fd, CAMGETPASSTHRU, &p_env->ccb) < 0) { cdio_warn ("open: %s", strerror (errno)); return false; } sprintf (pass,"/dev/%.15s%u", p_env->ccb.cgdl.periph_name, p_env->ccb.cgdl.unit_number); p_env->cam = cam_open_pass (pass,O_RDWR,NULL); if (!p_env->cam) return false; p_env->gen.init = true; p_env->b_cam_init = true; return true; }
static access_mode_t str_to_access_mode_win32(const char *psz_access_mode) { const access_mode_t default_access_mode = WIN_NT ? _AM_IOCTL : _AM_ASPI; if (NULL==psz_access_mode) return default_access_mode; if (!strcmp(psz_access_mode, "ioctl")) return _AM_IOCTL; else if (!strcmp(psz_access_mode, "ASPI")) { #ifdef _XBOX cdio_warn ("XBOX doesn't support access type: %s. Default used instead.", psz_access_mode); return default_access_mode; #else return _AM_ASPI; #endif } else if (!strcmp(psz_access_mode, "MMC_RDWR")) { return _AM_MMC_RDWR; } else if (!strcmp(psz_access_mode, "MMC_RDWR_EXCL")) { return _AM_MMC_RDWR_EXCL; } else { cdio_warn ("unknown access type: %s. Default used instead.", psz_access_mode); return default_access_mode; } }
/* Adjust the p_iso's i_datastart, i_byte_offset and i_framesize based on whether we find a frame header or not. */ static void adjust_fuzzy_pvd( iso9660_t *p_iso ) { long int i_byte_offset; if (!p_iso) return; i_byte_offset = (ISO_PVD_SECTOR * p_iso->i_framesize) + p_iso->i_fuzzy_offset + p_iso->i_datastart; /* If we have a raw 2352-byte frame then we should expect to see a sync frame and a header. */ if (CDIO_CD_FRAMESIZE_RAW == p_iso->i_framesize) { char buf[CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE]; i_byte_offset -= CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE; if ( DRIVER_OP_SUCCESS != cdio_stream_seek (p_iso->stream, i_byte_offset, SEEK_SET) ) return; if (sizeof(buf) == cdio_stream_read (p_iso->stream, buf, sizeof(buf), 1)) { /* Does the sector frame header suggest Mode 1 format? */ if (!memcmp(CDIO_SECTOR_SYNC_HEADER, buf+CDIO_CD_SUBHEADER_SIZE, CDIO_CD_SYNC_SIZE)) { if (buf[14+CDIO_CD_SUBHEADER_SIZE] != 0x16) { cdio_warn ("Expecting the PVD sector header MSF to be 0x16, is: %x", buf[14]); } if (buf[15+CDIO_CD_SUBHEADER_SIZE] != 0x1) { cdio_warn ("Expecting the PVD sector mode to be Mode 1 is: %x", buf[15]); } p_iso->b_mode2 = nope; p_iso->b_xa = nope; } else if (!memcmp(CDIO_SECTOR_SYNC_HEADER, buf, CDIO_CD_SYNC_SIZE)) { /* Frame header indicates Mode 2 Form 1*/ if (buf[14] != 0x16) { cdio_warn ("Expecting the PVD sector header MSF to be 0x16, is: %x", buf[14]); } if (buf[15] != 0x2) { cdio_warn ("Expecting the PVD sector mode to be Mode 2 is: %x", buf[15]); } p_iso->b_mode2 = yep; /* Do do: check Mode 2 Form 2? */ } else { /* Has no frame header */ p_iso->i_framesize = M2RAW_SECTOR_SIZE; p_iso->i_fuzzy_offset = (CDIO_CD_FRAMESIZE_RAW - M2RAW_SECTOR_SIZE) * ISO_PVD_SECTOR + p_iso->i_fuzzy_offset + p_iso->i_datastart; p_iso->i_datastart = 0; } } } }
/*! Run a SCSI MMC command. p_user_data internal CD structure. i_timeout_ms time in milliseconds we will wait for the command to complete. If this value is -1, use the default time-out value. i_cdb Size of p_cdb p_cdb CDB bytes. e_direction direction the transfer is to go. i_buf Size of buffer p_buf Buffer for data, both sending and receiving Return 0 if no error. */ int run_mmc_cmd_freebsd_cam( const void *p_user_data, unsigned int i_timeout_ms, unsigned int i_cdb, const mmc_cdb_t *p_cdb, cdio_mmc_direction_t e_direction, unsigned int i_buf, /*in/out*/ void *p_buf ) { const _img_private_t *p_env = p_user_data; int i_status; int direction = CAM_DEV_QFRZDIS; union ccb ccb; if (!p_env || !p_env->cam) return -2; memset(&ccb, 0, sizeof(ccb)); ccb.ccb_h.path_id = p_env->cam->path_id; ccb.ccb_h.target_id = p_env->cam->target_id; ccb.ccb_h.target_lun = p_env->cam->target_lun; ccb.ccb_h.timeout = i_timeout_ms; if (!i_buf) direction |= CAM_DIR_NONE; else direction |= (e_direction == SCSI_MMC_DATA_READ)?CAM_DIR_IN : CAM_DIR_OUT; memcpy(ccb.csio.cdb_io.cdb_bytes, p_cdb->field, i_cdb); ccb.csio.cdb_len = mmc_get_cmd_len(ccb.csio.cdb_io.cdb_bytes[0]); cam_fill_csio (&(ccb.csio), 1, NULL, direction | CAM_DEV_QFRZDIS, MSG_SIMPLE_Q_TAG, p_buf, i_buf, sizeof(ccb.csio.sense_data), ccb.csio.cdb_len, 30*1000); if (cam_send_ccb(p_env->cam, &ccb) < 0) { cdio_warn ("transport failed: %s", strerror(errno)); return -1; } if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { return 0; } errno = EIO; i_status = ERRCODE(((unsigned char *)&ccb.csio.sense_data)); if (i_status == 0) i_status = -1; else CREAM_ON_ERRNO(((unsigned char *)&ccb.csio.sense_data)); cdio_warn ("transport failed: %d", i_status); return i_status; }
/*! Return a string containing the default CD device if none is specified. if CdIo is NULL (we haven't initialized a specific device driver), then find a suitable one and return the default device for that. NULL is returned if we couldn't get a default device. */ char * cdio_get_default_device_os2(void) { #ifdef HAVE_OS2_CDROM struct { USHORT us_drive_count; USHORT us_drive_first; } s_drive_letters; HFILE h_cd2; ULONG ul_action; ULONG ul_param_len; ULONG ul_data_len; char sz_drive_str[ 3 ] = "X:"; ULONG rc; rc = DosOpen((PSZ)"CD-ROM2$", &h_cd2, &ul_action, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL ); if( rc ) { cdio_warn("cdio_get_default_device_os2 : DosOpen(CD-ROM2$) = %ld\n", rc ); return NULL; } rc = DosDevIOCtl( h_cd2, IOCTL_CDROMDISK2, CDROMDISK2_DRIVELETTERS, NULL, 0, &ul_param_len, &s_drive_letters, sizeof( s_drive_letters ), &ul_data_len ); DosClose( h_cd2 ); if( rc ) { cdio_warn("cdio_get_default_device_os2 : DosDevIOCtl(DRIVELETTERS) = 0x%lx\n", rc ); return NULL; } if( s_drive_letters.us_drive_count == 0 ) return NULL; sz_drive_str[0] = 'A' + s_drive_letters.us_drive_first; return strdup( sz_drive_str ); #else return NULL; #endif }
/*! Set the volume of an audio CD. @param p_cdio the CD object to be acted upon. */ static driver_return_code_t audio_set_volume_os2 ( void *p_user_data, cdio_audio_volume_t *p_volume) { _img_private_t *p_env = p_user_data; struct { UCHAR auch_sign[4]; } s_param = {{'C', 'D', '0', '1'}}; struct { struct { BYTE uc_in_ch; BYTE uc_vol; } as_out_ch[4]; } s_data; ULONG ul_param_len; ULONG ul_data_len; ULONG rc; int i; /* first retrive current input ch. */ rc = DosDevIOCtl( p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETCHANNEL, &s_param, sizeof( s_param ), &ul_param_len, &s_data, sizeof( s_data ), &ul_data_len ); if( rc ) { cdio_warn("audio_set_volume_os2 : DosDevIOCtl(GETCHANNEL) = 0x%lx\n", rc ); return DRIVER_OP_ERROR; } for( i = 0; i < 4; i++ ) s_data.as_out_ch[ i ].uc_vol = p_volume->level[ i ]; /* now set volumes */ rc = DosDevIOCtl( p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_SETCHANNELCTRL, &s_param, sizeof( s_param ), &ul_param_len, &s_data, sizeof( s_data ), &ul_data_len ); if( rc ) { cdio_warn("audio_set_volume_os2 : DosDevIOCtl(SETCHANNELCTRL) = 0x%lx\n", rc ); return DRIVER_OP_ERROR; } return DRIVER_OP_SUCCESS; }
CdioDataSource_t * cdio_stdio_new(const char pathname[]) { CdioDataSource_t *new_obj = NULL; cdio_stream_io_functions funcs = { NULL, NULL, NULL, NULL, NULL, NULL }; _UserData *ud = NULL; struct stat statbuf; if (stat (pathname, &statbuf) == -1) { cdio_warn ("could not retrieve file info for `%s': %s", pathname, strerror (errno)); return NULL; } ud = calloc (1, sizeof (_UserData)); ud->pathname = strdup(pathname); ud->st_size = statbuf.st_size; /* let's hope it doesn't change... */ funcs.open = _stdio_open; funcs.seek = _stdio_seek; funcs.stat = _stdio_stat; funcs.read = _stdio_read; funcs.close = _stdio_close; funcs.free = _stdio_free; new_obj = cdio_stream_new(ud, &funcs); return new_obj; }
static void cued_rip_epilogue(rip_context_t *rip) { free(rip->mmcBuf); #ifdef CUED_HAVE_PARANOIA if (ripUseParanoia) { rip->paranoiaCtlObj->read_audio = rip->save_read_paranoid; cdio_paranoia_free(rip->paranoiaRipObj); cdio_cddap_close_no_free_cdio(rip->paranoiaCtlObj); } #endif // CUED_HAVE_PARANOIA if (rip->qSubChannelFileName && rip->qSubChannelFile != stdout) { fclose(rip->qSubChannelFile); } if (rip->crcFailure || rip->crcSuccess) { int totalCrcs = rip->crcSuccess + rip->crcFailure; if (rip->crcFailure * 100 / totalCrcs > 5) { cdio_warn("greater than 5 percent of Q sub-channel records failed CRC check (try --qsc-fq?)"); } if (ripVerbose) { printf("progress: correctly read %d of %d Q sub-channel records\n", rip->crcSuccess, totalCrcs); } } }
static bool check_pvd (const iso9660_pvd_t *p_pvd) { if ( ISO_VD_PRIMARY != from_711(p_pvd->type) ) { cdio_warn ("unexpected PVD type %d", p_pvd->type); return false; } if (strncmp (p_pvd->id, ISO_STANDARD_ID, strlen (ISO_STANDARD_ID))) { cdio_warn ("unexpected ID encountered (expected `" ISO_STANDARD_ID "', got `%.5s'", p_pvd->id); return false; } return true; }
/*! Set the key "arg" to "value" in source device. */ static int set_arg_os2 (void *p_user_data, const char key[], const char value[]) { _img_private_t *p_env = p_user_data; if (!strcmp (key, "source")) { if (!value) return DRIVER_OP_ERROR; free (p_env->gen.source_name); p_env->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { if (!strcmp(value, "OS2")) p_env->access_mode = _AM_OS2; else cdio_warn ("unknown access type: %s. ignored.", value); } else return DRIVER_OP_ERROR; return DRIVER_OP_SUCCESS; }
/*! Return the media catalog number MCN. Note: string is malloc'd so caller should free() then returned string when done with it. */ char * get_mcn_win32ioctl (const _img_private_t *p_env) { DWORD dw_bytes_returned; SUB_Q_MEDIA_CATALOG_NUMBER mcn; CDROM_SUB_Q_DATA_FORMAT q_data_format; memset( &mcn, 0, sizeof(mcn) ); q_data_format.Format = CDIO_SUBCHANNEL_MEDIA_CATALOG; /* MSDN info on CDROM_SUB_Q_DATA_FORMAT says if Format is set to get MCN, track must be set 0. */ q_data_format.Track=0; if( ! DeviceIoControl( p_env->h_device_handle, IOCTL_CDROM_READ_Q_CHANNEL, &q_data_format, sizeof(q_data_format), &mcn, sizeof(mcn), &dw_bytes_returned, NULL ) ) { cdio_warn( "could not read Q Channel at track %d", 1); } else if (mcn.Mcval) return strdup(mcn.MediaCatalog); return NULL; }
static driver_return_code_t audio_stop_os2 (void *p_user_data) { _img_private_t *p_env = p_user_data; struct { UCHAR auch_sign[4]; } s_param = {{'C', 'D', '0', '1'}}; ULONG ul_param_len; ULONG ul_data_len; ULONG rc; rc = DosDevIOCtl( p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_STOPAUDIO, &s_param, sizeof( s_param ), &ul_param_len, NULL, 0, &ul_data_len ); if( rc ) { cdio_warn("audio_stop_os2 : DosDevIOCtl(STOPAUDIO) = 0x%lx\n", rc ); return DRIVER_OP_ERROR; } return DRIVER_OP_SUCCESS; }
/*! Seek to a position i_start and then read i_blocks. Number of blocks read is returned. One normally expects the return to be equal to i_blocks. */ driver_return_code_t udf_read_sectors (const udf_t *p_udf, void *ptr, lsn_t i_start, long i_blocks) { driver_return_code_t ret; long i_read; off_t i_byte_offset; if (!p_udf) return 0; /* Without the cast, i_start * UDF_BLOCKSIZE may be evaluated as 32 bit */ i_byte_offset = ((off_t)i_start) * UDF_BLOCKSIZE; /* Since we're using SEEK_SET, the value must be positive */ if (i_byte_offset < 0) { if (sizeof(off_t) <= 4) /* probably missing LFS */ cdio_warn("Large File Support is required to access streams of 2 GB or more"); return DRIVER_OP_BAD_PARAMETER; } if (p_udf->b_stream) { ret = cdio_stream_seek (p_udf->stream, i_byte_offset, SEEK_SET); if (DRIVER_OP_SUCCESS != ret) return ret; i_read = cdio_stream_read (p_udf->stream, ptr, UDF_BLOCKSIZE, i_blocks); if (i_read) return DRIVER_OP_SUCCESS; return DRIVER_OP_ERROR; } else { return cdio_read_data_sectors(p_udf->cdio, ptr, i_start, UDF_BLOCKSIZE, i_blocks); } }
/*! Close tray on CD-ROM. @param p_user_data the CD object to be acted upon. */ driver_return_code_t close_tray_os2 (const char *psz_os2_drive) { #ifdef HAVE_OS2_CDROM struct { BYTE uc_cmd_info; BYTE uc_drive; } s_param; ULONG ul_param_len; ULONG ul_data_len; ULONG rc; s_param.uc_cmd_info = 3; s_param.uc_drive = toupper(psz_os2_drive[0]) - 'A'; rc = DosDevIOCtl( ( HFILE )-1, IOCTL_DISK, DSK_UNLOCKEJECTMEDIA, &s_param, sizeof( s_param ), &ul_param_len, NULL, 0, &ul_data_len ); if( rc && rc != 99 /* device in use */ ) { cdio_warn("close_tray_os2 : DosDevIOCtl(UNLOCKEJECTMEDIA) = 0x%lx\n", rc ); return DRIVER_OP_ERROR; } return DRIVER_OP_SUCCESS; #else return DRIVER_OP_UNSUPPORTED; #endif /* HAVE_OS2_CDROM */ }
/*! Eject media in CD-ROM drive. Return DRIVER_OP_SUCCESS if successful, DRIVER_OP_ERROR on error. */ driver_return_code_t eject_media_freebsd_ioctl (_img_private_t *p_env) { _img_private_t *p_obj = p_env; int ret=DRIVER_OP_ERROR; if (ioctl(p_obj->gen.fd, CDIOCALLOW) == -1) { cdio_warn("ioctl(fd, CDIOCALLOW) failed: %s\n", strerror(errno)); } else if (ioctl(p_obj->gen.fd, CDIOCEJECT) == -1) { cdio_warn("ioctl(CDIOCEJECT) failed: %s\n", strerror(errno)); } else { ret=DRIVER_OP_SUCCESS;; } return ret; }
/*! Eject media. */ static driver_return_code_t eject_media_os2 (void *p_user_data) { _img_private_t *p_env = p_user_data; struct { BYTE uc_cmd_info; BYTE uc_drive; } s_param; ULONG ul_param_len; ULONG ul_data_len; ULONG rc; s_param.uc_cmd_info = 2; s_param.uc_drive = p_env->uc_drive; rc = DosDevIOCtl( ( HFILE )-1, IOCTL_DISK, DSK_UNLOCKEJECTMEDIA, &s_param, sizeof( s_param ), &ul_param_len, NULL, 0, &ul_data_len ); if( rc ) { cdio_warn("eject_media_os2 : DosDevIOCtl(UNLOCKEJECTMEDIA) = 0x%lx\n", rc ); return DRIVER_OP_ERROR; } return DRIVER_OP_SUCCESS; }
/*! Return the size of the CD in logical block address (LBA) units. */ static lsn_t get_disc_last_lsn_os2 (void *p_user_data) { _img_private_t *p_env = p_user_data; struct { UCHAR auch_sign[4]; } s_param = {{'C', 'D', '0', '1'}}; ULONG ul_data_volume_size; ULONG ul_param_len; ULONG ul_data_len; ULONG rc; rc = DosDevIOCtl( p_env->h_cd, IOCTL_CDROMDISK, CDROMDISK_GETVOLUMESIZE, &s_param, sizeof( s_param ), &ul_param_len, &ul_data_volume_size, sizeof( ul_data_volume_size ), &ul_data_len ); if( rc ) { cdio_warn("get_disc_last_lsn_os2 : DosDevIOCtl(GETVOLUMESIZE) = 0x%lx\n", rc ); return CDIO_INVALID_LSN; } return ul_data_volume_size; }
void cdio_lsn_to_msf (lsn_t lsn, msf_t *msf) { int m, s, f; cdio_assert (msf != 0); if ( lsn >= -CDIO_PREGAP_SECTORS ){ m = (lsn + CDIO_PREGAP_SECTORS) / CDIO_CD_FRAMES_PER_MIN; lsn -= m * CDIO_CD_FRAMES_PER_MIN; s = (lsn + CDIO_PREGAP_SECTORS) / CDIO_CD_FRAMES_PER_SEC; lsn -= s * CDIO_CD_FRAMES_PER_SEC; f = lsn + CDIO_PREGAP_SECTORS; } else { m = (lsn + CDIO_CD_MAX_LSN) / CDIO_CD_FRAMES_PER_MIN; lsn -= m * (CDIO_CD_FRAMES_PER_MIN); s = (lsn+CDIO_CD_MAX_LSN) / CDIO_CD_FRAMES_PER_SEC; lsn -= s * CDIO_CD_FRAMES_PER_SEC; f = lsn + CDIO_CD_MAX_LSN; } if (m > 6) { cdio_warn ("number of minutes (%d) truncated to 99.", m); m = 6; } msf->m = cdio_to_bcd8 (m); msf->s = cdio_to_bcd8 (s); msf->f = cdio_to_bcd8 (f); }
/*! Set the arg "key" with "value" in the source device. Currently "source" and "access-mode" are valid keys. "source" sets the source device in I/O operations "access-mode" sets the the method of CD access 0 is returned if no error was found, and nonzero if there as an error. */ static int _cdio_set_arg (void *env, const char key[], const char value[]) { _img_private_t *_obj = env; if (!strcmp (key, "source")) { if (!value) return -2; free (_obj->gen.source_name); _obj->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { if (!strcmp(value, "IOCTL")) _obj->access_mode = _AM_IOCTL; else if (!strcmp(value, "READ_CD")) _obj->access_mode = _AM_READ_CD; else if (!strcmp(value, "READ_10")) _obj->access_mode = _AM_READ_10; else { cdio_warn ("unknown access type: %s. ignored.", value); } } else return -1; return 0; }
void * /* list of char* -- caller must free it */ iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_mode2) { iso9660_stat_t stat; cdio_assert (cdio != NULL); cdio_assert (pathname != NULL); if (iso9660_fs_stat (cdio, pathname, &stat, is_mode2)) return NULL; if (stat.type != _STAT_DIR) return NULL; { unsigned offset = 0; uint8_t *_dirbuf = NULL; CdioList *retval = _cdio_list_new (); if (stat.size != ISO_BLOCKSIZE * stat.secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", (unsigned) stat.size, (unsigned long int) ISO_BLOCKSIZE * stat.secsize); } _dirbuf = _cdio_malloc (stat.secsize * ISO_BLOCKSIZE); if (is_mode2) { if (cdio_read_mode2_sectors (cdio, _dirbuf, stat.lsn, false, stat.secsize)) cdio_assert_not_reached (); } else { if (cdio_read_mode1_sectors (cdio, _dirbuf, stat.lsn, false, stat.secsize)) cdio_assert_not_reached (); } while (offset < (stat.secsize * ISO_BLOCKSIZE)) { const iso9660_dir_t *idr = (void *) &_dirbuf[offset]; if (!iso9660_get_dir_len(idr)) { offset++; continue; } _cdio_list_append (retval, _idr2name (idr)); offset += iso9660_get_dir_len(idr); } cdio_assert (offset == (stat.secsize * ISO_BLOCKSIZE)); free (_dirbuf); return retval; } }
/*! Read pathname (a directory) and return a list of iso9660_stat_t of the files inside that. The caller must free the returned result. */ CdioList_t * iso9660_ifs_readdir (iso9660_t *p_iso, const char pathname[]) { iso9660_stat_t *p_stat; if (!p_iso) return NULL; if (!pathname) return NULL; p_stat = iso9660_ifs_stat (p_iso, pathname); if (!p_stat) return NULL; if (p_stat->type != _STAT_DIR) { free(p_stat); return NULL; } { long int ret; unsigned offset = 0; uint8_t *_dirbuf = NULL; CdioList_t *retval = _cdio_list_new (); if (p_stat->size != ISO_BLOCKSIZE * p_stat->secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", (unsigned int) p_stat->size, (unsigned long int) ISO_BLOCKSIZE * p_stat->secsize); } _dirbuf = _cdio_malloc (p_stat->secsize * ISO_BLOCKSIZE); ret = iso9660_iso_seek_read (p_iso, _dirbuf, p_stat->lsn, p_stat->secsize); if (ret != ISO_BLOCKSIZE*p_stat->secsize) return NULL; while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) { iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; iso9660_stat_t *p_iso9660_stat; if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, true, p_iso->i_joliet_level); _cdio_list_append (retval, p_iso9660_stat); offset += iso9660_get_dir_len(p_iso9660_dir); } cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE)); free (_dirbuf); free (p_stat); return retval; } }
/*! Read and cache the CD's Track Table of Contents and track info. Return false if unsuccessful; */ static bool read_toc_freebsd (void *p_user_data) { _img_private_t *p_env = p_user_data; track_t i, j; /* read TOC header */ if ( ioctl(p_env->gen.fd, CDIOREADTOCHEADER, &p_env->tochdr) == -1 ) { cdio_warn("error in ioctl(CDIOREADTOCHEADER): %s\n", strerror(errno)); return false; } p_env->gen.i_first_track = p_env->tochdr.starting_track; p_env->gen.i_tracks = p_env->tochdr.ending_track - p_env->gen.i_first_track + 1; j=0; for (i=p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++, j++) { struct ioc_read_toc_single_entry *p_toc = &(p_env->tocent[i-p_env->gen.i_first_track]); p_toc->track = i; p_toc->address_format = CD_LBA_FORMAT; if ( ioctl(p_env->gen.fd, CDIOREADTOCENTRY, p_toc) ) { cdio_warn("%s %d: %s\n", "error in ioctl CDROMREADTOCENTRY for track", i, strerror(errno)); return false; } set_track_flags(&(p_env->gen.track_flags[i]), p_toc->entry.control); } p_env->tocent[j].track = CDIO_CDROM_LEADOUT_TRACK; p_env->tocent[j].address_format = CD_LBA_FORMAT; if ( ioctl(p_env->gen.fd, CDIOREADTOCENTRY, &(p_env->tocent[j]) ) ){ cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCENTRY for leadout track", strerror(errno)); return false; } p_env->gen.toc_init = true; return true; }
/*! Initialization routine. This is the only thing that doesn't get called via a function pointer. In fact *we* are the ones to set that up. */ CdIo_t * cdio_open_am_cdrdao (const char *psz_source_name, const char *psz_access_mode) { if (psz_access_mode != NULL && strcmp(psz_access_mode, "image")) cdio_warn ("there is only one access mode, 'image' for cdrdao. Arg %s ignored", psz_access_mode); return cdio_open_cdrdao(psz_source_name); }
/*! Read the Primary Volume Descriptor for an ISO 9660 image. True is returned if read, and false if there was an error. */ bool iso9660_ifs_read_pvd (const iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_pvd) { if (0 == iso9660_iso_seek_read (p_iso, p_pvd, ISO_PVD_SECTOR, 1)) { cdio_warn ("error reading PVD sector (%d)", ISO_PVD_SECTOR); return false; } return check_pvd(p_pvd); }
/*! Initialization routine. This is the only thing that doesn't get called via a function pointer. In fact *we* are the ones to set that up. */ CdIo_t * cdio_open_am_os2 (const char *psz_source_name, const char *psz_access_mode) { if (psz_access_mode != NULL) cdio_warn ("there is only one access mode for OS/2. Arg %s ignored", psz_access_mode); return cdio_open_os2(psz_source_name); }