Implemented seekdir() and telldir(). They were declared in <dirent.h> already.
So either +alphabranch or remove the declarations from <dirent.h>. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32679 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
28563f792b
commit
b02c147c05
@ -16,6 +16,8 @@ struct __DIR {
|
||||
int fd;
|
||||
short next_entry;
|
||||
unsigned short entries_left;
|
||||
long seek_position;
|
||||
long current_position;
|
||||
struct dirent first_entry;
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -11,14 +12,75 @@
|
||||
|
||||
#include <dirent_private.h>
|
||||
#include <syscalls.h>
|
||||
#include <syscall_utils.h>
|
||||
|
||||
|
||||
#define RETURN_AND_SET_ERRNO(err) \
|
||||
if (err < 0) { \
|
||||
errno = err; \
|
||||
return -1; \
|
||||
} \
|
||||
return err;
|
||||
static int
|
||||
do_seek_dir(DIR* dir)
|
||||
{
|
||||
if (dir->seek_position == dir->current_position)
|
||||
return 0;
|
||||
|
||||
// If the seek position lies before the current position (the usual case),
|
||||
// rewind to the beginning.
|
||||
if (dir->seek_position < dir->current_position) {
|
||||
status_t status = _kern_rewind_dir(dir->fd);
|
||||
if (status < 0) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir->current_position = 0;
|
||||
dir->entries_left = 0;
|
||||
}
|
||||
|
||||
// Now skip entries until we have reached seek_position.
|
||||
while (dir->seek_position > dir->current_position) {
|
||||
ssize_t count;
|
||||
long toSkip = dir->seek_position - dir->current_position;
|
||||
if (toSkip == dir->entries_left) {
|
||||
// we have to skip exactly all of the currently buffered entries
|
||||
dir->current_position = dir->seek_position;
|
||||
dir->entries_left = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (toSkip < dir->entries_left) {
|
||||
// we have to skip only some of the buffered entries
|
||||
for (; toSkip > 0; toSkip--) {
|
||||
struct dirent* entry = (struct dirent*)
|
||||
((uint8*)&dir->first_entry + dir->next_entry);
|
||||
dir->entries_left--;
|
||||
dir->next_entry += entry->d_reclen;
|
||||
}
|
||||
|
||||
dir->current_position = dir->seek_position;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// we have to skip more than the currently buffered entries
|
||||
dir->current_position += dir->entries_left;
|
||||
dir->entries_left = 0;
|
||||
|
||||
count = _kern_read_dir(dir->fd, &dir->first_entry, DIRENT_BUFFER_SIZE,
|
||||
USHRT_MAX);
|
||||
if (count <= 0) {
|
||||
if (count < 0)
|
||||
errno = count;
|
||||
|
||||
// end of directory
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir->next_entry = 0;
|
||||
dir->entries_left = count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
DIR *
|
||||
@ -41,6 +103,8 @@ opendir(const char *path)
|
||||
|
||||
dir->fd = fd;
|
||||
dir->entries_left = 0;
|
||||
dir->seek_position = 0;
|
||||
dir->current_position = 0;
|
||||
|
||||
return dir;
|
||||
}
|
||||
@ -62,12 +126,19 @@ readdir(DIR *dir)
|
||||
{
|
||||
ssize_t count;
|
||||
|
||||
if (dir->seek_position != dir->current_position) {
|
||||
if (do_seek_dir(dir) != 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dir->entries_left > 0) {
|
||||
struct dirent *dirent
|
||||
= (struct dirent *)((uint8 *)&dir->first_entry + dir->next_entry);
|
||||
|
||||
dir->entries_left--;
|
||||
dir->next_entry += dirent->d_reclen;
|
||||
dir->seek_position++;
|
||||
dir->current_position++;
|
||||
|
||||
return dirent;
|
||||
}
|
||||
@ -86,6 +157,8 @@ readdir(DIR *dir)
|
||||
|
||||
dir->entries_left = count - 1;
|
||||
dir->next_entry = dir->first_entry.d_reclen;
|
||||
dir->seek_position++;
|
||||
dir->current_position++;
|
||||
|
||||
return &dir->first_entry;
|
||||
}
|
||||
@ -112,11 +185,21 @@ readdir_r(DIR *dir, struct dirent *entry, struct dirent **_result)
|
||||
void
|
||||
rewinddir(DIR *dir)
|
||||
{
|
||||
status_t status = _kern_rewind_dir(dir->fd);
|
||||
if (status < 0)
|
||||
errno = status;
|
||||
else
|
||||
dir->entries_left = 0;
|
||||
dir->seek_position = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
seekdir(DIR* dir, long int position)
|
||||
{
|
||||
dir->seek_position = position;
|
||||
}
|
||||
|
||||
|
||||
long int
|
||||
telldir(DIR* dir)
|
||||
{
|
||||
return dir->seek_position;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user