diff options
Diffstat (limited to 'lib/cdutils.cpp')
-rw-r--r-- | lib/cdutils.cpp | 1882 |
1 files changed, 941 insertions, 941 deletions
diff --git a/lib/cdutils.cpp b/lib/cdutils.cpp index d9efe68..2d9263b 100644 --- a/lib/cdutils.cpp +++ b/lib/cdutils.cpp @@ -1,941 +1,941 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: cdutils.cpp,v 1.30 2004-07-30 00:49:47 pixel Exp $ */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include "generic.h" -#include "cdutils.h" -#include "Output.h" - -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) : 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; - free(rootDir); -} - -unsigned char cdutils::from_BCD(unsigned char x) { - return ((x & 0xf) + ((x & 0xf0) >> 4) * 10); -} - -unsigned char cdutils::to_BCD(unsigned char x) { - return ((x / 10) << 4) | (x % 10); -} - -bool cdutils::is_valid_BCD(unsigned char x) { - return (((x & 15) < 10) && ((x >> 4) < 10)); -} - -unsigned long cdutils::from_MSF(unsigned char m, unsigned char s, unsigned char f, unsigned long start) { - return (from_BCD(m) * 60 + from_BCD(s)) * 75 + from_BCD(f) - start; -} - -unsigned long cdutils::from_MSF(unsigned long msf, unsigned long start) { - unsigned char - f = msf & 0xff, - s = (msf >> 8) & 0xff, - m = (msf >> 16) & 0xff; - - return from_MSF(m, s, f, start); -} - -void cdutils::to_MSF(int sect, unsigned char & m, unsigned char & s, unsigned char & f, unsigned long start) { - sect += start; - f = to_BCD(sect % 75); - sect /= 75; - s = to_BCD(sect % 60); - m = to_BCD(sect / 60); -} - -unsigned long cdutils::to_MSF(int sect, unsigned long start) { - unsigned char m, s, f; - to_MSF(sect, m, s, f, start); - return f | (s << 8) | (m << 16); -} - -Handle * cdutils::open_ppf(String ppf, String comment) throw (GeneralException) { - int i, l; - - if (ppf_file) - throw GeneralException("Tried to open_ppf() while already opened."); - ppf_file = new Output(ppf); - ppf_file->write("PPF20\001", 6); - - l = comment.strlen(); - if (l >= 50) { - ppf_file->write(comment.to_charp(), 50); - } else { - char * t = " "; - ppf_file->write(comment.to_charp(), l); - for (i = l; i < 50; i++) { - ppf_file->write(t, 1); - } - } - - l = f_iso_r->GetSize(); - ppf_file->write(&l, sizeof(l)); - - f_iso_r->seek(0x9320, SEEK_SET); -// copy(f_iso_r, ppf_file, 1024); - return ppf_file; -} - -void cdutils::write_ppf(Byte * old_sec, Byte * new_sec, int sec_num) { - int i, l = 0, o; - - for (i = 0; i < 2352; i++) { - if (old_sec[i] == new_sec[i]) { - if (l != 0) { - o = 2352 * sec_num + i; - ppf_file->write(&o, sizeof(o)); - ppf_file->write(&l, 1); - ppf_file->write(new_sec + i - l - 1, l); - l = 0; - } - } else { - l++; - if (l == 255) { - o = 2352 * sec_num + i; - ppf_file->write(&o, 4); - ppf_file->write(&l, 1); - ppf_file->write(new_sec + i - 255, 255); - l = 0; - } - } - } -} - -void cdutils::close_ppf() throw (GeneralException) { - if (ppf_file) { - delete ppf_file; - ppf_file = 0; - } else { - throw GeneralException("Tried to close_ppf() without previous opening"); - } -} - -void cdutils::set_iso_w(Handle * w) { - if (!f_iso_w) - f_iso_w = w; -} - -String cdutils::format_date(String input) { - String output; - - output = input.extract(6, 7) + '/'; - output += input.extract(4, 5) + '/'; - output += input.extract(0, 3) + ' '; - output += input.extract(8, 9) + ':'; - output += input.extract(10, 11) + ':'; - output += input.extract(12, 13) + '.'; - output += input.extract(14, 15); - output += String("").set("%+3.1f", ((float) (*((input.to_charp()) + 16))) / 4); - return output; -} - -Uint16 cdutils::swap_word(Uint16 i) { - return (i >> 8) | (i << 8); -} - -Uint32 cdutils::swap_dword(Uint32 i) { - return (i >> 24) | ((i >> 8) & 0x0000ff00) | ((i << 8) & 0x00ff0000) | (i << 24); -} - -int cdutils::guess_type(int number) { - Byte header[24]; - - if (number >= 0) { - sector_seek(number); - } - - f_iso_r->read(header, 24); - f_iso_r->seek(-24, SEEK_CUR); - if (header[15] == 1) { - return MODE_1; - } else if (header[15] == 2) { - if (*((unsigned long *) &(header[16])) == *((unsigned long *) &(header[20]))) { - if ((header[16] == 0) && (header[17] == 0) && (header[19] == 0)) { - if (header[18] & 0x20) { - return MODE_2_FORM_2; - } else { - return MODE_2_FORM_1; - } - } - } - return MODE_2; - } - - return MODE_0; -} - -void cdutils::sector_seek(long sector) { - f_iso_r->seek(2352 * sector); - if (f_iso_w) - f_iso_w->seek(2352 * sector); -} - -long cdutils::read_sector(Byte * buffer, int type, int number) { - if (number >= 0) { - sector_seek(number); - } - - if (type == GUESS) { - type = guess_type(); - } - - f_iso_r->seek(sec_offsts[type], SEEK_CUR); - f_iso_r->read(buffer, sec_sizes[type]); - f_iso_r->seek(2352 - sec_offsts[type] - sec_sizes[type], SEEK_CUR); - return sec_sizes[type]; -} - -void cdutils::read_datas(Byte * buffer, long size, int type, int number) { - Byte sector[2352]; - int i, n, reste; - - if (type == GUESS) { - type = guess_type(number); - } - - n = size / sec_sizes[type]; - reste = size - n * sec_sizes[type]; - - sector_seek(number); - for (i = 0; i < n; i++) { - read_sector(buffer + i * sec_sizes[type], type); - } - - if (reste) { - read_sector(sector, type); - bcopy((char *) sector, (char *) (buffer + n * sec_sizes[type]), reste); - } -} - -void cdutils::read_file(Handle * file, long size, int type, int number) { - Byte sector[2352]; - int i, n, reste; - - if (type == GUESS) { - type = guess_type(number); - } - - n = size / sec_sizes[type]; - reste = size - n * sec_sizes[type]; - - for (i = 0; i < n; i++) { - sector_seek(number + i); - try { - read_sector(sector, type); - } - catch(...) { - memset(sector, 0, 2352); - } - file->write(sector, sec_sizes[type]); - } - - sector_seek(number + n); - if (reste) { - try { - read_sector(sector, type); - } - catch(...) { - memset(sector, 0, 2352); - } - file->write(sector, reste); - } -} - -void cdutils::write_sector(Byte * buffer, int type, int number) throw (GeneralException) { - Byte old_sector[2352], new_sector[2352]; - - if (type == GUESS) { - type = guess_type(number); - } - - if (number >= 0) { - sector_seek(number); - } else { - number = f_iso_r->tell() / 2352; - } - - f_iso_r->read(old_sector, 2352); - - yazedc_o.minute = old_sector[12]; - yazedc_o.second = old_sector[13]; - yazedc_o.frame = old_sector[14]; - - bcopy((char *) old_sector, (char *) new_sector, 2532); - bcopy((char *) buffer, (char *) new_sector + sec_offsts[type], sec_sizes[type]); - - yazedc_o.do_encode_L2(new_sector, type, 0); - if (f_iso_w) { - f_iso_w->write(new_sector, 2352); - } else if (ppf_file) { - write_ppf(old_sector, new_sector, number); - } else { - throw GeneralException("No writing method for iso file"); - } -} - -void cdutils::write_datas(Byte * buffer, long size, int type, int number) { - long nbsectors, i; - unsigned char sector[2352]; - - if (type == GUESS) { - type = guess_type(number); - } - - if (number >= 0) { - sector_seek(number); - } - - nbsectors = size / sec_sizes[type]; - - for (i = 0; i < nbsectors; i++) { - write_sector(buffer + i * sec_sizes[type], type, number + i); - } - - if (size % sec_sizes[type]) { - memset(sector, 0, 2352); - bcopy((char *) (buffer + i * sec_sizes[type]), (char *) sector, size % sec_sizes[type]); - write_sector(sector, type, number + i); - } -} - -void cdutils::write_file(Handle * file, long size, int type, int number) { - long nbsectors, i; - unsigned char buffer[2352]; - - if (type == GUESS) { - type = guess_type(number); - } - - if (number >= 0) { - sector_seek(number); - } - - if (size < 0) - size = file->GetSize(); - nbsectors = size / sec_sizes[type]; - - if (size % sec_sizes[type]) { - nbsectors++; - } - - for (i = 0; i < nbsectors; i++) { - memset(buffer, 0, 2352); - size = file->read(buffer, sec_sizes[type]); - write_sector(buffer, type); - } -} - -void cdutils::create_sector(int type, int number, bool eof) throw (GeneralException) { - Byte sector[2352]; - if (!f_iso_w) - throw GeneralException("Can't create sector: ISO not in write mode"); - - to_MSF(number, yazedc_o.minute, yazedc_o.second, yazedc_o.frame); - memset(sector, 0, 2352); - if ((type == MODE2_FORM1) || (type == MODE2_FORM2)) { - sector[16] = sector[20] = 0; // File Number - sector[17] = sector[21] = 0; // Channel Number - sector[18] = sector[22] = 8 | (eof ? 129 : 0) | - (type == MODE2_FORM2 ? 32 : 0); - sector[19] = sector[23] = 0; // Coding Info - } - yazedc_o.do_encode_L2(sector, type, 0); - - f_iso_w->seek(2352 * number); - - f_iso_w->write(sector, 2352); - - sector_seek(number); -} - -void cdutils::show_head_entry(void) { - printm(M_BARE, "Sector Size Date Time Flags Name XA flags\n"); -} - -int cdutils::show_entry(struct DirEntry * dir) { - char pbuf[200], pad; - int s; - if ((!dir) || (!dir->R)) { - return 1; - } - - strncpy(pbuf, dir->id, dir->N); - pbuf[dir->N] = 0; - if ((dir->N == 1) && (pbuf[0] == 0)) { - strcpy(pbuf, "."); - } - if ((dir->N == 1) && (pbuf[0] == 1)) { - 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 %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); - return dir->R; -} - -int cdutils::show_dir(struct DirEntry * dir) { - unsigned int ptr; - Byte * buffer; - - if (!(dir->Flags & 2)) { - return 0; - } - - buffer = (Byte *) malloc(dir->Size); - read_datas(buffer, dir->Size, GUESS, dir->Sector); - - ptr = 0; - while(ptr < dir->Size) { - ptr += show_entry((struct DirEntry *) &(buffer[ptr])); - } - - free(buffer); - return 1; -} - -struct cdutils::DirEntry cdutils::find_dir_entry(struct DirEntry * dir, String name) { - unsigned int ptr, size; - unsigned char * buffer; - struct DirEntry r = {0, 0, 0, 0, 0}; - - if (!(dir->Flags & 2)) { - return r; - } - - buffer = (unsigned char *) malloc(size = dir->Size); - read_datas(buffer, dir->Size, GUESS, dir->Sector); - - ptr = 0; - while(ptr < size) { - dir = (struct DirEntry *) &(buffer[ptr]); - if (!dir->R) { - ptr++; - } else { - if (!strncmp(name.to_charp(), (char *) &(dir->id), dir->N)) { - r = *dir; - } - ptr += dir->R; - } - } - - free(buffer); - return r; -} - -struct cdutils::DirEntry * cdutils::find_dir_entry(Byte ** bufout, struct cdutils::DirEntry * dir, String name) { - unsigned int ptr, size; - Byte * buffer; - struct DirEntry * rdir = 0; - *bufout = 0; - - if (!(dir->Flags & 2)) { - return 0; - } - - buffer = (Byte *) malloc(size = dir->Size); - read_datas(buffer, dir->Size, GUESS, dir->Sector); - - ptr = 0; - while(ptr < size) { - dir = (struct DirEntry *) &(buffer[ptr]); - if (!dir->R) { - ptr++; - } else { - if (!strncmp(name.to_charp(), (char *) &(dir->id), dir->N)) { - rdir = dir; - } - ptr += dir->R; - } - } - - if (rdir && rdir->R) { - free(*bufout); - *bufout = buffer; - } else { - free(buffer); - rdir = 0; - } - return rdir; -} - -int cdutils::show_iso_infos() { - char buffer[2048]; - char pbuff[130]; - short int s, nogood = 0; - - read_sector((Byte *) buffer, GUESS, 16); - - printm(M_BARE, "Sector guessed mode : " + sec_modes[guess_type(16)] + "\n"); - printm(M_BARE, "offset-size-info : contents\n"); - printm(M_BARE, " 0 - 1- 1 : %i\n", buffer[0]); - memcpy(pbuff, buffer + 1, 5); - pbuff[5] = 0; - printm(M_BARE, " 1 - 5-`CD001' : %s\n", pbuff); - printm(M_BARE, " 6 - 2- 1 : %i\n", s = *((short int *) &(buffer[6]))); - printm(M_BARE, "(*this was the signature*)\n"); - if (buffer[0] != 1) nogood = 1; - if (strcmp(pbuff, "CD001")) nogood = 1; - if (s != 1) nogood = 1; - - if (nogood) { - printm(M_BARE, "Not a valid iso9660 file.\n"); - return 0; - } - - memcpy(pbuff, buffer + 8, 32); - pbuff[32] = 0; - printm(M_BARE, " 8 - 32- SYSID : %s\n", pbuff); - memcpy(pbuff, buffer + 40, 32); - pbuff[32] = 0; - printm(M_BARE, " 40 - 32- VOLID : %s\n", pbuff); - printm(M_BARE, " 80 - 8- SNum : %li\n", *((long int *) &(buffer[80]))); - printm(M_BARE, " 120 - 4- VOLSiz : %i\n", *((short int *) &(buffer[120]))); - printm(M_BARE, " 124 - 4- VOLNum : %i\n", *((short int *) &(buffer[124]))); - printm(M_BARE, " 128 - 4- SSize : %i\n", *((short int *) &(buffer[128]))); - printm(M_BARE, " 132 - 8- PSize : %li\n", *((long int *) &(buffer[132]))); - printm(M_BARE, " 140 - 4- 1SLPath: %i\n", *((short int *) &(buffer[140]))); - printm(M_BARE, " 144 - 4- 2SLPath: %i\n", *((short int *) &(buffer[144]))); - printm(M_BARE, " 148 - 4- 1SBPath: %i\n", swap_word(*((short int *) &(buffer[150])))); - printm(M_BARE, " 152 - 4- 2SBPath: %i\n", swap_word(*((short int *) &(buffer[154])))); - memcpy(pbuff, buffer + 190, 128); - pbuff[128] = 0; - printm(M_BARE, " 190 - 128- VStId : %s\n", pbuff); - memcpy(pbuff, buffer + 318, 128); - pbuff[128] = 0; - printm(M_BARE, " 318 - 128- PubId : %s\n", pbuff); - memcpy(pbuff, buffer + 446, 128); - pbuff[128] = 0; - printm(M_BARE, " 446 - 128- DPrId : %s\n", pbuff); - memcpy(pbuff, buffer + 574, 128); - pbuff[128] = 0; - printm(M_BARE, " 574 - 128- AppId : %s\n", pbuff); - memcpy(pbuff, buffer + 702, 37); - pbuff[37] = 0; - printm(M_BARE, " 702 - 37- CpyFile: %s\n", pbuff); - memcpy(pbuff, buffer + 739, 37); - pbuff[37] = 0; - printm(M_BARE, " 739 - 37- AbsFile: %s\n", pbuff); - memcpy(pbuff, buffer + 776, 37); - pbuff[37] = 0; - printm(M_BARE, " 776 - 37- BibFile: %s\n", pbuff); - printm(M_BARE, " 813 - 17- DTCreat: " + format_date(&buffer[813]) + "\n"); - printm(M_BARE, " 830 - 17- DTModif: " + format_date(&buffer[830]) + "\n"); - printm(M_BARE, " 847 - 17- DTExpir: " + format_date(&buffer[847]) + "\n"); - printm(M_BARE, " 864 - 17- DTEffec: " + format_date(&buffer[864]) + "\n"); - - printm(M_BARE, "Root record:\n"); - show_head_entry(); - show_entry((DirEntry *) &(buffer[156])); - - return 1; -} - -int cdutils::get_iso_infos() { - Byte buffer[2048]; - char pbuff[130]; - short int s, nogood = 0; - int rootsec; - - read_sector(buffer, GUESS, 16); - - memcpy(pbuff, buffer + 1, 5); - pbuff[5] = 0; - - s = *((short int *) &(buffer[6])); - if (buffer[0] != 1) nogood = 1; - if (strcmp(pbuff, "CD001")) nogood = 1; - if (s != 1) nogood = 1; - - if (nogood) { - printm(M_ERROR, "Not a valid iso9660 file.\n"); - return 0; - } - - pt1 = *((short int *) &(buffer[140])); - pt2 = *((short int *) &(buffer[144])); - snum = *((int *) &(buffer[80])); - ptl = *((long int *) &(buffer[132])); - rootsec = ((struct DirEntry *) (&buffer[156]))->Sector; - read_sector(buffer, GUESS, rootsec); - rootDir = (struct DirEntry *) malloc(buffer[0]); - memcpy(rootDir, buffer, buffer[0]); - return 1; -} - -int cdutils::get_pt_infos() { - Byte * buffer; - - if ((pt1 <= 0) && (pt2 <= 0)) - if (!get_iso_infos()) - return 0; - - if ((!pt1) & (!pt2)) { - printm(M_ERROR, "No path table defined.\n"); - return 0; - } - - buffer = (Byte *) malloc(ptl); - read_datas(buffer, ptl, GUESS, !pt1 ? pt2 : pt1); - - if (buffer[0] == 1) - if (buffer[1] == 0) - if (buffer[6] == 1) - if (buffer[7] == 0) - if (buffer[8] == 0) - if (buffer[9] == 0) - root = *((unsigned long int *) &(buffer[2])); - - free(buffer); - return root ? 1 : 0; -} - -int cdutils::show_pt_infos() { - Byte * buffer; - char pbuf[100]; - int i, ptr; - - if ((pt1 <= 0) && (pt2 <= 0)) - if (!get_iso_infos()) - return 0; - - if ((!pt1) & (!pt2)) { - printm(M_ERROR, "No path table defined.\n"); - return 0; - } - - buffer = (Byte *) malloc(ptl + 2); - read_datas(buffer, ptl, GUESS, !pt1 ? pt2 : pt1); - - printm(M_BARE, "node^paren@sector : name\n"); - for (ptr = 0, i = 1; buffer[ptr]; ptr += ptr & 1, i++) { - strncpy(pbuf, (char *) &(buffer[8 + ptr]), buffer[ptr]); - pbuf[buffer[ptr]] = 0; - printm(M_BARE, "%3i ^ %3i @ %6i: %s\n", i, *((unsigned short *) &(buffer[6 + ptr])), *((unsigned long *) &(buffer[2 + ptr])), pbuf); - ptr += 8 + buffer[ptr]; - } - - free(buffer); - return 1; -} - -struct cdutils::DirEntry cdutils::find_path(String path) { - char * newpath = path.strdup(); - char ** pts = split(newpath, '/'); - struct DirEntry dir = {0, 0, 0, 0, 0}; - - if ((pt1 <= 0) && (pt2 <= 0)) - if (!get_iso_infos()) { - free(newpath); - return dir; - } - - if ((!pt1) & (!pt2)) { - printm(M_ERROR, "No path table defined.\n"); - free(newpath); - return dir; - } - - if (!**pts) - pts++; - - for (dir = *rootDir; *pts; pts++) { - if (!strlen(*pts)) - continue; - dir = find_dir_entry(&dir, *pts); - if (!dir.R) { - free(newpath); - return dir; - } - } - - free(newpath); - return dir; -} - -struct cdutils::DirEntry cdutils::find_parent(String path) { - char * newpath = path.strdup(); - char ** pts, * p; - struct DirEntry dir = {0, 0, 0, 0, 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 dir; - } - - if ((!pt1) & (!pt2)) { - printm(M_ERROR, "No path table defined.\n"); - free(newpath); - return dir; - } - - if (!**pts) - pts++; - - for (dir = *rootDir; *pts; pts++) { - if (!strlen(*pts)) - continue; - dir = find_dir_entry(&dir, *pts); - if (!dir.R) { - free(newpath); - return dir; - } - } - - 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") { - Byte datas[2352]; - bool eof; - - if (mode == GUESS) { - mode = cd->guess_type(sector); - } - if (_size == -1) { - size = 0; - if ((mode == MODE2_FORM1) || (mode == MODE2_FORM2)) { - do { - cd->read_sector(datas, MODE_RAW, sector + size++); - eof = datas[18] & 0x80; - } while (!eof); - size *= sec_sizes[mode]; - } - } - dir = 0; - itell = 0; -} - -cdfile::~cdfile() { - free(dir); -} - -ssize_t cdfile::read(void *buf, size_t count) throw (GeneralException) { - Byte buffer[2352]; - size_t startsec, startbyte, nstartbytes; - - count = MIN(count, (size_t) (size - itell)); - - if (!count) { - close(); - 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, count, mode, startsec + 1); - } - - 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; -} +/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002-2003 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* $Id: cdutils.cpp,v 1.31 2004-10-19 15:58:41 pixel Exp $ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "generic.h"
+#include "cdutils.h"
+#include "Output.h"
+
+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) : 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;
+ free(rootDir);
+}
+
+unsigned char cdutils::from_BCD(unsigned char x) {
+ return ((x & 0xf) + ((x & 0xf0) >> 4) * 10);
+}
+
+unsigned char cdutils::to_BCD(unsigned char x) {
+ return ((x / 10) << 4) | (x % 10);
+}
+
+bool cdutils::is_valid_BCD(unsigned char x) {
+ return (((x & 15) < 10) && ((x >> 4) < 10));
+}
+
+unsigned long cdutils::from_MSF(unsigned char m, unsigned char s, unsigned char f, unsigned long start) {
+ return (from_BCD(m) * 60 + from_BCD(s)) * 75 + from_BCD(f) - start;
+}
+
+unsigned long cdutils::from_MSF(unsigned long msf, unsigned long start) {
+ unsigned char
+ f = msf & 0xff,
+ s = (msf >> 8) & 0xff,
+ m = (msf >> 16) & 0xff;
+
+ return from_MSF(m, s, f, start);
+}
+
+void cdutils::to_MSF(int sect, unsigned char & m, unsigned char & s, unsigned char & f, unsigned long start) {
+ sect += start;
+ f = to_BCD(sect % 75);
+ sect /= 75;
+ s = to_BCD(sect % 60);
+ m = to_BCD(sect / 60);
+}
+
+unsigned long cdutils::to_MSF(int sect, unsigned long start) {
+ unsigned char m, s, f;
+ to_MSF(sect, m, s, f, start);
+ return f | (s << 8) | (m << 16);
+}
+
+Handle * cdutils::open_ppf(String ppf, String comment) throw (GeneralException) {
+ int i, l;
+
+ if (ppf_file)
+ throw GeneralException("Tried to open_ppf() while already opened.");
+ ppf_file = new Output(ppf);
+ ppf_file->write("PPF20\001", 6);
+
+ l = comment.strlen();
+ if (l >= 50) {
+ ppf_file->write(comment.to_charp(), 50);
+ } else {
+ char * t = " ";
+ ppf_file->write(comment.to_charp(), l);
+ for (i = l; i < 50; i++) {
+ ppf_file->write(t, 1);
+ }
+ }
+
+ l = f_iso_r->GetSize();
+ ppf_file->write(&l, sizeof(l));
+
+ f_iso_r->seek(0x9320, SEEK_SET);
+// copy(f_iso_r, ppf_file, 1024);
+ return ppf_file;
+}
+
+void cdutils::write_ppf(Byte * old_sec, Byte * new_sec, int sec_num) {
+ int i, l = 0, o;
+
+ for (i = 0; i < 2352; i++) {
+ if (old_sec[i] == new_sec[i]) {
+ if (l != 0) {
+ o = 2352 * sec_num + i;
+ ppf_file->write(&o, sizeof(o));
+ ppf_file->write(&l, 1);
+ ppf_file->write(new_sec + i - l - 1, l);
+ l = 0;
+ }
+ } else {
+ l++;
+ if (l == 255) {
+ o = 2352 * sec_num + i;
+ ppf_file->write(&o, 4);
+ ppf_file->write(&l, 1);
+ ppf_file->write(new_sec + i - 255, 255);
+ l = 0;
+ }
+ }
+ }
+}
+
+void cdutils::close_ppf() throw (GeneralException) {
+ if (ppf_file) {
+ delete ppf_file;
+ ppf_file = 0;
+ } else {
+ throw GeneralException("Tried to close_ppf() without previous opening");
+ }
+}
+
+void cdutils::set_iso_w(Handle * w) {
+ if (!f_iso_w)
+ f_iso_w = w;
+}
+
+String cdutils::format_date(String input) {
+ String output;
+
+ output = input.extract(6, 7) + '/';
+ output += input.extract(4, 5) + '/';
+ output += input.extract(0, 3) + ' ';
+ output += input.extract(8, 9) + ':';
+ output += input.extract(10, 11) + ':';
+ output += input.extract(12, 13) + '.';
+ output += input.extract(14, 15);
+ output += String("").set("%+3.1f", ((float) (*((input.to_charp()) + 16))) / 4);
+ return output;
+}
+
+Uint16 cdutils::swap_word(Uint16 i) {
+ return (i >> 8) | (i << 8);
+}
+
+Uint32 cdutils::swap_dword(Uint32 i) {
+ return (i >> 24) | ((i >> 8) & 0x0000ff00) | ((i << 8) & 0x00ff0000) | (i << 24);
+}
+
+int cdutils::guess_type(int number) {
+ Byte header[24];
+
+ if (number >= 0) {
+ sector_seek(number);
+ }
+
+ f_iso_r->read(header, 24);
+ f_iso_r->seek(-24, SEEK_CUR);
+ if (header[15] == 1) {
+ return MODE_1;
+ } else if (header[15] == 2) {
+ if (*((unsigned long *) &(header[16])) == *((unsigned long *) &(header[20]))) {
+ if ((header[16] == 0) && (header[17] == 0) && (header[19] == 0)) {
+ if (header[18] & 0x20) {
+ return MODE_2_FORM_2;
+ } else {
+ return MODE_2_FORM_1;
+ }
+ }
+ }
+ return MODE_2;
+ }
+
+ return MODE_0;
+}
+
+void cdutils::sector_seek(long sector) {
+ f_iso_r->seek(2352 * sector);
+ if (f_iso_w)
+ f_iso_w->seek(2352 * sector);
+}
+
+long cdutils::read_sector(Byte * buffer, int type, int number) {
+ if (number >= 0) {
+ sector_seek(number);
+ }
+
+ if (type == GUESS) {
+ type = guess_type();
+ }
+
+ f_iso_r->seek(sec_offsts[type], SEEK_CUR);
+ f_iso_r->read(buffer, sec_sizes[type]);
+ f_iso_r->seek(2352 - sec_offsts[type] - sec_sizes[type], SEEK_CUR);
+ return sec_sizes[type];
+}
+
+void cdutils::read_datas(Byte * buffer, long size, int type, int number) {
+ Byte sector[2352];
+ int i, n, reste;
+
+ if (type == GUESS) {
+ type = guess_type(number);
+ }
+
+ n = size / sec_sizes[type];
+ reste = size - n * sec_sizes[type];
+
+ sector_seek(number);
+ for (i = 0; i < n; i++) {
+ read_sector(buffer + i * sec_sizes[type], type);
+ }
+
+ if (reste) {
+ read_sector(sector, type);
+ bcopy((char *) sector, (char *) (buffer + n * sec_sizes[type]), reste);
+ }
+}
+
+void cdutils::read_file(Handle * file, long size, int type, int number) {
+ Byte sector[2352];
+ int i, n, reste;
+
+ if (type == GUESS) {
+ type = guess_type(number);
+ }
+
+ n = size / sec_sizes[type];
+ reste = size - n * sec_sizes[type];
+
+ for (i = 0; i < n; i++) {
+ sector_seek(number + i);
+ try {
+ read_sector(sector, type);
+ }
+ catch(...) {
+ memset(sector, 0, 2352);
+ }
+ file->write(sector, sec_sizes[type]);
+ }
+
+ sector_seek(number + n);
+ if (reste) {
+ try {
+ read_sector(sector, type);
+ }
+ catch(...) {
+ memset(sector, 0, 2352);
+ }
+ file->write(sector, reste);
+ }
+}
+
+void cdutils::write_sector(Byte * buffer, int type, int number) throw (GeneralException) {
+ Byte old_sector[2352], new_sector[2352];
+
+ if (type == GUESS) {
+ type = guess_type(number);
+ }
+
+ if (number >= 0) {
+ sector_seek(number);
+ } else {
+ number = f_iso_r->tell() / 2352;
+ }
+
+ f_iso_r->read(old_sector, 2352);
+
+ yazedc_o.minute = old_sector[12];
+ yazedc_o.second = old_sector[13];
+ yazedc_o.frame = old_sector[14];
+
+ bcopy((char *) old_sector, (char *) new_sector, 2532);
+ bcopy((char *) buffer, (char *) new_sector + sec_offsts[type], sec_sizes[type]);
+
+ yazedc_o.do_encode_L2(new_sector, type, 0);
+ if (f_iso_w) {
+ f_iso_w->write(new_sector, 2352);
+ } else if (ppf_file) {
+ write_ppf(old_sector, new_sector, number);
+ } else {
+ throw GeneralException("No writing method for iso file");
+ }
+}
+
+void cdutils::write_datas(Byte * buffer, long size, int type, int number) {
+ long nbsectors, i;
+ unsigned char sector[2352];
+
+ if (type == GUESS) {
+ type = guess_type(number);
+ }
+
+ if (number >= 0) {
+ sector_seek(number);
+ }
+
+ nbsectors = size / sec_sizes[type];
+
+ for (i = 0; i < nbsectors; i++) {
+ write_sector(buffer + i * sec_sizes[type], type, number + i);
+ }
+
+ if (size % sec_sizes[type]) {
+ memset(sector, 0, 2352);
+ bcopy((char *) (buffer + i * sec_sizes[type]), (char *) sector, size % sec_sizes[type]);
+ write_sector(sector, type, number + i);
+ }
+}
+
+void cdutils::write_file(Handle * file, long size, int type, int number) {
+ long nbsectors, i;
+ unsigned char buffer[2352];
+
+ if (type == GUESS) {
+ type = guess_type(number);
+ }
+
+ if (number >= 0) {
+ sector_seek(number);
+ }
+
+ if (size < 0)
+ size = file->GetSize();
+ nbsectors = size / sec_sizes[type];
+
+ if (size % sec_sizes[type]) {
+ nbsectors++;
+ }
+
+ for (i = 0; i < nbsectors; i++) {
+ memset(buffer, 0, 2352);
+ size = file->read(buffer, sec_sizes[type]);
+ write_sector(buffer, type);
+ }
+}
+
+void cdutils::create_sector(int type, int number, bool eof) throw (GeneralException) {
+ Byte sector[2352];
+ if (!f_iso_w)
+ throw GeneralException("Can't create sector: ISO not in write mode");
+
+ to_MSF(number, yazedc_o.minute, yazedc_o.second, yazedc_o.frame);
+ memset(sector, 0, 2352);
+ if ((type == MODE2_FORM1) || (type == MODE2_FORM2)) {
+ sector[16] = sector[20] = 0; // File Number
+ sector[17] = sector[21] = 0; // Channel Number
+ sector[18] = sector[22] = 8 | (eof ? 129 : 0) |
+ (type == MODE2_FORM2 ? 32 : 0);
+ sector[19] = sector[23] = 0; // Coding Info
+ }
+ yazedc_o.do_encode_L2(sector, type, 0);
+
+ f_iso_w->seek(2352 * number);
+
+ f_iso_w->write(sector, 2352);
+
+ sector_seek(number);
+}
+
+void cdutils::show_head_entry(void) {
+ printm(M_BARE, "Sector Size Date Time Flags Name XA flags\n");
+}
+
+int cdutils::show_entry(struct DirEntry * dir) {
+ char pbuf[200], pad;
+ int s;
+ if ((!dir) || (!dir->R)) {
+ return 1;
+ }
+
+ strncpy(pbuf, dir->id, dir->N);
+ pbuf[dir->N] = 0;
+ if ((dir->N == 1) && (pbuf[0] == 0)) {
+ strcpy(pbuf, ".");
+ }
+ if ((dir->N == 1) && (pbuf[0] == 1)) {
+ 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 %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);
+ return dir->R;
+}
+
+int cdutils::show_dir(struct DirEntry * dir) {
+ unsigned int ptr;
+ Byte * buffer;
+
+ if (!(dir->Flags & 2)) {
+ return 0;
+ }
+
+ buffer = (Byte *) malloc(dir->Size);
+ read_datas(buffer, dir->Size, GUESS, dir->Sector);
+
+ ptr = 0;
+ while(ptr < dir->Size) {
+ ptr += show_entry((struct DirEntry *) &(buffer[ptr]));
+ }
+
+ free(buffer);
+ return 1;
+}
+
+struct cdutils::DirEntry cdutils::find_dir_entry(struct DirEntry * dir, String name) {
+ unsigned int ptr, size;
+ unsigned char * buffer;
+ struct DirEntry r = {0, 0, 0, 0, 0};
+
+ if (!(dir->Flags & 2)) {
+ return r;
+ }
+
+ buffer = (unsigned char *) malloc(size = dir->Size);
+ read_datas(buffer, dir->Size, GUESS, dir->Sector);
+
+ ptr = 0;
+ while(ptr < size) {
+ dir = (struct DirEntry *) &(buffer[ptr]);
+ if (!dir->R) {
+ ptr++;
+ } else {
+ if (!strncmp(name.to_charp(), (char *) &(dir->id), dir->N)) {
+ r = *dir;
+ }
+ ptr += dir->R;
+ }
+ }
+
+ free(buffer);
+ return r;
+}
+
+struct cdutils::DirEntry * cdutils::find_dir_entry(Byte ** bufout, struct cdutils::DirEntry * dir, String name) {
+ unsigned int ptr, size;
+ Byte * buffer;
+ struct DirEntry * rdir = 0;
+ *bufout = 0;
+
+ if (!(dir->Flags & 2)) {
+ return 0;
+ }
+
+ buffer = (Byte *) malloc(size = dir->Size);
+ read_datas(buffer, dir->Size, GUESS, dir->Sector);
+
+ ptr = 0;
+ while(ptr < size) {
+ dir = (struct DirEntry *) &(buffer[ptr]);
+ if (!dir->R) {
+ ptr++;
+ } else {
+ if (!strncmp(name.to_charp(), (char *) &(dir->id), dir->N)) {
+ rdir = dir;
+ }
+ ptr += dir->R;
+ }
+ }
+
+ if (rdir && rdir->R) {
+ free(*bufout);
+ *bufout = buffer;
+ } else {
+ free(buffer);
+ rdir = 0;
+ }
+ return rdir;
+}
+
+int cdutils::show_iso_infos() {
+ char buffer[2048];
+ char pbuff[130];
+ short int s, nogood = 0;
+
+ read_sector((Byte *) buffer, GUESS, 16);
+
+ printm(M_BARE, "Sector guessed mode : " + sec_modes[guess_type(16)] + "\n");
+ printm(M_BARE, "offset-size-info : contents\n");
+ printm(M_BARE, " 0 - 1- 1 : %i\n", buffer[0]);
+ memcpy(pbuff, buffer + 1, 5);
+ pbuff[5] = 0;
+ printm(M_BARE, " 1 - 5-`CD001' : %s\n", pbuff);
+ printm(M_BARE, " 6 - 2- 1 : %i\n", s = *((short int *) &(buffer[6])));
+ printm(M_BARE, "(*this was the signature*)\n");
+ if (buffer[0] != 1) nogood = 1;
+ if (strcmp(pbuff, "CD001")) nogood = 1;
+ if (s != 1) nogood = 1;
+
+ if (nogood) {
+ printm(M_BARE, "Not a valid iso9660 file.\n");
+ return 0;
+ }
+
+ memcpy(pbuff, buffer + 8, 32);
+ pbuff[32] = 0;
+ printm(M_BARE, " 8 - 32- SYSID : %s\n", pbuff);
+ memcpy(pbuff, buffer + 40, 32);
+ pbuff[32] = 0;
+ printm(M_BARE, " 40 - 32- VOLID : %s\n", pbuff);
+ printm(M_BARE, " 80 - 8- SNum : %li\n", *((long int *) &(buffer[80])));
+ printm(M_BARE, " 120 - 4- VOLSiz : %i\n", *((short int *) &(buffer[120])));
+ printm(M_BARE, " 124 - 4- VOLNum : %i\n", *((short int *) &(buffer[124])));
+ printm(M_BARE, " 128 - 4- SSize : %i\n", *((short int *) &(buffer[128])));
+ printm(M_BARE, " 132 - 8- PSize : %li\n", *((long int *) &(buffer[132])));
+ printm(M_BARE, " 140 - 4- 1SLPath: %i\n", *((long int *) &(buffer[140])));
+ printm(M_BARE, " 144 - 4- 2SLPath: %i\n", *((long int *) &(buffer[144])));
+ printm(M_BARE, " 148 - 4- 1SBPath: %i\n", swap_word(*((long int *) &(buffer[150]))));
+ printm(M_BARE, " 152 - 4- 2SBPath: %i\n", swap_word(*((long int *) &(buffer[154]))));
+ memcpy(pbuff, buffer + 190, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 190 - 128- VStId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 318, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 318 - 128- PubId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 446, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 446 - 128- DPrId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 574, 128);
+ pbuff[128] = 0;
+ printm(M_BARE, " 574 - 128- AppId : %s\n", pbuff);
+ memcpy(pbuff, buffer + 702, 37);
+ pbuff[37] = 0;
+ printm(M_BARE, " 702 - 37- CpyFile: %s\n", pbuff);
+ memcpy(pbuff, buffer + 739, 37);
+ pbuff[37] = 0;
+ printm(M_BARE, " 739 - 37- AbsFile: %s\n", pbuff);
+ memcpy(pbuff, buffer + 776, 37);
+ pbuff[37] = 0;
+ printm(M_BARE, " 776 - 37- BibFile: %s\n", pbuff);
+ printm(M_BARE, " 813 - 17- DTCreat: " + format_date(&buffer[813]) + "\n");
+ printm(M_BARE, " 830 - 17- DTModif: " + format_date(&buffer[830]) + "\n");
+ printm(M_BARE, " 847 - 17- DTExpir: " + format_date(&buffer[847]) + "\n");
+ printm(M_BARE, " 864 - 17- DTEffec: " + format_date(&buffer[864]) + "\n");
+
+ printm(M_BARE, "Root record:\n");
+ show_head_entry();
+ show_entry((DirEntry *) &(buffer[156]));
+
+ return 1;
+}
+
+int cdutils::get_iso_infos() {
+ Byte buffer[2048];
+ char pbuff[130];
+ short int s, nogood = 0;
+ int rootsec;
+
+ read_sector(buffer, GUESS, 16);
+
+ memcpy(pbuff, buffer + 1, 5);
+ pbuff[5] = 0;
+
+ s = *((short int *) &(buffer[6]));
+ if (buffer[0] != 1) nogood = 1;
+ if (strcmp(pbuff, "CD001")) nogood = 1;
+ if (s != 1) nogood = 1;
+
+ if (nogood) {
+ printm(M_ERROR, "Not a valid iso9660 file.\n");
+ return 0;
+ }
+
+ pt1 = *((short int *) &(buffer[140]));
+ pt2 = *((short int *) &(buffer[144]));
+ snum = *((int *) &(buffer[80]));
+ ptl = *((long int *) &(buffer[132]));
+ rootsec = ((struct DirEntry *) (&buffer[156]))->Sector;
+ read_sector(buffer, GUESS, rootsec);
+ rootDir = (struct DirEntry *) malloc(buffer[0]);
+ memcpy(rootDir, buffer, buffer[0]);
+ return 1;
+}
+
+int cdutils::get_pt_infos() {
+ Byte * buffer;
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos())
+ return 0;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return 0;
+ }
+
+ buffer = (Byte *) malloc(ptl);
+ read_datas(buffer, ptl, GUESS, !pt1 ? pt2 : pt1);
+
+ if (buffer[0] == 1)
+ if (buffer[1] == 0)
+ if (buffer[6] == 1)
+ if (buffer[7] == 0)
+ if (buffer[8] == 0)
+ if (buffer[9] == 0)
+ root = *((unsigned long int *) &(buffer[2]));
+
+ free(buffer);
+ return root ? 1 : 0;
+}
+
+int cdutils::show_pt_infos() {
+ Byte * buffer;
+ char pbuf[100];
+ int i, ptr;
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos())
+ return 0;
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ return 0;
+ }
+
+ buffer = (Byte *) malloc(ptl + 2);
+ read_datas(buffer, ptl, GUESS, !pt1 ? pt2 : pt1);
+
+ printm(M_BARE, "node^paren@sector : name\n");
+ for (ptr = 0, i = 1; buffer[ptr]; ptr += ptr & 1, i++) {
+ strncpy(pbuf, (char *) &(buffer[8 + ptr]), buffer[ptr]);
+ pbuf[buffer[ptr]] = 0;
+ printm(M_BARE, "%3i ^ %3i @ %6i: %s\n", i, *((unsigned short *) &(buffer[6 + ptr])), *((unsigned long *) &(buffer[2 + ptr])), pbuf);
+ ptr += 8 + buffer[ptr];
+ }
+
+ free(buffer);
+ return 1;
+}
+
+struct cdutils::DirEntry cdutils::find_path(String path) {
+ char * newpath = path.strdup();
+ char ** pts = split(newpath, '/');
+ struct DirEntry dir = {0, 0, 0, 0, 0};
+
+ if ((pt1 <= 0) && (pt2 <= 0))
+ if (!get_iso_infos()) {
+ free(newpath);
+ return dir;
+ }
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ free(newpath);
+ return dir;
+ }
+
+ if (!**pts)
+ pts++;
+
+ for (dir = *rootDir; *pts; pts++) {
+ if (!strlen(*pts))
+ continue;
+ dir = find_dir_entry(&dir, *pts);
+ if (!dir.R) {
+ free(newpath);
+ return dir;
+ }
+ }
+
+ free(newpath);
+ return dir;
+}
+
+struct cdutils::DirEntry cdutils::find_parent(String path) {
+ char * newpath = path.strdup();
+ char ** pts, * p;
+ struct DirEntry dir = {0, 0, 0, 0, 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 dir;
+ }
+
+ if ((!pt1) & (!pt2)) {
+ printm(M_ERROR, "No path table defined.\n");
+ free(newpath);
+ return dir;
+ }
+
+ if (!**pts)
+ pts++;
+
+ for (dir = *rootDir; *pts; pts++) {
+ if (!strlen(*pts))
+ continue;
+ dir = find_dir_entry(&dir, *pts);
+ if (!dir.R) {
+ free(newpath);
+ return dir;
+ }
+ }
+
+ 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") {
+ Byte datas[2352];
+ bool eof;
+
+ if (mode == GUESS) {
+ mode = cd->guess_type(sector);
+ }
+ if (_size == -1) {
+ size = 0;
+ if ((mode == MODE2_FORM1) || (mode == MODE2_FORM2)) {
+ do {
+ cd->read_sector(datas, MODE_RAW, sector + size++);
+ eof = datas[18] & 0x80;
+ } while (!eof);
+ size *= sec_sizes[mode];
+ }
+ }
+ dir = 0;
+ itell = 0;
+}
+
+cdfile::~cdfile() {
+ free(dir);
+}
+
+ssize_t cdfile::read(void *buf, size_t count) throw (GeneralException) {
+ Byte buffer[2352];
+ size_t startsec, startbyte, nstartbytes;
+
+ count = MIN(count, (size_t) (size - itell));
+
+ if (!count) {
+ close();
+ 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, count, mode, startsec + 1);
+ }
+
+ 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;
+}
|