mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
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:
committed by
Laurent Vivier
parent
02d95dc3cd
commit
d2cc5db789
@@ -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
13
fs/iso9660/build.xml
Normal 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
58
fs/iso9660/iso9660.h
Normal 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__ */
|
||||
15
fs/iso9660/iso9660_close.c
Normal file
15
fs/iso9660/iso9660_close.c
Normal 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);
|
||||
}
|
||||
19
fs/iso9660/iso9660_closedir.c
Normal file
19
fs/iso9660/iso9660_closedir.c
Normal 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
104
fs/iso9660/iso9660_fs.c
Normal 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
161
fs/iso9660/iso9660_fs.h
Normal 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 */
|
||||
37
fs/iso9660/iso9660_lseek.c
Normal file
37
fs/iso9660/iso9660_lseek.c
Normal 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
195
fs/iso9660/iso9660_mount.c
Normal 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
39
fs/iso9660/iso9660_open.c
Normal 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;
|
||||
}
|
||||
133
fs/iso9660/iso9660_opendir.c
Normal file
133
fs/iso9660/iso9660_opendir.c
Normal 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
74
fs/iso9660/iso9660_read.c
Normal 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;
|
||||
}
|
||||
50
fs/iso9660/iso9660_readdir.c
Normal file
50
fs/iso9660/iso9660_readdir.c
Normal 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
26
fs/iso9660/libiso9660.h
Normal 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__ */
|
||||
Reference in New Issue
Block a user