diff options
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/Makefile | 4 | ||||
-rw-r--r-- | lib/cdreader.cpp | 118 |
2 files changed, 120 insertions, 2 deletions
diff --git a/lib/Makefile b/lib/Makefile index c351a36..ab722f9 100755 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,9 +1,9 @@ #!/usr/bin/make -f -CPPFLAGS=-Wall -g -O3 -mcpu=i686 -pedantic -pedantic-errors -Werror -I../includes -DHAVE_ZLIB +CPPFLAGS=-Wall -g -O3 -mcpu=i686 -pedantic -Werror -I../includes -DHAVE_ZLIB CXX=g++ -OBJECTS = cdutils.o lzss.o yazedc.o dteutils.o +OBJECTS = cdutils.o lzss.o yazedc.o dteutils.o cdreader.o TARGET = lib.a all: ${TARGET} diff --git a/lib/cdreader.cpp b/lib/cdreader.cpp new file mode 100644 index 0000000..a501b6d --- /dev/null +++ b/lib/cdreader.cpp @@ -0,0 +1,118 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "cdreader.h" +#include "Exceptions.h" +#include "generic.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif + +#ifdef __linux__ +#include <sys/ioctl.h> +#include <linux/cdrom.h> + +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; + + 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; + + if (ioctl(GetHandle(), CDROMREADRAW, buf) < 0) { + throw GeneralException(String("unable to read cd sector: ") + strerror(errno)); + } + + sector++; +} + +void cdreader::sectorseek(int sec) { + sector = sec; +} + +#endif |