mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 06:48:31 +00:00
Refix readdir() on OpenBSD
We now have better tests which are catching these kinds of bugs.
This commit is contained in:
parent
f7c7b949fd
commit
a5f3456333
2 changed files with 25 additions and 2 deletions
|
@ -73,6 +73,19 @@ struct dirent$bsd {
|
||||||
char d_name[256];
|
char d_name[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenBSD getdents() ABI.
|
||||||
|
*/
|
||||||
|
struct dirent$openbsd {
|
||||||
|
uint64_t d_fileno;
|
||||||
|
int64_t d_off;
|
||||||
|
uint16_t d_reclen;
|
||||||
|
uint8_t d_type;
|
||||||
|
uint8_t d_namlen;
|
||||||
|
uint8_t __zomg[4];
|
||||||
|
char d_name[256];
|
||||||
|
};
|
||||||
|
|
||||||
static textwindows noinline DIR *opendir$nt(const char *name) {
|
static textwindows noinline DIR *opendir$nt(const char *name) {
|
||||||
int len;
|
int len;
|
||||||
DIR *res;
|
DIR *res;
|
||||||
|
@ -194,6 +207,7 @@ struct dirent *readdir(DIR *dir) {
|
||||||
long basep;
|
long basep;
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
struct dirent$bsd *bsd;
|
struct dirent$bsd *bsd;
|
||||||
|
struct dirent$openbsd *obsd;
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
if (dir->buf_pos >= dir->buf_end) {
|
if (dir->buf_pos >= dir->buf_end) {
|
||||||
basep = dir->tell; /* <- what does xnu do */
|
basep = dir->tell; /* <- what does xnu do */
|
||||||
|
@ -202,10 +216,19 @@ struct dirent *readdir(DIR *dir) {
|
||||||
dir->buf_pos = 0;
|
dir->buf_pos = 0;
|
||||||
dir->buf_end = rc;
|
dir->buf_end = rc;
|
||||||
}
|
}
|
||||||
if (IsLinux() || IsOpenbsd()) {
|
if (IsLinux()) {
|
||||||
ent = (struct dirent *)(dir->buf + dir->buf_pos);
|
ent = (struct dirent *)(dir->buf + dir->buf_pos);
|
||||||
dir->buf_pos += ent->d_reclen;
|
dir->buf_pos += ent->d_reclen;
|
||||||
dir->tell = ent->d_off;
|
dir->tell = ent->d_off;
|
||||||
|
} else if (IsOpenbsd()) {
|
||||||
|
obsd = (struct dirent$openbsd *)(dir->buf + dir->buf_pos);
|
||||||
|
dir->buf_pos += obsd->d_reclen;
|
||||||
|
ent = &dir->ent;
|
||||||
|
ent->d_ino = obsd->d_fileno;
|
||||||
|
ent->d_off = obsd->d_off;
|
||||||
|
ent->d_reclen = obsd->d_reclen;
|
||||||
|
ent->d_type = obsd->d_type;
|
||||||
|
memcpy(ent->d_name, obsd->d_name, obsd->d_namlen + 1);
|
||||||
} else {
|
} else {
|
||||||
bsd = (struct dirent$bsd *)(dir->buf + dir->buf_pos);
|
bsd = (struct dirent$bsd *)(dir->buf + dir->buf_pos);
|
||||||
dir->buf_pos += bsd->d_reclen;
|
dir->buf_pos += bsd->d_reclen;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_DIRENT_H_
|
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_DIRENT_H_
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
|
||||||
struct dirent { /* openbsd and linux getdents64 abi */
|
struct dirent { /* linux getdents64 abi */
|
||||||
uint64_t d_ino; /* inode number */
|
uint64_t d_ino; /* inode number */
|
||||||
int64_t d_off; /* implementation-dependent location number */
|
int64_t d_off; /* implementation-dependent location number */
|
||||||
uint16_t d_reclen; /* byte length of this whole struct and string */
|
uint16_t d_reclen; /* byte length of this whole struct and string */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue