Simplify directory reading.

This commit is contained in:
Jonas 'Sortie' Termansen 2015-11-20 02:57:09 +01:00
parent 56085108b6
commit 2e4b15daed
34 changed files with 139 additions and 590 deletions

View File

@ -148,7 +148,7 @@ bool RespondMakeDir(int chl, ino_t ino)
return RespondMessage(chl, FSM_RESP_MKDIR, &body, sizeof(body)); return RespondMessage(chl, FSM_RESP_MKDIR, &body, sizeof(body));
} }
bool RespondReadDir(int chl, struct kernel_dirent* dirent) bool RespondReadDir(int chl, struct dirent* dirent)
{ {
struct fsm_resp_readdirents body; struct fsm_resp_readdirents body;
body.ino = dirent->d_ino; body.ino = dirent->d_ino;
@ -371,8 +371,8 @@ void HandleReadDir(int chl, struct fsm_req_readdirents* msg, Filesystem* fs)
} }
union union
{ {
struct kernel_dirent kernel_entry; struct dirent kernel_entry;
uint8_t padding[sizeof(struct kernel_dirent) + 256]; uint8_t padding[sizeof(struct dirent) + 256];
}; };
memset(&kernel_entry, 0, sizeof(kernel_entry)); memset(&kernel_entry, 0, sizeof(kernel_entry));
@ -398,13 +398,12 @@ void HandleReadDir(int chl, struct fsm_req_readdirents* msg, Filesystem* fs)
if ( entry->inode && entry->name_len && !(msg->rec_num--) ) if ( entry->inode && entry->name_len && !(msg->rec_num--) )
{ {
kernel_entry.d_reclen = sizeof(kernel_entry) + entry->name_len; kernel_entry.d_reclen = sizeof(kernel_entry) + entry->name_len;
kernel_entry.d_nextoff = 0;
kernel_entry.d_ino = entry->inode; kernel_entry.d_ino = entry->inode;
kernel_entry.d_dev = 0; kernel_entry.d_dev = 0;
kernel_entry.d_type = 0; // TODO: Support this! kernel_entry.d_type = 0; // TODO: Support this!
kernel_entry.d_namlen = entry->name_len; kernel_entry.d_namlen = entry->name_len;
memcpy(kernel_entry.d_name, entry->name, entry->name_len); memcpy(kernel_entry.d_name, entry->name, entry->name_len);
size_t dname_offset = offsetof(struct kernel_dirent, d_name); size_t dname_offset = offsetof(struct dirent, d_name);
padding[dname_offset + kernel_entry.d_namlen] = '\0'; padding[dname_offset + kernel_entry.d_namlen] = '\0';
block->Unref(); block->Unref();
inode->Unref(); inode->Unref();

View File

@ -351,9 +351,8 @@ int Descriptor::isatty(ioctx_t* ctx)
} }
ssize_t Descriptor::readdirents(ioctx_t* ctx, ssize_t Descriptor::readdirents(ioctx_t* ctx,
struct kernel_dirent* dirent, struct dirent* dirent,
size_t size, size_t size)
size_t maxcount)
{ {
// TODO: COMPATIBILITY HACK: Traditionally, you can open a directory with // TODO: COMPATIBILITY HACK: Traditionally, you can open a directory with
// O_RDONLY and pass it to fdopendir and then use it, which doesn't // O_RDONLY and pass it to fdopendir and then use it, which doesn't
@ -370,35 +369,12 @@ ssize_t Descriptor::readdirents(ioctx_t* ctx,
// because the execute bit on directories control search permission. // because the execute bit on directories control search permission.
if ( !(dflags & (O_SEARCH | O_READ | O_WRITE)) ) if ( !(dflags & (O_SEARCH | O_READ | O_WRITE)) )
return errno = EPERM, -1; return errno = EPERM, -1;
if ( !maxcount )
return 0;
if ( 1 < maxcount )
maxcount = 1;
if ( SSIZE_MAX < size ) if ( SSIZE_MAX < size )
size = SSIZE_MAX; size = SSIZE_MAX;
if ( size < sizeof(*dirent) ) if ( size < sizeof(*dirent) )
return errno = EINVAL, -1; return errno = EINVAL, -1;
ScopedLock lock(&current_offset_lock); ScopedLock lock(&current_offset_lock);
ssize_t ret = vnode->readdirents(ctx, dirent, size, current_offset, maxcount); ssize_t ret = vnode->readdirents(ctx, dirent, size, current_offset);
if ( ret == 0 )
{
const char* name = "";
size_t name_length = strlen(name);
size_t needed = sizeof(*dirent) + name_length + 1;
struct kernel_dirent retdirent;
memset(&retdirent, 0, sizeof(retdirent));
retdirent.d_reclen = needed;
retdirent.d_nextoff = 0;
retdirent.d_namlen = name_length;
if ( !ctx->copy_to_dest(dirent, &retdirent, sizeof(retdirent)) )
return -1;
if ( size < needed )
return errno = ERANGE, -1;
if ( !ctx->copy_to_dest(dirent->d_name, name, name_length+1) )
return -1;
return needed;
}
if ( 0 < ret ) if ( 0 < ret )
current_offset++; current_offset++;
return ret; return ret;

View File

@ -217,39 +217,29 @@ Dir::~Dir()
delete[] children; delete[] children;
} }
ssize_t Dir::readdirents(ioctx_t* ctx, struct kernel_dirent* dirent, ssize_t Dir::readdirents(ioctx_t* ctx, struct dirent* dirent, size_t size,
size_t size, off_t start, size_t /*maxcount*/) off_t start)
{ {
ScopedLock lock(&dir_lock); ScopedLock lock(&dir_lock);
if ( children_used <= (uintmax_t) start ) if ( children_used <= (uintmax_t) start )
return 0; return 0;
struct kernel_dirent retdirent; struct dirent retdirent;
memset(&retdirent, 0, sizeof(retdirent)); memset(&retdirent, 0, sizeof(retdirent));
const char* name = children[start].name; const char* name = children[start].name;
size_t namelen = strlen(name); size_t namelen = strlen(name);
size_t needed = sizeof(*dirent) + namelen + 1; Ref<Inode> inode = children[start].inode;
ssize_t ret = -1; retdirent.d_reclen = sizeof(*dirent) + namelen + 1;
if ( size < needed ) retdirent.d_namlen = namelen;
{ retdirent.d_ino = inode->ino;
errno = ERANGE; retdirent.d_dev = inode->dev;
retdirent.d_namlen = namelen; retdirent.d_type = ModeToDT(inode->type);
}
else
{
Ref<Inode> inode = children[start].inode;
ret = needed;
retdirent.d_reclen = needed;
retdirent.d_nextoff = 0;
retdirent.d_namlen = namelen;
retdirent.d_ino = inode->ino;
retdirent.d_dev = inode->dev;
retdirent.d_type = ModeToDT(inode->type);
}
if ( !ctx->copy_to_dest(dirent, &retdirent, sizeof(retdirent)) ) if ( !ctx->copy_to_dest(dirent, &retdirent, sizeof(retdirent)) )
return -1; return -1;
if ( 0 <= ret && !ctx->copy_to_dest(dirent->d_name, name, namelen+1) ) if ( size < retdirent.d_reclen )
return errno = ERANGE, -1;
if ( !ctx->copy_to_dest(dirent->d_name, name, namelen+1) )
return -1; return -1;
return ret; return (ssize_t) retdirent.d_reclen;
} }
size_t Dir::FindChild(const char* filename) size_t Dir::FindChild(const char* filename)

View File

@ -65,8 +65,8 @@ class Dir : public AbstractInode
public: public:
Dir(dev_t dev, ino_t ino, uid_t owner, gid_t group, mode_t mode); Dir(dev_t dev, ino_t ino, uid_t owner, gid_t group, mode_t mode);
virtual ~Dir(); virtual ~Dir();
virtual ssize_t readdirents(ioctx_t* ctx, struct kernel_dirent* dirent, virtual ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent,
size_t size, off_t start, size_t maxcount); size_t size, off_t start);
virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags, virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags,
mode_t mode); mode_t mode);
virtual int mkdir(ioctx_t* ctx, const char* filename, mode_t mode); virtual int mkdir(ioctx_t* ctx, const char* filename, mode_t mode);

