#include #include #include #include #include #include #include #include "cdreader.h" #include "Exceptions.h" #include "generic.h" #ifdef HAVE_CONFIG_H #include "config.h" #else #define _(x) x #endif #ifdef __linux__ #include #include cdreader::cdreader(const String & no) throw (GeneralException) : Handle(open(no.to_charp(), O_RDONLY)), n(no), sector(0) { #ifdef DEBUG fprintf(stderr, "Opening file %s, cdreader at %p\n", no.to_charp(), this); #endif if (GetHandle() < 0) { throw IOGeneral(String(_("Error opening file ")) + no + _(" for reading: ") + strerror(errno)); } struct stat s; fstat(GetHandle(), &s); if (!S_ISBLK(s.st_mode)) { throw GeneralException(no + " is not a block device."); } } cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n) { } bool cdreader::CanWrite() { return 0; } bool cdreader::CanRead() { return 1; } bool cdreader::CanSeek() { return 1; } String cdreader::GetName() { return n + " raw reading"; } ssize_t cdreader::GetSize() { return -1; } off_t cdreader::seek(off_t offset, int whence) throw (GeneralException) { switch (whence) { case SEEK_SET: itell = offset; break; case SEEK_CUR: itell += offset; break; case SEEK_END: throw GeneralException("Can not yet seek from the end of a CD."); } return itell; } ssize_t cdreader::read(void *buf, size_t count) throw (GeneralException) { char sector[CD_FRAMESIZE_RAW]; size_t r = count; size_t remain = itell % CD_FRAMESIZE_RAW; sectorseek(itell / CD_FRAMESIZE_RAW); while (count > 0) { size_t n = CD_FRAMESIZE_RAW - remain; getsector(sector); bcopy(sector, ((char *) buf) + remain, MIN(n, count)); count -= n; remain = 0; } return r; } void cdreader::getsector(void *buf, int sec) throw (GeneralException) { struct cdrom_msf * msf = (struct cdrom_msf *) buf; if (sec >= 0) sector = sec; fprintf(stderr, "Reading sector %i\n", sector); sector += 150; msf->cdmsf_min0 = sector /CD_SECS /CD_FRAMES; msf->cdmsf_sec0 = (sector /CD_FRAMES)%CD_SECS; msf->cdmsf_frame0= sector %CD_FRAMES; msf->cdmsf_min1 = (sector+1)/CD_SECS /CD_FRAMES; msf->cdmsf_sec1 = ((sector+1)/CD_FRAMES)%CD_SECS; msf->cdmsf_frame1= (sector+1)%CD_FRAMES; sector -= 150; if (ioctl(GetHandle(), CDROMREADRAW, buf) < 0) { throw GeneralException(String("unable to read cd sector ") + sector + ": " + strerror(errno)); } sector++; } void cdreader::sectorseek(int sec) { sector = sec; } #endif