;
; INT 22h AX=0020h Open directory
;
-%if IS_SYSLINUX
+%if IS_PXELINUX
+comapi_opendir equ comapi_err
+
+%else
comapi_opendir:
mov es,P_ES
mov si,P_SI
mov P_EAX,eax
clc
ret
-%else
-comapi_opendir equ comapi_err
%endif
;
; INT 22h AX=0021h Read directory
;
-%if IS_SYSLINUX
+%if IS_PXELINUX
+comapi_readdir equ comapi_err
+
+%else
comapi_readdir:
mov esi,P_ESI ; The address of DIR structure
pm_call readdir
mov P_EAX,eax ; The address of newly read dirent structure
ret
-%else
-comapi_readdir equ comapi_err
%endif
;
* open dir, return the file structure pointer in _eax_, or NULL if failed
*/
void opendir(com32sys_t *regs)
-{
- this_fs->fs_ops->opendir(regs);
+{
+ char *src = MK_PTR(regs->es, regs->esi.w[0]);
+ char *dst = MK_PTR(regs->ds, regs->edi.w[0]);
+ strcpy(dst, src);
+ searchdir(regs);
regs->eax.l = (uint32_t)handle_to_file(regs->esi.w[0]);
}
else
ret = bmap_traditional(fs, inode, block);
- if (!ret) {
- printf("ERROR: something error happend at linsector..\n");
- return 0;
- }
-
return ret;
}
#include <stdio.h>
#include <string.h>
+#include <sys/dirent.h>
#include <cache.h>
#include <core.h>
#include <disk.h>
return p;
}
+/*
+ * Read one directory entry at a time
+ */
+static struct dirent * ext2_readdir(struct file *file)
+{
+ struct fs_info *fs = file->fs;
+ struct inode *inode = file->inode;
+ struct dirent *dirent;
+ struct ext2_dir_entry *de;
+ struct cache_struct *cs;
+ int index = file->offset >> fs->block_shift;
+ block_t block;
+
+ if (!(block = bmap(fs, inode, index)))
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, block);
+ de = (struct ext2_dir_entry *)(cs->data + (file->offset & (BLOCK_SIZE(fs) - 1)));
+
+ if (!(dirent = malloc(sizeof(*dirent)))) {
+ malloc_error("dirent structure in ext2_readdir");
+ return NULL;
+ }
+ dirent->d_ino = de->d_inode;
+ dirent->d_off = file->offset;
+ dirent->d_reclen = de->d_rec_len;
+ dirent->d_type = de->d_file_type;
+ memcpy(dirent->d_name, de->d_name, de->d_name_len);
+ dirent->d_name[de->d_name_len] = '\0';
+
+ file->offset += de->d_rec_len; /* Update for next reading */
+
+ return dirent;
+}
/* Load the config file, return 1 if failed, or 0 */
static int ext2_load_config(void)
.iget_root = ext2_iget_root,
.iget_current = ext2_iget_current,
.iget = ext2_iget,
- .follow_symlink = ext2_follow_symlink
+ .follow_symlink = ext2_follow_symlink,
+ .readdir = ext2_readdir
};
return vfat_find_entry(dname, parent);
}
-/*
- * The open dir function, just call the searchdir function directly.
- * I don't think we need call the mangle_name function first
- */
-void vfat_opendir(com32sys_t *regs)
+static struct dirent * vfat_readdir(struct file *file)
{
- char *src = MK_PTR(regs->es, regs->esi.w[0]);
- char *dst = MK_PTR(regs->ds, regs->edi.w[0]);
- strcpy(dst, src);
- searchdir(regs);
+ struct fs_info *fs = file->fs;
+ struct dirent *dirent;
+ struct fat_dir_entry *de;
+ struct fat_long_name_entry *long_de;
+ struct cache_struct *cs;
+
+ sector_t sector = get_the_right_sector(file);
+
+ uint8_t vfat_init, vfat_next, vfat_csum;
+ uint8_t id;
+ int entries_left;
+ int checksum;
+ int long_entry = 0;
+ int sec_off = file->offset & ((1 << fs->sector_shift) - 1);
+
+ cs = get_cache_block(fs->fs_dev, sector);
+ de = (struct fat_dir_entry *)(cs->data + sec_off);
+ entries_left = ((1 << fs->sector_shift) - sec_off) >> 5;
+
+ while (1) {
+ while(entries_left--) {
+ if (de->name[0] == 0)
+ return NULL;
+ if ((uint8_t)de->name[0] == 0xe5)
+ goto invalid;
+
+ if (de->attr == 0x0f) {
+ /*
+ * It's a long name entry.
+ */
+ long_de = (struct fat_long_name_entry *)de;
+ id = long_de->id;
+
+ if (id & 0x40) {
+ /* init vfat_csum and vfat_init */
+ vfat_csum = long_de->checksum;
+ id &= 0x3f;
+ vfat_init = id;
+
+ /* ZERO the long_name buffer */
+ memset(long_name, 0, sizeof long_name);
+ } else {
+ if (long_de->checksum != vfat_csum ||
+ id != vfat_next)
+ goto invalid;
+ }
+
+ vfat_next = --id;
+
+ /* got the long entry name */
+ long_entry_name(long_de);
+ memcpy(long_name + id * 13, entry_name, 13);
+
+ if (id == 0)
+ long_entry = 1;
+
+ de++;
+ file->offset += sizeof(struct fat_dir_entry);
+ continue; /* Try the next entry */
+ } else {
+ /*
+ * It's a short entry
+ */
+ if (de->attr & 0x08) /* ignore volume labels */
+ goto invalid;
+
+ if (long_entry == 1) {
+ /* Got a long entry */
+ checksum = get_checksum(de->name);
+ if (checksum == vfat_csum)
+ goto got;
+ } else {
+ /* Use the long_name buffer to store a short one. */
+ int i;
+ char *p = long_name;
+
+ for (i = 0; i < 8; i++) {
+ if (de->name[i] == ' ')
+ break;
+ *p++ = de->name[i];
+ }
+ *p++ = '.';
+ if (de->name[8] == ' ') {
+ *--p = '\0';
+ } else {
+ for (i = 8; i < 11; i++) {
+ if (de->name[i] == ' ')
+ break;
+ *p++ = de->name[i];
+ }
+ *p = '\0';
+ }
+
+ goto got;
+ }
+ }
+
+ invalid:
+ de++;
+ file->offset += sizeof(struct fat_dir_entry);
+ }
+
+ /* Try with the next sector */
+ sector = get_next_sector(fs, sector);
+ if (!sector)
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, sector);
+ de = (struct fat_dir_entry *)cs->data;
+ entries_left = 1 << (fs->sector_shift - 5);
+ }
+
+got:
+ if (!(dirent = malloc(sizeof(*dirent)))) {
+ malloc_error("dirent structure in vfat_readdir");
+ return NULL;
+ }
+ dirent->d_ino = 0; /* Inode number is invalid to FAT fs */
+ dirent->d_off = file->offset;
+ dirent->d_reclen = 0;
+ dirent->d_type = get_inode_mode(de->attr);
+ strcpy(dirent->d_name, long_name);
+
+ file->offset += sizeof(*de); /* Update for next reading */
+
+ return dirent;
}
-
/* Load the config file, return 1 if failed, or 0 */
static int vfat_load_config(void)
{
- static const char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg";
- static const char syslinux_cfg2[] = "/syslinux/syslinux.cfg";
- static const char syslinux_cfg3[] = "/syslinux.cfg";
- const char * const syslinux_cfg[] =
- { syslinux_cfg1, syslinux_cfg2, syslinux_cfg3 };
+ const char * const syslinux_cfg[] = {
+ "/boot/syslinux/syslinux.cfg",
+ "/syslinux/syslinux.cfg",
+ "/syslinux.cfg"
+ };
com32sys_t regs;
char *p;
int i = 0;
strcpy(ConfigName, "syslinux.cfg");
strcpy(CurrentDirName, syslinux_cfg[i]);
p = strrchr(CurrentDirName, '/');
- *p = '\0';
+ *(p + 1) = '\0'; /* In case we met '/syslinux.cfg' */
return 0;
}
.mangle_name = vfat_mangle_name,
.unmangle_name = generic_unmangle_name,
.load_config = vfat_load_config,
- .opendir = vfat_opendir,
- .readdir = NULL,
+ .readdir = vfat_readdir,
.iget_root = vfat_iget_root,
.iget_current = NULL,
.iget = vfat_iget,
#include <stdio.h>
#include <string.h>
+#include <sys/dirent.h>
#include <core.h>
#include <cache.h>
#include <disk.h>
return iso_get_inode(de);
}
+/* Convert to lower case string */
+static void tolower_str(char *str)
+{
+ while (*str) {
+ if (*str >= 'A' && *str <= 'Z')
+ *str = *str + 0x20;
+ str++;
+ }
+}
+
+static struct dirent *iso_readdir(struct file *file)
+{
+ struct fs_info *fs = file->fs;
+ struct inode *inode = file->inode;
+ struct iso_dir_entry *de, tmpde;
+ struct dirent *dirent;
+ struct cache_struct *cs = NULL;
+ block_t block = *file->inode->data + (file->offset >> fs->block_shift);
+ int offset = file->offset & (BLOCK_SIZE(fs) - 1);
+ int i = 0;
+ int de_len, de_name_len;
+ char *de_name;
+
+ while (1) {
+ if (!cs) {
+ if (++i > inode->blocks)
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, block++);
+ }
+ de = (struct iso_dir_entry *)(cs->data + offset);
+
+ de_len = de->length;
+ if (de_len == 0) { /* move on to the next block */
+ cs = NULL;
+ file->offset = (file->offset + BLOCK_SIZE(fs) - 1)
+ >> fs->block_shift;
+ continue;
+ }
+ offset += de_len;
+
+ /* Make sure we have a full directory entry */
+ if (offset >= BLOCK_SIZE(fs)) {
+ int slop = de_len + BLOCK_SIZE(fs) - offset;
+
+ memcpy(&tmpde, de, slop);
+ offset &= BLOCK_SIZE(fs) - 1;
+ if (offset) {
+ if (++i > inode->blocks)
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, block++);
+ memcpy((void *)&tmpde + slop, cs->data, offset);
+ }
+ de = &tmpde;
+ }
+
+ if (de_len < 33) {
+ printf("Corrupted directory entry in sector %u\n",
+ (uint32_t)(block - 1));
+ return NULL;
+ }
+
+ de_name_len = de->name_len;
+ de_name = de->name;
+ /* Handling the special case ".' and '..' here */
+ if((de_name_len == 1) && (*de_name == 0)) {
+ de_name = ".";
+ } else if ((de_name_len == 1) && (*de_name == 1)) {
+ de_name ="..";
+ de_name_len = 2;
+ }
+
+ break;
+ }
+
+ if (!(dirent = malloc(sizeof(*dirent)))) {
+ malloc_error("dirent structure in iso_readdir");
+ return NULL;
+ }
+
+ dirent->d_ino = 0; /* Inode number is invalid to ISO fs */
+ dirent->d_off = file->offset;
+ dirent->d_reclen = de_len;
+ dirent->d_type = get_inode_mode(de->flags);
+ iso_convert_name(dirent->d_name, de_name, de_name_len);
+ tolower_str(dirent->d_name);
+
+ file->offset += de_len; /* Update for next reading */
+
+ return dirent;
+}
+
/* Load the config file, return 1 if failed, or 0 */
static int iso_load_config(void)
{
.load_config = iso_load_config,
.iget_root = iso_iget_root,
.iget_current = NULL,
- .iget = iso_iget,
+ .iget = iso_iget,
+ .readdir = iso_readdir
};
char * (*follow_symlink)(struct inode *, const char *);
/* the _dir_ stuff */
- void (*opendir)(com32sys_t *);
struct dirent * (*readdir)(struct file *);
};