46#define DBG_NOTICE "[iso9660] Notice: "
47#define DBG_ERROR "[iso9660] Error: "
49#define dbglog(sev,prm...) printf(sev prm);
52#define MAX_ISO_FILES 8
57static int init_percd();
64static void utf2ucs(
char * ucs,
const char * utf) {
70 }
else if (
c < 0xc0) {
75 c |= ((*utf++) & 0x3f) << 6;
83static void ucs2utfn(
char * utf,
const char * ucs,
size_t len) {
94 }
else if (
c <= 0x7ff) {
95 *utf++ = 0xc0 | (
c >> 6);
96 *utf++ = 0x80 | (
c & 0x3f);
98 *utf++ = 0xe0 | (
c >> 12);
99 *utf++ = 0x80 | ((
c >> 6) & 0x3f);
100 *utf++ = 0x80 | (
c & 0x3f);
106static int ucscompare(
const char * isofn,
const char * normalfn,
int isosize) {
110 for (i=0; i<isosize; i+=2) {
111 c0 = ((int)isofn[i] << 8) | ((int)isofn[i+1]);
112 c1 = ((int)normalfn[i] << 8) | ((int)normalfn[i+1]);
114 if (c0 ==
';')
break;
117 if (tolower(c0) != tolower(c1))
121 c1 = ((int)normalfn[i] << 8) | (normalfn[i+1]);
124 if (c1 !=
'/' && c1 !=
'\0')
130static int isjoliet(
char * p) {
131 if (p[0] ==
'%' && p[1] ==
'/') {
167static u32 ntohl_32(
const void *
data) {
169 return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | (d[3] << 0);
174static u32 htohl_32(
const void *
data) {
176 return (d[0] << 0) | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
183static u32 iso_733(
const u8 *from) {
return htohl_32(from); }
202#define NUM_CACHE_BLOCKS 16
207static unsigned int * cache_mutex;
215 cache[i]->sector = -1;
230 cache[i] = cache[i+1];
237static void iso_break_all();
246 if (cache[i]->sector == sector) {
247 bgrad_cache(cache, i);
255 if (cache[i]->sector == -1)
break;
269 dbglog(
DBG_ERROR,
"fs_iso9660: can't read_sectors for %d: %d\n", (
unsigned int)sector,
j);
274 cache[i]->
sector = sector;
277 bgrad_cache(cache, i);
287static int bdread(
u32 sector) {
288 return bread_cache(dcache, sector);
292static int biread(
u32 sector) {
293 return bread_cache(icache, sector);
297static void bclear() {
298 bclear_cache(dcache);
299 bclear_cache(icache);
306static u32 session_base = 0;
309static u32 root_extent = 0, root_size = 0;
317static int init_percd() {
327 for (i=1; i<=3; i++) {
328 blk = biread(session_base + i + 16);
330 if (memcmp((
char *)icache[
blk]->
data,
"\02CD001", 6) == 0) {
331 joliet = isjoliet((
char *)icache[
blk]->
data+88);
340 blk = biread(session_base + 16);
341 if (
blk < 0)
return i;
342 if (memcmp((
char*)icache[
blk]->
data,
"\01CD001", 6)) {
350 root_extent = iso_733(root_dirent.
extent);
351 root_size = iso_733(root_dirent.
size);
360static int fncompare(
const char *isofn,
int isosize,
const char *normalfn) {
365 for (i=0; i<isosize; i++) {
367 if (isofn[i] ==
';')
break;
370 if (isofn[i] ==
'.' &&
371 (i == (isosize-1) || isofn[i+1] ==
';'))
375 if (tolower(isofn[i]) != tolower(normalfn[i]))
380 if (normalfn[i] !=
'/' && normalfn[i] !=
'\0')
409 size_left = (int)dir_size;
412 char * ucsname = rrname;
416 utf2ucs(ucsname, fn);
418 while (size_left > 0) {
419 c = biread(dir_extent);
420 if (
c < 0)
return NULL;
422 for (i=0; i<2048 && i<size_left; ) {
445 while ((len >= 4) && ((pnt[3] == 1) || (pnt[3] == 2))) {
446 if (strncmp(pnt,
"NM", 2) == 0) {
447 rrnamelen = pnt[2] - 5;
448 strncpy(rrname, pnt+5, rrnamelen);
449 rrname[rrnamelen] = 0;
457 char *p = strchr(fn,
'/');
465 if (!strnicmp(rrname, fn, fnlen)) {
504 while ((cur = strchr(fn,
'/'))) {
508 start = find_object(fn, 1, iso_733(start->
extent), iso_733(start->
size));
517 start = find_object(fn,
dir, iso_733(start->
extent), iso_733(start->
size));
543static unsigned int * fh_mutex;
549static void iso_break_all() {
559static int iso_open(
const char *fn,
int mode) {
563 if (memcmp(fn,
"dvd:/", 6))
565 else if (memcmp(fn,
"dvd", 3) && memcmp(fn + 4,
":/", 2))
569 if (mode != O_RDONLY && mode !=
O_DIR)
573 if (!percd_done && init_percd() < 0)
578 de = find_object_path(fn, (mode &
O_DIR)?1:0, &root_dirent);
586 fh[fd].first_extent = -1;
595 fh[fd].first_extent = iso_733(de->
extent);
596 fh[fd].dir = (mode &
O_DIR)?1:0;
598 fh[fd].size = iso_733(de->
size);
605static void iso_close(
int fd) {
609 fh[fd].first_extent = 0;
614static ssize_t iso_read(
int fd,
void *buf,
size_t bytes) {
615 int rv, toread, thissect,
c;
628 toread = (bytes > (fh[fd].size - fh[fd].ptr)) ?
629 fh[fd].size - fh[fd].ptr : bytes;
630 if (toread == 0)
break;
633 thissect = 2048 - (fh[fd].ptr % 2048);
643 if (thissect == 2048 && toread >= 2048) {
645 thissect = toread / 2048;
646 if (thissect>32) thissect=32;
647 toread = thissect * 2048;
653 if (iso9660_dev->
readSectors(fh[fd].first_extent + fh[fd].ptr/2048, thissect, outbuf) < 0)
656 toread = (toread > thissect) ? thissect : toread;
662 memcpy(outbuf, dcache[
c]->
data + (fh[fd].
ptr%2048), toread);
667 fh[fd].ptr += toread;
676static off_t iso_seek(
int fd, off_t offset,
int whence) {
687 fh[fd].ptr += offset;
690 fh[fd].ptr = fh[fd].size + offset;
697 if (fh[fd].
ptr < 0) fh[fd].ptr = 0;
698 if (fh[fd].
ptr > fh[fd].
size) fh[fd].ptr = fh[fd].size;
704static off_t iso_tell(
int fd) {
712static size_t iso_total(
int fd) {
721static void fn_postprocess(
char *fnin) {
724 while (*fn && *fn !=
';') {
731 if (fn > fnin && fn[-1] ==
'.') {
737static struct dirent *iso_readdir(
int fd) {
751 while(fh[fd].
ptr < fh[fd].
size) {
754 if (
c < 0)
return NULL;
760 fh[fd].ptr += 2048 - (fh[fd].ptr%2048);
778 fh[fd].dirent.d_name[de->
name_len] = 0;
787 while ((len >= 4) && ((pnt[3] == 1) || (pnt[3] == 2))) {
788 if (strncmp(pnt,
"NM", 2) == 0) {
790 fh[fd].dirent.d_name[pnt[2] - 5] = 0;
801 fh[fd].dirent.d_type =
DT_DIR;
804 fh[fd].dirent.d_type =
DT_REG;
809 return &fh[fd].dirent;
824static int iso_last_status;
825static int iso_vblank_hnd;
826static void iso_vblank(
u32 evt) {
831 if (cdrom_get_status(&
status, &disc_type) < 0)
834 if (iso_last_status !=
status) {
835 if (
status == CD_STATUS_OPEN ||
status == CD_STATUS_NO_DISC)
844static int iso_ioctl(
int hnd,
void *
data,
size_t size) {
855 memset(fh, 0,
sizeof(fh));
858 fh[0].first_extent = -1;
861 cache_mutex = malloc(
sizeof(
u32));
862 fh_mutex = malloc(
sizeof(
u32));
877 iso_last_status = -1;
894 if (cache_mutex !=
NULL)
896 if (fh_mutex !=
NULL)
898 cache_mutex = fh_mutex =
NULL;
903static int _ISO9660_open_r(
struct _reent *r,
void *fileStruct,
const char *path,
int flags,
int mode)
906 file->
fd = iso_open(path, flags);
910static int _ISO9660_close_r(
struct _reent *r,
int fd)
917static ssize_t _ISO9660_read_r(
struct _reent *r,
int fd,
char *
ptr,
size_t len)
920 return iso_read(fd,
ptr, len);
923static off_t _ISO9660_seek_r(
struct _reent *r,
int fd, off_t pos,
int dir)
926 return iso_seek(fd, pos,
dir);
929static int _ISO9660_fstat_r(
struct _reent *r,
int fd,
struct stat *st)
932 memset(st, 0,
sizeof(
stat));
933 st->st_size = iso_total(fd);
934 st->st_mode = S_IFREG;
935 st->st_blksize = 65536;
939static int _ISO9660_stat_r(
struct _reent *r,
const char *path,
struct stat *st)
941 int fd = iso_open(path, O_RDONLY);
942 memset(st, 0,
sizeof(
stat));
943 st->st_size = iso_total(fd);
944 st->st_mode = S_IFREG;
945 st->st_blksize = 65536;
950static int _ISO9660_chdir_r(
struct _reent *r,
const char *path)
980static DIR_ITER* _ISO9660_diropen_r(
struct _reent *r,
DIR_ITER *dirState,
const char *path)
1009static int _ISO9660_dirreset_r(
struct _reent *r,
DIR_ITER *dirState)
1023static int _ISO9660_dirnext_r(
struct _reent *r,
DIR_ITER *dirState,
char *filename,
struct stat *st)
1046static int _ISO9660_dirclose_r(
struct _reent *r,
DIR_ITER *dirState)
1062static int _ISO9660_statvfs_r(
struct _reent *r,
const char *path,
struct statvfs *buf)
1106 _ISO9660_dirreset_r,
1108 _ISO9660_dirclose_r,
1121 if (!name || strlen(name) > 8 || !disc_interface)
1124 if (!disc_interface->
startup())
1130 sprintf(devname,
"%s:", name);
1134 devops = malloc(
sizeof(dotab_iso9660) + strlen(name) + 1);
1139 nameCopy = (
char*) (devops + 1);
1141 iso9660_dev = disc_interface;
1145 memcpy(devops, &dotab_iso9660,
sizeof(dotab_iso9660));
1146 strcpy(nameCopy, name);
1147 devops->
name = nameCopy;
1157static bool check_dev_name(
const char* name,
char *devname,
size_t devname_size)
1165 if (len == 0 || len > devname_size-2)
1169 strcpy(devname, name);
1170 if (devname[len-1] !=
':')
1171 strcat(devname,
":");
1179 if (! check_dev_name(name, devname,
sizeof(devname)))
1190 if (!check_dev_name(name, devname,
sizeof(devname)))
void lock(unsigned int *lock)
void unlock(unsigned int *lock)
#define DISKIO_ERROR_NO_MEDIA
struct filestruct_s FILE_STRUCT
#define dbglog(sev, prm...)
int fs_iso9660_shutdown()
bool ISO9660_Mount(const char *name, const DISC_INTERFACE *disc_interface)
const char * ISO9660_GetVolumeLabel(const char *name)
bool ISO9660_Unmount(const char *name)
int stat(const char *file, struct stat *st)
int RemoveDevice(const char *name)
int AddDevice(const devoptab_t *device)
int FindDevice(const char *name)
FN_MEDIUM_ISINSERTED isInserted
FN_MEDIUM_READSECTORS readSectors
FN_MEDIUM_STARTUP startup
uint8_t u8
8bit unsigned integer
int32_t s32
32bit signed integer
uint32_t u32
32bit unsigned integer