Currently the dir word works by using /packages/misc-files to open a directory in a similar way to a file and then

special-casing directory actions. This is wrong in that in order to list the contents of a directory, open-dev must return true 
for any device which contains a valid filesystem, regardless of whether or not the supplied arguments reference a valid path.

This causes us a problem because in order to implement multiple references in boot-device correctly, we have to fail if we open 
a specific device with invalid arguments (such as a non-existent file reference). This patch therefore makes the following changes:

1) Create a static method in each of the filesystem packages to implement dir
2) Enhance the partition/disk handlers to record the phandle of any detected filesystem during open
3) Create a new dir method in the partition/disk handlers which invokes the static dir method for the currently detected 
filesystem

Hence we can now open a raw device/partition and invoke dir on its filesystem without having to open a specific file-reference 
first. Following shortly is a patch to switch the main dir word over to use this new system.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>


git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@816 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
Mark Cave-Ayland
2010-07-10 13:11:22 +00:00
committed by Mark Cave-Ayland
parent 930ce00f5f
commit a5511ad95c
9 changed files with 263 additions and 30 deletions

View File

@@ -33,7 +33,7 @@ typedef struct {
DECLARE_NODE( ext2, 0, sizeof(ext2_info_t), "+/packages/ext2-files" );
/*
static const int days_month[12] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static const int days_month_leap[12] =
@@ -83,28 +83,6 @@ print_date(time_t sec)
year, month, day, hour, minute, second);
}
static void
dir_fs ( file_desc_t *fd)
{
ext2_COMMON *common = (ext2_COMMON *)fd;
struct ext2_dir_entry_2 *entry;
struct ext2_inode inode;
if (common->type != DIR)
return;
forth_printf("\n");
while ( (entry = ext2_readdir(common->dir)) ) {
ext2_get_inode(common->dir->volume, entry->inode, &inode);
forth_printf("% 10d ", inode.i_size);
print_date(inode.i_mtime);
if (S_ISDIR(inode.i_mode))
forth_printf("%s\\\n", entry->name);
else
forth_printf("%s\n", entry->name);
}
}
*/
/************************************************************************/
/* Standard package methods */
@@ -233,6 +211,52 @@ ext2_files_get_fstype( ext2_info_t *mi )
PUSH( (ucell)strdup("ext2") );
}
/* static method, ( pathstr len ihandle -- ) */
static void
ext2_files_dir( ext2_info_t *dummy )
{
ext2_COMMON *common;
ext2_VOLUME *volume;
struct ext2_dir_entry_2 *entry;
struct ext2_inode inode;
int fd;
ihandle_t ih = POP();
char *path = pop_fstr_copy();
fd = open_ih( ih );
if ( fd == -1 ) {
free( path );
return;
}
volume = ext2_mount(fd);
if (!volume) {
return;
}
common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON));
common->dir = ext2_opendir(volume, path);
forth_printf("\n");
while ( (entry = ext2_readdir(common->dir)) ) {
ext2_get_inode(common->dir->volume, entry->inode, &inode);
forth_printf("% 10d ", inode.i_size);
print_date(inode.i_mtime);
if (S_ISDIR(inode.i_mode))
forth_printf("%s\\\n", entry->name);
else
forth_printf("%s\n", entry->name);
}
ext2_closedir( common->dir );
ext2_umount( volume );
close_io( fd );
free( common );
free( path );
}
/* static method, ( pos.d ih -- flag? ) */
static void
@@ -265,6 +289,7 @@ NODE_METHODS( ext2 ) = {
{ "read", ext2_files_read },
{ "seek", ext2_files_seek },
{ "load", ext2_files_load },
{ "dir", ext2_files_dir },
/* special */
{ "get-path", ext2_files_get_path },

View File

@@ -356,6 +356,15 @@ grubfs_files_probe( grubfs_info_t *dummy )
RET ( 0 );
}
/* static method, ( pathstr len ihandle -- ) */
static void
grubfs_files_dir( grubfs_info_t *mi )
{
forth_printf("dir method not implemented for grubfs filesystem\n");
POP();
POP();
POP();
}
static void
grubfs_initializer( grubfs_info_t *dummy )
@@ -370,6 +379,7 @@ NODE_METHODS( grubfs ) = {
{ "read", grubfs_files_read },
{ "seek", grubfs_files_seek },
{ "load", grubfs_files_load },
{ "dir", grubfs_files_dir },
/* special */
{ "get-path", grubfs_files_get_path },

View File

@@ -144,7 +144,6 @@ _do_search( hfs_info_t *mi, const char *sname )
return mi->common->file;
}
/*
static const int days_month[12] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
@@ -195,6 +194,7 @@ print_date(time_t sec)
year, month, day, hour, minute, second);
}
/*
static void
dir_fs( file_desc_t *fd )
{
@@ -485,6 +485,83 @@ hfs_files_volume_name( hfs_info_t *mi )
PUSH ((ucell)volname);
}
/* static method, ( pathstr len ihandle -- ) */
static void
hfs_files_dir( hfs_info_t *dummy )
{
hfsvol *volume;
hfscommon *common;
hfsdirent ent;
const char *s;
char buf[256], *tmppath;
int fd;
ihandle_t ih = POP();
char *path = pop_fstr_copy();
fd = open_ih( ih );
if ( fd == -1 ) {
free( path );
return;
}
volume = hfs_mount(fd, 0);
if (!volume) {
return;
}
common = malloc(sizeof(hfscommon));
if (strcmp(path, "\\") == 0) {
common->dir = hfs_opendir(volume, ":");
} else {
if (path[strlen(path) - 1] == '\\') {
path[strlen(path) - 1] = 0;
}
tmppath = path;
for( tmppath-- ;; ) {
int n;
s = ++tmppath;
tmppath = strchr(s, '\\');
if( !tmppath || !tmppath[1])
break;
n = MIN( sizeof(buf)-1, (path-s) );
if( !n )
continue;
strncpy( buf, s, n );
buf[n] = 0;
if( hfs_chdir(volume, buf) ) {
free(common);
free(path);
return;
}
}
common->dir = hfs_opendir(volume, s);
}
forth_printf("\n");
while( !hfs_readdir(common->dir, &ent) ) {
forth_printf("% 10d ", ent.u.file.dsize);
print_date(ent.mddate);
if( ent.flags & HFS_ISDIR )
forth_printf("%s\\\n", ent.name);
else
forth_printf("%s\n", ent.name);
}
hfs_closedir( common->dir );
hfs_umount( volume );
close_io( fd );
free( common );
free( path );
}
/* static method, ( pos.d ih -- flag? ) */
static void
hfs_files_probe( hfs_info_t *dummy )
@@ -515,6 +592,7 @@ NODE_METHODS( hfs ) = {
{ "read", hfs_files_read },
{ "seek", hfs_files_seek },
{ "load", hfs_files_load },
{ "dir", hfs_files_dir },
/* special */
{ "open-nwrom", hfs_files_open_nwrom },

View File

@@ -24,6 +24,7 @@
#include "unicode.h"
#include "blockiter.h"
#include "libc/diskio.h"
#include "libc/vsprintf.h"
#define MAC_OS_ROM_CREATOR 0x63687270 /* 'chrp' */
#define MAC_OS_ROM_TYPE 0x74627869 /* 'tbxi' */
@@ -432,6 +433,16 @@ hfsp_files_volume_name( hfsp_info_t *mi )
PUSH ((ucell)volname);
}
/* static method, ( pathstr len ihandle -- ) */
static void
hfsp_files_dir( hfsp_info_t *dummy )
{
forth_printf("dir method not implemented for HFS+ filesystem\n");
POP();
POP();
POP();
}
/* static method, ( pos.d ih -- flag? ) */
static void
hfsp_files_probe( hfsp_info_t *dummy )
@@ -449,7 +460,6 @@ hfsp_files_probe( hfsp_info_t *dummy )
RET (ret);
}
static void
hfsp_initializer( hfsp_info_t *dummy )
{
@@ -463,6 +473,7 @@ NODE_METHODS( hfsp ) = {
{ "read", hfsp_files_read },
{ "seek", hfsp_files_seek },
{ "load", hfsp_files_load },
{ "dir", hfsp_files_dir },
/* special */
{ "open-nwrom", hfsp_files_open_nwrom },

View File

@@ -156,17 +156,37 @@ iso9660_files_load( iso9660_info_t *mi)
PUSH( size );
}
/* static method, ( pathstr len ihandle -- ) */
static void
iso9660_files_dir( iso9660_info_t *mi )
iso9660_files_dir( iso9660_info_t *dummy )
{
iso9660_VOLUME *volume;
iso9660_COMMON *common;
struct iso_directory_record *idr;
char name_buf[256];
int fd;
if (mi->common->type != DIR)
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(mi->common->dir)) ) {
while ( (idr = iso9660_readdir(common->dir)) ) {
forth_printf("% 10d ", isonum_733(idr->size));
forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
@@ -174,12 +194,20 @@ iso9660_files_dir( iso9660_info_t *mi )
idr->date[1], /* month */
idr->date[2], /* day */
idr->date[3], idr->date[4], idr->date[5]);
iso9660_name(mi->common->dir->volume, idr, name_buf);
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? ) */