[syslinux] [PATCH 1/1] COM32 API: Add functions for directory use
Gene Cumm
gene.cumm at gmail.com
Tue Feb 10 19:18:18 PST 2009
From: Gene Cumm <gene.cumm at gmail.com>
COM32: Add directory functions getcwd(), opendir(), readdir() and closedir().
This depends on the patch that I just submitted creating the COMBOOT API calls.
Signed-off-by: Gene Cumm <gene.cumm at gmail.com>
---
The intention is to create the library calls with (hopefully) POSIX
compliance such that a small application written to use these 4 POSIX
calls will work properly.
diff --git a/com32/include/dirent.h b/com32/include/dirent.h
new file mode 100644
index 0000000..956b911
--- /dev/null
+++ b/com32/include/dirent.h
@@ -0,0 +1,36 @@
+/*
+ * dirent.h
+ */
+
+#ifndef _DIRENT_H
+#define _DIRENT_H
+
+#include <klibc/extern.h>
+#include <klibc/compiler.h>
+#include <stddef.h>
+#include <sys/types.h>
+
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
+struct dirent {
+ long d_ino; /* Inode/File number */
+ off_t d_size; /* Size of file */
+ mode_t d_mode; /* Type of file */
+ 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 */
+} DIR;
+
+__extern DIR *opendir(const char *);
+__extern struct dirent *readdir(DIR *);
+__extern int closedir(DIR *);
+__extern DIR *fdopendir(int);
+
+#endif /* Not _DIRENT_H */
diff --git a/com32/include/unistd.h b/com32/include/unistd.h
index d0b8309..c0b52d6 100644
--- a/com32/include/unistd.h
+++ b/com32/include/unistd.h
@@ -22,6 +22,9 @@ __extern int isatty(int);
__extern int getscreensize(int, int *, int *);
+__extern char *getcwd(char *, int);
+__extern int chdir(const char *);
+
/* Standard file descriptor numbers. */
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 91405a0..0cc4061 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -21,6 +21,8 @@ LIBOBJS = \
asprintf.o vasprintf.o strlcpy.o strlcat.o \
vsscanf.o zalloc.o \
\
+ opendir.o readdir.o closedir.o getcwd.o chdir.o fdopendir.o \
+ \
libgcc/__ashldi3.o libgcc/__udivdi3.o \
libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \
libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \
diff --git a/com32/lib/chdir.c b/com32/lib/chdir.c
new file mode 100644
index 0000000..88dceec
--- /dev/null
+++ b/com32/lib/chdir.c
@@ -0,0 +1,13 @@
+/*
+ * chdir.c
+ */
+
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+
+int chdir(const char *path)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/com32/lib/closedir.c b/com32/lib/closedir.c
new file mode 100644
index 0000000..8a0430e
--- /dev/null
+++ b/com32/lib/closedir.c
@@ -0,0 +1,29 @@
+/*
+ * closedir.c
+ */
+
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <com32.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int closedir(DIR *dir)
+{
+ int rv;
+ com32sys_t regs;
+ if (dir == NULL) {
+ 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;
+}
diff --git a/com32/lib/fdopendir.c b/com32/lib/fdopendir.c
new file mode 100644
index 0000000..83a7ac6
--- /dev/null
+++ b/com32/lib/fdopendir.c
@@ -0,0 +1,13 @@
+/*
+ * fdopendir.c
+ */
+
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+
+DIR *fdopendir(int __fd)
+{
+ errno = ENOSYS;
+ return NULL;
+}
diff --git a/com32/lib/getcwd.c b/com32/lib/getcwd.c
new file mode 100644
index 0000000..95008bb
--- /dev/null
+++ b/com32/lib/getcwd.c
@@ -0,0 +1,29 @@
+/*
+ * getcwd.c
+ */
+
+#include <syslinux/config.h>
+#include <klibc/compiler.h>
+#include <com32.h>
+
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+
+char *getcwd(char *buf, size_t size)
+{
+ static com32sys_t reg;
+ char *pwdstr, *ret;
+
+ reg.eax.w[0] = 0x001f;
+ __intcall(0x22, ®, ®);
+ pwdstr = MK_PTR(reg.es, reg.ebx.w[0]);
+ if ((strlen(pwdstr) < size) && (buf != NULL)) {
+ strcpy(buf, pwdstr);
+ ret = buf;
+ } else {
+ ret = NULL;
+ errno = ERANGE;
+ }
+ return ret;
+}
diff --git a/com32/lib/opendir.c b/com32/lib/opendir.c
new file mode 100644
index 0000000..aa2ba5b
--- /dev/null
+++ b/com32/lib/opendir.c
@@ -0,0 +1,41 @@
+/*
+ * opendir.c
+ */
+
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <com32.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+DIR *opendir(const char *pathname)
+{
+ DIR *newdir;
+ com32sys_t regs;
+
+ newdir = NULL;
+
+ strlcpy(__com32.cs_bounce, pathname, __com32.cs_bounce_size);
+
+ regs.eax.w[0] = 0x0020;
+ regs.esi.w[0] = OFFS(__com32.cs_bounce);
+ 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;
+ }
+
+ /* We're done */
+ return newdir;
+}
diff --git a/com32/lib/readdir.c b/com32/lib/readdir.c
new file mode 100644
index 0000000..bfa5252
--- /dev/null
+++ b/com32/lib/readdir.c
@@ -0,0 +1,54 @@
+/*
+ * readdir.c
+ */
+
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <com32.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+struct dirent *readdir(DIR *dir)
+{
+ struct dirent *newde;
+ 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));
+
+ 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);
+
+ __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;
+ }
+
+ return newde;
+}
More information about the Syslinux
mailing list