#endif
struct dirent {
- long d_ino; /* Inode/File number */
- off_t d_size; /* Size of file */
- mode_t d_mode; /* Type of file */
+ uint32_t d_ino;
+ uint32_t d_off;
+ uint16_t d_reclen;
+ uint16_t d_type;
char d_name[NAME_MAX + 1];
};
typedef struct {
- short dd_stat; /* status return from last lookup */
- uint16_t dd_fd;
- size_t dd_sect;
- char dd_name[NAME_MAX + 1]; /* directory */
+ uint16_t dd_stat;
+ uint16_t dd_sect;
+ uint64_t dd_offset;
+ char dd_name[NAME_MAX + 1];
} DIR;
__extern DIR *opendir(const char *);
int closedir(DIR * dir)
{
- int rv;
- com32sys_t regs;
- if (dir == NULL) {
+ int rv = -1;
+
+ if (dir) {
+ /*
+ com32sys_t regs;
+ memset(®s, 0, sizeof regs);
+ regs.eax.w[0] = 0x0022;
+ regs.esi.l = OFFS_WRT(dir, 0);
+ __com32.cs_intcall(0x22, ®s, ®s);
+ */
+ free(dir);
rv = 0;
- } else {
- memset(®s, 0, sizeof regs); /* ?Needed? */
- regs.eax.w[0] = 0x0022;
- regs.esi.w[0] = dir->dd_fd;
- __com32.cs_intcall(0x22, ®s, ®s);
- free(dir); /* garbage collection? */
- rv = 0;
- }
- return rv;
+ }
+
+ return rv;
}
DIR *opendir(const char *pathname)
{
- DIR *newdir;
+ DIR *newdir = NULL;
com32sys_t regs;
-
- newdir = NULL;
-
+
strlcpy(__com32.cs_bounce, pathname, __com32.cs_bounce_size);
regs.eax.w[0] = 0x0020;
regs.es = SEG(__com32.cs_bounce);
__com32.cs_intcall(0x22, ®s, ®s);
-
+
if (!(regs.eflags.l & EFLAGS_CF)) {
- /* Initialization: malloc() then zero */
- newdir = calloc(1, sizeof(DIR));
- strcpy(newdir->dd_name, pathname);
- newdir->dd_fd = regs.esi.w[0];
- newdir->dd_sect = regs.eax.l;
- newdir->dd_stat = 0;
+ /* Initialization: malloc() then zero */
+ newdir = calloc(1, sizeof(DIR));
+ strcpy(newdir->dd_name, pathname);
+ newdir->dd_sect = regs.eax.l;
+ newdir->dd_offset = 0;
+ newdir->dd_stat = 0;
}
/* We're done */
struct dirent *readdir(DIR * dir)
{
- struct dirent *newde;
+ struct dirent *newde = NULL;;
com32sys_t regs;
-
- newde = NULL;
- if ((dir != NULL) && (dir->dd_fd != 0) && (dir->dd_stat >= 0)) {
- memset(__com32.cs_bounce, 0, 32);
- memset(®s, 0, sizeof(regs));
-
+
+ if ((dir !=NULL) && (dir->dd_sect != 0) && (dir->dd_stat != 0xffff)) {
+ memset(®s, 0, sizeof(regs));
regs.eax.w[0] = 0x0021;
- regs.esi.w[0] = dir->dd_fd;
- regs.edi.w[0] = OFFS(__com32.cs_bounce);
- regs.es = SEG(__com32.cs_bounce);
-
+ regs.esi.l = (uint32_t)dir;
__com32.cs_intcall(0x22, ®s, ®s);
-
- /* Don't do this as we won't be able to rewind.
- dir->dd_fd = regs.esi.w[0]; /* Shouldn't be needed? */
- if ((!(regs.eflags.l & EFLAGS_CF)) && (regs.esi.w[0] != 0)) {
- newde = calloc(1, sizeof(newde));
- if (newde != NULL) {
- strcpy(newde->d_name, __com32.cs_bounce);
- newde->d_mode = regs.edx.b[0];
- newde->d_size = regs.eax.l;
- newde->d_ino = regs.ebx.l;
- dir->dd_stat = 1;
- } else {
- dir->dd_stat = -2;
- errno = ENOMEM;
- }
- } else {
- dir->dd_stat = -1;
- errno = EIO; /* Is this the right nmber? */
- }
- } else {
- errno = EBADF;
+ newde = (struct dirent *)(regs.eax.l);
}
-
+
return newde;
}
MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \
pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 meminfo.c32 \
sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 kbdmap.c32 cmd.c32 \
- vpdtest.c32 host.c32
+ vpdtest.c32 host.c32 dir.c32
TESTFILES =
--- /dev/null
+/*
+ * A dir test module
+ */
+#include <stdio.h>
+#include <console.h>
+#include <string.h>
+#include <com32.h>
+#include <dirent.h>
+
+int main(int argc, char *argv[])
+{
+ DIR *dir;
+ struct dirent *de;
+
+ openconsole(&dev_null_r, &dev_stdcon_w);
+
+ if (argc != 2) {
+ printf("Usage: dir direcotry\n");
+ return 0;
+ }
+
+ dir = opendir(argv[1]);
+ if (dir == NULL) {
+ printf("Unable to read dir: %s\n", argv[1]);
+ return 0;
+ }
+
+ while ((de = readdir(dir)) != NULL)
+ printf("%s\n", de->d_name);
+
+ closedir(dir);
+
+ return 0;
+}
+
ROSH_DEBUG("--'%s'\n", filestr);
}
fd = open(filestr, O_RDONLY);
- if (fd != -1) {
+ if (fd == -1) {
status = fstat(fd, &fdstat);
if (S_ISDIR(fdstat.st_mode)) {
ROSH_DEBUG("PATH '%s' is a directory\n", ifilstr);
filepos = 0;
d = opendir(filestr);
if (d != NULL) {
- printf("DIR:'%s' %08x %8d\n", d->dd_name, d->dd_fd,
- d->dd_sect);
+ printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect,
+ d->dd_offset);
de = readdir(d);
while (de != NULL) {
filepos++;
#ifdef DO_DEBUG
// if (strlen(de->d_name) > 25) de->d_name[25] = 0;
- switch (de->d_mode) {
+ switch (de->d_type) {
case 16:
ty = 'D';
break;
default:
ty = '*';
}
- printf("@%8d:%8d:%4d ", (int)de->d_ino, (int)de->d_size,
- de->d_mode);
#endif /* DO_DEBUG */
// printf("%s\n", de->d_name);
printf("'%s'\n", de->d_name);
de = readdir(d);
// if(filepos>15){ de = NULL; printf("Force Break\n");}
}
- printf("Dir.dd_fd: '%8d'\n", d->dd_fd);
closedir(d);
} else {
rosh_error(0, "dir:NULL", filestr);
;
%if IS_SYSLINUX
comapi_opendir:
- push ds
- mov ds,P_ES
+ mov es,P_ES
mov si,P_SI
mov di,InitRD
- pm_call mangle_name
- pop ds
- pm_call searchdir
+ pm_call opendir
jz comapi_err ; Didn't find a directory
cmp eax,0
jz comapi_err ; Found nothing
;
%if IS_SYSLINUX
comapi_readdir:
- mov es,P_ES
- mov di,P_DI
- mov si,P_SI
- pm_call vfat_readdir
- mov P_EAX,eax
- mov P_DL,dl
- mov P_EBX,ebx
- mov P_SI,si
+ 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
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <dir.h>
+#include <fs.h>
+#include <core.h>
+
+/* The dir log structure, to log the status of the dir_buf. */
+struct dir_log {
+ int offset; /* how far from the dir_buf */
+ int index; /* which dir entry have we go */
+};
+static struct dir_log log = {0, 0};
+
+/* The dir buffer used by fill_dir to store the newly read dirs*/
+#define DB_SIZE 2048
+char dir_buf[DB_SIZE];
+
+void opendir(com32sys_t *regs)
+{
+ int ds = regs->ds; /* save ds */
+
+ regs->ds = regs->es;
+ regs->es = ds;
+ mangle_name(regs);
+ regs->ds = ds; /* restore ds */
+ searchdir(regs);
+}
+
+/*
+ * Fill the dir buffer; return 1 for not full, 0 for full
+ */
+int fill_dir(struct dirent *de)
+{
+ int de_len = de->d_reclen;
+ if (log.offset + de_len <= DB_SIZE) {
+ memcpy(dir_buf + log.offset, de, de_len);
+ log.offset += de_len;
+ log.index ++;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Read one dirent at one time.
+ *
+ * @input: _esi_ register stores the address of DIR structure
+ * @output: _eax_ register stores the address of newly read dirent structure
+ */
+void readdir(com32sys_t *regs)
+{
+ extern struct fs_info *this_fs;
+ DIR *dir = (DIR *)regs->esi.l;
+ struct dirent *de = NULL;
+ static int offset;
+
+ /* If we haven't fill the dir buffer, fill it */
+ if (log.index == 0) {
+ this_fs->fs_ops->readdir(this_fs, dir);
+ if (log.offset == 0) {
+ regs->eax.l = 0;
+ return;
+ }
+ offset = 0; /* reset the _offset_ */
+ }
+
+ if (offset < log.offset) {
+ de = (struct dirent *)(dir_buf + offset);
+ offset += de->d_reclen;
+ }
+ if (offset >= log.offset) /* reach the end of buffer, reset it */
+ memset(&log, 0, sizeof log);
+
+ /* Return the newly read de in _eax_ register */
+ regs->eax.l = (uint32_t)de;
+}
+
+void closedir(com32sys_t *regs)
+{
+ regs->esi.w[0] = 0;
+}
+
+
extern fs_init, searchdir, getfssec, mangle_name, load_config
extern unmangle_name, close_file
-%if IS_SYSLINUX
- ; fat.c
- extern vfat_readdir
-%endif
+ ; dir.c
+ extern opendir, readdir, readdir
%endif ; EXTERN_INC
for (i = 0; i < MAX_OPEN; i++) {
if (!file->open_file)
return file;
+ file++;
}
return NULL;
#include <core.h>
#include <disk.h>
#include <fs.h>
+#include <dir.h>
#include "fat_fs.h"
#define ROOT_DIR_WORD 0x002f
/* Strip terminal slashes or whitespace */
while (1) {
if (dst == p)
- break;
+ break;
+ if (*(dst-1) == '/' && dst-1 == p) /* it's the '/' case */
+ break;
if ((*(dst-1) != '/') && (*(dst-1) != '.'))
break;
}
if (attr & 0x10) {
- dir_sector = PrevDir;
- found_dir:
+ found_dir:
open_file = alloc_fill_dir(dir_sector);
/*
* for dir, we use the file->file_len to store the sector number
-/**
- * readdir:
- *
+/*
* read one file from a directory
- *
- * returns the file's name in the filename string buffer
- *
- * @param: filename
- * @param: file
- *
+ * return 1 if error, or 0 if success
*/
-void vfat_readdir(com32sys_t *regs)/*
- struct fs_info *fs, struct open_file_t* dir_file,
- char* filename, uint32_t *file_len, uint8_t *attr)
- */
+void vfat_readdir(struct fs_info *fs, DIR *dir)
{
uint32_t sector, sec_off;
/* make it to be 1 to check if we have met a long name entry before */
uint8_t id = 1;
uint8_t init_id, next_id;
+ uint8_t checksum = 0;
uint8_t entries_left;
int i;
-
- char *filename = MK_PTR(regs->es, regs->edi.w[0]);
- struct open_file_t *dir_file = MK_PTR(regs->ds, regs->esi.w[0]);
-
+ int not_full = 1;
+ struct dirent de;
+ char *de_name = de.d_name;
struct cache_struct *cs;
- struct fat_dir_entry *dir;
- struct fat_long_name_entry *long_dir;
- struct open_file_t file;
-
- sector = dir_file->file_sector;
- sec_off = dir_file->file_bytesleft;
+ struct fat_dir_entry *fat_dir;
+ struct fat_long_name_entry *long_dir;
+
+ sector = dir->dd_sect;
+ sec_off = dir->dd_offset;
if (!sector)
- goto fail;
-
+ return 1;
entries_left = (SECTOR_SIZE - sec_off) >> 5;
cs = get_cache_block(this_fs->fs_dev, sector);
- dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */
+ fat_dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */
- while (1) {
- if (dir->name[0] == 0)
- goto fail;
-
- if (dir->attr == FAT_ATTR_LONG_NAME) {
+ while (not_full) {
+ if (!entries_left) {
+ sector = nextsector(fs, sector);
+ if (!sector)
+ goto end;
+ cs = get_cache_block(fs->fs_dev, sector);
+ fat_dir = (struct fat_dir_entry *)cs->data;
+ }
+
+ if (fat_dir->name[0] == 0)
+ goto end;
+ if (fat_dir->attr == FAT_ATTR_LONG_NAME) {
/* it's a long name */
- long_dir = (struct fat_long_name_entry *)dir;
+ long_dir = (struct fat_long_name_entry *)fat_dir;
if (long_dir->id & 0x40) {
+ checksum = long_dir->checksum;
init_id = id = long_dir->id & 0x3f;
id--;
} else {
next_id = (long_dir->id & 0x3f) - 1;
id--;
- if (id != next_id)
+ if (id != next_id || long_dir->checksum != checksum)
goto next_entry;
}
long_entry_name(long_dir);
- memcpy(filename + id * 13, entry_name, 13);
-
+ memcpy(de_name + id * 13, entry_name, 13);
- /*
+ /*
* we need go on with the next entry
* and we will fall through to next entry
*/
} else {
/* it's a short entry */
- if (!id) /* we got a long name match */
- break;
+ if (!id) {
+ /* Got a long name match */
+ //if (get_checksum(fat_dir->name) != checksum)
+ //goto next_entry;
+
+ /* reset _id_ and _checksum_ */
+ id = 1;
+ checksum = 0;
+ goto fill;
+ }
- if (dir->attr & FAT_ATTR_VOLUME_ID)
- goto next_entry;
+ if (fat_dir->attr & FAT_ATTR_VOLUME_ID ||
+ get_checksum(fat_dir->name) != checksum )
+ goto next_entry;
for(i = 0; i < 8; i ++) {
- if (dir->name[i] == ' ')
+ if (fat_dir->name[i] == ' ')
break;
- *filename++ = dir->name[i];
- }
-
- *filename++ = '.';
-
+ *de_name++ = fat_dir->name[i];
+ }
+ *de_name++ = '.';
for (i = 8; i < 11; i ++) {
- if (dir->name[i] == ' ')
+ if (fat_dir->name[i] == ' ')
break;
- *filename ++ = dir->name[i];
- }
-
+ *de_name ++ = fat_dir->name[i];
+ }
/* check if we have got an extention */
- if (*(filename - 1) == '.')
- *(filename - 1) = '\0';
+ if (*(de_name - 1) == '.')
+ *(de_name - 1) = '\0';
else
- *filename = '\0';
-
- break;
+ *de_name = '\0';
+
+ fill:
+ de.d_type = fat_dir->attr;
+ de.d_reclen = DIR_REC_LEN(de.d_name);
+ not_full = fill_dir(&de);
+ de_name = de.d_name; /* reset the de_name pointer */
}
next_entry:
- dir ++;
- entries_left --;
-
- if (!entries_left) {
- sector = nextsector(this_fs, sector);
- if (!sector)
- goto fail;
- cs = get_cache_block(this_fs->fs_dev, sector);
- dir = (struct fat_dir_entry *)cs->data;
- }
+ entries_left --;
+ fat_dir ++;
}
- /* finally , we get what we want */
- entries_left --;
- if (!entries_left) {
- sector = nextsector(this_fs, sector);
+ /* dir buffer filled, now it's time to update the DIR structure */
+ if (!entries_left) {
+ sector = nextsector(fs, sector);
if (!sector)
- goto fail;
- dir_file->file_bytesleft = 0;
- } else
- dir_file->file_bytesleft = SECTOR_SIZE - (entries_left << 5);
- dir_file->file_sector = sector;
-
- file.file_sector = sector;
- file.file_bytesleft = (SECTOR_SIZE - (entries_left << DIRENT_SHIFT)) & 0xffff;
-
- regs->eax.l = dir->file_size;
- regs->ebx.l = first_sector(dir);
- regs->edx.b[0] = dir->attr;
-
- return;
-
- fail:
- //close_dir(dir);
- regs->eax.l = 0;
- regs->esi.w[0] = 0;
- regs->eflags.l |= EFLAGS_CF;
+ return 1;
+ dir->dd_offset = 0;
+ } else {
+ dir->dd_offset = SECTOR_SIZE - (entries_left << 5);
+ }
+ dir->dd_sect = sector;
+ return;
+
+ end:
+ /* Reach the end of this directory */
+ dir->dd_stat = -1;
}
static void vfat_load_config(com32sys_t *regs)
.close_file = vfat_close_file,
.mangle_name = vfat_mangle_name,
.unmangle_name = generic_unmangle_name,
- .load_config = vfat_load_config
+ .load_config = vfat_load_config,
+ .readdir = vfat_readdir
};
--- /dev/null
+#ifndef DIR_H
+#define DIR_H
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <com32.h>
+#include "disk.h"
+
+struct dirent {
+ uint32_t d_ino;
+ uint32_t d_off;
+ uint16_t d_reclen;
+ uint16_t d_type;
+ char d_name[256];
+};
+
+typedef struct {
+ uint16_t dd_stat;
+ uint16_t dd_sect;
+ sector_t dd_offset;
+ char dd_name[256];
+} DIR;
+
+#define DIR_REC_LEN(name) (12 + strlen(name) + 1 + 3) & ~3
+
+/*
+ * funtions
+ */
+int fill_dir(struct dirent *);
+
+#endif /* dir.h */
#include <com32.h>
#include "core.h"
#include "disk.h"
+#include "dir.h"
/*
* Maximum number of open files. This is *currently* constrained by the
void (*mangle_name)(char *, const char *);
char * (*unmangle_name)(char *, const char *);
void (*load_config)(com32sys_t *);
+
+ /* the _dir_ stuff */
+ void (*readdir)(struct fs_info *, DIR *);
};
enum dev_type {CHS, EDD};
return (unsigned char)c > ' ';
}
+/*
+ * functions
+ */
+void mangle_name(com32sys_t *);
+void searchdir(com32sys_t *);
+
+
+
#endif /* FS_H */