View File

@ -217,8 +217,8 @@ public:
const struct timespec* ctime, const struct timespec* ctime,
const struct timespec* mtime); const struct timespec* mtime);
virtual int isatty(ioctx_t* ctx); virtual int isatty(ioctx_t* ctx);
virtual ssize_t readdirents(ioctx_t* ctx, struct kernel_dirent* dirent, virtual ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent,
size_t size, off_t start, size_t maxcount); size_t size, off_t start);
virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags, virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags,
mode_t mode); mode_t mode);
virtual int mkdir(ioctx_t* ctx, const char* filename, mode_t mode); virtual int mkdir(ioctx_t* ctx, const char* filename, mode_t mode);
@ -1009,8 +1009,8 @@ int Unode::isatty(ioctx_t* ctx)
return ret; return ret;
} }
ssize_t Unode::readdirents(ioctx_t* ctx, struct kernel_dirent* dirent, ssize_t Unode::readdirents(ioctx_t* ctx, struct dirent* dirent, size_t size,
size_t size, off_t start, size_t /*maxcount*/) off_t start)
{ {
Channel* channel = server->Connect(ctx); Channel* channel = server->Connect(ctx);
if ( !channel ) if ( !channel )
@ -1030,9 +1030,9 @@ ssize_t Unode::readdirents(ioctx_t* ctx, struct kernel_dirent* dirent,
goto break_if; goto break_if;
} }
struct kernel_dirent entry; struct dirent entry;
memset(&entry, 0, sizeof(entry));
entry.d_reclen = sizeof(entry) + resp.namelen + 1; entry.d_reclen = sizeof(entry) + resp.namelen + 1;
entry.d_nextoff = 0;
entry.d_namlen = resp.namelen; entry.d_namlen = resp.namelen;
entry.d_dev = (dev_t) server; entry.d_dev = (dev_t) server;
entry.d_ino = resp.ino; entry.d_ino = resp.ino;
@ -1041,14 +1041,13 @@ ssize_t Unode::readdirents(ioctx_t* ctx, struct kernel_dirent* dirent,
if ( !ctx->copy_to_dest(dirent, &entry, sizeof(entry)) ) if ( !ctx->copy_to_dest(dirent, &entry, sizeof(entry)) )
goto break_if; goto break_if;
size_t needed = sizeof(*dirent) + resp.namelen + 1; if ( size < entry.d_reclen && (errno = ERANGE) )
if ( size < needed && (errno = ERANGE) )
goto break_if; goto break_if;
uint8_t nul = 0; char nul = '\0';
if ( channel->KernelRecv(ctx, dirent->d_name, resp.namelen) && if ( channel->KernelRecv(ctx, dirent->d_name, resp.namelen) &&
ctx->copy_to_dest(&dirent->d_name[resp.namelen], &nul, 1) ) ctx->copy_to_dest(&dirent->d_name[resp.namelen], &nul, 1) )
ret = (ssize_t) needed; ret = (ssize_t) entry.d_reclen;
} break_if: } break_if:
channel->KernelClose(); channel->KernelClose();
return ret; return ret;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012, 2014. Copyright(C) Jonas 'Sortie' Termansen 2012, 2014, 2015.
This file is part of Sortix. This file is part of Sortix.
@ -54,11 +54,7 @@ typedef __ino_t ino_t;
#include <stddef.h> #include <stddef.h>
#endif #endif
#ifndef NULL #if __USE_SORTIX
#define __need_NULL
#include <stddef.h>
#endif
#define DT_UNKNOWN __DT_UNKNOWN #define DT_UNKNOWN __DT_UNKNOWN
#define DT_BLK __DT_BLK #define DT_BLK __DT_BLK
#define DT_CHR __DT_CHR #define DT_CHR __DT_CHR
@ -67,14 +63,16 @@ typedef __ino_t ino_t;
#define DT_LNK __DT_LNK #define DT_LNK __DT_LNK
#define DT_REG __DT_REG #define DT_REG __DT_REG
#define DT_SOCK __DT_SOCK #define DT_SOCK __DT_SOCK
#endif
#if __USE_SORTIX
#define IFTODT(x) __IFTODT(x) #define IFTODT(x) __IFTODT(x)
#define DTTOIF(x) __DTTOIF(x) #define DTTOIF(x) __DTTOIF(x)
#endif
struct kernel_dirent struct dirent
{ {
size_t d_reclen; size_t d_reclen;
size_t d_nextoff;
size_t d_namlen; size_t d_namlen;
ino_t d_ino; ino_t d_ino;
dev_t d_dev; dev_t d_dev;
@ -82,13 +80,6 @@ struct kernel_dirent
__extension__ char d_name[]; __extension__ char d_name[];
}; };
static __inline struct kernel_dirent* kernel_dirent_next(struct kernel_dirent* ent)
{
if ( !ent->d_nextoff )
return NULL;
return (struct kernel_dirent*) ((uint8_t*) ent + ent->d_nextoff);
}
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

