static int parse_dirfile(char *buf, size_t nbytes, struct file *file, void *dstbuf, filldir_t filldir) { while (nbytes >= FUSE_NAME_OFFSET) { struct fuse_dirent *dirent = (struct fuse_dirent *) buf; size_t reclen = FUSE_DIRENT_SIZE(dirent); int over; if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) return -EIO; if (reclen > nbytes) break; if (memchr(dirent->name, '/', dirent->namelen) != NULL) return -EIO; over = filldir(dstbuf, dirent->name, dirent->namelen, file->f_pos, dirent->ino, dirent->type); if (over) break; buf += reclen; nbytes -= reclen; file->f_pos = dirent->off; } return 0; }
static int parse_dirfile(char *buf, size_t nbytes, struct file *file, struct dir_context *ctx) { while (nbytes >= FUSE_NAME_OFFSET) { struct fuse_dirent *dirent = (struct fuse_dirent *) buf; size_t reclen = FUSE_DIRENT_SIZE(dirent); if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) return -EIO; if (reclen > nbytes) break; if (!dir_emit(ctx, dirent->name, dirent->namelen, dirent->ino, dirent->type)) break; buf += reclen; nbytes -= reclen; ctx->pos = dirent->off; } return 0; }
int fuse_internal_readdir_processdata(struct uio *uio, size_t reqsize, void *buf, size_t bufsize, void *param) { int err = 0; int cou = 0; int bytesavail; size_t freclen; struct dirent *de; struct fuse_dirent *fudge; struct fuse_iov *cookediov = param; if (bufsize < FUSE_NAME_OFFSET) { return -1; } for (;;) { if (bufsize < FUSE_NAME_OFFSET) { err = -1; break; } fudge = (struct fuse_dirent *)buf; freclen = FUSE_DIRENT_SIZE(fudge); cou++; if (bufsize < freclen) { err = ((cou == 1) ? -1 : 0); break; } #ifdef ZERO_PAD_INCOMPLETE_BUFS if (isbzero(buf, FUSE_NAME_OFFSET)) { err = -1; break; } #endif if (!fudge->namelen || fudge->namelen > MAXNAMLEN) { err = EINVAL; break; } bytesavail = GENERIC_DIRSIZ((struct pseudo_dirent *) &fudge->namelen); if (bytesavail > uio_resid(uio)) { err = -1; break; } fiov_refresh(cookediov); fiov_adjust(cookediov, bytesavail); de = (struct dirent *)cookediov->base; de->d_fileno = fudge->ino; /* XXX: truncation */ de->d_reclen = bytesavail; de->d_type = fudge->type; de->d_namlen = fudge->namelen; memcpy((char *)cookediov->base + sizeof(struct dirent) - MAXNAMLEN - 1, (char *)buf + FUSE_NAME_OFFSET, fudge->namelen); ((char *)cookediov->base)[bytesavail] = '\0'; err = uiomove(cookediov->base, cookediov->len, uio); if (err) { break; } buf = (char *)buf + freclen; bufsize -= freclen; uio_setoffset(uio, fudge->off); } return err; }
__private_extern__ int fuse_internal_readdir_processdata(vnode_t vp, uio_t uio, __unused size_t reqsize, void *buf, size_t bufsize, struct fuse_iov *cookediov, int *numdirent) { int err = 0; int cou = 0; int n = 0; size_t bytesavail; size_t freclen; struct dirent *de; struct fuse_dirent *fudge; if (bufsize < FUSE_NAME_OFFSET) { return -1; } for (;;) { if (bufsize < FUSE_NAME_OFFSET) { err = -1; break; } fudge = (struct fuse_dirent *)buf; freclen = FUSE_DIRENT_SIZE(fudge); cou++; if (bufsize < freclen) { err = ((cou == 1) ? -1 : 0); break; } /* * if (isbzero(buf, FUSE_NAME_OFFSET)) { * // zero-pad incomplete buffer * ... * err = -1; * break; * } */ if (!fudge->namelen) { err = EINVAL; break; } if (fudge->namelen > FUSE_MAXNAMLEN) { err = EIO; break; } #define GENERIC_DIRSIZ(dp) \ ((sizeof(struct dirent) - (FUSE_MAXNAMLEN + 1)) + \ (((dp)->d_namlen + 1 + 3) & ~3)) bytesavail = GENERIC_DIRSIZ((struct pseudo_dirent *)&fudge->namelen); if (bytesavail > (size_t)uio_resid(uio)) { err = -1; break; } fiov_refresh(cookediov); fiov_adjust(cookediov, bytesavail); de = (struct dirent *)cookediov->base; #if __DARWIN_64_BIT_INO_T de->d_fileno = fudge->ino; #else de->d_fileno = (ino_t)fudge->ino; /* XXX: truncation */ #endif /* __DARWIN_64_BIT_INO_T */ de->d_reclen = bytesavail; de->d_type = fudge->type; de->d_namlen = fudge->namelen; /* Filter out any ._* files if the mount is configured as such. */ if (fuse_skip_apple_double_mp(vnode_mount(vp), fudge->name, fudge->namelen)) { de->d_fileno = 0; de->d_type = DT_WHT; } memcpy((char *)cookediov->base + sizeof(struct dirent) - FUSE_MAXNAMLEN - 1, (char *)buf + FUSE_NAME_OFFSET, fudge->namelen); ((char *)cookediov->base)[bytesavail] = '\0'; err = uiomove(cookediov->base, (int)cookediov->len, uio); if (err) { break; } n++; buf = (char *)buf + freclen; bufsize -= freclen; uio_setoffset(uio, fudge->off); } if (!err && numdirent) { *numdirent = n; } return err; }