[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(&regs, 0, sizeof regs);	/* ?Needed? */
+		regs.eax.w[0] = 0x0022;
+		regs.esi.w[0] = dir->dd_fd;
+		__com32.cs_intcall(0x22, &regs, &regs);
+		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, &reg, &reg);
+	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, &regs, &regs);
+
+	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(&regs, 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, &regs, &regs);
+
+		/* 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