From 9c5c79ad8679dfbb8c0d611cfc95c3ee767aef77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 9 Jul 2008 11:16:00 +0000 Subject: [PATCH] * 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 --- headers/posix/dirent.h | 12 ++--- headers/private/libroot/dirent_private.h | 22 +++++++++ src/system/libroot/os/fs_attr.c | 47 ++++++++---------- src/system/libroot/os/fs_index.c | 38 ++++++--------- src/system/libroot/os/fs_query.cpp | 35 ++++--------- src/system/libroot/posix/dirent.c | 62 ++++++++++++++++-------- 6 files changed, 110 insertions(+), 106 deletions(-) create mode 100644 headers/private/libroot/dirent_private.h diff --git a/headers/posix/dirent.h b/headers/posix/dirent.h index cf201de452..f915c5abfc 100644 --- a/headers/posix/dirent.h +++ b/headers/posix/dirent.h @@ -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 diff --git a/headers/private/libroot/dirent_private.h b/headers/private/libroot/dirent_private.h new file mode 100644 index 0000000000..785549bac4 --- /dev/null +++ b/headers/private/libroot/dirent_private.h @@ -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 + + +#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 */ diff --git a/src/system/libroot/os/fs_attr.c b/src/system/libroot/os/fs_attr.c index 2d84b244fb..c6838ce6a4 100644 --- a/src/system/libroot/os/fs_attr.c +++ b/src/system/libroot/os/fs_attr.c @@ -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 #include +#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); } diff --git a/src/system/libroot/os/fs_index.c b/src/system/libroot/os/fs_index.c index 84fdb983b7..c352cd0c8a 100644 --- a/src/system/libroot/os/fs_index.c +++ b/src/system/libroot/os/fs_index.c @@ -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 @@ -10,7 +10,8 @@ #include #include -#include "syscalls.h" +#include +#include #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); } diff --git a/src/system/libroot/os/fs_query.cpp b/src/system/libroot/os/fs_query.cpp index 510b4ca2e7..b74f116a51 100644 --- a/src/system/libroot/os/fs_query.cpp +++ b/src/system/libroot/os/fs_query.cpp @@ -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 #include -#include "syscalls.h" - - -// for the DIR structure -#define BUFFER_SIZE 2048 +#include +#include 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); } diff --git a/src/system/libroot/posix/dirent.c b/src/system/libroot/posix/dirent.c index dab57a56fc..929c4d4fb0 100644 --- a/src/system/libroot/posix/dirent.c +++ b/src/system/libroot/posix/dirent.c @@ -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 - #include #include +#include #include - -#define BUFFER_SIZE 4096 +#include +#include #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