* 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:
parent
6ad2f357dc
commit
9c5c79ad86
@ -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
|
||||
|
22
headers/private/libroot/dirent_private.h
Normal file
22
headers/private/libroot/dirent_private.h
Normal 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 */
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user