Add a cleaner implementation of ISO9660.

Enable it for powerpc and cross-powerpc

Signed-off-by: Laurent Vivier <Laurent@vivier.Eu>



git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@626 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
Laurent Vivier
2009-11-22 09:26:50 +00:00
committed by Laurent Vivier
parent 02d95dc3cd
commit d2cc5db789
19 changed files with 937 additions and 2 deletions

View File

@@ -8,5 +8,6 @@
<include href="grubfs/build.xml"/>
<include href="hfs/build.xml"/>
<include href="hfsplus/build.xml"/>
<include href="iso9660/build.xml"/>
</build>

13
fs/iso9660/build.xml Normal file
View File

@@ -0,0 +1,13 @@
<build>
<library name="fs" type="static" target="target">
<object source="iso9660_fs.c" condition="ISO9660"/>
<object source="iso9660_close.c" condition="ISO9660"/>
<object source="iso9660_closedir.c" condition="ISO9660"/>
<object source="iso9660_lseek.c" condition="ISO9660"/>
<object source="iso9660_mount.c" condition="ISO9660"/>
<object source="iso9660_open.c" condition="ISO9660"/>
<object source="iso9660_opendir.c" condition="ISO9660"/>
<object source="iso9660_read.c" condition="ISO9660"/>
<object source="iso9660_readdir.c" condition="ISO9660"/>
</library>
</build>

58
fs/iso9660/iso9660.h Normal file
View File

@@ -0,0 +1,58 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE, http://emile.sf.net
*
*/
#ifndef __ISO9660_H__
#define __ISO9660_H__
#include "iso9660_fs.h"
typedef struct iso9660_VOLUME {
int ucs_level;
struct iso_primary_descriptor *descriptor;
int fd;
} iso9660_VOLUME;
typedef struct iso9660_DIR {
iso9660_VOLUME *volume;
int extent;
int len;
int index;
unsigned char buffer[ISOFS_BLOCK_SIZE];
} iso9660_DIR;
typedef struct iso9660_FILE {
iso9660_VOLUME *volume;
char *path;
int base; /* first extent of the file */
int size; /* size of the file */
int offset;
int current;
unsigned char buffer[ISOFS_BLOCK_SIZE];
} iso9660_FILE;
static inline int isonum_721(char *p)
{
return ((p[0] & 0xff)
| ((p[1] & 0xff) << 8));
}
static inline int isonum_723(char *p)
{
return (isonum_721(p));
}
static inline int isonum_733(char *p)
{
return ((p[0] & 0xff) | ((p[1] & 0xff) << 8) |
((p[2] & 0xff) << 16) | ((p[3] & 0xff) << 24));
}
extern struct iso_directory_record *iso9660_get_root_node(iso9660_VOLUME* volume);
extern struct iso_directory_record* iso9660_get_node(iso9660_VOLUME *volume, struct iso_directory_record *dirnode, const char *path);
#endif /* __ISO9660_H__ */

View File

@@ -0,0 +1,15 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE bootloader, http://emile.sf.net
*
*/
#include "libiso9660.h"
void iso9660_close(iso9660_FILE *file)
{
free(file->path);
free(file);
}

View File

@@ -0,0 +1,19 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE, http://emile.sf.net
*
*/
#include "libiso9660.h"
int iso9660_closedir(iso9660_DIR *dir)
{
if (dir == NULL)
return -1;
free(dir);
return 0;
}

104
fs/iso9660/iso9660_fs.c Normal file
View File

