Files
rosetta/lib/libc/io/stdio/dir.c
T

82 lines
1.4 KiB
C
Raw Normal View History

#include "dir.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DEFAULT_BUFFER_SIZE 4096
static void dirent_convert(const struct dentry *in, struct dirent *out)
{
out->d_ino = in->d_ino;
out->d_type = in->d_type;
out->d_reclen = in->d_reclen;
strncpy(out->d_name, in->d_name, sizeof out->d_name - 1);
out->d_name[sizeof out->d_name - 1] = 0;
}
int __libc_dir_refill(struct __opaque_dir *d)
{
if (d->d_fd < 0) {
return EBADF;
}
if (d->d_flags & DIR_ERR) {
return EIO;
}
if (d->d_flags & DIR_EOF) {
return SUCCESS;
}
if (!d->d_buf) {
d->d_buf_max = DEFAULT_BUFFER_SIZE;
d->d_buf = malloc(d->d_buf_max);
if (!d->d_buf) {
d->d_buf_max = 0;
return ENOMEM;
}
}
long r = getdents(d->d_fd, (struct dentry *)d->d_buf, d->d_buf_max);
if (r < 0) {
return -r;
}
d->d_buf_datalen = r;
if (r > 0) {
struct dentry *dent
= (struct dentry *)(d->d_buf + d->d_buf_readptr);
dirent_convert(dent, &d->d_current);
}
return SUCCESS;
}
int __libc_dir_move_next(struct __opaque_dir *d)
{
if (d->d_fd < 0) {
return -EBADF;
}
if (d->d_flags & DIR_ERR) {
return -EIO;
}
if (d->d_flags & DIR_EOF) {
return -SUCCESS;
}
d->d_buf_readptr += d->d_current.d_reclen;
if (d->d_buf_readptr >= d->d_buf_datalen) {
return 0;
}
struct dentry *dent = (struct dentry *)(d->d_buf + d->d_buf_readptr);
dirent_convert(dent, &d->d_current);
return 1;
}