#include <sys/param.h>
#include <sys/types.h>
#include <sys/inttypes.h>
#include <sys/sysmacros.h>
#include <sys/cred.h>
#include <sys/user.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/proc.h>
#include <sys/uio.h>
#include <sys/debug.h>
#include <libfksmbfs.h>
#define set_errno(e) (-(e))
ssize_t
fake_pread(vnode_t *vp, void *cbuf, size_t count, off_t offset)
{
struct uio auio;
struct iovec aiov;
int fflag, ioflag, rwflag;
ssize_t bcount;
int error = 0;
u_offset_t fileoff = (u_offset_t)(ulong_t)offset;
const u_offset_t maxoff = MAXOFF32_T;
if ((bcount = (ssize_t)count) < 0)
return (set_errno(EINVAL));
fflag = FREAD;
rwflag = 0;
if (vp->v_type == VREG) {
if (bcount == 0)
goto out;
if (fileoff > maxoff) {
error = EINVAL;
goto out;
}
if (fileoff + bcount > maxoff)
bcount = (ssize_t)((offset_t)maxoff - fileoff);
} else if (vp->v_type == VFIFO) {
error = ESPIPE;
goto out;
}
aiov.iov_base = cbuf;
aiov.iov_len = bcount;
(void) VOP_RWLOCK(vp, rwflag, NULL);
auio.uio_loffset = fileoff;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_resid = bcount;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_llimit = MAXOFFSET_T;
auio.uio_fmode = fflag;
auio.uio_extflg = UIO_COPY_CACHED;
ioflag = auio.uio_fmode & (FAPPEND|FSYNC|FDSYNC|FRSYNC);
if ((ioflag & FRSYNC) == 0)
ioflag &= ~(FSYNC|FDSYNC);
error = VOP_READ(vp, &auio, ioflag, CRED(), NULL);
bcount -= auio.uio_resid;
VOP_RWUNLOCK(vp, rwflag, NULL);
if (error == EINTR && bcount != 0)
error = 0;
out:
if (error)
return (set_errno(error));
return (bcount);
}
ssize_t
fake_pwrite(vnode_t *vp, void *cbuf, size_t count, off_t offset)
{
struct uio auio;
struct iovec aiov;
int fflag, ioflag, rwflag;
ssize_t bcount;
int error = 0;
u_offset_t fileoff = (u_offset_t)(ulong_t)offset;
const u_offset_t maxoff = MAXOFF32_T;
if ((bcount = (ssize_t)count) < 0)
return (set_errno(EINVAL));
fflag = FREAD | FWRITE;
rwflag = 1;
if (vp->v_type == VREG) {
if (bcount == 0)
goto out;
if (fileoff > maxoff) {
error = EINVAL;
goto out;
}
if (fileoff == maxoff) {
error = EFBIG;
goto out;
}
if (fileoff + count > maxoff)
bcount = (ssize_t)((u_offset_t)maxoff - fileoff);
} else if (vp->v_type == VFIFO) {
error = ESPIPE;
goto out;
}
aiov.iov_base = cbuf;
aiov.iov_len = bcount;
(void) VOP_RWLOCK(vp, rwflag, NULL);
auio.uio_loffset = fileoff;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_resid = bcount;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_llimit = MAXOFFSET_T;
auio.uio_fmode = fflag;
auio.uio_extflg = UIO_COPY_CACHED;
ioflag = auio.uio_fmode & (FSYNC|FDSYNC|FRSYNC);
error = VOP_WRITE(vp, &auio, ioflag, CRED(), NULL);
bcount -= auio.uio_resid;
VOP_RWUNLOCK(vp, rwflag, NULL);
if (error == EINTR && bcount != 0)
error = 0;
out:
if (error)
return (set_errno(error));
return (bcount);
}