#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysmsg.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/vnode.h>
#include <sys/lock.h>
#include <sys/proc.h>
#include <sys/nlookup.h>
#include <sys/file.h>
#include <sys/sysent.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/acl.h>
static int vacl_set_acl(struct vnode *vp, acl_type_t type, struct acl *aclp);
static int vacl_get_acl(struct vnode *vp, acl_type_t type, struct acl *aclp);
static int vacl_aclcheck(struct vnode *vp, acl_type_t type, struct acl *aclp);
static int
vacl_set_acl(struct vnode *vp, acl_type_t type, struct acl *aclp)
{
struct thread *td = curthread;
struct acl inkernacl;
struct ucred *ucred;
int error;
error = copyin(aclp, &inkernacl, sizeof(struct acl));
if (error)
return(error);
ucred = td->td_ucred;
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_SETACL(vp, type, &inkernacl, ucred);
vn_unlock(vp);
return(error);
}
static int
vacl_get_acl(struct vnode *vp, acl_type_t type, struct acl *aclp)
{
struct thread *td = curthread;
struct acl inkernelacl;
struct ucred *ucred;
int error;
ucred = td->td_ucred;
error = VOP_GETACL(vp, type, &inkernelacl, ucred);
if (error == 0)
error = copyout(&inkernelacl, aclp, sizeof(struct acl));
return (error);
}
static int
vacl_delete(struct vnode *vp, acl_type_t type)
{
struct thread *td = curthread;
struct ucred *ucred;
int error;
ucred = td->td_ucred;
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_SETACL(vp, ACL_TYPE_DEFAULT, 0, ucred);
vn_unlock(vp);
return (error);
}
static int
vacl_aclcheck(struct vnode *vp, acl_type_t type, struct acl *aclp)
{
struct thread *td = curthread;
struct ucred *ucred;
struct acl inkernelacl;
int error;
ucred = td->td_ucred;
error = copyin(aclp, &inkernelacl, sizeof(struct acl));
if (error)
return(error);
error = VOP_ACLCHECK(vp, type, &inkernelacl, ucred);
return (error);
}
int
sys___acl_get_file(struct sysmsg *sysmsg,
const struct __acl_get_file_args *uap)
{
struct nlookupdata nd;
struct vnode *vp;
int error;
vp = NULL;
error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error == 0) {
error = vacl_get_acl(vp, uap->type, uap->aclp);
vrele(vp);
}
return (error);
}
int
sys___acl_set_file(struct sysmsg *sysmsg,
const struct __acl_set_file_args *uap)
{
struct nlookupdata nd;
struct vnode *vp;
int error;
vp = NULL;
error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error == 0) {
error = vacl_set_acl(vp, uap->type, uap->aclp);
vrele(vp);
}
return (error);
}
int
sys___acl_get_fd(struct sysmsg *sysmsg,
const struct __acl_get_fd_args *uap)
{
struct thread *td = curthread;
struct file *fp;
int error;
if ((error = holdvnode(td, uap->filedes, &fp)) != 0)
return(error);
error = vacl_get_acl((struct vnode *)fp->f_data, uap->type, uap->aclp);
fdrop(fp);
return (error);
}
int
sys___acl_set_fd(struct sysmsg *sysmsg,
const struct __acl_set_fd_args *uap)
{
struct thread *td = curthread;
struct file *fp;
int error;
if ((error = holdvnode(td, uap->filedes, &fp)) != 0)
return(error);
error = vacl_set_acl((struct vnode *)fp->f_data, uap->type, uap->aclp);
fdrop(fp);
return (error);
}
int
sys___acl_delete_file(struct sysmsg *sysmsg,
const struct __acl_delete_file_args *uap)
{
struct nlookupdata nd;
struct vnode *vp;
int error;
vp = NULL;
error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error == 0) {
error = vacl_delete(vp, uap->type);
vrele(vp);
}
return (error);
}
int
sys___acl_delete_fd(struct sysmsg *sysmsg,
const struct __acl_delete_fd_args *uap)
{
struct thread *td = curthread;
struct file *fp;
int error;
KKASSERT(td->td_proc);
if ((error = holdvnode(td, uap->filedes, &fp)) != 0)
return(error);
error = vacl_delete((struct vnode *)fp->f_data, uap->type);
fdrop(fp);
return (error);
}
int
sys___acl_aclcheck_file(struct sysmsg *sysmsg,
const struct __acl_aclcheck_file_args *uap)
{
struct nlookupdata nd;
struct vnode *vp;
int error;
vp = NULL;
error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
if (error == 0)
error = nlookup(&nd);
if (error == 0)
error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
nlookup_done(&nd);
if (error == 0) {
error = vacl_aclcheck(vp, uap->type, uap->aclp);
vrele(vp);
}
return (error);
}
int
sys___acl_aclcheck_fd(struct sysmsg *sysmsg,
const struct __acl_aclcheck_fd_args *uap)
{
struct thread *td = curthread;
struct file *fp;
int error;
KKASSERT(td->td_proc);
if ((error = holdvnode(td, uap->filedes, &fp)) != 0)
return(error);
error = vacl_aclcheck((struct vnode *)fp->f_data, uap->type, uap->aclp);
fdrop(fp);
return (error);
}