libposix: implemented libposix_getdents
This commit is contained in:
parent
97c4c2bccb
commit
9947978c05
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user