summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/fs/iso9660/iso9660_fs.c
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@intel.com>2015-08-28 09:58:54 +0800
committerYang Zhang <yang.z.zhang@intel.com>2015-09-01 12:44:00 +0800
commite44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch)
tree66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/openbios/fs/iso9660/iso9660_fs.c
parent9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff)
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/openbios/fs/iso9660/iso9660_fs.c')
-rw-r--r--qemu/roms/openbios/fs/iso9660/iso9660_fs.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_fs.c b/qemu/roms/openbios/fs/iso9660/iso9660_fs.c
new file mode 100644
index 000000000..d6f547be1
--- /dev/null
+++ b/qemu/roms/openbios/fs/iso9660/iso9660_fs.c
@@ -0,0 +1,263 @@
+/*
+ * /packages/iso9660-files filesystem handler
+ *
+ * (c) 2009 Laurent Vivier <Laurent@vivier.eu>
+ * (c) 2010 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libiso9660.h"
+#include "fs/fs.h"
+#include "libc/vsprintf.h"
+#include "libc/diskio.h"
+
+extern void iso9660_init( void );
+
+typedef struct {
+ enum { FILE, DIR } type;
+ union {
+ iso9660_FILE *file;
+ iso9660_DIR * dir;
+ };
+} iso9660_COMMON;
+
+typedef struct {
+ iso9660_VOLUME *volume;
+ iso9660_COMMON *common;
+} iso9660_info_t;
+
+DECLARE_NODE( iso9660, 0, sizeof(iso9660_info_t), "+/packages/iso9660-files" );
+
+/* ( -- success? ) */
+static void
+iso9660_files_open( iso9660_info_t *mi )
+{
+ int fd;
+ char *path = my_args_copy();
+
+ if ( ! path )
+ RET( 0 );
+
+ fd = open_ih( my_parent() );
+ if ( fd == -1 ) {
+ free( path );
+ RET( 0 );
+ }
+
+ mi->volume = iso9660_mount( fd );
+ if ( mi->volume == NULL ) {
+ free( path );
+ close_io( fd );
+ RET( 0 );
+ }
+
+ mi->common->dir = iso9660_opendir( mi->volume, path );
+ if ( mi->common->dir == NULL ) {
+ mi->common->file = iso9660_open( mi->volume, path );
+ if (mi->common->file == NULL) {
+ iso9660_umount( mi->volume );
+ close_io( fd );
+ free( path );
+ RET( 0 );
+ }
+ mi->common->type = FILE;
+ free( path );
+ RET( -1 );
+ }
+ mi->common->type = DIR;
+ free( path );
+
+ RET( -1 );
+}
+
+/* ( -- ) */
+static void
+iso9660_files_close( iso9660_info_t *mi )
+{
+ int fd = mi->volume->fd;
+
+ if (mi->common->type == FILE )
+ iso9660_close( mi->common->file );
+ else if ( mi->common->type == DIR )
+ iso9660_closedir( mi->common->dir );
+ iso9660_umount( mi->volume );
+ close_io( fd );
+}
+
+/* ( buf len -- actlen ) */
+static void
+iso9660_files_read( iso9660_info_t *mi )
+{
+ int count = POP();
+ char *buf = (char *)cell2pointer(POP());
+ int ret;
+
+ if ( mi->common->type != FILE )
+ PUSH( 0 );
+
+ ret = iso9660_read( mi->common->file, buf, count );
+
+ PUSH( ret );
+}
+
+/* ( pos.d -- status ) */
+static void
+iso9660_files_seek( iso9660_info_t *mi )
+{
+ long long pos = DPOP();
+ cell ret;
+ int offs = (int)pos;
+ int whence = SEEK_SET;
+
+ if (mi->common->type != FILE)
+ PUSH( -1 );
+
+ if( offs == -1 ) {
+ offs = 0;
+ whence = SEEK_END;
+ }
+
+ ret = iso9660_lseek(mi->common->file, offs, whence);
+
+ PUSH( (ret < 0)? -1 : 0 );
+}
+
+/* ( -- filepos.d ) */
+static void
+iso9660_files_offset( iso9660_info_t *mi )
+{
+ if ( mi->common->type != FILE )
+ DPUSH( -1 );
+
+ DPUSH( mi->common->file->offset );
+}
+
+/* ( addr -- size ) */
+static void
+iso9660_files_load( iso9660_info_t *mi)
+{
+ char *buf = (char*)cell2pointer(POP());
+ int ret, size;
+
+ if ( mi->common->type != FILE )
+ PUSH( 0 );
+
+ size = 0;
+ while(1) {
+ ret = iso9660_read( mi->common->file, buf, 512 );
+ if (ret <= 0)
+ break;
+ buf += ret;
+ size += ret;
+ if (ret != 512)
+ break;
+ }
+ PUSH( size );
+}
+
+/* static method, ( pathstr len ihandle -- ) */
+static void
+iso9660_files_dir( iso9660_info_t *dummy )
+{
+ iso9660_VOLUME *volume;
+ iso9660_COMMON *common;
+ struct iso_directory_record *idr;
+ char name_buf[256];
+ int fd;
+
+ ihandle_t ih = POP();
+ char *path = pop_fstr_copy();
+
+ fd = open_ih( ih );
+ if ( fd == -1 ) {
+ free( path );
+ return;
+ }
+
+ volume = iso9660_mount( fd );
+ if ( volume == NULL ) {
+ free ( path );
+ close_io( fd );
+ return;
+ }
+
+ common = malloc(sizeof(iso9660_COMMON));
+ common->dir = iso9660_opendir( volume, path );
+
+ forth_printf("\n");
+ while ( (idr = iso9660_readdir(common->dir)) ) {
+
+ forth_printf("% 10d ", isonum_733(idr->size));
+ forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
+ idr->date[0] + 1900, /* year */
+ idr->date[1], /* month */
+ idr->date[2], /* day */
+ idr->date[3], idr->date[4], idr->date[5]);
+ iso9660_name(common->dir->volume, idr, name_buf);
+ if (idr->flags[0] & 2)
+ forth_printf("%s\\\n", name_buf);
+ else
+ forth_printf("%s\n", name_buf);
+ }
+
+ iso9660_closedir( common->dir );
+ iso9660_umount( volume );
+
+ close_io( fd );
+
+ free( common );
+ free( path );
+}
+
+/* static method, ( pos.d ih -- flag? ) */
+static void
+iso9660_files_probe( iso9660_info_t *dummy )
+{
+ ihandle_t ih = POP_ih();
+ long long offs = DPOP();
+ int fd, ret = 0;
+
+ fd = open_ih(ih);
+ if (fd >= 0) {
+ if (iso9660_probe(fd, offs)) {
+ ret = -1;
+ }
+ close_io(fd);
+ } else {
+ ret = -1;
+ }
+
+ RET (ret);
+}
+
+static void
+iso9660_files_block_size( iso9660_info_t *dummy )
+{
+ PUSH(2048);
+}
+
+static void
+iso9660_initializer( iso9660_info_t *dummy )
+{
+ fword("register-fs-package");
+}
+
+NODE_METHODS( iso9660 ) = {
+ { "probe", iso9660_files_probe },
+ { "open", iso9660_files_open },
+ { "close", iso9660_files_close },
+ { "read", iso9660_files_read },
+ { "seek", iso9660_files_seek },
+ { "offset", iso9660_files_offset },
+ { "load", iso9660_files_load },
+ { "dir", iso9660_files_dir },
+ { "block-size", iso9660_files_block_size },
+ { NULL, iso9660_initializer },
+};
+
+void
+iso9660_init( void )
+{
+ REGISTER_NODE( iso9660 );
+}