#include <types.h>
#endif
-/* It's 14 for the kernel as it stands but may move to 30 so build
- that into userspace */
#define MAXNAMLEN 30
struct dirent *dd_buf; /* -> directory buffer */
} DIR; /* stream data from opendir() */
+
typedef int (*__dir_select_fn_t) __P ((struct dirent *));
typedef int (*__dir_compar_fn_t) __P ((struct dirent **, struct dirent **));
char d_name[31];
};
-/* Internal version */
+/* Kernel directory format off disk */
struct __dirent {
- int d_ino;
+ ino_t d_ino;
char d_name[30];
};
+/* Internal directory structure */
+struct _dir {
+ DIR d;
+ struct dirent de;
+ uint8_t buf[512];
+ uint8_t next;
+ uint8_t last;
+};
+
extern DIR *opendir __P ((char *__name));
extern int closedir __P ((DIR * __dirp));
extern struct dirent *readdir __P ((DIR * __dirp));
-/* close.c closedir implementation
+/* closedir.c closedir implementation
*
*/
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
-int closedir(DIR * dir)
+int closedir(DIR * dirp)
{
- if (dir == NULL || dir->dd_buf == NULL || dir->dd_fd == 0) {
+ struct _dir *dir = (struct _dir *)dirp;
+ if (dir == NULL || dir->d.dd_fd == -1) {
errno = EFAULT;
return -1;
}
- close(dir->dd_fd);
- free(dir->dd_buf);
- dir->dd_fd = 0;
- dir->dd_buf = NULL;
+ close(dir->d.dd_fd);
+ dir->d.dd_fd = -1;
free(dir);
return 0;
}
DIR *opendir(char *path)
{
struct stat statbuf;
- register DIR *dir;
+ struct _dir *dir;
if (stat(path, &statbuf) != 0)
- goto Err;
+ return NULL;
+
if ((statbuf.st_mode & S_IFDIR) == 0) {
errno = ENOTDIR;
- goto Err;
- }
- if ((dir = (DIR *) calloc(1, sizeof(DIR))) == NULL) {
- errno = ENOMEM;
- goto Err;
+ return NULL;
}
- if ((dir->dd_buf = calloc(1, sizeof(struct dirent))) == NULL) {
- free(dir);
+ if ((dir = calloc(1, sizeof(struct _dir))) == NULL) {
errno = ENOMEM;
- goto Err;
+ return NULL;
}
- if ((dir->dd_fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
- free(dir->dd_buf);
+ if ((dir->d.dd_fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
free(dir);
- Err:return NULL;
+ return NULL;
}
- return dir;
+ return (DIR *)dir;
}
#include <fcntl.h>
#include <string.h>
-struct dirent *readdir(DIR * dir)
+static struct __dirent *dnext(struct _dir *dir)
{
- struct __dirent direntry;
+ if (dir->next == dir->last) {
+ int l = read(dir->d.dd_fd, dir->buf, sizeof(dir->buf));
+ if (l == 0)
+ return NULL;
+ l /= 32;
+ dir->last = l;
+ dir->next = 0;
+ }
+ return (struct __dirent *)(dir->buf + 32 * dir->next++);
+}
+
+struct dirent *readdir(DIR * dirp)
+{
+ struct _dir *dir = (struct _dir *)dirp;
+ struct __dirent *direntry;
register struct dirent *buf;
int len;
- if (dir == NULL || dir->dd_buf == NULL || dir->dd_fd == 0) {
+ if (dir == NULL || dir->d.dd_fd == -1) {
errno = EFAULT;
return NULL;
- }
- direntry.d_name[0] = 0;
- while (direntry.d_name[0] == 0) {
- len = _getdirent(dir->dd_fd, &direntry, sizeof(direntry));
- if (len > sizeof(direntry)) {
- errno = ERANGE;
- return NULL;
- }
- if (len == 0)
+ }
+
+ do {
+ direntry = dnext(dir);
+ if (direntry == NULL)
return NULL;
- }
- buf = dir->dd_buf;
- buf->d_ino = direntry.d_ino;
+ } while (direntry->d_name[0] == 0);
+
+ buf = &dir->de;
+ buf->d_ino = direntry->d_ino;
buf->d_off = -1; /* FIXME */
- buf->d_reclen = len + 1;
- strncpy(buf->d_name, (char *) direntry.d_name, len - 2);
- buf->d_name[len - 2] = 0;
+ buf->d_reclen = 33;
+ strncpy(buf->d_name, (char *) direntry->d_name, 31);
+ buf->d_name[30] = 0;
return buf;
}