libposix: implemented libposix_getdents

This commit is contained in:
Giacomo Tesio 2017-08-22 01:42:33 +02:00
parent 97c4c2bccb
commit 9947978c05
2 changed files with 93 additions and 4 deletions

View File

@ -36,6 +36,7 @@
#ifndef _LIBPOSIX_DIRENT
#define _LIBPOSIX_DIRENT
/* dirent alias of stat(5) message.
* We (ab)use the fact that both 9P and Jehanne are little endian.
* With the new file protocol this might change.
@ -53,7 +54,7 @@ struct __attribute__((__packed__)) dirent
unsigned int __pad4__; /* don't use */
unsigned long d_filesize;
unsigned short d_namlen;
char* d_name;
char d_name[];
};
#define _DIRENT_HAVE_D_RECLEN
@ -64,6 +65,16 @@ struct __attribute__((__packed__)) dirent
#define _DIRENT_HAVE_D_NAMLEN
#undef _DIRENT_HAVE_D_OFF
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
#define DT_WHT 14
#endif /* _LIBPOSIX_DIRENT */
#ifndef _LIBPOSIX_H
@ -110,7 +121,7 @@ extern void POSIX_free(void *ptr);
extern unsigned int POSIX_sleep(unsigned int seconds);
extern int POSIX_pipe(int *errnop, int fildes[2]);
extern int libposix_getdents(int *errnop, int fd, struct dirent *buf, int buf_bytes);
extern int libposix_getdents(int *errnop, int fd, char *buf, int buf_bytes);
/* Library initialization
*/

View File

@ -17,6 +17,7 @@
*/
#include <u.h>
#include <lib9.h>
#include <9P2000.h>
#include <posix.h>
#include "internal.h"
@ -360,7 +361,84 @@ POSIX_stat(int *errnop, const char *file, void *pstat)
}
int
libposix_getdents(int *errnop, int fd, struct dirent *buf, int buf_bytes)
libposix_getdents(int *errnop, int fd, char *buf, int buf_bytes)
{
return 0;
#define MINSTATLEN (STATFIXLEN + 4) /* 4 = min (1 char) name, uid, gid, muid */
int r;
Dir *d;
struct dirent *dp;
char *p;
if(fd < 0)
goto FailWithEBADF;
if(buf == nil)
goto FailWithEFAULT;
if(buf_bytes < MINSTATLEN)
goto FailWithEINVAL;
d = dirfstat(fd);
if(d == nil)
goto FailWithENOENT; /* removed? */
r = d->mode & DMDIR;
free(d);
if(r == 0)
goto FailWithENOTDIR; /* not a directory */
r = read(fd, buf, buf_bytes);
if(r < 0)
goto FailWithENOENT; /* removed? */
if(r < MINSTATLEN)
goto FailWithEIO;
p = buf;
while(p - buf < r){
/* here we adjust 9P2000 stat info to match
* dirent specification
*/
dp = (struct dirent *)p;
/* the count field in stat structure exclude itself */
dp->d_reclen += BIT16SZ;
/* 9P2000 strings are not NUL-terminated */
dp->d_name[dp->d_namlen] = '\0';
/* we have to map types to UNIX */
if(dp->d_type & (DMDIR >> 24))
dp->d_type = DT_DIR;
else if(dp->__pad1__ == '|') /* kernel device == devpipe */
dp->d_type = DT_FIFO;
else
dp->d_type = DT_REG; /* UNIX lack fantasy :-) */
p += dp->d_reclen;
}
return r;
FailWithEBADF:
*errnop = __libposix_get_errno(PosixEBADF);
return -1;
FailWithEFAULT:
*errnop = __libposix_get_errno(PosixEFAULT);
return -1;
FailWithEINVAL:
*errnop = __libposix_get_errno(PosixEINVAL);
return -1;
FailWithENOENT:
*errnop = __libposix_get_errno(PosixENOENT);
return -1;
FailWithENOTDIR:
*errnop = __libposix_get_errno(PosixENOTDIR);
return -1;
FailWithEIO:
*errnop = __libposix_get_errno(PosixEIO);
return -1;
}