View File

@ -34,12 +34,12 @@
#include <sortix/kernel/kthread.h> #include <sortix/kernel/kthread.h>
#include <sortix/kernel/refcount.h> #include <sortix/kernel/refcount.h>
struct dirent;
struct stat; struct stat;
struct statvfs; struct statvfs;
struct termios; struct termios;
struct wincurpos; struct wincurpos;
struct winsize; struct winsize;
struct kernel_dirent;
namespace Sortix { namespace Sortix {
@ -75,8 +75,7 @@ public:
int utimens(ioctx_t* ctx, const struct timespec* atime, int utimens(ioctx_t* ctx, const struct timespec* atime,
const struct timespec* ctime, const struct timespec* mtime); const struct timespec* ctime, const struct timespec* mtime);
int isatty(ioctx_t* ctx); int isatty(ioctx_t* ctx);
ssize_t readdirents(ioctx_t* ctx, struct kernel_dirent* dirent, size_t size, ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent, size_t size);
size_t maxcount);
Ref<Descriptor> open(ioctx_t* ctx, const char* filename, int flags, Ref<Descriptor> open(ioctx_t* ctx, const char* filename, int flags,
mode_t mode = 0); mode_t mode = 0);
int mkdir(ioctx_t* ctx, const char* filename, mode_t mode); int mkdir(ioctx_t* ctx, const char* filename, mode_t mode);

View File

@ -34,12 +34,12 @@
#include <sortix/kernel/refcount.h> #include <sortix/kernel/refcount.h>
struct dirent;
struct stat; struct stat;
struct statvfs; struct statvfs;
struct termios; struct termios;
struct wincurpos; struct wincurpos;
struct winsize; struct winsize;
struct kernel_dirent;
namespace Sortix { namespace Sortix {
@ -76,8 +76,8 @@ public:
const struct timespec* ctime, const struct timespec* ctime,
const struct timespec* mtime) = 0; const struct timespec* mtime) = 0;
virtual int isatty(ioctx_t* ctx) = 0; virtual int isatty(ioctx_t* ctx) = 0;
virtual ssize_t readdirents(ioctx_t* ctx, struct kernel_dirent* dirent, virtual ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent,
size_t size, off_t start, size_t maxcount) = 0; size_t size, off_t start) = 0;
virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags, virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags,
mode_t mode) = 0; mode_t mode) = 0;
virtual int mkdir(ioctx_t* ctx, const char* filename, mode_t mode) = 0; virtual int mkdir(ioctx_t* ctx, const char* filename, mode_t mode) = 0;
@ -171,8 +171,8 @@ public:
const struct timespec* ctime, const struct timespec* ctime,
const struct timespec* mtime); const struct timespec* mtime);
virtual int isatty(ioctx_t* ctx); virtual int isatty(ioctx_t* ctx);
virtual ssize_t readdirents(ioctx_t* ctx, struct kernel_dirent* dirent, virtual ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent,
size_t size, off_t start, size_t maxcount); size_t size, off_t start);
virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags, virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags,
mode_t mode); mode_t mode);
virtual int mkdir(ioctx_t* ctx, const char* filename, mode_t mode); virtual int mkdir(ioctx_t* ctx, const char* filename, mode_t mode);

View File