@@ -0,0 +1,104 @@
/*
*
* (c) 2009 Laurent Vivier <Laurent@vivier.eu>
*
*/
#include "libiso9660.h"
#include "openbios/fs.h"
static void
umount( fs_ops_t *fs )
{
iso9660_VOLUME *volume = (iso9660_VOLUME *)fs->fs_data;
iso9660_umount( volume );
}
static file_desc_t *
open_path( fs_ops_t *fs, const char *path )
{
iso9660_VOLUME *volume = (iso9660_VOLUME *)fs->fs_data;
iso9660_FILE *file;
file = iso9660_open(volume, path);
return (file_desc_t *)file;
}
static char *
get_path( file_desc_t *fd, char *buf, int size )
{
iso9660_FILE *file = (iso9660_FILE*)fd;
strncpy(buf, file->path, size);
return buf;
}
static int
file_lseek( file_desc_t *fd, off_t offs, int whence )
{
iso9660_FILE *file = (iso9660_FILE*)fd;
return iso9660_lseek(file, offs, whence);
}
static void
file_close( file_desc_t *fd )
{
iso9660_FILE *file = (iso9660_FILE*)fd;
iso9660_close(file);
}
static int
file_read( file_desc_t *fd, void *buf, size_t count )
{
iso9660_FILE *file = (iso9660_FILE*)fd;
return iso9660_read(file, buf, count);
}
static char *
vol_name( fs_ops_t *fs, char *buf, int size )
{
iso9660_VOLUME *volume = (iso9660_VOLUME *)fs->fs_data;
strncpy(buf, volume->descriptor->volume_id, size);
return buf;
}
static const char *
get_fstype( fs_ops_t *fs )
{
return "ISO9660";
}
static const fs_ops_t iso9660_ops = {
.close_fs = umount,
.open_path = open_path,
.get_path = get_path,
.close = file_close,
.read = file_read,
.lseek = file_lseek,
.vol_name = vol_name,
.get_fstype = get_fstype,
};
int fs_iso9660_open(int fd, fs_ops_t *fs)
{
iso9660_VOLUME *volume;
volume = iso9660_mount(fd);
if (volume == NULL)
return -1;
*fs = iso9660_ops;
fs->fs_data = volume;
return 0;
}

161
fs/iso9660/iso9660_fs.h Normal file
View File

