aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Aleaxander <Aleaxander@gmail.com>2009-08-28 18:27:51 +0800
committerLiu Aleaxander <Aleaxander@gmail.com>2009-08-28 18:27:51 +0800
commitc29a8049d462815774bbce8f80a8471a985bafcd (patch)
tree38420b5b946d76a7c44629cbd54da0a5c646d0f7
parent6fcebf4ed2be8de96ff106c3755c7776f1c66804 (diff)
downloadsyslinux-c29a8049d462815774bbce8f80a8471a985bafcd.tar.gz
syslinux-c29a8049d462815774bbce8f80a8471a985bafcd.tar.xz
syslinux-c29a8049d462815774bbce8f80a8471a985bafcd.zip
Core: vfs-dir stuff re-implemented
We fist make it simple, as told by hpa. Here're the changes: 1, The DIR structure changed, just a file pointer included. 2. So, the open/close/read-dir stuff in com32/lib/ changed again. 3. We read one stuff from every readdir call. Signed-off-by: Liu Aleaxander <Aleaxander@gmail.com>
-rw-r--r--com32/include/dirent.h7
-rw-r--r--com32/lib/closedir.c16
-rw-r--r--com32/lib/opendir.c7
-rw-r--r--com32/lib/readdir.c4
-rw-r--r--com32/modules/dir.c1
-rw-r--r--com32/rosh/rosh.c3
-rw-r--r--core/comboot.inc8
-rw-r--r--core/dir.c68
-rw-r--r--core/extern.inc2
-rw-r--r--core/fs.c29
-rw-r--r--core/fs/fat/fat.c88
-rw-r--r--core/include/dir.h12
-rw-r--r--core/include/fs.h8
13 files changed, 101 insertions, 152 deletions
diff --git a/com32/include/dirent.h b/com32/include/dirent.h
index 0fc2e135..d2bfd627 100644
--- a/com32/include/dirent.h
+++ b/com32/include/dirent.h
@@ -22,11 +22,10 @@ struct dirent {
char d_name[NAME_MAX + 1];
};
+struct file;
+
typedef struct {
- uint16_t dd_stat;
- uint16_t dd_sect;
- uint64_t dd_offset;
- char dd_name[NAME_MAX + 1];
+ struct file *dd_dir;
} DIR;
__extern DIR *opendir(const char *);
diff --git a/com32/lib/closedir.c b/com32/lib/closedir.c
index dcf17049..9e43dd4d 100644
--- a/com32/lib/closedir.c
+++ b/com32/lib/closedir.c
@@ -16,15 +16,13 @@ int closedir(DIR * dir)
int rv = -1;
if (dir) {
- /*
- com32sys_t regs;
- memset(&regs, 0, sizeof regs);
- regs.eax.w[0] = 0x0022;
- regs.esi.l = OFFS_WRT(dir, 0);
- __com32.cs_intcall(0x22, &regs, &regs);
- */
- free(dir);
- rv = 0;
+ com32sys_t regs;
+ memset(&regs, 0, sizeof regs);
+ regs.eax.w[0] = 0x0022;
+ regs.esi.l = (uint32_t)dir;
+ __com32.cs_intcall(0x22, &regs, &regs);
+ free(dir);
+ rv = 0;
}
return rv;
diff --git a/com32/lib/opendir.c b/com32/lib/opendir.c
index 669a04a2..70f74c15 100644
--- a/com32/lib/opendir.c
+++ b/com32/lib/opendir.c
@@ -27,12 +27,9 @@ DIR *opendir(const char *pathname)
if (!(regs.eflags.l & EFLAGS_CF)) {
/* 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;
+ newdir->dd_dir = (struct file *)regs.eax.l;
}
-
+
/* We're done */
return newdir;
}
diff --git a/com32/lib/readdir.c b/com32/lib/readdir.c
index 7fca4761..6c95bd6d 100644
--- a/com32/lib/readdir.c
+++ b/com32/lib/readdir.c
@@ -13,16 +13,14 @@
struct dirent *readdir(DIR * dir)
{
- struct dirent *newde = NULL;;
+ struct dirent *newde;
com32sys_t regs;
- if ((dir !=NULL) && (dir->dd_sect != 0) && (dir->dd_stat != 0xffff)) {
memset(&regs, 0, sizeof(regs));
regs.eax.w[0] = 0x0021;
regs.esi.l = (uint32_t)dir;
__com32.cs_intcall(0x22, &regs, &regs);
newde = (struct dirent *)(regs.eax.l);
- }
return newde;
}
diff --git a/com32/modules/dir.c b/com32/modules/dir.c
index a3c98151..badc37de 100644
--- a/com32/modules/dir.c
+++ b/com32/modules/dir.c
@@ -20,6 +20,7 @@ int main(int argc, char *argv[])
}
dir = opendir(argv[1]);
+ printf("back from in main ...? \n");
if (dir == NULL) {
printf("Unable to read dir: %s\n", argv[1]);
return 0;
diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c
index c634a940..862497be 100644
--- a/com32/rosh/rosh.c
+++ b/com32/rosh/rosh.c
@@ -428,8 +428,7 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr)
filepos = 0;
d = opendir(filestr);
if (d != NULL) {
- printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect,
- d->dd_offset);
+ //printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, d->dd_offset);
de = readdir(d);
while (de != NULL) {
filepos++;
diff --git a/core/comboot.inc b/core/comboot.inc
index b078aa57..7f9b3a9b 100644
--- a/core/comboot.inc
+++ b/core/comboot.inc
@@ -900,6 +900,7 @@ comapi_getcwd:
; INT 22h AX=0020h Open directory
;
%if IS_SYSLINUX
+ global comapi_opendir
comapi_opendir:
mov es,P_ES
mov si,P_SI
@@ -909,8 +910,6 @@ comapi_opendir:
cmp eax,0
jz comapi_err ; Found nothing
mov P_EAX,eax
- mov P_CX,SECTOR_SIZE
- mov P_SI,si
clc
ret
%else
@@ -933,7 +932,10 @@ comapi_readdir equ comapi_err
;
; INT 22h AX=0022h Close directory
;
-comapi_closedir equ comapi_close
+comapi_closedir:
+ mov esi,P_ESI ; The address of DIR structure
+ pm_call closedir
+ ret
;
; INT 22h AX=0023h Query shuffler size
diff --git a/core/dir.c b/core/dir.c
index 07011256..1bc8a260 100644
--- a/core/dir.c
+++ b/core/dir.c
@@ -4,42 +4,15 @@
#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];
+extern struct fs_info *this_fs;
+/*
+ * open dir, return the file structure pointer in _eax_, or NULL if failed
+ */
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;
+ this_fs->fs_ops->opendir(regs);
+ regs->eax.l = (uint32_t)handle_to_file(regs->esi.w[0]);
}
/*
@@ -50,35 +23,22 @@ int fill_dir(struct dirent *de)
*/
void readdir(com32sys_t *regs)
{
- extern struct fs_info *this_fs;
- DIR *dir = (DIR *)regs->esi.l;
+ 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);
+ if (dir->dd_dir)
+ de = this_fs->fs_ops->readdir(dir->dd_dir);
+ else
+ de = NULL;
+
/* Return the newly read de in _eax_ register */
regs->eax.l = (uint32_t)de;
}
void closedir(com32sys_t *regs)
{
- regs->esi.w[0] = 0;
+ DIR *dir = (DIR *)regs->esi.l;
+ _close_file(dir->dd_dir);
}
diff --git a/core/extern.inc b/core/extern.inc
index 37024ec1..20adb768 100644
--- a/core/extern.inc
+++ b/core/extern.inc
@@ -17,6 +17,6 @@
extern unmangle_name, close_file
; dir.c
- extern opendir, readdir, readdir
+ extern opendir, readdir, closedir
%endif ; EXTERN_INC
diff --git a/core/fs.c b/core/fs.c
index 17303782..b6e112ad 100644
--- a/core/fs.c
+++ b/core/fs.c
@@ -9,7 +9,18 @@ struct fs_info *this_fs = NULL;
struct fs_info fs;
/* Actual file structures (we don't have malloc yet...) */
-static struct file Files[MAX_OPEN];
+struct file files[MAX_OPEN];
+/*
+ * Convert between a 16-bit file handle and a file structure
+ */
+inline uint16_t file_to_handle(struct file *file)
+{
+ return file ? (file - files)+1 : 0;
+}
+inline struct file *handle_to_file(uint16_t handle)
+{
+ return handle ? &files[handle-1] : NULL;
+}
/*
* Get an empty file structure
@@ -17,7 +28,7 @@ static struct file Files[MAX_OPEN];
static struct file *alloc_file(void)
{
int i;
- struct file *file = Files;
+ struct file *file = files;
for (i = 0; i < MAX_OPEN; i++) {
if (!file->open_file)
@@ -36,25 +47,13 @@ static inline void free_file(struct file *file)
memset(file, 0, sizeof *file);
}
-static void _close_file(struct file *file)
+void _close_file(struct file *file)
{
if (file->open_file)
file->fs->fs_ops->close_file(file);
free_file(file);
}
-/*
- * Convert between a 16-bit file handle and a file structure
- */
-static inline uint16_t file_to_handle(struct file *file)
-{
- return file ? (file - Files)+1 : 0;
-}
-static inline struct file *handle_to_file(uint16_t handle)
-{
- return handle ? &Files[handle-1] : NULL;
-}
-
void load_config(com32sys_t *regs)
{
this_fs->fs_ops->load_config(regs);
diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c
index f219995d..a2540420 100644
--- a/core/fs/fat/fat.c
+++ b/core/fs/fat/fat.c
@@ -659,12 +659,7 @@ static void vfat_searchdir(char *filename, struct file *file)
if (attr & 0x10) {
found_dir:
open_file = alloc_fill_dir(dir_sector);
- /*
- * for dir, we use the file->file_len to store the sector number
- * where the dir is.
- */
- file_len = dir_sector;
- } else if ((attr & 0x18) || (file_len == 0)) {
+ } else if ((attr & 0x18) || (file_len == 0)) {
fail:
file_len = 0;
open_file = NULL;
@@ -677,14 +672,22 @@ static void vfat_searchdir(char *filename, struct file *file)
file->open_file = open_file;
}
-
-
+/*
+ * 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)
+{
+ 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);
+}
/*
- * read one file from a directory
- * return 1 if error, or 0 if success
+ * read one file from a directory; return the newly read de structure
*/
-void vfat_readdir(struct fs_info *fs, DIR *dir)
+struct dirent* vfat_readdir(struct file *dir)
{
uint32_t sector, sec_off;
/* make it to be 1 to check if we have met a long name entry before */
@@ -693,32 +696,33 @@ void vfat_readdir(struct fs_info *fs, DIR *dir)
uint8_t checksum = 0;
uint8_t entries_left;
int i;
- int not_full = 1;
- struct dirent de;
+ static struct dirent de;
char *de_name = de.d_name;
struct cache_struct *cs;
struct fat_dir_entry *fat_dir;
- struct fat_long_name_entry *long_dir;
-
- sector = dir->dd_sect;
- sec_off = dir->dd_offset;
+ struct fat_long_name_entry *long_dir;
+ struct open_file_t *file = dir->open_file;
+ struct fs_info *fs = dir->fs;
+
+ sector = file->file_sector;
+ sec_off = file->file_bytesleft;
if (!sector)
- return 1;
+ return NULL;
entries_left = (SECTOR_SIZE - sec_off) >> 5;
cs = get_cache_block(this_fs->fs_dev, sector);
fat_dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */
- while (not_full) {
+ while (1) {
if (!entries_left) {
sector = nextsector(fs, sector);
if (!sector)
- goto end;
+ return NULL;
cs = get_cache_block(fs->fs_dev, sector);
fat_dir = (struct fat_dir_entry *)cs->data;
}
if (fat_dir->name[0] == 0)
- goto end;
+ return NULL;
if (fat_dir->attr == FAT_ATTR_LONG_NAME) {
/* it's a long name */
long_dir = (struct fat_long_name_entry *)fat_dir;
@@ -747,13 +751,10 @@ void vfat_readdir(struct fs_info *fs, DIR *dir)
if (!id) {
/* Got a long name match */
- //if (get_checksum(fat_dir->name) != checksum)
- //goto next_entry;
+ if (get_checksum(fat_dir->name) != checksum)
+ goto next_entry;
- /* reset _id_ and _checksum_ */
- id = 1;
- checksum = 0;
- goto fill;
+ break;
}
if (fat_dir->attr & FAT_ATTR_VOLUME_ID ||
@@ -777,33 +778,29 @@ void vfat_readdir(struct fs_info *fs, DIR *dir)
else
*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 */
+ break;
}
next_entry:
entries_left --;
fat_dir ++;
}
-
- /* dir buffer filled, now it's time to update the DIR structure */
+
+ /* found what we want, fill the de structure */
+ de.d_reclen = DIR_REC_LEN(de.d_name);
+ de.d_type = fat_dir->attr;
+
+ /* update the DIR structure */
+ entries_left--;
if (!entries_left) {
- sector = nextsector(fs, sector);
- if (!sector)
- return 1;
- dir->dd_offset = 0;
+ sector = nextsector(fs, sector);
+ file->file_bytesleft = 0;
} else {
- dir->dd_offset = SECTOR_SIZE - (entries_left << 5);
+ file->file_bytesleft = SECTOR_SIZE - (entries_left << 5);
}
- dir->dd_sect = sector;
- return;
-
- end:
- /* Reach the end of this directory */
- dir->dd_stat = -1;
+ file->file_sector = sector;
+
+ return &de;
}
static void vfat_load_config(com32sys_t *regs)
@@ -898,5 +895,6 @@ const struct fs_ops vfat_fs_ops = {
.mangle_name = vfat_mangle_name,
.unmangle_name = generic_unmangle_name,
.load_config = vfat_load_config,
+ .opendir = vfat_opendir,
.readdir = vfat_readdir
};
diff --git a/core/include/dir.h b/core/include/dir.h
index 454ca483..04f0d090 100644
--- a/core/include/dir.h
+++ b/core/include/dir.h
@@ -6,6 +6,7 @@
#include <string.h>
#include <com32.h>
#include "disk.h"
+#include "fs.h"
struct dirent {
uint32_t d_ino;
@@ -15,18 +16,13 @@ struct dirent {
char d_name[256];
};
+struct file;
+
typedef struct {
- uint16_t dd_stat;
- uint16_t dd_sect;
- sector_t dd_offset;
- char dd_name[256];
+ struct file *dd_dir;
} DIR;
#define DIR_REC_LEN(name) (12 + strlen(name) + 1 + 3) & ~3
-/*
- * funtions
- */
-int fill_dir(struct dirent *);
#endif /* dir.h */
diff --git a/core/include/fs.h b/core/include/fs.h
index d16a5689..a8b02945 100644
--- a/core/include/fs.h
+++ b/core/include/fs.h
@@ -52,7 +52,8 @@ struct fs_ops {
void (*load_config)(com32sys_t *);
/* the _dir_ stuff */
- void (*readdir)(struct fs_info *, DIR *);
+ void (*opendir)(com32sys_t *);
+ struct dirent * (*readdir)(struct file *);
};
enum dev_type {CHS, EDD};
@@ -92,7 +93,8 @@ static inline bool not_whitespace(char c)
*/
void mangle_name(com32sys_t *);
void searchdir(com32sys_t *);
-
-
+void _close_file(struct file *);
+inline uint16_t file_to_handle(struct file *);
+inline struct file *handle_to_file(uint16_t);
#endif /* FS_H */