@ -129,7 +129,7 @@ ssize_t sys_pwritev(int, const struct iovec*, int, off_t);
int sys_raise(int); int sys_raise(int);
uint64_t sys_rdmsr(uint32_t); uint64_t sys_rdmsr(uint32_t);
ssize_t sys_read(int, void*, size_t); ssize_t sys_read(int, void*, size_t);
ssize_t sys_readdirents(int, struct kernel_dirent*, size_t); ssize_t sys_readdirents(int, struct dirent*, size_t);
ssize_t sys_readlinkat(int, const char*, char*, size_t); ssize_t sys_readlinkat(int, const char*, char*, size_t);
ssize_t sys_readv(int, const struct iovec*, int); ssize_t sys_readv(int, const struct iovec*, int);
ssize_t sys_recv(int, void*, size_t, int); ssize_t sys_recv(int, void*, size_t, int);

View File

@ -33,12 +33,12 @@
#include <sortix/kernel/refcount.h> #include <sortix/kernel/refcount.h>
struct dirent;
struct stat; struct stat;
struct statvfs; struct statvfs;
struct termios; struct termios;
struct wincurpos; struct wincurpos;
struct winsize; struct winsize;
struct kernel_dirent;
namespace Sortix { namespace Sortix {
@ -72,8 +72,8 @@ public:
int utimens(ioctx_t* ctx, const struct timespec* atime, int utimens(ioctx_t* ctx, const struct timespec* atime,
const struct timespec* ctime, const struct timespec* mtime); const struct timespec* ctime, const struct timespec* mtime);
int isatty(ioctx_t* ctx); int isatty(ioctx_t* ctx);
ssize_t readdirents(ioctx_t* ctx, struct kernel_dirent* dirent, ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent, size_t size,
size_t size, off_t start, size_t maxcount); off_t start);
Ref<Vnode> open(ioctx_t* ctx, const char* filename, int flags, mode_t mode); Ref<Vnode> open(ioctx_t* ctx, const char* filename, int flags, mode_t mode);
int mkdir(ioctx_t* ctx, const char* filename, mode_t mode); int mkdir(ioctx_t* ctx, const char* filename, mode_t mode);
int unlink(ioctx_t* ctx, const char* filename); int unlink(ioctx_t* ctx, const char* filename);

View File

@ -383,11 +383,11 @@ bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref<Descriptor> desc)
union union
{ {
struct kernel_dirent dirent; struct dirent dirent;
uint8_t dirent_data[sizeof(struct kernel_dirent) + sizeof(uintmax_t) * 3]; uint8_t dirent_data[sizeof(struct dirent) + sizeof(uintmax_t) * 3];
}; };
while ( 0 < ctx.links->readdirents(&ctx.ioctx, &dirent, sizeof(dirent_data), 1) && while ( 0 < ctx.links->readdirents(&ctx.ioctx, &dirent, sizeof(dirent_data)) &&
((const char*) dirent.d_name)[0] ) ((const char*) dirent.d_name)[0] )
{ {
if ( ((const char*) dirent.d_name)[0] == '.' ) if ( ((const char*) dirent.d_name)[0] == '.' )

View File

@ -202,9 +202,9 @@ int AbstractInode::isatty(ioctx_t* /*ctx*/)
} }
ssize_t AbstractInode::readdirents(ioctx_t* /*ctx*/, ssize_t AbstractInode::readdirents(ioctx_t* /*ctx*/,
struct kernel_dirent* /*dirent*/, struct dirent* /*dirent*/,
size_t /*size*/, off_t /*start*/, size_t /*size*/,
size_t /*maxcount*/) off_t /*start*/)
{ {
if ( inode_type == INODE_TYPE_DIR ) if ( inode_type == INODE_TYPE_DIR )
return errno = EBADF, -1; return errno = EBADF, -1;

View File

@ -382,16 +382,15 @@ int sys_ioctl(int fd, int cmd, uintptr_t arg)
} }
} }
ssize_t sys_readdirents(int fd, struct kernel_dirent* dirent, size_t size) ssize_t sys_readdirents(int fd, struct dirent* dirent, size_t size)
{ {
if ( size < sizeof(kernel_dirent) ) { errno = EINVAL; return -1; }
if ( SSIZE_MAX < size ) if ( SSIZE_MAX < size )
size = SSIZE_MAX; size = SSIZE_MAX;
Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd); Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(fd);
if ( !desc ) if ( !desc )
return -1; return -1;
ioctx_t ctx; SetupUserIOCtx(&ctx); ioctx_t ctx; SetupUserIOCtx(&ctx);
return desc->readdirents(&ctx, dirent, size, 1 /*maxcount*/); return desc->readdirents(&ctx, dirent, size);
} }
int sys_fchdir(int fd) int sys_fchdir(int fd)

View File

@ -281,10 +281,10 @@ int Vnode::isatty(ioctx_t* ctx)
return inode->isatty(ctx); return inode->isatty(ctx);
} }
ssize_t Vnode::readdirents(ioctx_t* ctx, struct kernel_dirent* dirent, ssize_t Vnode::readdirents(ioctx_t* ctx, struct dirent* dirent,
size_t size, off_t start, size_t count) size_t size, off_t start)
{ {
return inode->readdirents(ctx, dirent, size, start, count); return inode->readdirents(ctx, dirent, size, start);
} }
int Vnode::mkdir(ioctx_t* ctx, const char* filename, mode_t mode) int Vnode::mkdir(ioctx_t* ctx, const char* filename, mode_t mode)

View File