@@ -0,0 +1,161 @@
#ifndef _ISO9660_FS_H
#define _ISO9660_FS_H
/* this file has been copied from linux 2.6.26 */
/*
* The isofs filesystem constants/structures
*/
/* This part borrowed from the bsd386 isofs */
#define ISODCL(from, to) (to - from + 1)
struct iso_volume_descriptor {
char type[ISODCL(1,1)]; /* 711 */
char id[ISODCL(2,6)];
char version[ISODCL(7,7)];
char data[ISODCL(8,2048)];
};
/* volume descriptor types */
#define ISO_VD_PRIMARY 1
#define ISO_VD_SUPPLEMENTARY 2
#define ISO_VD_END 255
#define ISO_STANDARD_ID "CD001"
struct iso_primary_descriptor {
char type [ISODCL ( 1, 1)]; /* 711 */
char id [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char unused1 [ISODCL ( 8, 8)];
char system_id [ISODCL ( 9, 40)]; /* achars */
char volume_id [ISODCL ( 41, 72)]; /* dchars */
char unused2 [ISODCL ( 73, 80)];
char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
char unused3 [ISODCL ( 89, 120)];
char volume_set_size [ISODCL (121, 124)]; /* 723 */
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
char logical_block_size [ISODCL (129, 132)]; /* 723 */
char path_table_size [ISODCL (133, 140)]; /* 733 */
char type_l_path_table [ISODCL (141, 144)]; /* 731 */
char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
char type_m_path_table [ISODCL (149, 152)]; /* 732 */
char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
char volume_set_id [ISODCL (191, 318)]; /* dchars */
char publisher_id [ISODCL (319, 446)]; /* achars */
char preparer_id [ISODCL (447, 574)]; /* achars */
char application_id [ISODCL (575, 702)]; /* achars */
char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
char file_structure_version [ISODCL (882, 882)]; /* 711 */
char unused4 [ISODCL (883, 883)];
char application_data [ISODCL (884, 1395)];
char unused5 [ISODCL (1396, 2048)];
};
/* Almost the same as the primary descriptor but two fields are specified */
struct iso_supplementary_descriptor {
char type [ISODCL ( 1, 1)]; /* 711 */
char id [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char flags [ISODCL ( 8, 8)]; /* 853 */
char system_id [ISODCL ( 9, 40)]; /* achars */
char volume_id [ISODCL ( 41, 72)]; /* dchars */
char unused2 [ISODCL ( 73, 80)];
char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
char escape [ISODCL ( 89, 120)]; /* 856 */
char volume_set_size [ISODCL (121, 124)]; /* 723 */
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
char logical_block_size [ISODCL (129, 132)]; /* 723 */
char path_table_size [ISODCL (133, 140)]; /* 733 */
char type_l_path_table [ISODCL (141, 144)]; /* 731 */
char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
char type_m_path_table [ISODCL (149, 152)]; /* 732 */
char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
char volume_set_id [ISODCL (191, 318)]; /* dchars */
char publisher_id [ISODCL (319, 446)]; /* achars */
char preparer_id [ISODCL (447, 574)]; /* achars */
char application_id [ISODCL (575, 702)]; /* achars */
char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
char file_structure_version [ISODCL (882, 882)]; /* 711 */
char unused4 [ISODCL (883, 883)];
char application_data [ISODCL (884, 1395)];
char unused5 [ISODCL (1396, 2048)];
};
#define HS_STANDARD_ID "CDROM"
struct hs_volume_descriptor {
char foo [ISODCL ( 1, 8)]; /* 733 */
char type [ISODCL ( 9, 9)]; /* 711 */
char id [ISODCL ( 10, 14)];
char version [ISODCL ( 15, 15)]; /* 711 */
char data[ISODCL(16,2048)];
};
struct hs_primary_descriptor {
char foo [ISODCL ( 1, 8)]; /* 733 */
char type [ISODCL ( 9, 9)]; /* 711 */
char id [ISODCL ( 10, 14)];
char version [ISODCL ( 15, 15)]; /* 711 */
char unused1 [ISODCL ( 16, 16)]; /* 711 */
char system_id [ISODCL ( 17, 48)]; /* achars */
char volume_id [ISODCL ( 49, 80)]; /* dchars */
char unused2 [ISODCL ( 81, 88)]; /* 733 */
char volume_space_size [ISODCL ( 89, 96)]; /* 733 */
char unused3 [ISODCL ( 97, 128)]; /* 733 */
char volume_set_size [ISODCL (129, 132)]; /* 723 */
char volume_sequence_number [ISODCL (133, 136)]; /* 723 */
char logical_block_size [ISODCL (137, 140)]; /* 723 */
char path_table_size [ISODCL (141, 148)]; /* 733 */
char type_l_path_table [ISODCL (149, 152)]; /* 731 */
char unused4 [ISODCL (153, 180)]; /* 733 */
char root_directory_record [ISODCL (181, 214)]; /* 9.1 */
};
/* We use this to help us look up the parent inode numbers. */
struct iso_path_table{
unsigned char name_len[2]; /* 721 */
char extent[4]; /* 731 */
char parent[2]; /* 721 */
char name[0];
} __attribute__((packed));
/* high sierra is identical to iso, except that the date is only 6 bytes, and
there is an extra reserved byte after the flags */
struct iso_directory_record {
char length [ISODCL (1, 1)]; /* 711 */
char ext_attr_length [ISODCL (2, 2)]; /* 711 */
char extent [ISODCL (3, 10)]; /* 733 */
char size [ISODCL (11, 18)]; /* 733 */
char date [ISODCL (19, 25)]; /* 7 by 711 */
char flags [ISODCL (26, 26)];
char file_unit_size [ISODCL (27, 27)]; /* 711 */
char interleave [ISODCL (28, 28)]; /* 711 */
char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
unsigned char name_len [ISODCL (33, 33)]; /* 711 */
char name [0];
} __attribute__((packed));
#define ISOFS_BLOCK_BITS 11
#define ISOFS_BLOCK_SIZE (1 << ISOFS_BLOCK_BITS)
#endif /* _ISO9660_FS_H */

View File

@@ -0,0 +1,37 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE, http://emile.sf.net
*
*/
#include "libiso9660.h"
int iso9660_lseek(iso9660_FILE *_file, long offset, int whence)
{
iso9660_FILE *file = (iso9660_FILE*)_file;
long new_offset;
switch(whence)
{
case SEEK_SET:
new_offset = offset;
break;
case SEEK_CUR:
new_offset = file->offset + offset;
break;
case SEEK_END:
new_offset = file->size + offset;
break;
default:
return -1;
}
if ( (new_offset < 0) || (new_offset > file->size) )
return -1;
file->offset = new_offset;
return new_offset;
}

195
fs/iso9660/iso9660_mount.c Normal file
View File

@@ -0,0 +1,195 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE, http://emile.sf.net
*
* some parts from mkisofs (c) J. Schilling
*
*/
#include "libiso9660.h"
#include "openbios/bindings.h"
#include "libc/diskio.h"
void iso9660_name(iso9660_VOLUME *volume, struct iso_directory_record *idr, char *buffer)
{
int j;
unsigned char uh, ul, uc;
buffer[0] = 0;
if (idr->name_len[0] == 1 && idr->name[0] == 0)
strcpy(buffer, ".");
else if (idr->name_len[0] == 1 && idr->name[0] == 1)
strcpy(buffer, "..");
else {
switch (volume->ucs_level) {
case 3:
case 2:
case 1:
/*
* Unicode name.
*/
for (j = 0; j < (int)idr->name_len[0] / 2; j++) {
uh = idr->name[j*2];
ul = idr->name[j*2+1];
/*
* unicode convertion
* up = unls->unls_uni2cs[uh];
*
* if (up == NULL)
* uc = '\0';
* else
* uc = up[ul];
*
* we use only low byte
*/
uc = ul;
buffer[j] = uc ? uc : '_';
}
buffer[idr->name_len[0]/2] = '\0';
break;
case 0:
/*
* Normal non-Unicode name.
*/
strncpy(buffer, idr->name, idr->name_len[0]);
buffer[idr->name_len[0]] = 0;
break;
default:
/*
* Don't know how to do these yet. Maybe they are the same
* as one of the above.
*/
break;
}
}
}
iso9660_VOLUME *iso9660_mount(int fd)
{
iso9660_VOLUME* volume;
struct iso_primary_descriptor *jpd;
struct iso_primary_descriptor ipd;
int block;
int ucs_level = 0;
/* read filesystem descriptor */
seek_io(fd, 16 * ISOFS_BLOCK_SIZE);
read_io(fd, &ipd, sizeof (ipd));
/*
* High sierra:
*
* DESC TYPE == 1 (VD_SFS) offset 8 len 1
* STR ID == "CDROM" offset 9 len 5
* STD_VER == 1 offset 14 len 1
*/
/* High Sierra format ? */
if ((((char *)&ipd)[8] == 1) &&
(strncmp(&((char *)&ipd)[9], "CDROM", 5) == 0) &&
(((char *)&ipd)[14] == 1)) {
printk("Incompatible format: High Sierra format\n");
return NULL;
}
/*
* ISO 9660:
*
* DESC TYPE == 1 (VD_PVD) offset 0 len 1
* STR ID == "CD001" offset 1 len 5
* STD_VER == 1 offset 6 len 1
*/
/* NOT ISO 9660 format ? */
if ((ipd.type[0] != ISO_VD_PRIMARY) ||
(strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
(ipd.version[0] != 1)) {
return NULL;
}
/* UCS info */
block = 16;
jpd = (struct iso_primary_descriptor *)
malloc(sizeof(struct iso_primary_descriptor));
if (jpd == NULL)
return NULL;
memcpy(jpd, &ipd, sizeof (ipd));
while ((uint8_t)jpd->type[0] != ISO_VD_END) {
/*
* If Joliet UCS escape sequence found, we may be wrong
*/
if (jpd->unused3[0] == '%' &&
jpd->unused3[1] == '/' &&
(jpd->unused3[3] == '\0' ||
jpd->unused3[3] == ' ') &&
(jpd->unused3[2] == '@' ||
jpd->unused3[2] == 'C' ||
jpd->unused3[2] == 'E')) {
if (jpd->version[0] != 1)
break;
}
block++;
seek_io(fd, block * ISOFS_BLOCK_SIZE);
read_io(fd, jpd, sizeof (*jpd));
}
ucs_level = 0;
if (((unsigned char) jpd->type[0] == ISO_VD_END)) {
memcpy(jpd, &ipd, sizeof (ipd));
} else {
switch (jpd->unused3[2]) {
case '@':
ucs_level = 1;
break;
case 'C':
ucs_level = 2;
break;
case 'E':
ucs_level = 3;
break;
}
if (ucs_level && jpd->unused3[3] == ' ')
printk("Warning: Joliet escape sequence uses illegal space at offset 3\n");
}
volume = (iso9660_VOLUME*)malloc(sizeof(iso9660_VOLUME));
if (volume == NULL)
return NULL;
volume->descriptor = jpd;
volume->ucs_level = ucs_level;
volume->fd = fd;
return volume;
}
int iso9660_umount(iso9660_VOLUME* volume)
{
if (volume == NULL)
return -1;
free(volume->descriptor);
free(volume);
return 0;
}
struct iso_directory_record *iso9660_get_root_node(iso9660_VOLUME* volume)
{
return (struct iso_directory_record *)volume->descriptor->root_directory_record;
}

39
fs/iso9660/iso9660_open.c Normal file
View File

@@ -0,0 +1,39 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE, http://emile.sf.net
*
*/
#include "libiso9660.h"
iso9660_FILE* iso9660_open(iso9660_VOLUME *volume, const char* pathname)
{
struct iso_directory_record *root;
struct iso_directory_record *idr;
iso9660_FILE *file;
root = iso9660_get_root_node(volume);
if (root == NULL)
return NULL;
idr = iso9660_get_node(volume, root, pathname);
if (idr == NULL)
return NULL;
file = (iso9660_FILE*)malloc(sizeof(iso9660_FILE));
if (file == NULL)
return NULL;
file->base = isonum_733((char *)idr->extent);
file->size = isonum_733((char *)idr->size);
file->offset = 0;
file->current = -1;
file->volume = volume;
file->path = strdup(pathname);
free(idr);
return file;
}

View File

@@ -0,0 +1,133 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE, http://emile.sf.net
*
*/
#include "libiso9660.h"
static inline int iso9660_is_directory(struct iso_directory_record * idr)
{
return ((idr->flags[0] & 2) != 0);
}
static iso9660_DIR* iso9660_opendir_node(iso9660_VOLUME *volume, struct iso_directory_record *node)
{
iso9660_DIR *dir;
dir = (iso9660_DIR*)malloc(sizeof(iso9660_DIR));
if (dir == NULL)
return NULL;
dir->extent = isonum_733((char *)node->extent);
dir->len = isonum_733((char *)node->size);
dir->index = sizeof (dir->buffer);
dir->volume = volume;
return dir;
}
static struct iso_directory_record* idr_new(struct iso_directory_record* idr)
{
struct iso_directory_record* result;
int size = sizeof(*idr) + (int)idr->name_len[0];
result = (struct iso_directory_record*)malloc(size);
memcpy(result, idr, size);
return result;
}
static struct iso_directory_record * seek_name(iso9660_VOLUME *volume,
struct iso_directory_record *idr,
char *name)
{
struct iso_directory_record *result;
char name_buf[256];
iso9660_DIR *dir;
dir = iso9660_opendir_node(volume, idr);
if (dir == NULL)
return NULL;
while ((idr = iso9660_readdir(dir)) != NULL)
{
iso9660_name(volume, idr, name_buf);
if (strcmp(name, name_buf) == 0)
{
result = idr_new(idr);
iso9660_closedir(dir);
return result;
}
}
iso9660_closedir(dir);
return NULL;
}
struct iso_directory_record* iso9660_get_node(
iso9660_VOLUME *volume,
struct iso_directory_record *dirnode,
const char *path)
{
struct iso_directory_record* result;
struct iso_directory_record* current;
char name[256];
int i;
current = idr_new(dirnode);
while(1)
{
/* ignore head '\' */
while (*path && *path == '\\')
path++;
if (*path == 0)
break;
/* extract first path component */
i = 0;
while (*path && *path != '\\')
name[i++] = *path++;
name[i] = 0;
/* seek first component in current directory */
result = seek_name(volume, current, name);
if (result == NULL)
return NULL;
free(current);
current = result;
}
return current;
}
iso9660_DIR* iso9660_opendir(iso9660_VOLUME *volume, const char *name)
{
iso9660_DIR *dir;
struct iso_directory_record *node;
node = iso9660_get_root_node((iso9660_VOLUME*)volume);
if (node == NULL)
return NULL;
node = iso9660_get_node((iso9660_VOLUME*)volume, node, name);
if (node == NULL)
return NULL;
if (!iso9660_is_directory(node)) {
free(node);
return NULL;
}
dir = iso9660_opendir_node((iso9660_VOLUME*)volume, node);
free(node);
dir->volume = (iso9660_VOLUME*)volume;
return dir;
}

74
fs/iso9660/iso9660_read.c Normal file
View File

@@ -0,0 +1,74 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE, http://emile.sf.net
*
*/
#include "libiso9660.h"
#include "openbios/bindings.h"
#include "libc/diskio.h"
size_t iso9660_read(iso9660_FILE *_file, char *buf, size_t count)
{
iso9660_FILE *file = (iso9660_FILE*)_file;
size_t read = 0;
if ( count > (file->size - file->offset) )
count = file->size - file->offset;
while (count > 0)
{
size_t part;
int offset_extent;
int offset_index;
offset_extent = file->base +
(file->offset / ISOFS_BLOCK_SIZE);
offset_index = file->offset % ISOFS_BLOCK_SIZE;
if (file->current != offset_extent)
{
if ( (offset_index == 0) &&
(count >= ISOFS_BLOCK_SIZE) )
{
/* direct i/o */
int extents_nb;
extents_nb = count / ISOFS_BLOCK_SIZE;
part = extents_nb * ISOFS_BLOCK_SIZE;
seek_io(file->volume->fd,
offset_extent * ISOFS_BLOCK_SIZE);
read_io(file->volume->fd, buf + read, part);
file->offset += part;
count -= part;
read += part;
continue;
}
file->current = offset_extent;
seek_io(file->volume->fd,
offset_extent * ISOFS_BLOCK_SIZE);
read_io(file->volume->fd, file->buffer,
ISOFS_BLOCK_SIZE);
}
part = ISOFS_BLOCK_SIZE - offset_index;
if (count < part)
part = count;
memcpy(buf + read, file->buffer + offset_index, part);
file->offset += part;
count -= part;
read += part;
}
return read;
}

View File

@@ -0,0 +1,50 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE, http://emile.sf.net
*
*/
#include "libiso9660.h"
#include "openbios/bindings.h"
#include "libc/diskio.h"
#define offsetof(t,m) ((long)&(((t *)0)->m))
static void read_extent(iso9660_DIR *dir)
{
seek_io(dir->volume->fd, dir->extent * ISOFS_BLOCK_SIZE);
read_io(dir->volume->fd, dir->buffer, ISOFS_BLOCK_SIZE);
dir->len -= ISOFS_BLOCK_SIZE;
dir->extent ++;
dir->index = 0;
}
struct iso_directory_record *iso9660_readdir(iso9660_DIR *dir)
{
struct iso_directory_record *idr;
if (dir->index >
ISOFS_BLOCK_SIZE - offsetof(struct iso_directory_record, name[0]))
{
if (dir->len <= 0)
return NULL;
read_extent(dir);
}
idr = (struct iso_directory_record *) &dir->buffer[dir->index];
if (idr->length[0] == 0) {
if (dir->len <= 0)
return NULL;
read_extent(dir);
idr = (struct iso_directory_record *) &dir->buffer[dir->index];
}
dir->index += dir->buffer[dir->index];
return idr;
}

26
fs/iso9660/libiso9660.h Normal file
View File

@@ -0,0 +1,26 @@
/*
*
* (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
*
* This file has been copied from EMILE, http://emile.sf.net
*
*/
#ifndef __LIBISO9660_H__
#define __LIBISO9660_H__
#include "openbios/config.h"
#include "iso9660.h"
extern iso9660_VOLUME* iso9660_mount(int fd);
extern int iso9660_umount(iso9660_VOLUME *volume);
extern iso9660_DIR* iso9660_opendir(iso9660_VOLUME *, const char *name);
extern iso9660_FILE* iso9660_open(iso9660_VOLUME *, const char *pathname);
extern int iso9660_closedir(iso9660_DIR *dir);
extern struct iso_directory_record *iso9660_readdir(iso9660_DIR *dir);
extern size_t iso9660_read(iso9660_FILE *file, char *buf, size_t count);
extern void iso9660_close(iso9660_FILE *file);
extern int iso9660_lseek(iso9660_FILE *file, long offset, int whence);
extern void iso9660_name(iso9660_VOLUME *volume, struct iso_directory_record * idr, char *buffer);
#endif /* __LIBISO9660_H__ */