Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108929306
D3226.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D3226.diff
View Options
Index: head/sys/compat/cloudabi/cloudabi_file.c
===================================================================
--- head/sys/compat/cloudabi/cloudabi_file.c
+++ head/sys/compat/cloudabi/cloudabi_file.c
@@ -28,6 +28,7 @@
#include <sys/param.h>
#include <sys/capsicum.h>
+#include <sys/dirent.h>
#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
@@ -35,11 +36,15 @@
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/syscallsubr.h>
+#include <sys/uio.h>
+#include <sys/vnode.h>
#include <compat/cloudabi/cloudabi_proto.h>
#include <compat/cloudabi/cloudabi_syscalldefs.h>
#include <compat/cloudabi/cloudabi_util.h>
+#include <security/mac/mac_framework.h>
+
static MALLOC_DEFINE(M_CLOUDABI_PATH, "cloudabipath", "CloudABI pathnames");
/*
@@ -197,13 +202,180 @@
return (ENOSYS);
}
+/* Converts a FreeBSD directory entry structure and writes it to userspace. */
+static int
+write_dirent(struct dirent *bde, cloudabi_dircookie_t cookie, struct uio *uio)
+{
+ cloudabi_dirent_t cde = {
+ .d_next = cookie,
+ .d_ino = bde->d_fileno,
+ .d_namlen = bde->d_namlen,
+ };
+ size_t len;
+ int error;
+
+ /* Convert file type. */
+ switch (bde->d_type) {
+ case DT_BLK:
+ cde.d_type = CLOUDABI_FILETYPE_BLOCK_DEVICE;
+ break;
+ case DT_CHR:
+ cde.d_type = CLOUDABI_FILETYPE_CHARACTER_DEVICE;
+ break;
+ case DT_DIR:
+ cde.d_type = CLOUDABI_FILETYPE_DIRECTORY;
+ break;
+ case DT_FIFO:
+ cde.d_type = CLOUDABI_FILETYPE_FIFO;
+ break;
+ case DT_LNK:
+ cde.d_type = CLOUDABI_FILETYPE_SYMBOLIC_LINK;
+ break;
+ case DT_REG:
+ cde.d_type = CLOUDABI_FILETYPE_REGULAR_FILE;
+ break;
+ case DT_SOCK:
+ /* The exact socket type cannot be derived. */
+ cde.d_type = CLOUDABI_FILETYPE_SOCKET_STREAM;
+ break;
+ default:
+ cde.d_type = CLOUDABI_FILETYPE_UNKNOWN;
+ break;
+ }
+
+ /* Write directory entry structure. */
+ len = sizeof(cde) < uio->uio_resid ? sizeof(cde) : uio->uio_resid;
+ error = uiomove(&cde, len, uio);
+ if (error != 0)
+ return (error);
+
+ /* Write filename. */
+ len = bde->d_namlen < uio->uio_resid ? bde->d_namlen : uio->uio_resid;
+ return (uiomove(bde->d_name, len, uio));
+}
+
int
cloudabi_sys_file_readdir(struct thread *td,
struct cloudabi_sys_file_readdir_args *uap)
{
+ struct iovec iov = {
+ .iov_base = uap->buf,
+ .iov_len = uap->nbyte
+ };
+ struct uio uio = {
+ .uio_iov = &iov,
+ .uio_iovcnt = 1,
+ .uio_resid = iov.iov_len,
+ .uio_segflg = UIO_USERSPACE,
+ .uio_rw = UIO_READ,
+ .uio_td = td
+ };
+ struct file *fp;
+ struct vnode *vp;
+ void *readbuf;
+ cap_rights_t rights;
+ cloudabi_dircookie_t offset;
+ int error;
- /* Not implemented. */
- return (ENOSYS);
+ /* Obtain directory vnode. */
+ error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp);
+ if (error != 0) {
+ if (error == EINVAL)
+ return (ENOTDIR);
+ return (error);
+ }
+ if ((fp->f_flag & FREAD) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ /*
+ * Call VOP_READDIR() and convert resulting data until the user
+ * provided buffer is filled.
+ */
+ readbuf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
+ offset = uap->cookie;
+ vp = fp->f_vnode;
+ while (uio.uio_resid > 0) {
+ struct iovec readiov = {
+ .iov_base = readbuf,
+ .iov_len = MAXBSIZE
+ };
+ struct uio readuio = {
+ .uio_iov = &readiov,
+ .uio_iovcnt = 1,
+ .uio_rw = UIO_READ,
+ .uio_segflg = UIO_SYSSPACE,
+ .uio_td = td,
+ .uio_resid = MAXBSIZE,
+ .uio_offset = offset
+ };
+ struct dirent *bde;
+ unsigned long *cookies, *cookie;
+ size_t readbuflen;
+ int eof, ncookies;
+
+ /* Validate file type. */
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ if (vp->v_type != VDIR) {
+ VOP_UNLOCK(vp, 0);
+ error = ENOTDIR;
+ goto done;
+ }
+#ifdef MAC
+ error = mac_vnode_check_readdir(td->td_ucred, vp);
+ if (error != 0) {
+ VOP_UNLOCK(vp, 0);
+ goto done;
+ }
+#endif /* MAC */
+
+ /* Read new directory entries. */
+ cookies = NULL;
+ ncookies = 0;
+ error = VOP_READDIR(vp, &readuio, fp->f_cred, &eof,
+ &ncookies, &cookies);
+ VOP_UNLOCK(vp, 0);
+ if (error != 0)
+ goto done;
+
+ /* Convert entries to CloudABI's format. */
+ readbuflen = MAXBSIZE - readuio.uio_resid;
+ bde = readbuf;
+ cookie = cookies;
+ while (readbuflen >= offsetof(struct dirent, d_name) &&
+ uio.uio_resid > 0 && ncookies > 0) {
+ /* Ensure that the returned offset always increases. */
+ if (readbuflen >= bde->d_reclen && bde->d_fileno != 0 &&
+ *cookie > offset) {
+ error = write_dirent(bde, *cookie, &uio);
+ if (error != 0) {
+ free(cookies, M_TEMP);
+ goto done;
+ }
+ }
+
+ if (offset < *cookie)
+ offset = *cookie;
+ ++cookie;
+ --ncookies;
+ readbuflen -= bde->d_reclen;
+ bde = (struct dirent *)((char *)bde + bde->d_reclen);
+ }
+ free(cookies, M_TEMP);
+ if (eof)
+ break;
+ }
+
+done:
+ fdrop(fp, td);
+ free(readbuf, M_TEMP);
+ if (error != 0)
+ return (error);
+
+ /* Return number of bytes copied to userspace. */
+ td->td_retval[0] = uap->nbyte - uio.uio_resid;
+ return (0);
}
int
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 30, 4:45 PM (3 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16338040
Default Alt Text
D3226.diff (4 KB)
Attached To
Mode
D3226: Implement CloudABI's readdir().
Attached
Detach File
Event Timeline
Log In to Comment