@ -36,16 +36,7 @@ ctype/tolower.o \
ctype/toupper.o \ ctype/toupper.o \
dirent/alphasort.o \ dirent/alphasort.o \
dirent/alphasort_r.o \ dirent/alphasort_r.o \
dirent/closedir.o \
dirent/dclearerr.o \
dirent/deof.o \
dirent/derror.o \
dirent/dirfd.o \ dirent/dirfd.o \
dirent/dnewdir.o \
dirent/dregister.o \
dirent/dunregister.o \
dirent/readdir.o \
dirent/rewinddir.o \
dirent/versionsort.o \ dirent/versionsort.o \
dirent/versionsort_r.o \ dirent/versionsort_r.o \
errno/errno.o \ errno/errno.o \
@ -330,9 +321,12 @@ $(CPUDIR)/fork.o \
$(CPUDIR)/setjmp.o \ $(CPUDIR)/setjmp.o \
$(CPUDIR)/signal.o \ $(CPUDIR)/signal.o \
$(CPUDIR)/syscall.o \ $(CPUDIR)/syscall.o \
dirent/closedir.o \
dirent/dscandir_r.o \ dirent/dscandir_r.o \
dirent/fdopendir.o \ dirent/fdopendir.o \
dirent/opendir.o \ dirent/opendir.o \
dirent/readdir.o \
dirent/rewinddir.o \
dirent/scandir.o \ dirent/scandir.o \
dlfcn/dlfcn.o \ dlfcn/dlfcn.o \
err/err.o \ err/err.o \

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014. Copyright(C) Jonas 'Sortie' Termansen 2011, 2014, 2015.
This file is part of the Sortix C Library. This file is part of the Sortix C Library.
@ -23,15 +23,13 @@
*******************************************************************************/ *******************************************************************************/
#include <dirent.h> #include <dirent.h>
#include <DIR.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
extern "C" int closedir(DIR* dir) extern "C" int closedir(DIR* dir)
{ {
int result = dir->close_func ? dir->close_func(dir->user) : 0; close(dir->fd);
dunregister(dir);
free(dir->entry); free(dir->entry);
if ( dir->free_func ) free(dir);
dir->free_func(dir); return 0;
return result;
} }

View File

@ -1,31 +0,0 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
dirent/dclearerr.cpp
Clears the error flag from a directory stream.
*******************************************************************************/
#include <dirent.h>
#include <DIR.h>
extern "C" void dclearerr(DIR* dir)
{
dir->flags &= ~_DIR_ERROR;
}

View File

@ -1,31 +0,0 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
dirent/deof.cpp
Returns the end-of-file flag of a directory stream.
*******************************************************************************/
#include <dirent.h>
#include <DIR.h>
extern "C" int deof(DIR* dir)
{
return dir->flags & _DIR_EOF;
}

View File

@ -1,31 +0,0 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
dirent/derror.cpp
Returns the error flag of a directory stream.
*******************************************************************************/
#include <dirent.h>
#include <DIR.h>
extern "C" int derror(DIR* dir)
{
return dir->flags & _DIR_ERROR;
}

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014. Copyright(C) Jonas 'Sortie' Termansen 2011, 2014, 2015.
This file is part of the Sortix C Library. This file is part of the Sortix C Library.
@ -23,12 +23,9 @@
*******************************************************************************/ *******************************************************************************/
#include <dirent.h> #include <dirent.h>
#include <DIR.h>
#include <errno.h> #include <errno.h>
extern "C" int dirfd(DIR* dir) extern "C" int dirfd(DIR* dir)
{ {
if ( !dir->fd_func ) return dir->fd;
return errno = EBADF, 0;
return dir->fd_func(dir->user);
} }

View File

@ -1,45 +0,0 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
dirent/dnewdir.cpp
Allocates and registers a new directory stream structure.
*******************************************************************************/
#include <dirent.h>
#include <DIR.h>
#include <stddef.h>
#include <stdlib.h>
static void dfreedir(DIR* dir)
{
free(dir);
}
extern "C" DIR* dnewdir(void)
{
DIR* dir = (DIR*) calloc(sizeof(DIR), 1);
if ( !dir )
return NULL;
dir->flags = 0;
dir->free_func = dfreedir;
dir->closedir_indirect = closedir;
dregister(dir);
return dir;
}

View File

@ -1,36 +0,0 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
dirent/dregister.cpp
Registers an directory stream for later automatic closing.
*******************************************************************************/
#include <dirent.h>
#include <pthread.h>
extern "C" void dregister(DIR* dir)
{
pthread_mutex_lock(&__first_dir_lock);
dir->flags |= _DIR_REGISTERED;
if ( (dir->next = __first_dir) )
dir->next->prev = dir;
__first_dir = dir;
pthread_mutex_unlock(&__first_dir_lock);
}

View File

