*_read_dir() now also returns "." and ".." Entries.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8920 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -97,6 +97,7 @@ struct devfs_cookie {
|
|||||||
struct devfs_cookie *next;
|
struct devfs_cookie *next;
|
||||||
struct devfs_cookie *prev;
|
struct devfs_cookie *prev;
|
||||||
struct devfs_vnode *ptr;
|
struct devfs_vnode *ptr;
|
||||||
|
int state; // iteration state
|
||||||
} dir;
|
} dir;
|
||||||
struct cookie_dev {
|
struct cookie_dev {
|
||||||
void *dcookie;
|
void *dcookie;
|
||||||
@@ -104,6 +105,14 @@ struct devfs_cookie {
|
|||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// directory iteration states
|
||||||
|
enum {
|
||||||
|
ITERATION_STATE_DOT = 0,
|
||||||
|
ITERATION_STATE_DOT_DOT = 1,
|
||||||
|
ITERATION_STATE_OTHERS = 2,
|
||||||
|
ITERATION_STATE_BEGIN = ITERATION_STATE_DOT,
|
||||||
|
};
|
||||||
|
|
||||||
/* the one and only allowed devfs instance */
|
/* the one and only allowed devfs instance */
|
||||||
static struct devfs *sDeviceFileSystem = NULL;
|
static struct devfs *sDeviceFileSystem = NULL;
|
||||||
|
|
||||||
@@ -961,6 +970,7 @@ devfs_open_dir(fs_volume _fs, fs_vnode _vnode, fs_cookie *_cookie)
|
|||||||
mutex_lock(&fs->lock);
|
mutex_lock(&fs->lock);
|
||||||
|
|
||||||
cookie->u.dir.ptr = vnode->stream.u.dir.dir_head;
|
cookie->u.dir.ptr = vnode->stream.u.dir.dir_head;
|
||||||
|
cookie->u.dir.state = ITERATION_STATE_BEGIN;
|
||||||
*_cookie = cookie;
|
*_cookie = cookie;
|
||||||
|
|
||||||
mutex_unlock(&fs->lock);
|
mutex_unlock(&fs->lock);
|
||||||
@@ -975,6 +985,10 @@ devfs_read_dir(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, struct dirent
|
|||||||
struct devfs_cookie *cookie = (struct devfs_cookie *)_cookie;
|
struct devfs_cookie *cookie = (struct devfs_cookie *)_cookie;
|
||||||
struct devfs *fs = (struct devfs *)_fs;
|
struct devfs *fs = (struct devfs *)_fs;
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
struct devfs_vnode *childNode = NULL;
|
||||||
|
const char *name = NULL;
|
||||||
|
struct devfs_vnode *nextChildNode = NULL;
|
||||||
|
int nextState = cookie->u.dir.state;
|
||||||
|
|
||||||
TRACE(("devfs_read_dir: vnode %p, cookie %p, buffer %p, size %ld\n", _vnode, cookie, dirent, bufferSize));
|
TRACE(("devfs_read_dir: vnode %p, cookie %p, buffer %p, size %ld\n", _vnode, cookie, dirent, bufferSize));
|
||||||
|
|
||||||
@@ -983,25 +997,49 @@ devfs_read_dir(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, struct dirent
|
|||||||
|
|
||||||
mutex_lock(&fs->lock);
|
mutex_lock(&fs->lock);
|
||||||
|
|
||||||
if (cookie->u.dir.ptr == NULL) {
|
switch (cookie->u.dir.state) {
|
||||||
|
case ITERATION_STATE_DOT:
|
||||||
|
childNode = vnode;
|
||||||
|
name = ".";
|
||||||
|
nextChildNode = vnode->stream.u.dir.dir_head;
|
||||||
|
nextState = cookie->u.dir.state + 1;
|
||||||
|
break;
|
||||||
|
case ITERATION_STATE_DOT_DOT:
|
||||||
|
childNode = vnode->parent;
|
||||||
|
name = "..";
|
||||||
|
nextChildNode = vnode->stream.u.dir.dir_head;
|
||||||
|
nextState = cookie->u.dir.state + 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
childNode = cookie->u.dir.ptr;
|
||||||
|
if (childNode) {
|
||||||
|
name = childNode->name;
|
||||||
|
nextChildNode = childNode->dir_next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!childNode) {
|
||||||
*_num = 0;
|
*_num = 0;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirent->d_dev = fs->id;
|
dirent->d_dev = fs->id;
|
||||||
dirent->d_ino = cookie->u.dir.ptr->id;
|
dirent->d_ino = childNode->id;
|
||||||
dirent->d_reclen = strlen(cookie->u.dir.ptr->name) + sizeof(struct dirent);
|
dirent->d_reclen = strlen(name) + sizeof(struct dirent);
|
||||||
|
|
||||||
if (dirent->d_reclen > bufferSize) {
|
if (dirent->d_reclen > bufferSize) {
|
||||||
status = ENOBUFS;
|
status = ENOBUFS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = user_strlcpy(dirent->d_name, cookie->u.dir.ptr->name, bufferSize - sizeof(struct dirent));
|
status = user_strlcpy(dirent->d_name, name,
|
||||||
|
bufferSize - sizeof(struct dirent));
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
cookie->u.dir.ptr = cookie->u.dir.ptr->dir_next;
|
cookie->u.dir.ptr = nextChildNode;
|
||||||
|
cookie->u.dir.state = nextState;
|
||||||
status = B_OK;
|
status = B_OK;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@@ -1026,6 +1064,7 @@ devfs_rewind_dir(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie)
|
|||||||
mutex_lock(&fs->lock);
|
mutex_lock(&fs->lock);
|
||||||
|
|
||||||
cookie->u.dir.ptr = vnode->stream.u.dir.dir_head;
|
cookie->u.dir.ptr = vnode->stream.u.dir.dir_head;
|
||||||
|
cookie->u.dir.state = ITERATION_STATE_BEGIN;
|
||||||
|
|
||||||
mutex_unlock(&fs->lock);
|
mutex_unlock(&fs->lock);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -68,6 +68,15 @@ struct rootfs_cookie {
|
|||||||
struct rootfs_cookie *prev;
|
struct rootfs_cookie *prev;
|
||||||
struct rootfs_vnode *ptr;
|
struct rootfs_vnode *ptr;
|
||||||
int oflags;
|
int oflags;
|
||||||
|
int state; // iteration state
|
||||||
|
};
|
||||||
|
|
||||||
|
// directory iteration states
|
||||||
|
enum {
|
||||||
|
ITERATION_STATE_DOT = 0,
|
||||||
|
ITERATION_STATE_DOT_DOT = 1,
|
||||||
|
ITERATION_STATE_OTHERS = 2,
|
||||||
|
ITERATION_STATE_BEGIN = ITERATION_STATE_DOT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ROOTFS_HASH_SIZE 16
|
#define ROOTFS_HASH_SIZE 16
|
||||||
@@ -623,6 +632,7 @@ rootfs_open_dir(fs_volume _fs, fs_vnode _v, fs_cookie *_cookie)
|
|||||||
|
|
||||||
cookie->ptr = vnode->stream.dir.dir_head;
|
cookie->ptr = vnode->stream.dir.dir_head;
|
||||||
//cookie->oflags = oflags;
|
//cookie->oflags = oflags;
|
||||||
|
cookie->state = ITERATION_STATE_BEGIN;
|
||||||
|
|
||||||
insert_cookie_in_jar(vnode, cookie);
|
insert_cookie_in_jar(vnode, cookie);
|
||||||
*_cookie = cookie;
|
*_cookie = cookie;
|
||||||
@@ -636,34 +646,63 @@ rootfs_open_dir(fs_volume _fs, fs_vnode _v, fs_cookie *_cookie)
|
|||||||
static status_t
|
static status_t
|
||||||
rootfs_read_dir(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num)
|
rootfs_read_dir(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num)
|
||||||
{
|
{
|
||||||
|
struct rootfs_vnode *vnode = (struct rootfs_vnode *)_vnode;
|
||||||
struct rootfs_cookie *cookie = _cookie;
|
struct rootfs_cookie *cookie = _cookie;
|
||||||
struct rootfs *fs = _fs;
|
struct rootfs *fs = _fs;
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
struct rootfs_vnode *childNode = NULL;
|
||||||
|
const char *name = NULL;
|
||||||
|
struct rootfs_vnode *nextChildNode = NULL;
|
||||||
|
int nextState = cookie->state;
|
||||||
|
|
||||||
TRACE(("rootfs_read_dir: vnode %p, cookie %p, buffer = %p, bufferSize = %ld, num = %p\n", _vnode, cookie, dirent, bufferSize,_num));
|
TRACE(("rootfs_read_dir: vnode %p, cookie %p, buffer = %p, bufferSize = %ld, num = %p\n", _vnode, cookie, dirent, bufferSize,_num));
|
||||||
|
|
||||||
mutex_lock(&fs->lock);
|
mutex_lock(&fs->lock);
|
||||||
|
|
||||||
if (cookie->ptr == NULL) {
|
switch (cookie->state) {
|
||||||
|
case ITERATION_STATE_DOT:
|
||||||
|
childNode = vnode;
|
||||||
|
name = ".";
|
||||||
|
nextChildNode = vnode->stream.dir.dir_head;
|
||||||
|
nextState = cookie->state + 1;
|
||||||
|
break;
|
||||||
|
case ITERATION_STATE_DOT_DOT:
|
||||||
|
childNode = vnode->parent;
|
||||||
|
name = "..";
|
||||||
|
nextChildNode = vnode->stream.dir.dir_head;
|
||||||
|
nextState = cookie->state + 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
childNode = cookie->ptr;
|
||||||
|
if (childNode) {
|
||||||
|
name = childNode->name;
|
||||||
|
nextChildNode = childNode->dir_next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!childNode) {
|
||||||
// we're at the end of the directory
|
// we're at the end of the directory
|
||||||
*_num = 0;
|
*_num = 0;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirent->d_dev = fs->id;
|
dirent->d_dev = fs->id;
|
||||||
dirent->d_ino = cookie->ptr->id;
|
dirent->d_ino = childNode->id;
|
||||||
dirent->d_reclen = strlen(cookie->ptr->name) + sizeof(struct dirent);
|
dirent->d_reclen = strlen(name) + sizeof(struct dirent);
|
||||||
|
|
||||||
if (dirent->d_reclen > bufferSize) {
|
if (dirent->d_reclen > bufferSize) {
|
||||||
status = ENOBUFS;
|
status = ENOBUFS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = user_strlcpy(dirent->d_name, cookie->ptr->name, bufferSize - sizeof(struct dirent));
|
status = user_strlcpy(dirent->d_name, name,
|
||||||
|
bufferSize - sizeof(struct dirent));
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
cookie->ptr = cookie->ptr->dir_next;
|
cookie->ptr = nextChildNode;
|
||||||
|
cookie->state = nextState;
|
||||||
status = B_OK;
|
status = B_OK;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@@ -683,6 +722,7 @@ rootfs_rewind_dir(fs_volume _fs, fs_vnode _vnode, fs_cookie _cookie)
|
|||||||
mutex_lock(&fs->lock);
|
mutex_lock(&fs->lock);
|
||||||
|
|
||||||
cookie->ptr = vnode->stream.dir.dir_head;
|
cookie->ptr = vnode->stream.dir.dir_head;
|
||||||
|
cookie->state = ITERATION_STATE_BEGIN;
|
||||||
|
|
||||||
mutex_unlock(&fs->lock);
|
mutex_unlock(&fs->lock);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user