summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/cdabstract.cpp8
-rw-r--r--lib/cdreader.cpp140
-rw-r--r--lib/cdutils.cpp234
-rw-r--r--lib/isobuilder.cpp781
4 files changed, 1135 insertions, 28 deletions
diff --git a/lib/cdabstract.cpp b/lib/cdabstract.cpp
index ce22fad..d7cf18e 100644
--- a/lib/cdabstract.cpp
+++ b/lib/cdabstract.cpp
@@ -25,7 +25,7 @@ bool cdabstract::canprobe() {
#ifdef __linux__
return true;
#endif
-#if defined (_MSC_VER) || defined (_MINGW32)
+#ifdef _WIN32
OSVERSIONINFO ov;
memset(&ov, 0, sizeof(OSVERSIONINFO));
ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@@ -61,7 +61,7 @@ std::vector<String> cdabstract::probe() throw (GeneralException) {
}
#endif
-#if defined (_MSC_VER) || defined (__MINGW32__)
+#ifdef _WIN32
for (i = 'A'; i <= 'Z'; i++) {
probed.set("%c:\\", i);
if (subprobe(probed))
@@ -72,7 +72,7 @@ std::vector<String> cdabstract::probe() throw (GeneralException) {
return r;
}
-#if defined (_MSC_VER) || defined (__MINGW32__)
+#ifdef _WIN32
HANDLE cdabstract::OpenIOCTLFile(char cLetter) {
HANDLE hF;
char szFName[16];
@@ -151,7 +151,7 @@ bool cdabstract::subprobe(String & probed) {
}
#endif
-#if defined (_MSC_VER) || defined (__MINGW32__)
+#ifdef _WIN32
int iDA, iDT, iDL;
char letter[4];
HANDLE h;
diff --git a/lib/cdreader.cpp b/lib/cdreader.cpp
index d3d315f..5507588 100644
--- a/lib/cdreader.cpp
+++ b/lib/cdreader.cpp
@@ -14,6 +14,9 @@
#endif
#include "cdabstract.h"
+#define nsectorsarow 1
+#define cachesize 2048
+
bool cdreader::CanWrite() const {
return 0;
}
@@ -57,7 +60,7 @@ ssize_t cdreader::read(void *buf, size_t count) throw (GeneralException) {
while (count > 0) {
size_t n = MIN(2352 - remain, count);
- getsector(sector);
+ fetchsector(sector);
bcopy(sector + remain, buf, n);
buf = ((char *) buf) + n;
itell += n;
@@ -72,6 +75,94 @@ void cdreader::sectorseek(int sec) {
sector = sec;
}
+void cdreader::fetchsector(void * buf, int sec) {
+ if (sec >= 0)
+ sector = sec;
+
+ if (sectors[sector]) {
+ actualize(sectors[sector]);
+ memcpy(buf, sectors[sector]->sector, 2352);
+ return;
+ }
+
+ Byte buffers[2352 * nsectorsarow];
+
+ getsector(buffers, sec = sector, nsectorsarow);
+
+ for (int i = nsectorsarow - 1; i >= 0; i--) {
+ introduce(buffers + i * 2352, sec + i);
+ }
+
+ memcpy(buf, buffers, 2352);
+
+ while (nsectors > cachesize) {
+ removetail();
+ }
+}
+
+cdreader::~cdreader() {
+ while (nsectors) {
+ removetail();
+ }
+}
+
+void cdreader::removetail() {
+ void * t = (void *) tail;
+ if (!tail)
+ return;
+
+ sectors[tail->n] = 0;
+
+ if (head == tail) {
+ free(t);
+ head = tail = 0;
+ nsectors = 0;
+ } else {
+ cachedsector * p;
+ (p = tail->prev)->next = 0;
+ free(t);
+ tail = p;
+ nsectors--;
+ }
+}
+
+void cdreader::actualize(cachedsector * s) {
+ if (s == head)
+ return;
+
+ if (s != tail) {
+ s->next->prev = s->prev;
+ } else {
+ tail = s->prev;
+ }
+ s->prev->next = s->next;
+
+ head->prev = s;
+ s->prev = 0;
+ s->next = head;
+ head = s;
+}
+
+void cdreader::introduce(Byte * datas, int n) {
+ cachedsector * s;
+
+ s = (cachedsector *) malloc(sizeof(cachedsector));
+ memcpy(s->sector, datas, 2352);
+ s->n = n;
+
+ if (head) {
+ s->next = head;
+ head->prev = s;
+ head = s;
+ } else {
+ head = tail = s;
+ s->prev = s->next = 0;
+ }
+ sectors[n] = s;
+
+ nsectors++;
+}
+
#ifdef __linux__
#include <unistd.h>
#include <sys/ioctl.h>
@@ -94,24 +185,35 @@ cdreader::cdreader(const String & no) throw (GeneralException) :
if (!S_ISBLK(s.st_mode)) {
throw GeneralException(no + " is not a block device.");
}
+
+ for (i = 0; i < 400000; i++) {
+ sectors[i] = 0;
+ }
+ head = tail = 0;
+ nsectors = 0;
}
cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n) {
+ for (i = 0; i < 400000; i++) {
+ sectors[i] = 0;
+ }
+ head = tail = 0;
+ nsectors = 0;
}
-void cdreader::getsector(void *buf, int sec) throw (GeneralException) {
+void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) {
struct cdrom_msf * msf = (struct cdrom_msf *) buf;
if (sec >= 0)
sector = sec;
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;
+ 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 + nb)/CD_SECS /CD_FRAMES;
+ msf->cdmsf_sec1 = ((sector + nb)/CD_FRAMES)%CD_SECS;
+ msf->cdmsf_frame1= (sector + nb)%CD_FRAMES;
sector -= 150;
@@ -119,7 +221,7 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) {
throw GeneralException(String("unable to read cd sector ") + sector + ": " + strerror(errno));
}
- sector++;
+ sector += nb;
}
#endif
@@ -128,10 +230,20 @@ cdreader::cdreader(const String & no) throw (GeneralException) :
Handle(-1), n(no), sector(0) {
if (!(hFile = cdabstract::OpenIOCTLFile(no[0])))
throw GeneralException("Error opening device " + no);
+ for (int i = 0; i < 400000; i++) {
+ sectors[i] = 0;
+ }
+ head = tail = 0;
+ nsectors = 0;
}
cdreader::cdreader(const cdreader & i) : Handle(i), n(i.n) {
- hFile = i.hFile;
+ hFile = i.hFile;
+ for (int x = 0; x < 400000; x++) {
+ sectors[x] = 0;
+ }
+ head = tail = 0;
+ nsectors = 0;
}
void cdreader::close() throw (GeneralException) {
@@ -150,7 +262,7 @@ typedef struct _RAW_READ_INFO {
TRACK_MODE_TYPE TrackMode;
} RAW_READ_INFO, *PRAW_READ_INFO;
-void cdreader::getsector(void *buf, int sec) throw (GeneralException) {
+void cdreader::getsector(void *buf, int sec, int nb) throw (GeneralException) {
RAW_READ_INFO rawIOCTL;
DWORD dwRet;
BOOL bStat;
@@ -159,14 +271,14 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) {
sector = sec;
rawIOCTL.DiskOffset.QuadPart = sector * 2048;
- rawIOCTL.SectorCount = 1;
+ rawIOCTL.SectorCount = nb;
rawIOCTL.TrackMode = YellowMode2;
while (!done) {
SetLastError(0);
bStat = DeviceIoControl(hFile, IOCTL_CDROM_RAW_READ,
&rawIOCTL, sizeof(RAW_READ_INFO),
- buf, 2352, &dwRet, NULL);
+ buf, 2352 * nb, &dwRet, NULL);
if (!bStat) {
DWORD dwErrCode = GetLastError();
if (dwErrCode == ERROR_INVALID_FUNCTION) {
@@ -192,6 +304,8 @@ void cdreader::getsector(void *buf, int sec) throw (GeneralException) {
done = true;
}
}
+
+ sector += nb;
}
#endif
diff --git a/lib/cdutils.cpp b/lib/cdutils.cpp
index 413f95d..b3468e7 100644
--- a/lib/cdutils.cpp
+++ b/lib/cdutils.cpp
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* $Id: cdutils.cpp,v 1.15 2003-11-25 01:55:45 pixel Exp $ */
+/* $Id: cdutils.cpp,v 1.16 2003-12-04 00:57:35 pixel Exp $ */
#include <stdio.h>
#include <string.h>
@@ -31,11 +31,14 @@ const long sec_sizes[7] = {0, 2048, 2336, 2048, 2324, 2352, 2352};
const long sec_offsts[7] = {0, 16, 16, 24, 24, 0, 0};
const String sec_modes[7] = {"MODE 0 (empty)", "MODE 1", "MODE 2", "MODE 2 FORM 1", "MODE 2 FORM 2", "Raw", "Autodetect"};
-cdutils::cdutils(Handle * r, Handle * w) : f_iso_r(r), f_iso_w(w), ppf_file(0), pt1(-1), pt2(-1), snum(0), ptl(0), root(0) {}
+cdutils::cdutils(Handle * r, Handle * w) : rootDir(0), f_iso_r(r), f_iso_w(w), ppf_file(0), pt1(-1), pt2(-1), snum(0), ptl(0), root(0) {}
cdutils::~cdutils() {
if (ppf_file)
delete ppf_file;
+ void * t = rootDir;
+ free(t);
+ rootDir = 0;
}
unsigned char cdutils::from_BCD(unsigned char x) {
@@ -328,12 +331,13 @@ void cdutils::write_file(Handle * file, int type, int number) {
}
void cdutils::show_head_entry(void) {
- printm(M_BARE, "Sector - Size - Date - Time - Flags - Name\n");
+ printm(M_BARE, "Sector Size Date Time Flags Name XA flags\n");
}
int cdutils::show_entry(struct DirEntry * dir) {
- char pbuf[200];
- if (!dir->R) {
+ char pbuf[200], pad;
+ int s;
+ if ((!dir) || (!dir->R)) {
return 1;
}
@@ -346,10 +350,32 @@ int cdutils::show_entry(struct DirEntry * dir) {
strcpy(pbuf, "..");
}
+ s = 33 + dir->N;
+ if (s & 1) {
+ s++;
+ pad = 1;
+ } else {
+ pad = 0;
+ }
+ if (s != dir->R) {
+ if ((s + 14) == dir->R) {
+ Byte * p;
+ p = (Byte *) dir->id + dir->N + pad;
+ if ((p[6] == 'X') && (p[7] == 'A')) {
+ sprintf(pbuf, "%-14s %c%c%c%c%c", pbuf,
+ p[4] & 0x80 ? 'd' : '-',
+ p[4] & 0x40 ? 'a' : '-',
+ p[4] & 0x20 ? 's' : '-',
+ p[4] & 0x10 ? 'x' : '-',
+ p[4] & 0x08 ? 'f' : '-');
+ }
+ }
+ }
+
if (dir->Year < 70)
dir->Year += 100;
- printm(M_BARE, "%6i - %8i - %2i/%02i/%04i - %2i:%02i:%02i%+03.1f - %c%c%c%c%c%c%c%c - %s\n",
+ printm(M_BARE, "%6i %9i %2i/%02i/%04i %2i:%02i:%02i%+03.1f %c%c%c%c%c%c%c%c %s\n",
dir->Sector, dir->Size, dir->Day, dir->Month, dir->Year + 1900, dir->Hour, dir->Minute, dir->Second, ((float) dir->Offset) / 4,
dir->Flags & 1 ? 'H' : '-', dir->Flags & 2 ? 'D' : '-', dir->Flags & 4 ? 'A' : '-', dir->Flags & 8 ? 'R' : '-',
dir->Flags & 16 ? 'P' : '-', dir->Flags & 32 ? '1' : '-', dir->Flags & 64 ? '1' : '-', dir->Flags & 128 ? 'C' : '-', pbuf);
@@ -432,9 +458,11 @@ struct cdutils::DirEntry * cdutils::find_dir_entry(Byte ** bufout, struct cdutil
}
if (rdir->R) {
+ free(*bufout);
*bufout = buffer;
} else {
free(buffer);
+ rdir = 0;
}
return rdir;
}
@@ -512,9 +540,10 @@ int cdutils::show_iso_infos() {
}
int cdutils::get_iso_infos() {
- unsigned char buffer[2048];
+ Byte buffer[2048];
char pbuff[130];
short int s, nogood = 0;
+ int rootsec;
read_sector(buffer, GUESS, 16);
@@ -535,7 +564,10 @@ int cdutils::get_iso_infos() {
pt2 = *((short int *) &(buffer[144]));
snum = *((int *) &(buffer[80]));
ptl = *((long int *) &(buffer[132]));
- rootDir = *((struct DirEntry *) &(buffer[156]));
+ rootsec = ((struct DirEntry *) (&buffer[156]))->Sector;
+ read_sector(buffer, GUESS, rootsec);
+ rootDir = (struct DirEntry *) malloc(buffer[0]);
+ memcpy(rootDir, buffer, buffer[0]);
return 1;
}
@@ -615,7 +647,7 @@ struct cdutils::DirEntry cdutils::find_path(String path) {
if (!**pts)
pts++;
- for (dir = rootDir; *pts; pts++) {
+ for (dir = *rootDir; *pts; pts++) {
if (!strlen(*pts))
continue;
dir = find_dir_entry(&dir, *pts);
@@ -639,7 +671,7 @@ struct cdutils::DirEntry cdutils::find_parent(String path) {
}
if (!*newpath) {
free(newpath);
- return rootDir;
+ return *rootDir;
}
pts = split(newpath, '/');
@@ -658,7 +690,7 @@ struct cdutils::DirEntry cdutils::find_parent(String path) {
if (!**pts)
pts++;
- for (dir = rootDir; *pts; pts++) {
+ for (dir = *rootDir; *pts; pts++) {
if (!strlen(*pts))
continue;
dir = find_dir_entry(&dir, *pts);
@@ -671,3 +703,183 @@ struct cdutils::DirEntry cdutils::find_parent(String path) {
free(newpath);
return dir;
}
+
+struct cdutils::DirEntry * cdutils::find_path(Byte ** bufout, String path) {
+ char * newpath = path.strdup();
+ char ** pts = split(newpath, '/');
+ struct DirEntry * dir;
+
+ *bufout = 0;
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos()) {
+ free(newpath);
+ return 0;
+ }
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ free(newpath);
+ return 0;
+ }
+
+ if (!**pts)
+ pts++;
+
+ for (dir = rootDir; *pts; pts++) {
+ if (!strlen(*pts))
+ continue;
+ dir = find_dir_entry(bufout, dir, *pts);
+ if (!dir) {
+ free(newpath);
+ free(*bufout);
+ return 0;
+ }
+ }
+
+ if (!dir) {
+ free(*bufout);
+ }
+
+ free(newpath);
+ return dir;
+}
+
+struct cdutils::DirEntry * cdutils::find_parent(Byte ** bufout, String path) {
+ char * newpath = path.strdup();
+ char ** pts, * p;
+ struct DirEntry * dir;
+
+ *bufout = 0;
+
+ if ((p = strchr(newpath, '/'))) {
+ *p = 0;
+ }
+ if (!*newpath) {
+ free(newpath);
+ return rootDir;
+ }
+ pts = split(newpath, '/');
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos()) {
+ free(newpath);
+ return 0;
+ }
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ free(newpath);
+ return 0;
+ }
+
+ if (!**pts)
+ pts++;
+
+ for (dir = rootDir; *pts; pts++) {
+ free(*bufout);
+ if (!strlen(*pts))
+ continue;
+ dir = find_dir_entry(bufout, dir, *pts);
+ if (!dir) {
+ free(newpath);
+ return dir;
+ }
+ }
+
+ if (!dir) {
+ free(*bufout);
+ }
+
+ free(newpath);
+ return dir;
+}
+
+cdfile::cdfile(cdutils * _cd, const cdutils::DirEntry * d, int _mode) : Handle(-1), cd(_cd), sector(d->Sector), mode(_mode), size(d->Size), name(d->id) {
+ if (mode == GUESS) {
+ mode = cd->guess_type(sector);
+ }
+ dir = (cdutils::DirEntry *) malloc(d->R);
+ memcpy(dir, d, d->R);
+ itell = 0;
+}
+
+cdfile::cdfile(cdutils * _cd, int _sector, ssize_t _size, int _mode) : Handle(-1), cd(_cd), sector(_sector), mode(_mode), size(_size), name("raw reading") {
+ if (_size == -1) {
+ size = 0;
+ }
+ if (mode == GUESS) {
+ mode = cd->guess_type(sector);
+ }
+ dir = 0;
+ itell = 0;
+}
+
+cdfile::~cdfile() {
+ void * t = dir;
+ free(t);
+ dir = 0;
+}
+
+ssize_t cdfile::read(void *buf, size_t count) throw (GeneralException) {
+ Byte buffer[2352];
+ size_t startsec, nsec, startbyte, nstartbytes;
+
+ count = MIN(count, (size_t) (size - itell));
+
+ if (!count)
+ return 0;
+
+ startsec = itell / sec_sizes[mode] + sector;
+ startbyte = itell % sec_sizes[mode];
+ nstartbytes = sec_sizes[mode] - startbyte;
+ nstartbytes = MIN(nstartbytes, count);
+ count -= nstartbytes;
+
+ cd->read_sector(buffer, mode, startsec);
+ memcpy(buf, buffer + startbyte, nstartbytes);
+ buf = (Byte *) buf + nstartbytes;
+
+ if (count) {
+ cd->read_datas((Byte *) buf, mode, startsec + 1, count);
+ }
+
+ itell += count + nstartbytes;
+
+ return count + nstartbytes;
+}
+
+bool cdfile::CanRead() const {
+ return true;
+}
+
+String cdfile::GetName() const {
+ return String("cdfile: ") + name;
+}
+
+bool cdfile::CanWatch() const {
+ return false;
+}
+
+ssize_t cdfile::GetSize() const {
+ return size;
+}
+
+bool cdfile::CanSeek() const {
+ return true;
+}
+
+off_t cdfile::seek(off_t off, int wheel) throw (GeneralException) {
+ switch (wheel) {
+ case SEEK_SET:
+ itell = off;
+ break;
+ case SEEK_CUR:
+ itell += off;
+ break;
+ case SEEK_END:
+ itell = size + off;
+ break;
+ }
+ return itell;
+}
diff --git a/lib/isobuilder.cpp b/lib/isobuilder.cpp
new file mode 100644
index 0000000..469d612
--- /dev/null
+++ b/lib/isobuilder.cpp
@@ -0,0 +1,781 @@
+#include "isobuilder.h"
+void isobuilder::Date::dump(Byte * datas) {
+ char pbuf[256];
+
+ sprintf(pbuf, "%04i", year);
+ memcpy(datas + 0, pbuf, 4);
+ sprintf(pbuf, "%02i", month);
+ memcpy(datas + 4, pbuf, 2);
+ sprintf(pbuf, "%02i", day);
+ memcpy(datas + 6, pbuf, 2);
+ sprintf(pbuf, "%02i", hour);
+ memcpy(datas + 8, pbuf, 2);
+ sprintf(pbuf, "%02i", minute);
+ memcpy(datas + 10, pbuf, 2);
+ sprintf(pbuf, "%02i", second);
+ memcpy(datas + 12, pbuf, 2);
+ sprintf(pbuf, "%02i", hundredths);
+ memcpy(datas + 14, pbuf, 2);
+
+ *((char *) (datas + 16)) = offset;
+}
+
+isobuilder::Date::Date(int) {
+ year = month = day = hour = minute = second = hundredths = offset = 0;
+}
+
+isobuilder::Date::Date(Byte * datas) {
+ char pbuf[256];
+ char * cdatas = (char *) datas;
+
+ memcpy(pbuf, cdatas + 0, 4);
+ pbuf[4] = 0;
+ sscanf(pbuf, "%d", &year);
+
+ memcpy(pbuf, cdatas + 4, 2);
+ pbuf[2] = 0;
+ sscanf(pbuf, "%d", &month);
+
+ memcpy(pbuf, cdatas + 6, 2);
+ pbuf[2] = 0;
+ sscanf(pbuf, "%d", &day);
+
+ memcpy(pbuf, cdatas + 8, 2);
+ pbuf[2] = 0;
+ sscanf(pbuf, "%d", &hour);
+
+ memcpy(pbuf, cdatas + 10, 2);
+ pbuf[2] = 0;
+ sscanf(pbuf, "%d", &minute);
+
+ memcpy(pbuf, cdatas + 12, 2);
+ pbuf[2] = 0;
+ sscanf(pbuf, "%d", &second);
+
+ memcpy(pbuf, cdatas + 14, 2);
+ pbuf[2] = 0;
+ sscanf(pbuf, "%d", &hundredths);
+
+ offset = *(cdatas + 16);
+}
+
+isobuilder::DirTree::DirTree(isobuilder::DirTree * _father, bool _dir) : father(_father), mode(-1), dir(_dir) {
+ DirTree * p;
+
+ child = brother = 0;
+
+ if (!father)
+ return;
+
+ creation = father->creation;
+
+ if (father->child) {
+ for (p = father->child; p->brother; p = p->brother);
+ p->brother = this;
+ } else {
+ father->child = this;
+ }
+}
+
+isobuilder::DirTree::~DirTree() {
+ while (child) {
+ delete child;
+ }
+
+ if (!father)
+ return;
+
+ if (father->child == this) {
+ father->child = brother;
+ } else {
+ // Dirty, should not happen.
+ DirTree * p;
+ for (p = father->child; p->brother != this; p = p->brother);
+ p->brother = brother;
+ }
+}
+
+void isobuilder::DirTree::dumpdirs(isobuilder * builder) throw (GeneralException) {
+ Byte * dir, * odir;
+ int cursiz, cursectsize, R;
+ String oldname;
+ DirTree * p;
+
+ odir = dir = (Byte *) malloc(cursiz = size);
+ cursectsize = 2048;
+
+ oldname = name;
+ name = ".";
+ R = buildentry(dir, cursectsize);
+ name = oldname;
+ cursectsize -= R;
+ dir += R;
+
+ if (father) {
+ oldname = father->name;
+ father->name = "..";
+ R = father->buildentry(dir, cursectsize);
+ father->name = oldname;
+ } else {
+ name = "..";
+ R = buildentry(dir, cursectsize);
+ name = ".";
+ }
+
+ cursectsize -= R;
+ dir += R;
+
+ for (p = child; p; p = p->brother) {
+ if (p->dir) {
+ p->dumpdirs(builder);
+ }
+ while (!(R = p->buildentry(dir, cursectsize))) {
+ cursiz -= 2048;
+ dir += cursectsize;
+ cursectsize = 2048;
+ if (!cursiz)
+ throw GeneralException("Directory is too small! Entries don't fit.");
+ }
+ cursectsize -= R;
+ dir += R;
+ }
+
+ builder->putdatas(odir, size, mode, sector);
+
+ free(odir);
+}
+
+int isobuilder::DirTree::buildpath(Byte * datas, int size, bool bigendian) throw (GeneralException) {
+ int N, r, tr;
+ Uint16 pn;
+ char pbuf[256], pad;
+
+ if (!dir) {
+ if (brother) {
+ return brother->buildpath(datas, size, bigendian);
+ } else {
+ return 0;
+ }
+ }
+
+ if (!father) {
+ numerate(1);
+ N = 1;
+ pbuf[0] = 0;
+ pn = 1;
+ } else {
+ N = name.strlen();
+ strcpy(pbuf, name.to_charp());
+ pn = father->node;
+ }
+
+ pad = N & 1;
+ size -= (r = N + pad + 8);
+
+ if (size < 0)
+ throw GeneralException("Path table too small.");
+
+ datas[0] = N;
+ datas[1] = 0;
+ *((Uint32 *) (datas + 2)) = bigendian ? cdutils::swap_dword(sector) : sector;
+ *((Uint16 *) (datas + 6)) = bigendian ? cdutils::swap_word(pn) : pn;
+ memcpy(datas + 8, pbuf, N);
+ if (pad)
+ datas[8 + N] = 0;
+
+ datas += r;
+
+ if (brother) {
+ tr = brother->buildpath(datas, size, bigendian);
+ r += tr;
+ size -= tr;
+ datas += tr;
+ }
+
+ if (child) {
+ tr = child->buildpath(datas, size, bigendian);
+ r += tr;
+ size -= tr;
+ datas += tr;
+ }
+
+ return r;
+}
+
+int isobuilder::DirTree::buildentry(Byte * buffer, int spaceleft, bool put_xa) {
+ int N, R;
+ char pbuf[256], pad;
+ Byte * p;
+ cdutils::DirEntry * d = (cdutils::DirEntry *) buffer;
+
+ put_xa = put_xa && have_xa;
+
+ memset(pbuf, 0, 256);
+
+ if (name == ".") {
+ N = 1;
+ pbuf[0] = 0;
+ } else if (name == "..") {
+ N = 1;
+ pbuf[0] = 1;
+ } else {
+ strcpy(pbuf, name.to_charp());
+ N = name.strlen();
+ if (!dir) {
+ N += 2;
+ strcat(pbuf, ";1");
+ }
+ }
+
+ R = N + 33;
+
+ if (R & 1) {
+ R++;
+ pad = 1;
+ } else {
+ pad = 0;
+ }
+
+ if (put_xa) {
+ R += 14;
+ p = (Byte *) pbuf + N + pad;
+ p[4] = 0x05;
+ p[5] = 0x55;
+ p[6] = 'X';
+ p[7] = 'A';
+
+ p[4] |= xa_dir ? 0x80 : 0;
+ p[4] |= xa_audio ? 0x40 : 0;
+ p[4] |= xa_str ? 0x20 : 0;
+ p[4] |= xa_xa ? 0x10 : 0;
+ p[4] |= xa_form1 ? 0x08 : 0;
+ }
+
+ if (R > spaceleft) {
+ return 0;
+ }
+
+ memset(d, 0, R);
+
+ d->R = R;
+ d->N = N;
+ memcpy(d->id, pbuf, N + pad + (put_xa ? 14 : 0));
+
+ d->Sector = sector;
+ d->BESector = cdutils::swap_dword(sector);
+ d->Size = size;
+ d->BESize = cdutils::swap_dword(size);
+ d->Year = creation.year - 1900;
+ d->Month = creation.month;
+ d->Day = creation.day;
+ d->Hour = creation.hour;
+ d->Minute = creation.minute;
+ d->Second = creation.second;
+ d->Offset = creation.offset;
+ d->Flags |= hidden ? 1 : 0;
+ d->Flags |= dir ? 2 : 0;
+
+ return R;
+}
+
+void isobuilder::DirTree::fromdir(cdutils::DirEntry * d) {
+ Date t;
+ char pbuf[200], pad;
+ int s;
+ if ((!d) || (!d->R)) {
+ return;
+ }
+
+ if ((d->N == 1) && (d->id[0] == 0)) {
+ name = ".";
+ } else if ((d->N == 1) && (d->id[0] == 1)) {
+ name = "..";
+ } else {
+ memcpy(pbuf, d->id, s = (d->N - ((d->Flags & 2) ? 0 : 2)));
+ pbuf[s] = 0;
+ name = pbuf;
+ }
+ hidden = d->Flags & 1;
+ if (d->Year < 70)
+ d->Year += 100;
+ t.year = d->Year;
+ t.month = d->Month;
+ t.day = d->Day;
+ t.hour = d->Hour;
+ t.second = d->Second;
+ t.hundredths = 0;
+ t.offset = d->Offset;
+
+ s = 33 + d->N;
+ if (s & 1) {
+ s++;
+ pad = 1;
+ } else {
+ pad = 0;
+ }
+ if (s != d->R) {
+ if ((s + 14) == d->R) {
+ Byte * p;
+ p = (Byte *) d->id + d->N + pad;
+ if ((p[6] == 'X') && (p[7] == 'A')) {
+ have_xa = true;
+ xa_dir = p[4] & 0x80;
+ xa_audio = p[4] & 0x40;
+ xa_str = p[4] & 0x20;
+ xa_xa = p[4] & 0x10;
+ xa_form1 = p[4] & 0x08;
+ }
+ }
+ }
+}
+
+void isobuilder::DirTree::setbasicsxa() {
+ have_xa = true;
+ if (dir)
+ xa_dir = true;
+ xa_form1 = true;
+}
+
+int isobuilder::DirTree::numerate(int n) {
+ DirTree * p;
+
+ if (!dir) {
+ if (brother) {
+ return brother->numerate(n);
+ } else {
+ return n;
+ }
+ }
+
+ node = n++;
+
+ if (brother)
+ n = brother->numerate(n);
+
+ if (child)
+ n = child->numerate(n);
+
+ return n;
+}
+
+isobuilder::isobuilder(Handle * _w, int _mode) : w(_w), sector(0), nsectors(0), basics(false), dmode(_mode) {
+ Byte sect[2352];
+ memset(sect, 0, 2352);
+
+ for (int i = 0; i < 16; i++) {
+ createsector(sect, MODE2, i);
+ }
+}
+
+isobuilder::~isobuilder() {
+ if (!closed)
+ close();
+ if (root)
+ delete root;
+}
+
+void isobuilder::foreword(Handle * forewords, int mode) {
+ Byte sect[2352];
+ for (int i = 0; i < 16; i++) {
+ forewords->read(sect, sec_sizes[mode]);
+ createsector(sect, mode, i);
+ }
+}
+
+void isobuilder::foreword(Byte * forewords, int mode) {
+ for (int i = 0; i < 16; i++) {
+ createsector(forewords + i * sec_sizes[mode], mode, i);
+ }
+}
+
+int isobuilder::getdispsect() {
+ return lastdispsect;
+}
+
+int isobuilder::putfile(Handle * file, int mode, int n) {
+ Byte datas[2352];
+ size_t filesize;
+ int fsect;
+
+ if (n >= 0) {
+ sector = n;
+ } else {
+ sector = lastdispsect;
+ }
+
+ fsect = sector;
+
+ filesize = file->GetSize();
+
+ while (filesize > 0) {
+ memset(datas, 0, 2352);
+ filesize -= file->read(datas, sec_sizes[mode]);
+ if ((mode == MODE2_FORM1) || (mode == MODE2_FORM2)) {
+ if (filesize) {
+ clearEOF();
+ } else {
+ setEOF();
+ }
+ }
+ createsector(datas, mode);
+ }
+
+ return fsect;
+}
+
+void isobuilder::putdatas(Byte * _datas, size_t size, int smode, int n) {
+ Byte datas[2352];
+ size_t eating;
+ if (n >= 0) {
+ sector = n;
+ } else {
+ sector = lastdispsect;
+ }
+
+ if (smode < 0)
+ smode = dmode;
+
+ while (size > 0) {
+ memset(datas, 0, 2352);
+ eating = MIN(size, (size_t) sec_sizes[smode]);
+ memcpy(datas, _datas, eating);
+ size -= eating;
+ _datas += eating;
+ if ((smode == MODE2_FORM1) || (smode == MODE2_FORM2)) {
+ if (size) {
+ clearEOF();
+ } else {
+ setEOF();
+ }
+ }
+ createsector(datas, smode);
+ }
+}
+
+void isobuilder::createsector(Byte * datas, int smode, int n) {
+ Byte dsector[2352];
+ if (n >= 0)
+ sector = n;
+
+ if (smode < 0)
+ smode = dmode;
+
+ w->seek(2352 * sector, SEEK_SET);
+
+ memcpy(dsector + sec_offsts[smode], datas, sec_sizes[smode]);
+
+ if ((smode == MODE2_FORM1) || (smode == MODE2_FORM2)) {
+ // Mode 2 Form 2 would be odd, but well....
+ dsector[16] = dsector[20] = 0; // File Number
+ dsector[17] = dsector[21] = 0; // Channel Number
+ dsector[18] = dsector[22] = sub_EOR | sub_EOF | 8 |
+ (smode == MODE2_FORM2 ? 32 : 0);
+ dsector[19] = dsector[23] = 0;
+ }
+
+ if (smode != MODE_RAW) {
+ sector += 150;
+ yazedc_o.minute = cdutils::to_BCD(sector / 60 / 75);
+ yazedc_o.second = cdutils::to_BCD((sector / 75) % 60);
+ yazedc_o.frame = cdutils::to_BCD(sector % 75);
+ sector -= 150;
+ yazedc_o.do_encode_L2(dsector, smode, 0);
+ }
+
+ w->write(dsector, 2352);
+
+ sector++;
+
+ nsectors = MAX(nsectors, sector);
+ lastdispsect = MAX(lastdispsect, sector);
+}
+
+void isobuilder::setEOF() {
+ sub_EOF = 128;
+ sub_EOR = 1;
+}
+
+void isobuilder::clearEOF() {
+ sub_EOF = sub_EOR = 0;
+}
+
+isobuilder::DirTree * isobuilder::setbasics(PVD _pvd, int _rootsize, int _ptsize, int _nvd) throw (GeneralException) {
+ if (basics) {
+ throw GeneralException("Basic ISO structures already set");
+ }
+ basics = true;
+
+ pvd = _pvd;
+ rootsize = _rootsize;
+ ptsize = _ptsize;
+ nvd = _nvd;
+
+ ptsect = 17 + nvd;
+ rootsect = ptsect + ptsize * 4;
+ lastdispsect = rootsect + rootsize;
+
+ root = new DirTree(0);
+ root->name = ".";
+ root->creation = pvd.volcreat;
+ root->sector = rootsect;
+ root->size = rootsize * 2048;
+ return root;
+}
+
+isobuilder::DirTree * isobuilder::createdir(DirTree * p, const String & _name, int size, cdutils::DirEntry * d, int mode) throw (GeneralException) {
+ DirTree * r;
+
+ if (!p)
+ throw GeneralException("Empty father");
+
+ if (closed)
+ throw GeneralException("ISO is closed");
+
+ if (!basics)
+ throw GeneralException("ISO basis not created (no root!)");
+
+ r = new DirTree(p);
+
+ r->name = _name;
+ r->creation = p->creation;
+ r->fromdir(d);
+ if (_name != "")
+ r->name = _name;
+ r->size = size * 2048;
+ r->sector = lastdispsect;
+ r->mode = mode;
+
+ lastdispsect += size;
+
+ return r;
+}
+
+isobuilder::DirTree * isobuilder::createfile(DirTree * p, Handle * file, const String & _name, cdutils::DirEntry * d, int mode) throw (GeneralException) {
+ DirTree * r;
+
+ if (!p)
+ throw GeneralException("Empty father");
+
+ if (closed)
+ throw GeneralException("ISO is closed");
+
+ if (!basics)
+ throw GeneralException("ISO basis not created (no root!)");
+
+ r = new DirTree(p, false);
+
+ r->name = _name;
+ r->creation = p->creation;
+ r->fromdir(d);
+ if (_name != "")
+ r->name = _name;
+ r->size = file->GetSize();
+ r->sector = putfile(file, mode);
+ r->mode = mode;
+}
+
+void isobuilder::copydir(isobuilder::DirTree * r, const String & _name, cdutils * cd, cdutils::DirEntry * d, int mode) {
+ Byte datas[2048];
+ cdutils::DirEntry * p;
+ int nsectors = d->Size / 2048, ssize, c = 0;
+ int fsize, osize;
+
+ r->fromdir(d);
+ if (_name != "")
+ r->name = _name;
+
+ while (nsectors) {
+ cd->read_sector(datas, mode, d->Sector + c++);
+ nsectors--;
+ p = (cdutils::DirEntry *) datas;
+ ssize = 2048;
+ while ((ssize) && (p->R)) {
+ ssize -= p->R;
+ char pbuf[256];
+ memcpy(pbuf, p->id, p->N);
+ pbuf[p->N] = 0;
+ if (p->Flags & 2) {
+ if (!((p->N == 1) && ((p->id[0] == 0) || (p->id[0] == 1))))
+ copydir(createdir(r, "", p->Size / 2048, p, mode), "", cd, p, mode);
+ } else {
+ printm(M_INFO, "Dupping %s\n", pbuf);
+ int fmode;
+ if (mode == MODE1) {
+ fmode = mode;
+ } else {
+ fmode = MODE2_FORM1;
+ osize = fsize = p->Size;
+ int s, pad;
+ s = 33 + p->N;
+ if (s & 1) {
+ s++;
+ pad = 1;
+ } else {
+ pad = 0;
+ }
+ if ((s != p->R) && ((s + 14) == p->R)) {
+ if (!(p->id[p->N + pad + 4] & 8)) {
+ fmode = MODE2;
+ fsize = (p->Size / 2048) * 2336;
+ }
+ }
+ }
+ p->Size = fsize;
+ createfile(r, &cdfile(cd, p, fmode), "", p, fmode)->size = osize;
+ p->Size = osize;
+ }
+ p = (cdutils::DirEntry *) (((Byte *) p) + p->R);
+ }
+ }
+}
+
+isobuilder::PVD isobuilder::createpvd(Handle * f) {
+ Byte datas[2048];
+ f->read(datas, 2048);
+ return createpvd(datas);
+}
+
+isobuilder::PVD isobuilder::createpvd(cdutils * cd) {
+ Byte datas[2048];
+ cd->read_sector(datas, GUESS, 16);
+ return createpvd(datas);
+}
+
+isobuilder::PVD isobuilder::createpvd(Byte * buffer) {
+ PVD r;
+ char pbuff[256];
+
+ memcpy(pbuff, buffer + 8, 32);
+ pbuff[32] = 0;
+ r.sysid = pbuff;
+ r.sysid.rtrim();
+ memcpy(pbuff, buffer + 40, 32);
+ pbuff[32] = 0;
+ r.volid = pbuff;
+ r.volid.rtrim();
+ memcpy(pbuff, buffer + 190, 128);
+ pbuff[128] = 0;
+ r.volsetid = pbuff;
+ r.volsetid.rtrim();
+ memcpy(pbuff, buffer + 318, 128);
+ pbuff[128] = 0;
+ r.pubid = pbuff;
+ r.pubid.rtrim();
+ memcpy(pbuff, buffer + 446, 128);
+ pbuff[128] = 0;
+ r.prepid = pbuff;
+ r.prepid.rtrim();
+ memcpy(pbuff, buffer + 574, 128);
+ pbuff[128] = 0;
+ r.appid = pbuff;
+ r.appid.rtrim();
+ memcpy(pbuff, buffer + 702, 37);
+ pbuff[37] = 0;
+ r.copyright = pbuff;
+ r.copyright.rtrim();
+ memcpy(pbuff, buffer + 739, 37);
+ pbuff[37] = 0;
+ r.abstract = pbuff;
+ r.abstract.rtrim();
+ memcpy(pbuff, buffer + 776, 37);
+ pbuff[37] = 0;
+ r.biblio = pbuff;
+ r.biblio.rtrim();
+
+ r.volcreat = Date(buffer + 813);
+ r.modif = Date(buffer + 830);
+ r.volexp = Date(buffer + 847);
+ r.voleff = Date(buffer + 864);
+
+ memcpy(r.appdata, buffer + 883, 512);
+
+ return r;
+}
+
+void isobuilder::close(Handle * cue, int mode) throw (GeneralException) {
+ Byte datas[2048];
+ Byte * pdatas;
+ char * cdatas = (char *) datas;
+ int psize;
+
+ memset(datas, 0, 2048);
+
+ pdatas = (Byte *) malloc(ptsize * 2048);
+ psize = root->buildpath(pdatas, ptsize * 2048);
+ putdatas(pdatas, ptsize * 2048, mode, ptsect);
+ putdatas(pdatas, ptsize * 2048, mode, ptsect + ptsize);
+ root->buildpath(pdatas, ptsize * 2048, true);
+ putdatas(pdatas, ptsize * 2048, mode, ptsect + ptsize * 2);
+ putdatas(pdatas, ptsize * 2048, mode, ptsect + ptsize * 3);
+ free(pdatas);
+
+ datas[0] = 1;
+ datas[1] = 67;
+ datas[2] = 68;
+ datas[3] = 48;
+ datas[4] = 48;
+ datas[5] = 49;
+ datas[6] = 1;
+ datas[7] = 0;
+
+ sprintf(cdatas + 8, "%-32s", pvd.sysid.to_charp());
+ sprintf(cdatas + 40, "%-32s", pvd.volid.to_charp());
+ *((Uint32 *) (datas + 80)) = nsectors;
+ *((Uint32 *) (datas + 84)) = cdutils::swap_dword(nsectors);
+
+ datas[120] = 1;
+ datas[121] = 0;
+ datas[122] = 0;
+ datas[123] = 1;
+ datas[124] = 1;
+ datas[125] = 0;
+ datas[126] = 0;
+ datas[127] = 1;
+ datas[128] = 0;
+ datas[129] = 8;
+ datas[130] = 8;
+ datas[131] = 0;
+ *((Uint32 *) (datas + 132)) = psize;
+ *((Uint32 *) (datas + 136)) = cdutils::swap_dword(psize);
+ *((Uint32 *) (datas + 140)) = ptsect;
+ *((Uint32 *) (datas + 144)) = ptsect + ptsize;
+ *((Uint32 *) (datas + 148)) = cdutils::swap_dword(ptsect + ptsize * 2);
+ *((Uint32 *) (datas + 152)) = cdutils::swap_dword(ptsect + ptsize * 2);
+
+ root->buildentry(datas + 156, 34, false);
+
+ sprintf(cdatas + 190, "%-128s", pvd.volsetid.to_charp());
+ sprintf(cdatas + 318, "%-128s", pvd.pubid.to_charp());
+ sprintf(cdatas + 446, "%-128s", pvd.prepid.to_charp());
+ sprintf(cdatas + 574, "%-128s", pvd.appid.to_charp());
+ sprintf(cdatas + 702, "%-37s", pvd.copyright.to_charp());
+ sprintf(cdatas + 739, "%-37s", pvd.appid.to_charp());
+ sprintf(cdatas + 776, "%-37s", pvd.biblio.to_charp());
+
+ pvd.volcreat.dump(datas + 813);
+ pvd.modif.dump(datas + 830);
+ pvd.volexp.dump(datas + 847);
+ pvd.voleff.dump(datas + 864);
+
+ memcpy(datas + 883, pvd.appdata, 512);
+
+ clearEOF();
+ sub_EOR = 1;
+ createsector(datas, mode, 16);
+
+ memset(datas, 0, 2048);
+ datas[0] =255;
+ datas[1] = 67;
+ datas[2] = 68;
+ datas[3] = 48;
+ datas[4] = 48;
+ datas[5] = 49;
+ datas[6] = 1;
+
+ setEOF();
+ createsector(datas, mode);
+
+ root->dumpdirs(this);
+
+ closed = true;
+}