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:
@@ -16,6 +16,8 @@ struct __DIR {
|
|||||||
int fd;
|
int fd;
|
||||||
short next_entry;
|
short next_entry;
|
||||||
unsigned short entries_left;
|
unsigned short entries_left;
|
||||||
|
long seek_position;
|
||||||
|
long current_position;
|
||||||
struct dirent first_entry;
|
struct dirent first_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2004-2008, Axel Dörfler, [email protected].
|
* Copyright 2004-2008, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -11,14 +12,75 @@
|
|||||||
|
|
||||||
#include <dirent_private.h>
|
#include <dirent_private.h>
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
#include <syscall_utils.h>
|
||||||
|
|
||||||
|
|
||||||
#define RETURN_AND_SET_ERRNO(err) \
|
static int
|
||||||
if (err < 0) { \
|
do_seek_dir(DIR* dir)
|
||||||
errno = err; \
|
{
|
||||||
return -1; \
|
if (dir->seek_position == dir->current_position)
|
||||||
} \
|
return 0;
|
||||||
return err;
|
|
||||||
|
// 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 *
|
DIR *
|
||||||
@@ -41,6 +103,8 @@ opendir(const char *path)
|
|||||||
|
|
||||||
dir->fd = fd;
|
dir->fd = fd;
|
||||||
dir->entries_left = 0;
|
dir->entries_left = 0;
|
||||||
|
dir->seek_position = 0;
|
||||||
|
dir->current_position = 0;
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
@@ -62,12 +126,19 @@ readdir(DIR *dir)
|
|||||||
{
|
{
|
||||||
ssize_t count;
|
ssize_t count;
|
||||||
|
|
||||||
|
if (dir->seek_position != dir->current_position) {
|
||||||
|
if (do_seek_dir(dir) != 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (dir->entries_left > 0) {
|
if (dir->entries_left > 0) {
|
||||||
struct dirent *dirent
|
struct dirent *dirent
|
||||||
= (struct dirent *)((uint8 *)&dir->first_entry + dir->next_entry);
|
= (struct dirent *)((uint8 *)&dir->first_entry + dir->next_entry);
|
||||||
|
|
||||||
dir->entries_left--;
|
dir->entries_left--;
|
||||||
dir->next_entry += dirent->d_reclen;
|
dir->next_entry += dirent->d_reclen;
|
||||||
|
dir->seek_position++;
|
||||||
|
dir->current_position++;
|
||||||
|
|
||||||
return dirent;
|
return dirent;
|
||||||
}
|
}
|
||||||
@@ -86,6 +157,8 @@ readdir(DIR *dir)
|
|||||||
|
|
||||||
dir->entries_left = count - 1;
|
dir->entries_left = count - 1;
|
||||||
dir->next_entry = dir->first_entry.d_reclen;
|
dir->next_entry = dir->first_entry.d_reclen;
|
||||||
|
dir->seek_position++;
|
||||||
|
dir->current_position++;
|
||||||
|
|
||||||
return &dir->first_entry;
|
return &dir->first_entry;
|
||||||
}
|
}
|
||||||
@@ -112,11 +185,21 @@ readdir_r(DIR *dir, struct dirent *entry, struct dirent **_result)
|
|||||||
void
|
void
|
||||||
rewinddir(DIR *dir)
|
rewinddir(DIR *dir)
|
||||||
{
|
{
|
||||||
status_t status = _kern_rewind_dir(dir->fd);
|
dir->seek_position = 0;
|
||||||
if (status < 0)
|
}
|
||||||
errno = status;
|
|
||||||
else
|
|
||||||
dir->entries_left = 0;
|
void
|
||||||
|
seekdir(DIR* dir, long int position)
|
||||||
|
{
|
||||||
|
dir->seek_position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long int
|
||||||
|
telldir(DIR* dir)
|
||||||
|
{
|
||||||
|
return dir->seek_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user