@ -1,41 +0,0 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
dirent/dunregister.cpp
Unregisters an directory stream for later automatic closing.
*******************************************************************************/
#include <dirent.h>
#include <pthread.h>
extern "C" void dunregister(DIR* dir)
{
if ( !(dir->flags & _DIR_REGISTERED) )
return;
pthread_mutex_lock(&__first_dir_lock);
if ( !dir->prev )
__first_dir = dir->next;
if ( dir->prev )
dir->prev->next = dir->next;
if ( dir->next )
dir->next->prev = dir->prev;
dir->flags &= ~_DIR_REGISTERED;
pthread_mutex_unlock(&__first_dir_lock);
}

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014. Copyright(C) Jonas 'Sortie' Termansen 2011, 2014, 2015.
This file is part of the Sortix C Library. This file is part of the Sortix C Library.
@ -22,129 +22,20 @@
*******************************************************************************/ *******************************************************************************/
#include <sys/readdirents.h>
#include <assert.h>
#include <dirent.h> #include <dirent.h>
#include <DIR.h> #include <DIR.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef struct fddir_sortix_struct
{
struct kernel_dirent* dirent;
struct kernel_dirent* current;
size_t direntsize;
int fd;
} fddir_sortix_t;
static int fddir_sortix_readents(fddir_sortix_t* info)
{
if ( !info->dirent )
{
// Allocate a buffer of at least sizeof(kernel_dirent).
info->direntsize = sizeof(struct kernel_dirent) + 4UL;
info->dirent = (struct kernel_dirent*) malloc(info->direntsize);
if ( !info->dirent )
return -1;
}
int saved_errno = errno;
if ( readdirents(info->fd, info->dirent, info->direntsize) < 0 )
{
if ( errno != ERANGE )
return -1;
errno = saved_errno;
size_t newdirentsize = sizeof(struct kernel_dirent) + info->dirent->d_namlen + 1;
if ( newdirentsize < info->direntsize )
newdirentsize *= 2;
struct kernel_dirent* newdirent = (struct kernel_dirent*) malloc(newdirentsize);
if ( !newdirent )
return -1;
free(info->dirent);
info->dirent = newdirent;
info->direntsize = newdirentsize;
return fddir_sortix_readents(info);
}
return 0;
}
static int fddir_sortix_read(void* user, struct dirent* dirent, size_t* size)
{
fddir_sortix_t* info = (fddir_sortix_t*) user;
if ( !info->current )
{
if ( fddir_sortix_readents(info) )
return -1;
info->current = info->dirent;
}
size_t provided = (user) ? *size : 0;
size_t needed = sizeof(struct dirent) + info->current->d_namlen + 1;
*size = needed;
if ( provided < needed )
return 1;
dirent->d_reclen = needed;
dirent->d_namlen = info->current->d_namlen;
dirent->d_ino = info->current->d_ino;
dirent->d_dev = info->current->d_dev;
dirent->d_type = info->current->d_type;
strcpy(dirent->d_name, info->current->d_name);
info->current = kernel_dirent_next(info->current);
return 0;
}
static int fddir_sortix_rewind(void* user)
{
fddir_sortix_t* info = (fddir_sortix_t*) user;
return lseek(info->fd, 0, SEEK_SET);
}
static int fddir_sortix_fd(void* user)
{
fddir_sortix_t* info = (fddir_sortix_t*) user;
return info->fd;
}
static int fddir_sortix_close(void* user)
{
fddir_sortix_t* info = (fddir_sortix_t*) user;
int result = close(info->fd);
free(info->dirent);
free(info);
return result;
}
extern "C" DIR* fdopendir(int fd) extern "C" DIR* fdopendir(int fd)
{ {
fddir_sortix_t* info = (fddir_sortix_t*) calloc(sizeof(fddir_sortix_t), 1);
if ( !info )
return NULL;
DIR* dir = dnewdir();
if ( !dir )
return free(info), (DIR*) NULL;
int old_dflags = fcntl(fd, F_GETFD); int old_dflags = fcntl(fd, F_GETFD);
if ( 0 <= old_dflags ) if ( 0 <= old_dflags && !(old_dflags & FD_CLOEXEC) )
fcntl(fd, F_SETFD, old_dflags | FD_CLOEXEC); fcntl(fd, F_SETFD, old_dflags | FD_CLOEXEC);
// TODO: Potentially reopen as O_EXEC when the kernel requires that.
info->fd = fd; DIR* dir = (DIR*) calloc(sizeof(DIR), 1);
if ( !dir )
dir->read_func = fddir_sortix_read; return NULL;
dir->rewind_func = fddir_sortix_rewind; dir->fd = fd;
dir->fd_func = fddir_sortix_fd;
dir->close_func = fddir_sortix_close;
dir->user = (void*) info;
return dir; return dir;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014. Copyright(C) Jonas 'Sortie' Termansen 2011, 2014, 2015.
This file is part of the Sortix C Library. This file is part of the Sortix C Library.
@ -24,16 +24,17 @@
#include <dirent.h> #include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <stddef.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
extern "C" DIR* opendir(const char* path) extern "C" DIR* opendir(const char* path)
{ {
int fd = open(path, O_RDONLY | O_DIRECTORY | O_CLOEXEC); int fd = open(path, O_SEARCH | O_DIRECTORY | O_CLOEXEC);
if ( fd < 0 ) if ( fd < 0 )
return NULL; return NULL;
DIR* dir = fdopendir(fd); DIR* dir = (DIR*) calloc(sizeof(DIR), 1);
if ( !dir ) if ( !dir )
return close(fd), (DIR*) NULL; return close(fd), (DIR*) NULL;
dir->fd = fd;
return dir; return dir;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014. Copyright(C) Jonas 'Sortie' Termansen 2011, 2014, 2015.
This file is part of the Sortix C Library. This file is part of the Sortix C Library.
@ -22,38 +22,34 @@
*******************************************************************************/ *******************************************************************************/
#include <sys/readdirents.h>
#include <dirent.h> #include <dirent.h>
#include <DIR.h>
#include <errno.h> #include <errno.h>
#include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
extern "C" struct dirent* readdir(DIR* dir) extern "C" struct dirent* readdir(DIR* dir)
{ {
int old_errno = errno; int old_errno = errno;
struct dirent fallback;
if ( !dir->read_func ) struct dirent* entry = dir->entry ? dir->entry : &fallback;
return dir->flags |= _DIR_ERROR, errno = EBADF, (struct dirent*) NULL; size_t size = dir->entry ? dir->size : sizeof(fallback);
ssize_t amount;
size_t size = dir->entrysize; while ( (amount = readdirents(dir->fd, entry, size)) < 0 )
int status;
while ( 0 < (status = dir->read_func(dir->user, dir->entry, &size)) )
{ {
struct dirent* biggerdir = (struct dirent*) malloc(size); if ( errno != ERANGE )
if ( !biggerdir ) return NULL;
return dir->flags |= _DIR_ERROR, (struct dirent*) NULL; errno = old_errno;
size_t needed = entry->d_reclen;
free(dir->entry); free(dir->entry);
dir->entry = biggerdir; dir->entry = NULL;
dir->entrysize = size; struct dirent* new_dirent = (struct dirent*) malloc(needed);
if ( !new_dirent )
return NULL;
entry = dir->entry = new_dirent;
size = dir->size = needed;
} }
if ( amount == 0 )
if ( status < 0 ) return NULL;
return dir->flags |= _DIR_ERROR, (struct dirent*) NULL;
dir->flags &= ~_DIR_ERROR;
if ( !dir->entry->d_name[0] )
return dir->flags |= _DIR_EOF, errno = old_errno, (struct dirent*) NULL;
return dir->entry; return dir->entry;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2014. Copyright(C) Jonas 'Sortie' Termansen 2011, 2014, 2015.
This file is part of the Sortix C Library. This file is part of the Sortix C Library.
@ -23,11 +23,9 @@
*******************************************************************************/ *******************************************************************************/
#include <dirent.h> #include <dirent.h>
#include <DIR.h> #include <unistd.h>
extern "C" void rewinddir(DIR* dir) extern "C" void rewinddir(DIR* dir)
{ {
if ( dir->rewind_func ) lseek(dir->fd, 0, SEEK_SET);
dir->rewind_func(dir->user);
dir->flags &= ~_DIR_EOF;
} }

View File

@ -54,26 +54,11 @@ typedef struct __DIR DIR;
struct __DIR struct __DIR
{ {
void* user;
int (*read_func)(void* user, struct dirent* dirent, size_t* size);
int (*rewind_func)(void* user);
int (*fd_func)(void* user);
int (*close_func)(void* user);
void (*free_func)(DIR* dir);
/* Application writers shouldn't use anything beyond this point. */
int (*closedir_indirect)(DIR*);
DIR* prev;
DIR* next;
struct dirent* entry; struct dirent* entry;
size_t entrysize; size_t size;
int flags; int fd;
}; };
#if defined(__is_sortix_libc)
extern DIR* __first_dir;
extern __pthread_mutex_t __first_dir_lock;
#endif
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

View File

@ -29,67 +29,25 @@
#include <sys/__/types.h> #include <sys/__/types.h>
#include <sortix/__/dirent.h> #include <sortix/dirent.h>
#if defined(__is_sortix_libc) #if defined(__is_sortix_libc)
#include <DIR.h> #include <DIR.h>
#endif #endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __dev_t_defined
#define __dev_t_defined
typedef __dev_t dev_t;
#endif
#ifndef __ino_t_defined
#define __ino_t_defined
typedef __ino_t ino_t;
#endif
#ifndef __size_t_defined
#define __size_t_defined
#define __need_size_t
#include <stddef.h>
#endif
#ifndef __DIR_defined #ifndef __DIR_defined
#define __DIR_defined #define __DIR_defined
typedef struct __DIR DIR; typedef struct __DIR DIR;
#endif #endif
#if __USE_SORTIX #ifdef __cplusplus
#define DT_UNKNOWN __DT_UNKNOWN extern "C" {
#define DT_BLK __DT_BLK
#define DT_CHR __DT_CHR
#define DT_DIR __DT_DIR
#define DT_FIFO __DT_FIFO
#define DT_LNK __DT_LNK
#define DT_REG __DT_REG
#define DT_SOCK __DT_SOCK
#endif #endif
#if __USE_SORTIX int closedir(DIR*);
#define IFTODT(x) __IFTODT(x) DIR* opendir(const char*);
#define DTTOIF(x) __DTTOIF(x) struct dirent* readdir(DIR*);
#endif void rewinddir(DIR*);
struct dirent
{
size_t d_reclen;
size_t d_namlen;
ino_t d_ino;
dev_t d_dev;
unsigned char d_type;
__extension__ char d_name[];
};
int closedir(DIR* dir);
DIR* opendir(const char* path);
struct dirent* readdir(DIR* dir);
void rewinddir(DIR* dir);
#if __USE_SORTIX || __USE_XOPEN #if __USE_SORTIX || __USE_XOPEN
/* TODO: seekdir */ /* TODO: seekdir */
@ -104,8 +62,8 @@ void rewinddir(DIR* dir);
/* Functions from POSIX 2008. */ /* Functions from POSIX 2008. */
#if __USE_SORTIX || 200809L <= __USE_POSIX #if __USE_SORTIX || 200809L <= __USE_POSIX
int alphasort(const struct dirent**, const struct dirent**); int alphasort(const struct dirent**, const struct dirent**);
int dirfd(DIR* dir); int dirfd(DIR*);
DIR* fdopendir(int fd); DIR* fdopendir(int);
int scandir(const char*, struct dirent***, int (*)(const struct dirent*), int scandir(const char*, struct dirent***, int (*)(const struct dirent*),
int (*)(const struct dirent**, const struct dirent**)); int (*)(const struct dirent**, const struct dirent**));
#endif #endif
@ -118,17 +76,11 @@ int versionsort(const struct dirent**, const struct dirent**);
/* Functions that are Sortix extensions. */ /* Functions that are Sortix extensions. */
#if __USE_SORTIX #if __USE_SORTIX
int alphasort_r(const struct dirent**, const struct dirent**, void*); int alphasort_r(const struct dirent**, const struct dirent**, void*);
void dclearerr(DIR* dir);
int deof(DIR* dif);
int derror(DIR* dir);
DIR* dnewdir(void);
void dregister(DIR* dir);
int dscandir_r(DIR*, struct dirent***, int dscandir_r(DIR*, struct dirent***,
int (*)(const struct dirent*, void*), int (*)(const struct dirent*, void*),
void*, void*,
int (*)(const struct dirent**, const struct dirent**, void*), int (*)(const struct dirent**, const struct dirent**, void*),
void*); void*);
void dunregister(DIR* dir);
int versionsort_r(const struct dirent**, const struct dirent**, void*); int versionsort_r(const struct dirent**, const struct dirent**, void*);
#endif #endif

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011. Copyright(C) Jonas 'Sortie' Termansen 2011, 2015.
This file is part of the Sortix C Library. This file is part of the Sortix C Library.
@ -29,22 +29,24 @@
#include <sys/__/types.h> #include <sys/__/types.h>
#include <sys/types.h>
#include <stddef.h>
#include <stdint.h>
#include <sortix/dirent.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __size_t_defined #ifndef __size_t_defined
#define __size_t_defined #define __size_t_defined
#define __need_size_t #define __need_size_t
#include <stddef.h> #include <stddef.h>
#endif #endif
ssize_t readdirents(int fd, struct kernel_dirent* dirent, size_t size); #ifndef __ssize_t_defined
#define __ssize_t_defined
typedef __ssize_t ssize_t;
#endif
struct dirent;
#ifdef __cplusplus
extern "C" {
#endif
ssize_t readdirents(int, struct dirent*, size_t);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -60,11 +60,8 @@ extern "C" void exit(int status)
__exit_handler_stack = __exit_handler_stack->next; __exit_handler_stack = __exit_handler_stack->next;
} }
pthread_mutex_lock(&__first_dir_lock);
pthread_mutex_lock(&__first_file_lock); pthread_mutex_lock(&__first_file_lock);
while ( __first_dir )
__first_dir->closedir_indirect(__first_dir);
for ( FILE* fp = __first_file; fp; fp = fp->next ) for ( FILE* fp = __first_file; fp; fp = fp->next )
{ {
flockfile(fp); flockfile(fp);

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2015.
This file is part of the Sortix C Library. This file is part of the Sortix C Library.
@ -18,16 +18,16 @@
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>. along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
sys/readdirents/readdirents.cpp sys/readdirents/readdirents.cpp
Reads entries from a directory file descriptor. Reads directory entries from a directory file descriptor.
*******************************************************************************/ *******************************************************************************/
#include <sys/readdirents.h> #include <sys/readdirents.h>
#include <sys/syscall.h> #include <sys/syscall.h>
DEFN_SYSCALL4(ssize_t, sys_readdirents, SYSCALL_READDIRENTS, int, struct kernel_dirent*, size_t, size_t); DEFN_SYSCALL3(ssize_t, sys_readdirents, SYSCALL_READDIRENTS, int, struct dirent*, size_t);
extern "C" ssize_t readdirents(int fd, struct kernel_dirent* dirent, size_t size) extern "C" ssize_t readdirents(int fd, struct dirent* dirent, size_t size)
{ {
return sys_readdirents(fd, dirent, size, 1); return sys_readdirents(fd, dirent, size);
} }

View File

@ -272,7 +272,8 @@ static bool do_chmod_directory(int fd,
joiner = ""; joiner = "";
bool success = true; bool success = true;
while ( struct dirent* entry = readdir(dir) ) struct dirent* entry;
while ( (errno = 0, entry = readdir(dir)) )
{ {
if ( !strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") ) if ( !strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") )
continue; continue;
@ -291,7 +292,7 @@ static bool do_chmod_directory(int fd,
free(entry_path); free(entry_path);
} }
if ( derror(dir) ) if ( errno != 0 )
{ {
error(0, errno, "reading directory: `%s'", path); error(0, errno, "reading directory: `%s'", path);
closedir(dir); closedir(dir);

View File

@ -223,7 +223,8 @@ bool disk_usage_file_at(int relfd,
} }
bool success = true; bool success = true;
while ( struct dirent* entry = readdir(dir) ) struct dirent* entry;
while ( (errno = 0, entry = readdir(dir)) )
{ {
if ( !strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") ) if ( !strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") )
continue; continue;
@ -249,14 +250,12 @@ bool disk_usage_file_at(int relfd,
if ( num_bytes_ptr ) if ( num_bytes_ptr )
*num_bytes_ptr = num_bytes; *num_bytes_ptr = num_bytes;
#if defined(__sortix__) if ( errno && errno != ENOTDIR )
if ( derror(dir) && errno != ENOTDIR )
{ {
error(0, errno, "reading directory `%s'", path); error(0, errno, "reading directory `%s'", path);
closedir(dir); closedir(dir);
return false; return false;
} }
#endif
if ( print_if_dir ) if ( print_if_dir )
print_disk_usage(num_bytes, block_size, flags, path); print_disk_usage(num_bytes, block_size, flags, path);