* Made DIR definition private, and moved it into the new dirent_private.h

header.
* Added fields necessary to make it possible to retrieve more than one
  dirent from the underlying file system.
* Unless some app creates a DIR on its own to it to feed readdir(), this
  change should be binary compatible. If we find an application misbehaving,
  we can still make it a GCC4 only thing.
* fs_attr/fs_index/fs_query now all use readdir() directly (as that one
  contains the logic to iterate through a number of dirents in userspace).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26339 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-07-09 11:16:00 +00:00
parent 6ad2f357dc
commit 9c5c79ad86
6 changed files with 110 additions and 106 deletions

View File

@ -1,6 +1,7 @@
/*
** Distributed under the terms of the Haiku License.
*/
/*
* Copyright 2002-2008, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _DIRENT_H
#define _DIRENT_H
@ -17,10 +18,7 @@ typedef struct dirent {
char d_name[1]; /* name of the entry (null byte terminated) */
} dirent_t;
typedef struct {
int fd;
struct dirent ent;
} DIR;
typedef struct __DIR DIR;
#ifndef MAXNAMLEN
# ifdef NAME_MAX

View File

@ -0,0 +1,22 @@
/*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#ifndef DIRENT_PRIVATE_H
#define DIRENT_PRIVATE_H
#include <dirent.h>
#define DIR_BUFFER_SIZE 4096
#define DIRENT_BUFFER_SIZE (DIR_BUFFER_SIZE - 2 * sizeof(int))
struct __DIR {
int fd;
short next_entry;
unsigned short entries_left;
struct dirent first_entry;
};
#endif /* DIRENT_PRIVATE_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de.
/*
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
@ -10,10 +10,12 @@
#include <fcntl.h>
#include <errno.h>
#include "dirent_private.h"
#include "syscalls.h"
// ToDo: think about adding special syscalls for the read/write/stat functions to speed them up
// TODO: think about adding special syscalls for the read/write/stat functions
// to speed them up
#define RETURN_AND_SET_ERRNO(status) \
{ \
@ -24,11 +26,8 @@
return status; \
}
// for the DIR structure
#define BUFFER_SIZE 2048
ssize_t
ssize_t
fs_read_attr(int fd, const char *attribute, uint32 type,
off_t pos, void *buffer, size_t readBytes)
{
@ -48,7 +47,7 @@ fs_read_attr(int fd, const char *attribute, uint32 type,
}
ssize_t
ssize_t
fs_write_attr(int fd, const char *attribute, uint32 type,
off_t pos, const void *buffer, size_t writeBytes)
{
@ -65,7 +64,7 @@ fs_write_attr(int fd, const char *attribute, uint32 type,
}
int
int
fs_remove_attr(int fd, const char *attribute)
{
status_t status = _kern_remove_attr(fd, attribute);
@ -74,7 +73,7 @@ fs_remove_attr(int fd, const char *attribute)
}
int
int
fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo)
{
struct stat stat;
@ -96,17 +95,17 @@ fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo)
/*
int
int
fs_open_attr(const char *path, const char *attribute, uint32 type, int openMode)
{
// ToDo: implement fs_open_attr() - or remove it completely
// TODO: implement fs_open_attr() - or remove it completely
// if it will be implemented, rename the current fs_open_attr() to fs_fopen_attr()
return B_ERROR;
}
*/
int
int
fs_open_attr(int fd, const char *attribute, uint32 type, int openMode)
{
status_t status;
@ -120,7 +119,7 @@ fs_open_attr(int fd, const char *attribute, uint32 type, int openMode)
}
int
int
fs_close_attr(int fd)
{
status_t status = _kern_close(fd);
@ -141,13 +140,14 @@ open_attr_dir(int file, const char *path)
}
/* allocate the memory for the DIR structure */
if ((dir = (DIR *)malloc(sizeof(DIR) + BUFFER_SIZE)) == NULL) {
if ((dir = (DIR *)malloc(DIR_BUFFER_SIZE)) == NULL) {
errno = B_NO_MEMORY;
_kern_close(fd);
return NULL;
}
dir->fd = fd;
dir->entries_left = 0;
return dir;
}
@ -167,7 +167,7 @@ fs_fopen_attr_dir(int fd)
}
int
int
fs_close_attr_dir(DIR *dir)
{
int status = _kern_close(dir->fd);
@ -181,22 +181,13 @@ fs_close_attr_dir(DIR *dir)
struct dirent *
fs_read_attr_dir(DIR *dir)
{
ssize_t count = _kern_read_dir(dir->fd, &dir->ent, BUFFER_SIZE, 1);
if (count <= 0) {
if (count < 0)
errno = count;
return NULL;
}
return &dir->ent;
return readdir(dir);
}
void
void
fs_rewind_attr_dir(DIR *dir)
{
int status = _kern_rewind_dir(dir->fd);
if (status < 0)
errno = status;
rewinddir(dir);
}

View File

@ -1,7 +1,7 @@
/*
** Copyright 2002, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include <fs_index.h>
@ -10,7 +10,8 @@
#include <fcntl.h>
#include <errno.h>
#include "syscalls.h"
#include <dirent_private.h>
#include <syscalls.h>
#define RETURN_AND_SET_ERRNO(status) \
@ -22,9 +23,6 @@
return status; \
}
// for the DIR structure
#define BUFFER_SIZE 2048
int
fs_create_index(dev_t device, const char *name, uint32 type, uint32 flags)
@ -35,7 +33,7 @@ fs_create_index(dev_t device, const char *name, uint32 type, uint32 flags)
}
int
int
fs_remove_index(dev_t device, const char *name)
{
status_t status = _kern_remove_index(device, name);
@ -44,7 +42,7 @@ fs_remove_index(dev_t device, const char *name)
}
int
int
fs_stat_index(dev_t device, const char *name, struct index_info *indexInfo)
{
struct stat stat;
@ -75,19 +73,20 @@ fs_open_index_dir(dev_t device)
}
/* allocate the memory for the DIR structure */
if ((dir = (DIR *)malloc(sizeof(DIR) + BUFFER_SIZE)) == NULL) {
if ((dir = (DIR *)malloc(DIR_BUFFER_SIZE)) == NULL) {
errno = B_NO_MEMORY;
_kern_close(fd);
return NULL;
}
dir->fd = fd;
dir->entries_left = 0;
return dir;
}
int
int
fs_close_index_dir(DIR *dir)
{
int status = _kern_close(dir->fd);
@ -101,22 +100,13 @@ fs_close_index_dir(DIR *dir)
struct dirent *
fs_read_index_dir(DIR *dir)
{
ssize_t count = _kern_read_dir(dir->fd, &dir->ent, BUFFER_SIZE, 1);
if (count <= 0) {
if (count < 0)
errno = count;
return NULL;
}
return &dir->ent;
return readdir(dir);
}
void
void
fs_rewind_index_dir(DIR *dir)
{
int status = _kern_rewind_dir(dir->fd);
if (status < 0)
errno = status;
rewinddir(dir);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
/*
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
@ -11,11 +11,8 @@
#include <fcntl.h>
#include <errno.h>
#include "syscalls.h"
// for the DIR structure
#define BUFFER_SIZE 2048
#include <dirent_private.h>
#include <syscalls.h>
static DIR *
@ -35,13 +32,16 @@ open_query_etc(dev_t device, const char *query,
}
// allocate a DIR
DIR *dir = (DIR *)malloc(BUFFER_SIZE);
DIR *dir = (DIR *)malloc(DIR_BUFFER_SIZE);
if (!dir) {
_kern_close(fd);
errno = B_NO_MEMORY;
return NULL;
}
dir->fd = fd;
dir->entries_left = 0;
return dir;
}
@ -84,24 +84,7 @@ fs_close_query(DIR *dir)
struct dirent *
fs_read_query(DIR *dir)
{
// check parameters
if (dir == NULL) {
errno = B_BAD_VALUE;
return NULL;
}
// read
int32 bufferSize = BUFFER_SIZE - ((uint8 *)&dir->ent - (uint8 *)dir);
ssize_t result = _kern_read_dir(dir->fd, &dir->ent, bufferSize, 1);
if (result < 0) {
errno = result;
return NULL;
}
if (result == 0) {
errno = B_ENTRY_NOT_FOUND;
return NULL;
}
return &dir->ent;
return readdir(dir);
}

View File

@ -1,17 +1,16 @@
/*
** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the Haiku License.
*/
/*
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include <syscalls.h>
#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#define BUFFER_SIZE 4096
#include <dirent_private.h>
#include <syscalls.h>
#define RETURN_AND_SET_ERRNO(err) \
@ -34,13 +33,14 @@ opendir(const char *path)
}
/* allocate the memory for the DIR structure */
if ((dir = (DIR *)malloc(sizeof(DIR) + BUFFER_SIZE)) == NULL) {
if ((dir = (DIR *)malloc(DIR_BUFFER_SIZE)) == NULL) {
errno = B_NO_MEMORY;
_kern_close(fd);
return NULL;
}
dir->fd = fd;
dir->entries_left = 0;
return dir;
}
@ -60,26 +60,42 @@ closedir(DIR *dir)
struct dirent *
readdir(DIR *dir)
{
/* get the next entry and return a pointer to a dirent structure
* containing the data
*/
ssize_t count = _kern_read_dir(dir->fd, &dir->ent, BUFFER_SIZE, 1);
ssize_t count;
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;
return dirent;
}
// we need to retrieve new entries
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 NULL;
}
return &dir->ent;
dir->entries_left = count - 1;
dir->next_entry = dir->first_entry.d_reclen;
return &dir->first_entry;
}
int
readdir_r(DIR *dir, struct dirent *entry, struct dirent **_result)
{
ssize_t count = _kern_read_dir(dir->fd, entry, sizeof(struct dirent) + B_FILE_NAME_LENGTH, 1);
ssize_t count = _kern_read_dir(dir->fd, entry, sizeof(struct dirent)
+ B_FILE_NAME_LENGTH, 1);
if (count < B_OK)
return count;
@ -99,14 +115,16 @@ rewinddir(DIR *dir)
status_t status = _kern_rewind_dir(dir->fd);
if (status < 0)
errno = status;
else
dir->entries_left = 0;
}
/** This is no POSIX compatible call; it's not exported in the headers
* but here for BeOS compatiblity.
*/
#ifndef _KERNEL_MODE
// ToDo: disable this for the kernel build! (will be possible once we use Kernel build rules for the kernel only)
/* This is no POSIX compatible call; it's not exported in the headers
* but here for BeOS compatiblity.
*/
int dirfd(DIR *dir);
@ -115,3 +133,5 @@ dirfd(DIR *dir)
{
return dir->fd;
}
#endif // !_KERNEL_MODE