text:
/*	$NetBSD: kern_systrace.c,v 1.37.2.1 2004/04/16 22:29:57 jmc Exp $	*/

/*
 * Copyright 2002, 2003 Niels Provos <provos@citi.umich.edu>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by Niels Provos.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_systrace.c,v 1.37.2.1 2004/04/16 22:29:57 jmc Exp $");

#include "opt_systrace.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/tree.h>
#include <sys/malloc.h>
#include <sys/syscall.h>
#include <sys/vnode.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/filio.h>
#include <sys/signalvar.h>
#include <sys/lock.h>
#include <sys/pool.h>
#include <sys/mount.h>
#include <sys/poll.h>
#include <sys/ptrace.h>
#include <sys/namei.h>
#include <sys/systrace.h>
#include <sys/sa.h>
#include <sys/savar.h>

#include <compat/common/compat_util.h>

#ifdef __NetBSD__
#define	SYSTRACE_LOCK(fst, p)	lockmgr(&fst->lock, LK_EXCLUSIVE, NULL)
#define	SYSTRACE_UNLOCK(fst, p)	lockmgr(&fst->lock, LK_RELEASE, NULL)
#else
#define	SYSTRACE_LOCK(fst, p)	lockmgr(&fst->lock, LK_EXCLUSIVE, NULL, p)
#define	SYSTRACE_UNLOCK(fst, p)	lockmgr(&fst->lock, LK_RELEASE, NULL, p)
#endif
#ifndef	M_XDATA
MALLOC_DEFINE(M_SYSTR, "systrace", "systrace");
#define	M_XDATA		M_SYSTR
#endif

#ifdef __NetBSD__
dev_type_open(systraceopen);
#else
cdev_decl(systrace);
#endif

#ifdef __NetBSD__
int	systracef_read(struct file *, off_t *, struct uio *, struct ucred *,
		int);
int	systracef_write(struct file *, off_t *, struct uio *, struct ucred *,
		int);
int	systracef_fcntl(struct file *, u_int, void *, struct proc *);
int	systracef_poll(struct file *, int, struct proc *);
#else
int	systracef_read(struct file *, off_t *, struct uio *, struct ucred *);
int	systracef_write(struct file *, off_t *, struct uio *, struct ucred *);
int	systracef_select(struct file *, int, struct proc *);
#endif
int	systracef_kqfilter(struct file *, struct knote *);
int	systracef_ioctl(struct file *, u_long, void *, struct proc *);
int	systracef_stat(struct file *, struct stat *, struct proc *);
int	systracef_close(struct file *, struct proc *);

struct str_policy {
	TAILQ_ENTRY(str_policy) next;

	int nr;

	const struct emul *emul;	/* Is only valid for this emulation */

	int refcount;

	int nsysent;
	u_char *sysent;
};

#define STR_PROC_ONQUEUE	0x01
#define STR_PROC_WAITANSWER	0x02
#define STR_PROC_SYSCALLRES	0x04
#define STR_PROC_REPORT		0x08	/* Report emulation */
#define STR_PROC_NEEDSEQNR	0x10	/* Answer must quote seqnr */
#define STR_PROC_SETEUID	0x20	/* Elevate privileges */
#define STR_PROC_SETEGID	0x40
#define STR_PROC_DIDSETUGID	0x80

struct str_process {
	TAILQ_ENTRY(str_process) next;

	struct proc *proc;
	const struct emul *oldemul;
	uid_t olduid;
	gid_t oldgid;

	pid_t pid;

	struct fsystrace *parent;
	struct str_policy *policy;

	struct systrace_replace *replace;
	char *fname[SYSTR_MAXFNAME];
	size_t nfname;

	int flags;
	short answer;
	short error;
	u_int16_t seqnr;	/* expected reply sequence number */

	uid_t seteuid;
	uid_t saveuid;
	gid_t setegid;
	gid_t savegid;
};

uid_t	systrace_seteuid(struct proc *,  uid_t);
gid_t	systrace_setegid(struct proc *,  gid_t);
void systrace_lock(void);
void systrace_unlock(void);

/* Needs to be called with fst locked */

int	systrace_attach(struct fsystrace *, pid_t);
int	systrace_detach(struct str_process *);
int	systrace_answer(struct str_process *, struct systrace_answer *);
int	systrace_io(struct str_process *, struct systrace_io *);
int	systrace_policy(struct fsystrace *, struct systrace_policy *);
int	systrace_preprepl(struct str_process *, struct systrace_replace *);
int	systrace_replace(struct str_process *, size_t, register_t []);
int	systrace_getcwd(struct fsystrace *, struct str_process *);
int	systrace_fname(struct str_process *, caddr_t, size_t);
void	systrace_replacefree(struct str_process *);

int	systrace_processready(struct str_process *);
struct proc *systrace_find(struct str_process *);
struct str_process *systrace_findpid(struct fsystrace *fst, pid_t pid);
void	systrace_wakeup(struct fsystrace *);
void	systrace_closepolicy(struct fsystrace *, struct str_policy *);
int	systrace_insert_process(struct fsystrace *, struct proc *,
	    struct str_process **);
struct str_policy *systrace_newpolicy(struct fsystrace *, int);
int	systrace_msg_child(struct fsystrace *, struct str_process *, pid_t);
int	systrace_msg_policyfree(struct fsystrace *, struct str_policy *);
int	systrace_msg_ask(struct fsystrace *, struct str_process *,
	    int, size_t, register_t []);
int	systrace_msg_result(struct fsystrace *, struct str_process *,
	    int, int, size_t, register_t [], register_t []);
int	systrace_msg_emul(struct fsystrace *, struct str_process *);
int	systrace_msg_ugid(struct fsystrace *, struct str_process *);
int	systrace_make_msg(struct str_process *, int, struct str_message *);

static struct fileops systracefops = {
	systracef_read,
	systracef_write,
	systracef_ioctl,
#ifdef __NetBSD__
	systracef_fcntl,
	systracef_poll,
#else
	systracef_select,
	systracef_kqfilter,
#endif
	systracef_stat,
	systracef_close
#ifdef __NetBSD__
	, systracef_kqfilter
#endif
};

struct pool systr_proc_pl;
struct pool systr_policy_pl;
struct pool systr_msgcontainer_pl;

int systrace_debug = 0;
struct lock systrace_lck;

#ifdef __NetBSD__
const struct cdevsw systrace_cdevsw = {
	systraceopen, noclose, noread, nowrite, noioctl,
	nostop, notty, nopoll, nommap, nokqfilter,
};
#endif

#define DPRINTF(y)	if (systrace_debug) printf y;

/* ARGSUSED */
int
systracef_read(struct file *fp, off_t *poff, struct uio *uio,
    struct ucred *cred
#ifdef __NetBSD__
    , int flags
#endif
)
{
	struct fsystrace *fst = (struct fsystrace *)fp->f_data;
	struct str_msgcontainer *cont;
	int error = 0;

	if (uio->uio_resid != sizeof(struct str_message))
		return (EINVAL);

 again:
	systrace_lock();
	SYSTRACE_LOCK(fst, curlwp);
	systrace_unlock();
	if ((cont = TAILQ_FIRST(&fst->messages)) != NULL) {
		error = uiomove((caddr_t)&cont->msg,
		    sizeof(struct str_message), uio);
		if (!error) {
			TAILQ_REMOVE(&fst->messages, cont, next);
			if (!SYSTR_MSG_NOPROCESS(cont))
				CLR(cont->strp->flags, STR_PROC_ONQUEUE);
			pool_put(&systr_msgcontainer_pl, cont);

		}
	} else if (TAILQ_FIRST(&fst->processes) == NULL) {
		/* EOF situation */
		;
	} else {
		if (fp->f_flag & FNONBLOCK)
			error = EAGAIN;
		else {
			SYSTRACE_UNLOCK(fst, curlwp);
			error = tsleep(fst, PWAIT|PCATCH, "systrrd", 0);
			if (error)
				goto out;
			goto again;
		}

	}

	SYSTRACE_UNLOCK(fst, curlwp);
 out:
	return (error);
}

/* ARGSUSED */
int
systracef_write(struct file *fp, off_t *poff, struct uio *uio,
    struct ucred *cred
#ifdef __NetBSD__
    , int flags
#endif
)
{
	return (EIO);
}

#define POLICY_VALID(x)	((x) == SYSTR_POLICY_PERMIT || \
			 (x) == SYSTR_POLICY_ASK || \
			 (x) == SYSTR_POLICY_NEVER)

/* ARGSUSED */
int
systracef_ioctl(struct file *fp, u_long cmd, void *data, struct proc *p)
{
	int ret = 0;
	struct fsystrace *fst = (struct fsystrace *)fp->f_data;
#ifdef __NetBSD__
	struct cwdinfo *cwdp;
#else
	struct filedesc *fdp;
#endif
	struct str_process *strp = NULL;
	pid_t pid = 0;

	switch (cmd) {
	case FIONBIO:
	case FIOASYNC:
		return (0);

	case STRIOCDETACH:
	case STRIOCREPORT:
		pid = *(pid_t *)data;
		if (!pid)
			ret = EINVAL;
		break;
	case STRIOCANSWER:
		pid = ((struct systrace_answer *)data)->stra_pid;
		if (!pid)
			ret = EINVAL;
		break;
	case STRIOCIO:
		pid = ((struct systrace_io *)data)->strio_pid;
		if (!pid)
			ret = EINVAL;
		break;
	case STRIOCGETCWD:
		pid = *(pid_t *)data;
		if (!pid)
			ret = EINVAL;
		break;
	case STRIOCATTACH:
	case STRIOCRESCWD:
	case STRIOCPOLICY:
		break;
	case STRIOCREPLACE:
		pid = ((struct systrace_replace *)data)->strr_pid;
		if (!pid)
			ret = EINVAL;
		break;
	default:
		ret = EINVAL;
		break;
	}

	if (ret)
		return (ret);

	systrace_lock();
	SYSTRACE_LOCK(fst, curlwp);
	systrace_unlock();
	if (pid) {
		strp = systrace_findpid(fst, pid);
		if (strp == NULL) {
			ret = ESRCH;
			goto unlock;
		}
	}

	switch (cmd) {
	case STRIOCATTACH:
		pid = *(pid_t *)data;
		if (!pid)
			ret = EINVAL;
		else
			ret = systrace_attach(fst, pid);
		DPRINTF(("%s: attach to %u: %d\n", __func__, pid, ret));
		break;
	case STRIOCDETACH:
		ret = systrace_detach(strp);
		break;
	case STRIOCREPORT:
		SET(strp->flags, STR_PROC_REPORT);
		break;
	case STRIOCANSWER:
		ret = systrace_answer(strp, (struct systrace_answer *)data);
		break;
	case STRIOCIO:
		ret = systrace_io(strp, (struct systrace_io *)data);
		break;
	case STRIOCPOLICY:
		ret = systrace_policy(fst, (struct systrace_policy *)data);
		break;
	case STRIOCREPLACE:
		ret = systrace_preprepl(strp, (struct systrace_replace *)data);
		break;
	case STRIOCRESCWD:
		if (!fst->fd_pid) {
			ret = EINVAL;
			break;
		}
#ifdef __NetBSD__
		cwdp = p->p_cwdi;

		/* Release cwd from other process */
		if (cwdp->cwdi_cdir)
			vrele(cwdp->cwdi_cdir);
		if (cwdp->cwdi_rdir)
			vrele(cwdp->cwdi_rdir);
		cwdp->cwdi_cdir = fst->fd_cdir;
		cwdp->cwdi_rdir = fst->fd_rdir;
#else
		fdp = p->p_fd;

		/* Release cwd from other process */
		if (fdp->fd_cdir)
			vrele(fdp->fd_cdir);
		if (fdp->fd_rdir)
			vrele(fdp->fd_rdir);
		/* This restores the cwd we had before */
		fdp->fd_cdir = fst->fd_cdir;
		fdp->fd_rdir = fst->fd_rdir;
#endif
		/* Note that we are normal again */
		fst->fd_pid = 0;
		fst->fd_cdir = fst->fd_rdir = NULL;
		break;
	case STRIOCGETCWD:
		ret = systrace_getcwd(fst, strp);
		break;
	default:
		ret = EINVAL;
		break;
	}

 unlock:
	SYSTRACE_UNLOCK(fst, curlwp);

	return (ret);
}

#ifdef __NetBSD__
/* ARGSUSED */
int
systracef_fcntl(struct file *fp, u_int cmd, void *data, struct proc *p)
{

	if (cmd == FNONBLOCK || cmd == FASYNC)
		return 0;

	return (EOPNOTSUPP);
}
#endif

#ifdef __NetBSD__
int
systracef_poll(struct file *fp, int events, struct proc *p)
{
	struct fsystrace *fst = (struct fsystrace *)fp->f_data;
	int revents = 0;

	if ((events & (POLLIN | POLLRDNORM)) == 0)
		return (revents);

	systrace_lock();
	SYSTRACE_LOCK(fst, p);
	systrace_unlock();
	if (!TAILQ_EMPTY(&fst->messages))
		revents |= events & (POLLIN | POLLRDNORM);
	if (revents == 0)
		selrecord(p, &fst->si);
	SYSTRACE_UNLOCK(fst, p);

	return (revents);
}
#else
int
systracef_select(struct file *fp, int which, struct proc *p)
{
	struct fsystrace *fst = (struct fsystrace *)fp->f_data;
	int ready = 0;

	if (which != FREAD)
		return (0);

	systrace_lock();
	SYSTRACE_LOCK(fst, p);
	systrace_unlock();
	ready = TAILQ_FIRST(&fst->messages) != NULL;
	if (!ready)
		selrecord(p, &fst->si);
	SYSTRACE_UNLOCK(fst, p);

	return (ready);
}
#endif /* __NetBSD__ */

/* ARGSUSED */
int
systracef_kqfilter(struct file *fp, struct knote *kn)
{
	return (1);
}

/* ARGSUSED */
int
systracef_stat(struct file *fp, struct stat *sb, struct proc *p)
{
	return (EOPNOTSUPP);
}

/* ARGSUSED */
int
systracef_close(struct file *fp, struct proc *p)
{
	struct fsystrace *fst = (struct fsystrace *)fp->f_data;
	struct str_process *strp;
	struct str_msgcontainer *cont;
	struct str_policy *strpol;

	systrace_lock();
	SYSTRACE_LOCK(fst, curlwp);
	systrace_unlock();

	/* Untrace all processes */
	for (strp = TAILQ_FIRST(&fst->processes); strp;
	    strp = TAILQ_FIRST(&fst->processes)) {
		struct proc *q = strp->proc;

		systrace_detach(strp);
		psignal(q, SIGKILL);
	}

	/* Clean up fork and exit messages */
	for (cont = TAILQ_FIRST(&fst->messages); cont;
	    cont = TAILQ_FIRST(&fst->messages)) {
		TAILQ_REMOVE(&fst->messages, cont, next);
		pool_put(&systr_msgcontainer_pl, cont);
	}

	/* Clean up all policies */
	for (strpol = TAILQ_FIRST(&fst->policies); strpol;
	    strpol = TAILQ_FIRST(&fst->policies))
		systrace_closepolicy(fst, strpol);

	/* Release vnodes */
	if (fst->fd_cdir)
		vrele(fst->fd_cdir);
	if (fst->fd_rdir)
		vrele(fst->fd_rdir);
	SYSTRACE_UNLOCK(fst, curlwp);

	FREE(fp->f_data, M_XDATA);
	fp->f_data = NULL;

	return (0);
}

void
systrace_lock(void)
{
#ifdef __NetBSD__
	lockmgr(&systrace_lck, LK_EXCLUSIVE, NULL);
#else
	lockmgr(&systrace_lck, LK_EXCLUSIVE, NULL, curlwp);
#endif
}

void
systrace_unlock(void)
{
#ifdef __NetBSD__
	lockmgr(&systrace_lck, LK_RELEASE, NULL);
#else
	lockmgr(&systrace_lck, LK_RELEASE, NULL, curlwp);
#endif
}

void
systrace_init(void)
{
	pool_init(&systr_proc_pl, sizeof(struct str_process), 0, 0, 0,
	    "strprocpl", NULL);
	pool_init(&systr_policy_pl, sizeof(struct str_policy), 0, 0, 0,
	    "strpolpl", NULL);
	pool_init(&systr_msgcontainer_pl, sizeof(struct str_msgcontainer),
	    0, 0, 0, "strmsgpl", NULL);
	lockinit(&systrace_lck, PLOCK, "systrace", 0, 0);
}

int
systraceopen(dev_t dev, int flag, int mode, struct proc *p)
{
	struct fsystrace *fst;
	struct file *fp;
	int error, fd;

	/* falloc() will use the descriptor for us. */
	if ((error = falloc(p, &fp, &fd)) != 0)
		return (error);

	MALLOC(fst, struct fsystrace *, sizeof(*fst), M_XDATA, M_WAITOK);

	memset(fst, 0, sizeof(struct fsystrace));
	lockinit(&fst->lock, PLOCK, "systrace", 0, 0);

	TAILQ_INIT(&fst->processes);
	TAILQ_INIT(&fst->messages);
	TAILQ_INIT(&fst->policies);

	if (suser(p->p_ucred, &p->p_acflag) == 0)
		fst->issuser = 1;
	fst->p_ruid = p->p_cred->p_ruid;
	fst->p_rgid = p->p_cred->p_rgid;

	fp->f_flag = FREAD | FWRITE;
	fp->f_type = DTYPE_MISC;
	fp->f_ops = &systracefops;
	fp->f_data = (caddr_t) fst;

	curlwp->l_dupfd = fd;	/* XXX */
	FILE_SET_MATURE(fp);
	FILE_UNUSE(fp, p);

	return (ENXIO);
}

void
systrace_wakeup(struct fsystrace *fst)
{
	wakeup((caddr_t)fst);
	selwakeup(&fst->si);
}

struct proc *
systrace_find(struct str_process *strp)
{
	struct proc *proc;

	if ((proc = pfind(strp->pid)) == NULL)
		return (NULL);

	if (proc != strp->proc)
		return (NULL);

	if (!ISSET(proc->p_flag, P_SYSTRACE))
		return (NULL);

	return (proc);
}

void
systrace_sys_exit(struct proc *proc)
{
	struct str_process *strp;
	struct fsystrace *fst;

	systrace_lock();
	strp = proc->p_systrace;
	if (strp != NULL) {
		fst = strp->parent;
		SYSTRACE_LOCK(fst, curlwp);
		systrace_unlock();

		/* Insert Exit message */
		systrace_msg_child(fst, strp, -1);

		systrace_detach(strp);
		SYSTRACE_UNLOCK(fst, curlwp);
	} else
		systrace_unlock();
	CLR(proc->p_flag, P_SYSTRACE);
}

void
systrace_sys_fork(struct proc *oldproc, struct proc *p)
{
	struct str_process *oldstrp, *strp;
	struct fsystrace *fst;

	systrace_lock();
	oldstrp = oldproc->p_systrace;
	if (oldstrp == NULL) {
		systrace_unlock();
		return;
	}

	fst = oldstrp->parent;
	SYSTRACE_LOCK(fst, curlwp);
	systrace_unlock();

	if (systrace_insert_process(fst, p, &strp)) {
		/* We need to kill the child */
		psignal(p, SIGKILL);
		goto out;
	}

	/* Reference policy */
	if ((strp->policy = oldstrp->policy) != NULL)
		strp->policy->refcount++;

	/* Insert fork message */
	systrace_msg_child(fst, oldstrp, p->p_pid);
 out:
	SYSTRACE_UNLOCK(fst, curlwp);
}

int
systrace_enter(struct proc *p, register_t code, void *v)
{
	const struct sysent *callp;
	struct str_process *strp;
	struct str_policy *strpolicy;
	struct fsystrace *fst;
	struct pcred *pc;
	int policy, error = 0, maycontrol = 0, issuser = 0;
	size_t argsize;

	systrace_lock();
	strp = p->p_systrace;
	if (strp == NULL) {
		systrace_unlock();
		return (EINVAL);
	}

	KASSERT(strp->proc == p);

	fst = strp->parent;

	SYSTRACE_LOCK(fst, p);
	systrace_unlock();

	/*
	 * We can not monitor a SUID process unless we are root,
	 * but we wait until it executes something unprivileged.
	 * A non-root user may only monitor if the real uid and
	 * real gid match the monitored process.  Changing the
	 * uid or gid causes P_SUGID to be set.
	 */
	if (fst->issuser) {
		maycontrol = 1;
		issuser = 1;
	} else if (!(p->p_flag & P_SUGID)) {
		maycontrol = fst->p_ruid == p->p_cred->p_ruid &&
		    fst->p_rgid == p->p_cred->p_rgid;
	}

	if (!maycontrol) {
		policy = SYSTR_POLICY_PERMIT;
	} else {
		/* Find out current policy */
		if ((strpolicy = strp->policy) == NULL)
			policy = SYSTR_POLICY_ASK;
		else {
			if (code >= strpolicy->nsysent)
				policy = SYSTR_POLICY_NEVER;
			else
				policy = strpolicy->sysent[code];
		}
	}

	callp = p->p_emul->e_sysent + code;

	/* Fast-path */
	if (policy != SYSTR_POLICY_ASK) {
		if (policy != SYSTR_POLICY_PERMIT) {
			if (policy > 0)
				error = policy;
			else
				error = EPERM;
		}
		strp->oldemul = NULL;
		systrace_replacefree(strp);
		SYSTRACE_UNLOCK(fst, p);
		return (error);
	}

	/* Get the (adjusted) argsize */
	argsize = callp->sy_argsize;
#ifdef _LP64
	if (p->p_flag & P_32)
		argsize = argsize << 1;
#endif

	/* Puts the current process to sleep, return unlocked */
	error = systrace_msg_ask(fst, strp, code, argsize, v);

	/* lock has been released in systrace_msg_ask() */
	fst = NULL;
	/* We might have detached by now for some reason */
	if (!error && (strp = p->p_systrace) != NULL) {
		/* XXX - do I need to lock here? */
		if (strp->answer == SYSTR_POLICY_NEVER) {
			error = strp->error;
			systrace_replacefree(strp);
		} else {
			if (ISSET(strp->flags, STR_PROC_SYSCALLRES)) {
#ifndef __NetBSD__
				CLR(strp->flags, STR_PROC_SYSCALLRES);
#endif
			}
			/* Replace the arguments if necessary */
			if (strp->replace != NULL) {
				error = systrace_replace(strp, argsize, v);
			}
		}
	}

	systrace_lock();
	if ((strp = p->p_systrace) == NULL)
		goto out;

	if (error) {
		strp->oldemul = NULL;
		goto out;
	}

	pc = p->p_cred;
	strp->oldemul = p->p_emul;
	strp->olduid = pc->p_ruid;
	strp->oldgid = pc->p_rgid;

	/* Elevate privileges as desired */
	if (issuser) {
		if (ISSET(strp->flags, STR_PROC_SETEUID)) {
			strp->saveuid = systrace_seteuid(p, strp->seteuid);
			SET(strp->flags, STR_PROC_DIDSETUGID);
		}
		if (ISSET(strp->flags, STR_PROC_SETEGID)) {
			strp->savegid = systrace_setegid(p, strp->setegid);
			SET(strp->flags, STR_PROC_DIDSETUGID);
		}
	} else
		CLR(strp->flags,
		    STR_PROC_SETEUID|STR_PROC_SETEGID|STR_PROC_DIDSETUGID);

 out:
	systrace_unlock();
	return (error);
}

void
systrace_exit(struct proc *p, register_t code, void *v, register_t retval[],
    int error)
{
	const struct sysent *callp;
	struct str_process *strp;
	struct fsystrace *fst;
	struct pcred *pc;

	/* Report change in emulation */
	systrace_lock();
	strp = p->p_systrace;
	if (strp == NULL || strp->oldemul == NULL) {
		systrace_unlock();
		return;
	}
	DPRINTF(("exit syscall %lu, oldemul %p\n", (u_long)code, strp->oldemul));

	/* Return to old privileges */
	pc = p->p_cred;
	if (ISSET(strp->flags, STR_PROC_DIDSETUGID)) {
		if (ISSET(strp->flags, STR_PROC_SETEUID)) {
			if (pc->pc_ucred->cr_uid == strp->seteuid)
				systrace_seteuid(p, strp->saveuid);
		}
		if (ISSET(strp->flags, STR_PROC_SETEGID)) {
			if (pc->pc_ucred->cr_gid == strp->setegid)
				systrace_setegid(p, strp->savegid);
		}
	}
	CLR(strp->flags,
	    STR_PROC_SETEUID|STR_PROC_SETEGID|STR_PROC_DIDSETUGID);

	systrace_replacefree(strp);

	if (p->p_flag & P_SUGID) {
		if ((fst = strp->parent) == NULL || !fst->issuser) {
			systrace_unlock();
			return;
		}
	}

	/* See if we should force a report */
	if (ISSET(strp->flags, STR_PROC_REPORT)) {
		CLR(strp->flags, STR_PROC_REPORT);
		strp->oldemul = NULL;
	}

	if (p->p_emul != strp->oldemul && strp != NULL) {
		fst = strp->parent;
		SYSTRACE_LOCK(fst, p);
		systrace_unlock();

		/* Old policy is without meaning now */
		if (strp->policy) {
			systrace_closepolicy(fst, strp->policy);
			strp->policy = NULL;
		}
		systrace_msg_emul(fst, strp);
	} else
		systrace_unlock();

	/* Report if effective uid or gid changed */
	systrace_lock();
	strp = p->p_systrace;
	if (strp != NULL && (strp->olduid != p->p_cred->p_ruid ||
	    strp->oldgid != p->p_cred->p_rgid)) {

		fst = strp->parent;
		SYSTRACE_LOCK(fst, p);
		systrace_unlock();

		systrace_msg_ugid(fst, strp);
	} else
		systrace_unlock();

	/* Report result from system call */
	systrace_lock();
	strp = p->p_systrace;
	if (strp != NULL && ISSET(strp->flags, STR_PROC_SYSCALLRES)) {
		size_t argsize;

		CLR(strp->flags, STR_PROC_SYSCALLRES);
		fst = strp->parent;
		SYSTRACE_LOCK(fst, p);
		systrace_unlock();
		DPRINTF(("will ask syscall %lu, strp %p\n", (u_long)code, strp));

		/* Get the (adjusted) argsize */
		callp = p->p_emul->e_sysent + code;
		argsize = callp->sy_argsize;
#ifdef _LP64
		if (p->p_flag & P_32)
			argsize = argsize << 1;
#endif

		systrace_msg_result(fst, strp, error, code, argsize, v, retval);
	} else {
		DPRINTF(("will not ask syscall %lu, strp %p\n", (u_long)code, strp));
		systrace_unlock();
	}
}

uid_t
systrace_seteuid(struct proc *p,  uid_t euid)
{
	struct pcred *pc = p->p_cred;
	uid_t oeuid = pc->pc_ucred->cr_uid;

	if (pc->pc_ucred->cr_uid == euid)
		return (oeuid);

	/*
	 * Copy credentials so other references do not see our changes.
	 */
	pc->pc_ucred = crcopy(pc->pc_ucred);
	pc->pc_ucred->cr_uid = euid;
	p_sugid(p);

	return (oeuid);
}

gid_t
systrace_setegid(struct proc *p,  gid_t egid)
{
	struct pcred *pc = p->p_cred;
	gid_t oegid = pc->pc_ucred->cr_gid;

	if (pc->pc_ucred->cr_gid == egid)
		return (oegid);

	/*
	 * Copy credentials so other references do not see our changes.
	 */
	pc->pc_ucred = crcopy(pc->pc_ucred);
	pc->pc_ucred->cr_gid = egid;
	p_sugid(p);

	return (oegid);
}

/* Called with fst locked */

int
systrace_answer(struct str_process *strp, struct systrace_answer *ans)
{
	int error = 0;

	DPRINTF(("%s: %u: policy %d\n", __func__,
	    ans->stra_pid, ans->stra_policy));

	if (!POLICY_VALID(ans->stra_policy)) {
		error = EINVAL;
		goto out;
	}

	/* Check if answer is in sync with us */
	if (ans->stra_seqnr != strp->seqnr) {
		error = ESRCH;
		goto out;
	}

	if ((error = systrace_processready(strp)) != 0)
		goto out;

	strp->answer = ans->stra_policy;
	strp->error = ans->stra_error;
	if (!strp->error)
		strp->error = EPERM;
	if (ISSET(ans->stra_flags, SYSTR_FLAGS_RESULT))
		SET(strp->flags, STR_PROC_SYSCALLRES);

	/* See if we should elevate privileges for this system call */
	if (ISSET(ans->stra_flags, SYSTR_FLAGS_SETEUID)) {
		SET(strp->flags, STR_PROC_SETEUID);
		strp->seteuid = ans->stra_seteuid;
	}
	if (ISSET(ans->stra_flags, SYSTR_FLAGS_SETEGID)) {
		SET(strp->flags, STR_PROC_SETEGID);
		strp->setegid = ans->stra_setegid;
	}

	/* Clearing the flag indicates to the process that it woke up */
	CLR(strp->flags, STR_PROC_WAITANSWER);
	wakeup(strp);
 out:

	return (error);
}

int
systrace_policy(struct fsystrace *fst, struct systrace_policy *pol)
{
	struct str_policy *strpol;
	struct str_process *strp;

	switch(pol->strp_op) {
	case SYSTR_POLICY_NEW:
		DPRINTF(("%s: new, ents %d\n", __func__,
			    pol->strp_maxents));
		if (pol->strp_maxents <= 0 || pol->strp_maxents > 1024)
			return (EINVAL);
		strpol = systrace_newpolicy(fst, pol->strp_maxents);
		if (strpol == NULL)
			return (ENOBUFS);
		pol->strp_num = strpol->nr;
		break;
	case SYSTR_POLICY_ASSIGN:
		DPRINTF(("%s: %d -> pid %d\n", __func__,
			    pol->strp_num, pol->strp_pid));

		/* Find right policy by number */
		TAILQ_FOREACH(strpol, &fst->policies, next)
		    if (strpol->nr == pol->strp_num)
			    break;
		if (strpol == NULL)
			return (EINVAL);

		strp = systrace_findpid(fst, pol->strp_pid);
		if (strp == NULL)
			return (EINVAL);

		/* Check that emulation matches */
		if (strpol->emul && strpol->emul != strp->proc->p_emul)
			return (EINVAL);

		if (strp->policy)
			systrace_closepolicy(fst, strp->policy);
		strp->policy = strpol;
		strpol->refcount++;

		/* Record emulation for this policy */
		if (strpol->emul == NULL)
			strpol->emul = strp->proc->p_emul;

		break;
	case SYSTR_POLICY_MODIFY:
		DPRINTF(("%s: %d: code %d -> policy %d\n", __func__,
		    pol->strp_num, pol->strp_code, pol->strp_policy));
		if (!POLICY_VALID(pol->strp_policy))
			return (EINVAL);
		TAILQ_FOREACH(strpol, &fst->policies, next)
		    if (strpol->nr == pol->strp_num)
			    break;
		if (strpol == NULL)
			return (EINVAL);
		if (pol->strp_code < 0 || pol->strp_code >= strpol->nsysent)
			return (EINVAL);
		strpol->sysent[pol->strp_code] = pol->strp_policy;
		break;
	default:
		return (EINVAL);
	}

	return (0);
}

int
systrace_processready(struct str_process *strp)
{
	if (ISSET(strp->flags, STR_PROC_ONQUEUE))
		return (EBUSY);

	if (!ISSET(strp->flags, STR_PROC_WAITANSWER))
		return (EBUSY);

	/* XXX - ignore until systrace knows about lwps. :-(
	if (strp->proc->p_stat != LSSLEEP)
		return (EBUSY);
	*/
	return (0);
}

int
systrace_getcwd(struct fsystrace *fst, struct str_process *strp)
{
#ifdef __NetBSD__
	struct cwdinfo *mycwdp, *cwdp;
#else
	struct filedesc *myfdp, *fdp;
#endif
	int error;

	DPRINTF(("%s: %d\n", __func__, strp->pid));

	error = systrace_processready(strp);
	if (error)
		return (error);

#ifdef __NetBSD__
	mycwdp = curproc->p_cwdi;
	cwdp = strp->proc->p_cwdi;
	if (mycwdp == NULL || cwdp == NULL)
		return (EINVAL);

	/* Store our current values */
	fst->fd_pid = strp->pid;
	fst->fd_cdir = mycwdp->cwdi_cdir;
	fst->fd_rdir = mycwdp->cwdi_rdir;

	if ((mycwdp->cwdi_cdir = cwdp->cwdi_cdir) != NULL)
		VREF(mycwdp->cwdi_cdir);
	if ((mycwdp->cwdi_rdir = cwdp->cwdi_rdir) != NULL)
		VREF(mycwdp->cwdi_rdir);
#else
	myfdp = curlwp->p_fd;
	fdp = strp->proc->p_fd;
	if (myfdp == NULL || fdp == NULL)
		return (EINVAL);

	/* Store our current values */
	fst->fd_pid = strp->pid;
	fst->fd_cdir = myfdp->fd_cdir;
	fst->fd_rdir = myfdp->fd_rdir;

	if ((myfdp->fd_cdir = fdp->fd_cdir) != NULL)
		VREF(myfdp->fd_cdir);
	if ((myfdp->fd_rdir = fdp->fd_rdir) != NULL)
		VREF(myfdp->fd_rdir);
#endif

	return (0);
}

int
systrace_io(struct str_process *strp, struct systrace_io *io)
{
	struct proc *p = curproc, *t = strp->proc;
	struct uio uio;
	struct iovec iov;
	int error = 0;

	DPRINTF(("%s: %u: %p(%lu)\n", __func__,
	    io->strio_pid, io->strio_offs, (u_long)io->strio_len));

	switch (io->strio_op) {
	case SYSTR_READ:
		uio.uio_rw = UIO_READ;
		break;
	case SYSTR_WRITE:
		uio.uio_rw = UIO_WRITE;
		break;
	default:
		return (EINVAL);
	}

	error = systrace_processready(strp);
	if (error)
		goto out;

	iov.iov_base = io->strio_addr;
	iov.iov_len = io->strio_len;
	uio.uio_iov = &iov;
	uio.uio_iovcnt = 1;
	uio.uio_offset = (off_t)(long)io->strio_offs;
	uio.uio_resid = io->strio_len;
	uio.uio_segflg = UIO_USERSPACE;
	uio.uio_procp = p;

#ifdef __NetBSD__
	error = process_domem(p, t, &uio);
#else
	error = procfs_domem(p, t, NULL, &uio);
#endif
	io->strio_len -= uio.uio_resid;
 out:

	return (error);
}

int
systrace_attach(struct fsystrace *fst, pid_t pid)
{
	int error = 0;
	struct proc *proc, *p = curproc;

	if ((proc = pfind(pid)) == NULL) {
		error = ESRCH;
		goto out;
	}

	if (ISSET(proc->p_flag, P_INEXEC)) {
		error = EAGAIN;
		goto out;
	}

	/*
	 * You can't attach to a process if:
	 *	(1) it's the process that's doing the attaching,
	 */
	if (proc->p_pid == p->p_pid) {
		error = EINVAL;
		goto out;
	}

	/*
	 *	(2) it's a system process
	 */
	if (ISSET(proc->p_flag, P_SYSTEM)) {
		error = EPERM;
		goto out;
	}

	/*
	 *	(3) it's being traced already
	 */
	if (ISSET(proc->p_flag, P_SYSTRACE)) {
		error = EBUSY;
		goto out;
	}

	/*
	 *	(4) it's not owned by you, or the last exec
	 *	    gave us setuid/setgid privs (unless
	 *	    you're root), or...
	 *
	 *      [Note: once P_SUGID gets set in execve(), it stays
	 *	set until the process does another execve(). Hence
	 *	this prevents a setuid process which revokes its
	 *	special privileges using setuid() from being
	 *	traced. This is good security.]
	 */
	if ((proc->p_cred->p_ruid != p->p_cred->p_ruid ||
		ISSET(proc->p_flag, P_SUGID)) &&
	    (error = suser(p->p_ucred, &p->p_acflag)) != 0)
		goto out;

	/*
	 *	(5) ...it's init, which controls the security level
	 *	    of the entire system, and the system was not
	 *          compiled with permanently insecure mode turned
	 *	    on.
	 */
	if ((proc->p_pid == 1) && (securelevel > -1)) {
		error = EPERM;
		goto out;
	}

	error = systrace_insert_process(fst, proc, NULL);

#if defined(__NetBSD__) && defined(__HAVE_SYSCALL_INTERN)
	/*
	 * Make sure we're using the version of the syscall handler that
	 * has systrace hooks.
	 */
	if (!error)
		(*proc->p_emul->e_syscall_intern)(proc);
#endif
 out:
	return (error);
}

/* Prepare to replace arguments */

int
systrace_preprepl(struct str_process *strp, struct systrace_replace *repl)
{
	size_t len;
	int i, ret = 0;

	ret = systrace_processready(strp);
	if (ret)
		return (ret);

	systrace_replacefree(strp);

	if (repl->strr_nrepl < 0 || repl->strr_nrepl > SYSTR_MAXARGS)
		return (EINVAL);

	for (i = 0, len = 0; i < repl->strr_nrepl; i++) {
		len += repl->strr_offlen[i];
		if (repl->strr_offlen[i] == 0)
			continue;
		if (repl->strr_offlen[i] + repl->strr_off[i] > len)
			return (EINVAL);
	}

	/* Make sure that the length adds up */
	if (repl->strr_len != len)
		return (EINVAL);

	/* Check against a maximum length */
	if (repl->strr_len > 2048)
		return (EINVAL);

	strp->replace = (struct systrace_replace *)
	    malloc(sizeof(struct systrace_replace) + len, M_XDATA, M_WAITOK);

	memcpy(strp->replace, repl, sizeof(struct systrace_replace));
	ret = copyin(repl->strr_base, strp->replace + 1, len);
	if (ret) {
		free(strp->replace, M_XDATA);
		strp->replace = NULL;
		return (ret);
	}

	/* Adjust the offset */
	repl = strp->replace;
	repl->strr_base = (caddr_t)(repl + 1);

	return (0);
}

/*
 * Replace the arguments with arguments from the monitoring process.
 */

int
systrace_replace(struct str_process *strp, size_t argsize, register_t args[])
{
	struct proc *p = strp->proc;
	struct systrace_replace *repl = strp->replace;
	caddr_t sg, kdata, udata, kbase, ubase;
	int i, maxarg, ind, ret = 0;

	maxarg = argsize/sizeof(register_t);
#ifdef __NetBSD__
	sg = stackgap_init(p, 0);
	ubase = stackgap_alloc(p, &sg, repl->strr_len);
#else
	sg = stackgap_init(p->p_emul);
	ubase = stackgap_alloc(&sg, repl->strr_len);
#endif

	kbase = repl->strr_base;
	for (i = 0; i < maxarg && i < repl->strr_nrepl; i++) {
		ind = repl->strr_argind[i];
		if (ind < 0 || ind >= maxarg) {
			ret = EINVAL;
			goto out;
		}
		if (repl->strr_offlen[i] == 0) {
			args[ind] = repl->strr_off[i];
			continue;
		}
		kdata = kbase + repl->strr_off[i];
		udata = ubase + repl->strr_off[i];
		if (repl->strr_flags[i] & SYSTR_NOLINKS) {
			ret = systrace_fname(strp, kdata, repl->strr_offlen[i]);
			if (ret != 0)
				goto out;
		}
		if (copyout(kdata, udata, repl->strr_offlen[i])) {
			ret = EINVAL;
			goto out;
		}

		/* Replace the argument with the new address */
		args[ind] = (register_t)(intptr_t)udata;
	}

 out:
	return (ret);
}

int
systrace_fname(struct str_process *strp, caddr_t kdata, size_t len)
{

	if (strp->nfname >= SYSTR_MAXFNAME || len < 2)
		return EINVAL;

	strp->fname[strp->nfname] = kdata;
	strp->fname[strp->nfname][len - 1] = '\0';
	strp->nfname++;

	return 0;
}

void
systrace_replacefree(struct str_process *strp)
{

	if (strp->replace != NULL) {
		free(strp->replace, M_XDATA);
		strp->replace = NULL;
	}
	while (strp->nfname > 0) {
		strp->nfname--;
		strp->fname[strp->nfname] = NULL;
	}
}

void
systrace_namei(struct nameidata *ndp)
{
	struct str_process *strp;
	struct fsystrace *fst;
	struct componentname *cnp = &ndp->ni_cnd;
	size_t i;

	systrace_lock();
	strp = cnp->cn_proc->p_systrace;
	if (strp != NULL) {
		fst = strp->parent;
		SYSTRACE_LOCK(fst, curlwp);
		systrace_unlock();

		for (i = 0; i < strp->nfname; i++) {
			if (strcmp(cnp->cn_pnbuf, strp->fname[i]) == 0) {
				/* ELOOP if namei() tries to readlink */
				ndp->ni_loopcnt = MAXSYMLINKS;
				cnp->cn_flags &= ~FOLLOW;
				cnp->cn_flags |= NOFOLLOW;
				break;
			}
		}
		SYSTRACE_UNLOCK(fst, curlwp);
	} else
		systrace_unlock();
}

struct str_process *
systrace_findpid(struct fsystrace *fst, pid_t pid)
{
	struct str_process *strp;
	struct proc *proc = NULL;

	TAILQ_FOREACH(strp, &fst->processes, next)
	    if (strp->pid == pid)
		    break;

	if (strp == NULL)
		return (NULL);

	proc = systrace_find(strp);

	return (proc ? strp : NULL);
}

int
systrace_detach(struct str_process *strp)
{
	struct proc *proc;
	struct fsystrace *fst = NULL;
	int error = 0;

	DPRINTF(("%s: Trying to detach from %d\n", __func__, strp->pid));

	if ((proc = systrace_find(strp)) != NULL) {
		CLR(proc->p_flag, P_SYSTRACE);
		proc->p_systrace = NULL;
	} else
		error = ESRCH;

	if (ISSET(strp->flags, STR_PROC_WAITANSWER)) {
		CLR(strp->flags, STR_PROC_WAITANSWER);
		wakeup(strp);
	}

	fst = strp->parent;
	systrace_wakeup(fst);

	TAILQ_REMOVE(&fst->processes, strp, next);
	fst->nprocesses--;

	if (strp->policy)
		systrace_closepolicy(fst, strp->policy);
	systrace_replacefree(strp);
	pool_put(&systr_proc_pl, strp);

	return (error);
}

void
systrace_closepolicy(struct fsystrace *fst, struct str_policy *policy)
{
	if (--policy->refcount)
		return;

	fst->npolicies--;

	if (policy->nsysent)
		free(policy->sysent, M_XDATA);

	TAILQ_REMOVE(&fst->policies, policy, next);

	pool_put(&systr_policy_pl, policy);
}

int
systrace_insert_process(struct fsystrace *fst, struct proc *proc,
    struct str_process **pstrp)
{
	struct str_process *strp;

	strp = pool_get(&systr_proc_pl, PR_NOWAIT);
	if (strp == NULL)
		return (ENOBUFS);

	memset((caddr_t)strp, 0, sizeof(struct str_process));
	strp->pid = proc->p_pid;
	strp->proc = proc;
	strp->parent = fst;

	TAILQ_INSERT_TAIL(&fst->processes, strp, next);
	fst->nprocesses++;

	proc->p_systrace = strp;
	SET(proc->p_flag, P_SYSTRACE);

	/* Pass the new pointer back to the caller */
	if (pstrp != NULL)
		*pstrp = strp;

	return (0);
}

struct str_policy *
systrace_newpolicy(struct fsystrace *fst, int maxents)
{
	struct str_policy *pol;
	int i;

	if (fst->npolicies > SYSTR_MAX_POLICIES && !fst->issuser) {
		struct str_policy *tmp;

		/* Try to find a policy for freeing */
		TAILQ_FOREACH(tmp, &fst->policies, next) {
			if (tmp->refcount == 1)
				break;
		}

		if (tmp == NULL)
			return (NULL);

		/* Notify userland about freed policy */
		systrace_msg_policyfree(fst, tmp);
		/* Free this policy */
		systrace_closepolicy(fst, tmp);
	}

	pol = pool_get(&systr_policy_pl, PR_NOWAIT);
	if (pol == NULL)
		return (NULL);

	DPRINTF(("%s: allocating %d -> %lu\n", __func__,
		     maxents, (u_long)maxents * sizeof(int)));

	memset((caddr_t)pol, 0, sizeof(struct str_policy));

	pol->sysent = (u_char *)malloc(maxents * sizeof(u_char),
	    M_XDATA, M_WAITOK);
	pol->nsysent = maxents;
	for (i = 0; i < maxents; i++)
		pol->sysent[i] = SYSTR_POLICY_ASK;

	fst->npolicies++;
	pol->nr = fst->npolicynr++;
	pol->refcount = 1;

	TAILQ_INSERT_TAIL(&fst->policies, pol, next);

	return (pol);
}

int
systrace_msg_ask(struct fsystrace *fst, struct str_process *strp,
    int code, size_t argsize, register_t args[])
{
	struct str_message msg;
	struct str_msg_ask *msg_ask = &msg.msg_data.msg_ask;
	int i;

	msg_ask->code = code;
	msg_ask->argsize = argsize;
	for (i = 0; i < (argsize/sizeof(register_t)) && i < SYSTR_MAXARGS; i++)
		msg_ask->args[i] = args[i];

	return (systrace_make_msg(strp, SYSTR_MSG_ASK, &msg));
}

int
systrace_msg_result(struct fsystrace *fst, struct str_process *strp,
    int error, int code, size_t argsize, register_t args[], register_t rval[])
{
	struct str_message msg;
	struct str_msg_ask *msg_ask = &msg.msg_data.msg_ask;
	int i;

	msg_ask->code = code;
	msg_ask->argsize = argsize;
	msg_ask->result = error;
	for (i = 0; i < (argsize/sizeof(register_t)) && i < SYSTR_MAXARGS; i++)
		msg_ask->args[i] = args[i];

	msg_ask->rval[0] = rval[0];
	msg_ask->rval[1] = rval[1];

	return (systrace_make_msg(strp, SYSTR_MSG_RES, &msg));
}

int
systrace_msg_emul(struct fsystrace *fst, struct str_process *strp)
{
	struct str_message msg;
	struct str_msg_emul *msg_emul = &msg.msg_data.msg_emul;
	struct proc *p = strp->proc;

	memcpy(msg_emul->emul, p->p_emul->e_name, SYSTR_EMULEN);

	return (systrace_make_msg(strp, SYSTR_MSG_EMUL, &msg));
}

int
systrace_msg_ugid(struct fsystrace *fst, struct str_process *strp)
{
	struct str_message msg;
	struct str_msg_ugid *msg_ugid = &msg.msg_data.msg_ugid;
	struct proc *p = strp->proc;

	msg_ugid->uid = p->p_cred->p_ruid;
	msg_ugid->gid = p->p_cred->p_rgid;

	return (systrace_make_msg(strp, SYSTR_MSG_UGID, &msg));
}

int
systrace_make_msg(struct str_process *strp, int type, struct str_message *tmsg)
{
	struct str_msgcontainer *cont;
	struct str_message *msg;
	struct fsystrace *fst = strp->parent;
	int st;

	cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK);
	memset(cont, 0, sizeof(struct str_msgcontainer));
	cont->strp = strp;

	msg = &cont->msg;

	/* Copy the already filled in fields */
	memcpy(&msg->msg_data, &tmsg->msg_data, sizeof(msg->msg_data));

	/* Add the extra fields to the message */
	msg->msg_seqnr = ++strp->seqnr;
	msg->msg_type = type;
	msg->msg_pid = strp->pid;
	if (strp->policy)
		msg->msg_policy = strp->policy->nr;
	else
		msg->msg_policy = -1;

	SET(strp->flags, STR_PROC_WAITANSWER);
	if (ISSET(strp->flags, STR_PROC_ONQUEUE))
		goto out;

	TAILQ_INSERT_TAIL(&fst->messages, cont, next);
	SET(strp->flags, STR_PROC_ONQUEUE);

 out:
	systrace_wakeup(fst);

	/* Release the lock - XXX */
	SYSTRACE_UNLOCK(fst, strp->proc);

	while (1) {
		int f;
		f = curlwp->l_flag & L_SA;
		curlwp->l_flag &= ~L_SA;
		st = tsleep(strp, PWAIT | PCATCH, "systrmsg", 0);
		curlwp->l_flag |= f;
		if (st != 0)
			return (ERESTART);
		/* If we detach, then everything is permitted */
		if ((strp = curproc->p_systrace) == NULL)
			return (0);
		if (!ISSET(strp->flags, STR_PROC_WAITANSWER))
			break;
	}

	return (0);
}

int
systrace_msg_child(struct fsystrace *fst, struct str_process *strp, pid_t npid)
{
	struct str_msgcontainer *cont;
	struct str_message *msg;
	struct str_msg_child *msg_child;

	cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK);
	memset(cont, 0, sizeof(struct str_msgcontainer));
	cont->strp = strp;

	msg = &cont->msg;

	DPRINTF(("%s: %p: pid %d -> pid %d\n", __func__,
		    msg, strp->pid, npid));

	msg_child = &msg->msg_data.msg_child;

	msg->msg_type = SYSTR_MSG_CHILD;
	msg->msg_pid = strp->pid;
	if (strp->policy)
		msg->msg_policy = strp->policy->nr;
	else
		msg->msg_policy = -1;
	msg_child->new_pid = npid;

	TAILQ_INSERT_TAIL(&fst->messages, cont, next);

	systrace_wakeup(fst);

	return (0);
}

int
systrace_msg_policyfree(struct fsystrace *fst, struct str_policy *strpol)
{
	struct str_msgcontainer *cont;
	struct str_message *msg;

	cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK);
	memset(cont, 0, sizeof(struct str_msgcontainer));

	msg = &cont->msg;

	DPRINTF(("%s: free %d\n", __func__, strpol->nr));

	msg->msg_type = SYSTR_MSG_POLICYFREE;
	msg->msg_policy = strpol->nr;

	TAILQ_INSERT_TAIL(&fst->messages, cont, next);

	systrace_wakeup(fst);

	return (0);
}


text:
import React from 'react';
import PropTypes from 'prop-types';

import User, { UserRights, userRightLabel } from 'models/User';
import UserAvatar from 'components/users/UserAvatar';
import Select from 'components/utilities/Select';
import Button from 'components/utilities/Button';
import Icon from 'components/utilities/Icon';

const propTypes = {
  user: PropTypes.instanceOf(User),
  disabled: PropTypes.bool,
  disabledReason: PropTypes.string,
  onChangeUserRights: PropTypes.func.isRequired,
  onRemoveUserRights: PropTypes.func.isRequired,
};

function SecretUserListItem(props) {
  const {
    user,
    disabled,
    disabledReason,
    onChangeUserRights,
    onRemoveUserRights,
  } = props;

  return (

        <UserAvatar user={user} size="large" />
        {user.username}

        <Select
          value={user.rights}
          options={UserRights.map(rights => [rights, userRightLabel(rights)])}
          size="small"
          disabled={disabled}
          title={disabledReason}
          onChange={({ value }) => onChangeUserRights(user, value)}
        />
        <Button
          buttonStyle="icon"
          onClick={() => onRemoveUserRights(user)}
          disabled={disabled}
          title={disabledReason}
          size="small"
          iconOnly
        >
          <Icon id="close" />
        </Button>

  );
}
SecretUserListItem.propTypes = propTypes;

export default SecretUserListItem;

redpajama_set_name: RedPajamaGithub


text:
package net.cpollet.jixture.fixtures.transformers;

import net.cpollet.jixture.fixtures.Fixture;

/**
 * @author Christophe Pollet
 */
public interface FixtureTransformer<From extends Fixture, To extends Fixture> {
	Class getFromType();

	To transform(From fixture);
}


text:
<?php defined('SYSPATH') OR die('No direct script access.');

class Model_Tart_Filter extends Kohana_Model_Tart_Filter {}


text:
package com.example.whuassist.service;

import com.example.whuassist.HttpCallbackListener;
import com.example.whuassist.WhuHttpUtil;
import com.example.whuassist.WhuUtil;
import com.example.whuassist.receiver.AutoUpdateReceiver;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Binder;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;

public class AutoUpdateService extends Service {
	private AutoUpdateBinder mBinder=new AutoUpdateBinder();
	class AutoUpdateBinder extends Binder{
		/*
		 * ºÍactivityͨÐÅ
		 */
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return mBinder;
	}
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub

		long anHour=60*60*1000;
		long triggerTime=SystemClock.elapsedRealtime()+anHour;

		if(checkNetworkConnection()){
			new Thread(new Runnable() {

				@Override
				public void run() {
					// TODO Auto-generated method stub
					WhuHttpUtil.getInstance().Loginweb("http://210.42.121.241/servlet/Svlt_QueryStuScore?year=0&term=&learnType=&scoreFlag=0", null, new HttpCallbackListener() {

						@Override
						public void onFinish(String txt) {
							// TODO Auto-generated method stub
							Log.d("schedule", txt);
							WhuUtil.scoreParse(txt);

						}

						@Override
						public void onError(String txt) {
							// TODO Auto-generated method stub

						}
					});
				}
			}).start();
		}

		AlarmManager manager=(AlarmManager) getSystemService(ALARM_SERVICE);
		Intent i=new Intent(this,AutoUpdateReceiver.class);
		PendingIntent pi=PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_NO_CREATE);
		manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, pi);
		return super.onStartCommand(intent, flags, startId);
	}
	public boolean checkNetworkConnection(){
		//¼ì²âµ±Ç°ÍøÂç״̬
		ConnectivityManager manager=
				(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo info=manager.getActiveNetworkInfo();
		if(info!=null&&info.isAvailable()){
			return true;
		}
		return false;
	}
}


text: My github pages.


text:
namespace org { namespace alljoyn { namespace Icon {

// This class, and the associated EventArgs classes, exist for the benefit of JavaScript developers who
// do not have the ability to implement IIconService. Instead, IconServiceEventAdapter
// provides the Interface implementation and exposes a set of compatible events to the developer.
public ref class IconServiceEventAdapter sealed : [Windows::Foundation::Metadata::Default] IIconService
{
public:
    // Method Invocation Events
    event Windows::Foundation::TypedEventHandler<IconServiceEventAdapter^, IconGetUrlCalledEventArgs^>^ GetUrlCalled;
    event Windows::Foundation::TypedEventHandler<IconServiceEventAdapter^, IconGetContentCalledEventArgs^>^ GetContentCalled;

    // Property Read Events
    event Windows::Foundation::TypedEventHandler<IconServiceEventAdapter^, IconGetVersionRequestedEventArgs^>^ GetVersionRequested;
    event Windows::Foundation::TypedEventHandler<IconServiceEventAdapter^, IconGetMimeTypeRequestedEventArgs^>^ GetMimeTypeRequested;
    event Windows::Foundation::TypedEventHandler<IconServiceEventAdapter^, IconGetSizeRequestedEventArgs^>^ GetSizeRequested;

    // Property Write Events

    // IIconService Implementation
    virtual Windows::Foundation::IAsyncOperation<IconGetUrlResult^>^ GetUrlAsync(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);
    virtual Windows::Foundation::IAsyncOperation<IconGetContentResult^>^ GetContentAsync(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);

    virtual Windows::Foundation::IAsyncOperation<IconGetVersionResult^>^ GetVersionAsync(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);
    virtual Windows::Foundation::IAsyncOperation<IconGetMimeTypeResult^>^ GetMimeTypeAsync(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);
    virtual Windows::Foundation::IAsyncOperation<IconGetSizeResult^>^ GetSizeAsync(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);

};

} } }


text:
package wrangler

import (
	"fmt"
	"strings"

	hk "github.com/youtube/vitess/go/vt/hook"
	"golang.org/x/net/context"

	topodatapb "github.com/youtube/vitess/go/vt/proto/topodata"
)

// ExecuteHook will run the hook on the tablet
func (wr *Wrangler) ExecuteHook(ctx context.Context, tabletAlias *topodatapb.TabletAlias, hook *hk.Hook) (hookResult *hk.HookResult, err error) {
	if strings.Contains(hook.Name, "/") {
		return nil, fmt.Errorf("hook name cannot have a '/' in it")
	}
	ti, err := wr.ts.GetTablet(ctx, tabletAlias)
	if err != nil {
		return nil, err
	}
	return wr.ExecuteTabletHook(ctx, ti.Tablet, hook)
}

// ExecuteTabletHook will run the hook on the provided tablet.
func (wr *Wrangler) ExecuteTabletHook(ctx context.Context, tablet *topodatapb.Tablet, hook *hk.Hook) (hookResult *hk.HookResult, err error) {
	return wr.tmc.ExecuteHook(ctx, tablet, hook)
}


text:
package consulo.csharp.lang.psi;

import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.EmptyStub;
import com.intellij.psi.tree.TokenSet;
import consulo.csharp.lang.psi.impl.source.CSharpStubNullableTypeImpl;
import consulo.csharp.lang.psi.impl.source.CSharpStubPointerTypeImpl;
import consulo.csharp.lang.psi.impl.source.CSharpUsingTypeStatementImpl;
import consulo.csharp.lang.psi.impl.stub.elementTypes.*;
import consulo.dotnet.psi.DotNetPointerType;

import javax.annotation.Nonnull;

/**
 * @author VISTALL
 * @since 15.12.13.
 */
public interface CSharpStubElements
{
	CSharpFileStubElementType FILE = new CSharpFileStubElementType();
	CSharpDummyDefElementType DUMMY_DECLARATION = new CSharpDummyDefElementType();
	CSharpNamespaceStubElementType NAMESPACE_DECLARATION = new CSharpNamespaceStubElementType();
	CSharpTypeStubElementType TYPE_DECLARATION = new CSharpTypeStubElementType();
	CSharpMethodStubElementType METHOD_DECLARATION = new CSharpMethodStubElementType();
	CSharpIndexMethodStubElementType INDEX_METHOD_DECLARATION = new CSharpIndexMethodStubElementType();
	CSharpConstructorStubElementType CONSTRUCTOR_DECLARATION = new CSharpConstructorStubElementType();
	CSharpConversionMethodStubElementType CONVERSION_METHOD_DECLARATION = new CSharpConversionMethodStubElementType();
	CSharpPropertyElementType PROPERTY_DECLARATION = new CSharpPropertyElementType();
	CSharpEventElementType EVENT_DECLARATION = new CSharpEventElementType();
	CSharpFieldStubElementType FIELD_DECLARATION = new CSharpFieldStubElementType();
	CSharpEnumConstantStubElementType ENUM_CONSTANT_DECLARATION = new CSharpEnumConstantStubElementType();
	CSharpTypeListElementType EXTENDS_LIST = new CSharpTypeListElementType("EXTENDS_LIST");
	CSharpParameterListStubElementType PARAMETER_LIST = new CSharpParameterListStubElementType();
	CSharpParameterStubElementType PARAMETER = new CSharpParameterStubElementType();
	CSharpUsingNamespaceStatementStubElementType USING_NAMESPACE_STATEMENT = new CSharpUsingNamespaceStatementStubElementType();
	CSharpIdentifierStubElementType IDENTIFIER = new CSharpIdentifierStubElementType();
	CSharpEmptyStubElementType<CSharpUsingTypeStatement> USING_TYPE_STATEMENT = new CSharpEmptyStubElementType<CSharpUsingTypeStatement>
			("USING_TYPE_STATEMENT")
	{
		@Override
		public CSharpUsingTypeStatement createPsi(@Nonnull EmptyStub<CSharpUsingTypeStatement> stub)
		{
			return new CSharpUsingTypeStatementImpl(stub, this);
		}

		@Nonnull
		@Override
		public PsiElement createElement(@Nonnull ASTNode astNode)
		{
			return new CSharpUsingTypeStatementImpl(astNode);
		}
	};
	CSharpTypeDefStubElementType TYPE_DEF_STATEMENT = new CSharpTypeDefStubElementType();
	CSharpGenericParameterListStubElementType GENERIC_PARAMETER_LIST = new CSharpGenericParameterListStubElementType();
	CSharpGenericParameterStubElementType GENERIC_PARAMETER = new CSharpGenericParameterStubElementType();
	CSharpXAccessorStubElementType XACCESSOR = new CSharpXAccessorStubElementType();
	CSharpGenericConstraintListStubElementType GENERIC_CONSTRAINT_LIST = new CSharpGenericConstraintListStubElementType();
	CSharpGenericConstraintStubElementType GENERIC_CONSTRAINT = new CSharpGenericConstraintStubElementType();
	CSharpGenericConstraintKeywordValueStubElementType GENERIC_CONSTRAINT_KEYWORD_VALUE = new CSharpGenericConstraintKeywordValueStubElementType();
	CSharpGenericConstraintTypeValueStubElementType GENERIC_CONSTRAINT_TYPE_VALUE = new CSharpGenericConstraintTypeValueStubElementType();
	CSharpModifierListStubElementType MODIFIER_LIST = new CSharpModifierListStubElementType();
	CSharpAttributeListStubElementType ATTRIBUTE_LIST = new CSharpAttributeListStubElementType();
	CSharpAttributeStubElementType ATTRIBUTE = new CSharpAttributeStubElementType();

	TokenSet USING_CHILDREN = TokenSet.create(USING_NAMESPACE_STATEMENT, USING_TYPE_STATEMENT, TYPE_DEF_STATEMENT);

	CSharpEmptyStubElementType<CSharpNullableType> NULLABLE_TYPE = new CSharpEmptyStubElementType<CSharpNullableType>("NULLABLE_TYPE")
	{
		@Nonnull
		@Override
		public PsiElement createElement(@Nonnull ASTNode astNode)
		{
			return new CSharpStubNullableTypeImpl(astNode);
		}

		@Override
		public CSharpStubNullableTypeImpl createPsi(@Nonnull EmptyStub<CSharpNullableType> stub)
		{
			return new CSharpStubNullableTypeImpl(stub, this);
		}
	};

	CSharpEmptyStubElementType<DotNetPointerType> POINTER_TYPE = new CSharpEmptyStubElementType<DotNetPointerType>("POINTER_TYPE")
	{
		@Nonnull
		@Override
		public PsiElement createElement(@Nonnull ASTNode astNode)
		{
			return new CSharpStubPointerTypeImpl(astNode);
		}

		@Override
		public CSharpStubPointerTypeImpl createPsi(@Nonnull EmptyStub<DotNetPointerType> stub)
		{
			return new CSharpStubPointerTypeImpl(stub, this);
		}
	};

	CSharpTupleTypeStubElementType TUPLE_TYPE = new CSharpTupleTypeStubElementType();

	CSharpTupleVariableStubElementType TUPLE_VARIABLE = new CSharpTupleVariableStubElementType();

	CSharpNativeTypeStubElementType NATIVE_TYPE = new CSharpNativeTypeStubElementType();

	CSharpArrayTypeStubElementType ARRAY_TYPE = new CSharpArrayTypeStubElementType();

	CSharpUserTypeStubElementType USER_TYPE = new CSharpUserTypeStubElementType();

	CSharpTypeListElementType TYPE_ARGUMENTS = new CSharpTypeListElementType("TYPE_ARGUMENTS");

	CSharpReferenceExpressionStubElementType REFERENCE_EXPRESSION = new CSharpReferenceExpressionStubElementType();

	TokenSet GENERIC_CONSTRAINT_VALUES = TokenSet.create(GENERIC_CONSTRAINT_KEYWORD_VALUE, GENERIC_CONSTRAINT_TYPE_VALUE);

	TokenSet TYPE_SET = TokenSet.create(NULLABLE_TYPE, POINTER_TYPE, NATIVE_TYPE, TUPLE_TYPE, ARRAY_TYPE, USER_TYPE);

	TokenSet QUALIFIED_MEMBERS = TokenSet.create(NAMESPACE_DECLARATION, TYPE_DECLARATION, METHOD_DECLARATION, CONSTRUCTOR_DECLARATION,
			PROPERTY_DECLARATION, EVENT_DECLARATION, FIELD_DECLARATION, ENUM_CONSTANT_DECLARATION, CONVERSION_METHOD_DECLARATION,
			INDEX_METHOD_DECLARATION);
}


text:
using System;
using System.ServiceModel.Configuration;

namespace Moonlit.Wcf.DependencyResolverExtensions
{
    public class DependencyResolverBehaviorElement : BehaviorExtensionElement
    {
        protected override object CreateBehavior()
        {
            var unityContainer = DependencyResolverContainerFactory.Container;

            return new DependencyResolverBehavior(unityContainer);
        }

        public override Type BehaviorType
        {
            get { return typeof(DependencyResolverBehavior); }
        }
    }
}


text:
/*
 * REST API Documentation for Schoolbus
 *
 * API Sample
 *
 * OpenAPI spec version: v1
 *
 *
 */

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using SchoolBusAPI.Models;
using SchoolBusAPI.ViewModels;
using SchoolBusAPI.Mappings;
using Microsoft.EntityFrameworkCore;

namespace SchoolBusAPI.Services.Impl
{
    /// <summary>
    ///
    /// </summary>
    public class SchoolBusOwnerService : ISchoolBusOwnerService
    {

        private readonly DbAppContext _context;

        /// <summary>
        /// Create a service and set the database context
        /// </summary>
        public SchoolBusOwnerService (DbAppContext context)
        {
            _context = context;
        }

        private void AdjustSchoolBusOwner (SchoolBusOwner item)
        {
            // adjust Primary Contact.
            if (item.PrimaryContact != null)
            {
                int primary_contact_id = item.PrimaryContact.Id;
                var primary_contact_exists = _context.Contacts.Any(a => a.Id == primary_contact_id);
                if (primary_contact_exists)
                {
                    Contact contact = _context.Contacts.First(a => a.Id == primary_contact_id);
                    item.PrimaryContact = contact;
                }
                else
                {
                    item.PrimaryContact = null;
                }
            }

            // adjust District.
            if (item.District != null)
            {
                int district_id = item.District.Id;
                var district_exists = _context.ServiceAreas.Any(a => a.Id == district_id);
                if (district_exists)
                {
                    District district = _context.Districts.First(a => a.Id == district_id);
                    item.District = district;
                }
                else
                {
                    item.District = null;
                }
            }

            // adjust contacts
            if (item.Contacts != null)
            {
                for (int i = 0; i < item.Contacts.Count; i++)
                {
                    Contact contact = item.Contacts[i];
                    if (contact != null)
                    {
                        int contact_id = contact.Id;
                        bool contact_exists = _context.Contacts.Any(a => a.Id == contact_id);
                        if (contact_exists)
                        {
                            Contact new_contact = _context.Contacts.First(a => a.Id == contact_id);
                            item.Contacts[i] = new_contact;
                        }
                        else
                        {
                            item.Contacts[i] = null;
                        }
                    }
                }
            }

        }

        /// <summary>
        ///
        /// </summary>

        /// <param name="items"></param>
        /// <response code="201">SchoolBusOwners created</response>

        public virtual IActionResult SchoolbusownersBulkPostAsync (SchoolBusOwner[] items)
        {
            if (items == null)
            {
                return new BadRequestResult();
            }
            foreach (SchoolBusOwner item in items)
            {
                AdjustSchoolBusOwner(item);

                var exists = _context.SchoolBusOwners.Any(a => a.Id == item.Id);
                if (exists)
                {
                    _context.SchoolBusOwners.Update(item);
                }
                else
                {
                    _context.SchoolBusOwners.Add(item);
                }
            }
            // Save the changes
            _context.SaveChanges();

            return new NoContentResult();
        }
        /// <summary>
        ///
        /// </summary>

        /// <response code="200">OK</response>

        public virtual IActionResult SchoolbusownersGetAsync ()
        {
            var result = _context.SchoolBusOwners
                .Include(x => x.Attachments)
                .Include(x => x.Contacts)
                .Include(x => x.District.Region)
                .Include(x => x.History)
                .Include(x => x.Notes)
                .Include(x => x.PrimaryContact)
                .ToList();
            return new ObjectResult(result);
        }
        /// <summary>
        ///
        /// </summary>
        /// <remarks>Returns attachments for a particular SchoolBusOwner</remarks>
        /// <param name="id">id of SchoolBusOwner to fetch attachments for</param>
        /// <response code="200">OK</response>

        public virtual IActionResult SchoolbusownersIdAttachmentsGetAsync (int id)
        {
            var exists = _context.SchoolBusOwners.Any(a => a.Id == id);
            if (exists)
            {
                SchoolBusOwner schoolBusOwner = _context.SchoolBusOwners
                    .Include(x => x.Attachments)
                    .First(a => a.Id == id);
                var result = MappingExtensions.GetAttachmentListAsViewModel(schoolBusOwner.Attachments);
                return new ObjectResult(result);
            }
            else
            {
                // record not found
                return new StatusCodeResult(404);
            }
        }

        public virtual IActionResult SchoolbusownersIdDeletePostAsync (int id)
        {
            var exists = _context.SchoolBusOwners.Any(a => a.Id == id);
            if (exists)
            {
                var item = _context.SchoolBusOwners.First(a => a.Id == id);
                _context.SchoolBusOwners.Remove(item);
                // Save the changes
                _context.SaveChanges();
                return new ObjectResult(item);
            }
            else
            {
                // record not found
                return new StatusCodeResult(404);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <remarks>Returns a particular SchoolBusOwner</remarks>
        /// <param name="id">id of SchoolBusOwner to fetch</param>
        /// <response code="200">OK</response>

        public virtual IActionResult SchoolbusownersIdGetAsync (int id)
        {
            var exists = _context.SchoolBusOwners.Any(a => a.Id == id);
            if (exists)
            {
                var result = _context.SchoolBusOwners
                    .Include(x => x.Attachments)
                    .Include(x => x.Contacts)
                    .Include(x => x.District.Region)
                    .Include(x => x.History)
                    .Include(x => x.Notes)
                    .Include(x => x.PrimaryContact)
                    .First(a => a.Id == id);
                return new ObjectResult(result);
            }
            else
            {
                // record not found
                return new StatusCodeResult(404);
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <remarks>Returns History for a particular SchoolBusOwner</remarks>
        /// <param name="id">id of SchoolBusOwner to fetch History for</param>
        /// <response code="200">OK</response>
        public virtual IActionResult SchoolbusownersIdHistoryGetAsync(int id, int? offset, int? limit)
        {
            bool exists = _context.SchoolBusOwners.Any(a => a.Id == id);
            if (exists)
            {
                SchoolBusOwner schoolBusOwner = _context.SchoolBusOwners
                    .Include(x => x.History)
                    .First(a => a.Id == id);

                List<History> data = schoolBusOwner.History.OrderByDescending(y => y.LastUpdateTimestamp).ToList();

                if (offset == null)
                {
                    offset = 0;
                }
                if (limit == null)
                {
                    limit = data.Count() - offset;
                }
                List<HistoryViewModel> result = new List<HistoryViewModel>();

                for (int i = (int)offset; i < data.Count() && i < offset + limit; i++)
                {
                    result.Add(data[i].ToViewModel(id));
                }

                return new ObjectResult(result);
            }
            else
            {
                // record not found
                return new StatusCodeResult(404);
            }

        }

        public virtual IActionResult SchoolbusownersIdHistoryPostAsync(int id, History item)
        {
            HistoryViewModel result = new HistoryViewModel();

            bool exists = _context.SchoolBusOwners.Any(a => a.Id == id);
            if (exists)
            {
                SchoolBusOwner schoolBusOwner = _context.SchoolBusOwners
                    .Include(x => x.History)
                    .First(a => a.Id == id);
                if (schoolBusOwner.History == null)
                {
                    schoolBusOwner.History = new List<History>();
                }
                // force add
                item.Id = 0;
                schoolBusOwner.History.Add(item);

                _context.SchoolBusOwners.Update(schoolBusOwner);
                _context.SaveChanges();
            }

            result.HistoryText = item.HistoryText;
            result.Id = item.Id;
            result.LastUpdateTimestamp = item.LastUpdateTimestamp;
            result.LastUpdateUserid = item.LastUpdateUserid;
            result.AffectedEntityId = id;

            return new ObjectResult(result);
        }

        /// <summary>
        ///
        /// </summary>
        /// <remarks>Returns notes for a particular SchoolBusOwner</remarks>
        /// <param name="id">id of SchoolBusOwner to fetch notes for</param>
        /// <response code="200">OK</response>

        public virtual IActionResult SchoolbusownersIdNotesGetAsync (int id)
        {
            var exists = _context.SchoolBusOwners.Any(a => a.Id == id);
            if (exists)
            {
                SchoolBusOwner schoolBusOwner = _context.SchoolBusOwners
                    .Include(x => x.Notes)
                    .First(a => a.Id == id);
                var result = schoolBusOwner.Notes;
                return new ObjectResult(result);
            }
            else
            {
                // record not found
                return new StatusCodeResult(404);
            }
        }
        /// <summary>
        ///
        /// </summary>

        /// <param name="id">id of SchoolBusOwner to fetch</param>
        /// <response code="200">OK</response>
        /// <response code="404">SchoolBusOwner not found</response>

        public virtual IActionResult SchoolbusownersIdPutAsync (int id, SchoolBusOwner body)
        {
            AdjustSchoolBusOwner(body);

            var exists = _context.SchoolBusOwners.Any(a => a.Id == id);
            if (exists && id == body.Id)
            {
                _context.SchoolBusOwners.Update(body);
                // Save the changes
                _context.SaveChanges();
                return new ObjectResult(body);
            }
            else
            {
                // record not found
                return new StatusCodeResult(404);
            }
        }

        /// <summary>
        /// Utility function used by the owner view service
        /// </summary>
        /// <param name="schoolBusOwnerId">Owner for which to lookup inspections</param>
        /// <returns>Date of next inspection, or null if there is none</returns>
        private DateTime? GetNextInspectionDate (int schoolBusOwnerId)
        {
            DateTime? result = null;

            // next inspection is drawn from the schoolbus table
            bool exists = _context.SchoolBuss.Any(x => x.SchoolBusOwner.Id == schoolBusOwnerId && x.NextInspectionDate != null && x.Status.ToLower() == "active");
            if (exists)
            {
                SchoolBus schoolbus = _context.SchoolBuss.Where(x => x.SchoolBusOwner.Id == schoolBusOwnerId && x.NextInspectionDate != null && x.Status.ToLower() == "active")
                    .OrderByDescending(x => x.NextInspectionDate)
                    .First();
                result = schoolbus.NextInspectionDate;
            }
            return result;
        }

        /// <summary>
        /// Utility function used by the owner view service
        /// </summary>
        /// <param name="schoolBusOwnerId">Owner for which to lookup school buses</param>
        /// <returns>Number of associated school buses</returns>
        private int GetNumberSchoolBuses(int schoolBusOwnerId)
        {
            int result = 0;

            // next inspection is drawn from the inspections table.
            bool exists = _context.SchoolBuss.Any(x => x.SchoolBusOwner.Id == schoolBusOwnerId);
            if (exists)
            {
                result = _context.SchoolBuss.Where(x => x.SchoolBusOwner.Id == schoolBusOwnerId && x.Status.ToLower() == "active")
                    .Count();

            }
            return result;
        }

        private string GetNextInspectionTypeCode(int schoolBusOwnerId)
        {
            string result = null;

            // next inspection is drawn from the inspections table.
            bool exists = _context.SchoolBuss.Any(x => x.SchoolBusOwner.Id == schoolBusOwnerId && x.NextInspectionDate != null && x.Status.ToLower() == "active");
            if (exists)
            {
                var record = _context.SchoolBuss
                    .Where(x => x.SchoolBusOwner.Id == schoolBusOwnerId && x.NextInspectionDate != null && x.Status.ToLower() == "active")
                    .OrderByDescending(x => x.NextInspectionDate)
                    .First();
                result = record.NextInspectionTypeCode;
            }
            return result;
        }

        /// <summary>
        /// View service used by the view school bus owner page
        /// </summary>
        /// <param name="id">SchoolBusOwner Id</param>
        /// <returns>A SchoolBusOwnerViewModel, or 404 if the record does not exist</returns>
        public IActionResult SchoolbusownersIdViewGetAsync(int id)
        {
            var exists = _context.SchoolBusOwners.Any(a => a.Id == id);
            if (exists)
            {
                SchoolBusOwner schoolBusOwner = _context.SchoolBusOwners.First(a => a.Id == id);
                SchoolBusOwnerViewModel result = schoolBusOwner.ToViewModel();
                // populate the calculated fields.
                result.NextInspectionDate = GetNextInspectionDate(id); ;
                result.NumberOfBuses = GetNumberSchoolBuses(id);
                result.NextInspectionTypeCode = GetNextInspectionTypeCode(id);
                return new ObjectResult(result);
            }
            else
            {
                // record not found
                return new StatusCodeResult(404);
            }
        }

        /// <summary>
        ///
        /// </summary>

        /// <param name="body"></param>
        /// <response code="201">SchoolBusOwner created</response>

        public virtual IActionResult SchoolbusownersPostAsync (SchoolBusOwner body)
        {
            AdjustSchoolBusOwner(body);
            body.DateCreated = DateTime.UtcNow;
            _context.SchoolBusOwners.Add(body);
            _context.SaveChanges();
            return new ObjectResult(body);
        }

        /// <summary>
        /// Searches school bus owners
        /// </summary>
        /// <remarks>Used for the search school bus owners.</remarks>
        /// <param name="districts">Districts (array of id numbers)</param>
        /// <param name="inspectors">Assigned School Bus Inspectors (array of id numbers)</param>
        /// <param name="owner"></param>
        /// <param name="includeInactive">True if Inactive schoolbuses will be returned</param>
        /// <response code="200">OK</response>
        public virtual IActionResult SchoolbusownersSearchGetAsync(int?[] districts, int?[] inspectors, int? owner, bool? includeInactive)
        {
            // Eager loading of related data
            var data = _context.SchoolBusOwners
                .Include(x => x.Attachments)
                .Include(x => x.Contacts)
                .Include(x => x.District.Region)
                .Include(x => x.History)
                .Include(x => x.Notes)
                .Include(x => x.PrimaryContact)
                .Select(x => x);

            // Note that Districts searches SchoolBus Districts, not SchoolBusOwner Districts
            if (districts != null)
            {
                List<int> ids = new List<int>();

                // get the owner ids for matching records.
                foreach (int? district in districts)
                {
                    if (district != null)
                    {
                        var buses = _context.SchoolBuss
                            .Include(x => x.District)
                            .Include(x => x.SchoolBusOwner)
                            .Where(x => x.District.Id == district);
                        foreach (var bus in buses)
                        {
                            if (bus.SchoolBusOwner != null)
                            {
                                ids.Add(bus.SchoolBusOwner.Id);
                            }
                        }

                    }
                }

                if (ids.Count > 0)
                {
                    data = data.Where(x => ids.Contains(x.Id));
                }

            }

            if (inspectors != null)
            {
                List<int> ids = new List<int>();

                // get the owner ids for matching records.
                foreach (int? inspector in inspectors)
                {
                    if (inspector != null)
                    {
                        var buses = _context.SchoolBuss
                            .Include(x => x.Inspector)
                            .Include( x => x.SchoolBusOwner)
                            .Where(x => x.Inspector.Id == inspector);
                        foreach (var bus in buses)
                        {
                            if (bus.SchoolBusOwner != null)
                            {
                                ids.Add(bus.SchoolBusOwner.Id);
                            }
                        }

                    }
                }

                if (ids.Count > 0)
                {
                    data = data.Where(x => ids.Contains(x.Id));
                }

            }

            if (owner != null)
            {
                data = data.Where(x => x.Id == owner);
            }

            if (includeInactive == null || includeInactive == false)
            {
                data = data.Where(x => x.Status == "Active");
            }

            // now convert the results to the view model.
            var result = new List<SchoolBusOwnerViewModel>();
            foreach (SchoolBusOwner item in data)
            {
                SchoolBusOwnerViewModel record = item.ToViewModel();
                result.Add(record);
            }
            // second pass to get the calculated fields
            foreach (SchoolBusOwnerViewModel item in result)
            {
                // populate the calculated fields.
                item.NextInspectionDate = GetNextInspectionDate(item.Id); ;
                item.NumberOfBuses = GetNumberSchoolBuses(item.Id);
                item.NextInspectionTypeCode = GetNextInspectionTypeCode(item.Id);
            }
            return new ObjectResult(result);
        }
    }
}


text:
package validation

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	errs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"

	"github.com/golang/glog"
)

// ServiceLister is an abstract interface for testing.
type ServiceLister interface {
	ListServices(api.Context) (*api.ServiceList, error)
}

func validateVolumes(volumes []api.Volume) (util.StringSet, errs.ValidationErrorList) {
	allErrs := errs.ValidationErrorList{}

	allNames := util.StringSet{}
	for i := range volumes {
		vol := &volumes[i] // so we can set default values
		el := errs.ValidationErrorList{}
		if vol.Source == nil {
			// TODO: Enforce that a source is set once we deprecate the implied form.
			vol.Source = &api.VolumeSource{
				EmptyDir: &api.EmptyDir{},
			}
		}
		el = validateSource(vol.Source).Prefix("source")
		if len(vol.Name) == 0 {
			el = append(el, errs.NewFieldRequired("name", vol.Name))
		} else if !util.IsDNSLabel(vol.Name) {
			el = append(el, errs.NewFieldInvalid("name", vol.Name, ""))
		} else if allNames.Has(vol.Name) {
			el = append(el, errs.NewFieldDuplicate("name", vol.Name))
		}
		if len(el) == 0 {
			allNames.Insert(vol.Name)
		} else {
			allErrs = append(allErrs, el.PrefixIndex(i)...)
		}
	}
	return allNames, allErrs
}

func validateSource(source *api.VolumeSource) errs.ValidationErrorList {
	numVolumes := 0
	allErrs := errs.ValidationErrorList{}
	if source.HostDir != nil {
		numVolumes++
		allErrs = append(allErrs, validateHostDir(source.HostDir).Prefix("hostDirectory")...)
	}
	if source.EmptyDir != nil {
		numVolumes++
		// EmptyDirs have nothing to validate
	}
	if source.GitRepo != nil {
		numVolumes++
		allErrs = append(allErrs, validateGitRepo(source.GitRepo)...)
	}
	if source.GCEPersistentDisk != nil {
		numVolumes++
		allErrs = append(allErrs, validateGCEPersistentDisk(source.GCEPersistentDisk)...)
	}
	if numVolumes != 1 {
		allErrs = append(allErrs, errs.NewFieldInvalid("", source, "exactly 1 volume type is required"))
	}
	return allErrs
}

func validateHostDir(hostDir *api.HostDir) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	if hostDir.Path == "" {
		allErrs = append(allErrs, errs.NewNotFound("path", hostDir.Path))
	}
	return allErrs
}

func validateGitRepo(gitRepo *api.GitRepo) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	if gitRepo.Repository == "" {
		allErrs = append(allErrs, errs.NewFieldRequired("gitRepo.Repository", gitRepo.Repository))
	}
	return allErrs
}

func validateGCEPersistentDisk(PD *api.GCEPersistentDisk) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	if PD.PDName == "" {
		allErrs = append(allErrs, errs.NewFieldRequired("PD.PDName", PD.PDName))
	}
	if PD.FSType == "" {
		allErrs = append(allErrs, errs.NewFieldRequired("PD.FSType", PD.FSType))
	}
	if PD.Partition < 0 || PD.Partition > 255 {
		allErrs = append(allErrs, errs.NewFieldInvalid("PD.Partition", PD.Partition, ""))
	}
	return allErrs
}

var supportedPortProtocols = util.NewStringSet(string(api.ProtocolTCP), string(api.ProtocolUDP))

func validatePorts(ports []api.Port) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	allNames := util.StringSet{}
	for i := range ports {
		pErrs := errs.ValidationErrorList{}
		port := &ports[i] // so we can set default values
		if len(port.Name) > 0 {
			if len(port.Name) > 63 || !util.IsDNSLabel(port.Name) {
				pErrs = append(pErrs, errs.NewFieldInvalid("name", port.Name, ""))
			} else if allNames.Has(port.Name) {
				pErrs = append(pErrs, errs.NewFieldDuplicate("name", port.Name))
			} else {
				allNames.Insert(port.Name)
			}
		}
		if port.ContainerPort == 0 {
			pErrs = append(pErrs, errs.NewFieldRequired("containerPort", port.ContainerPort))
		} else if !util.IsValidPortNum(port.ContainerPort) {
			pErrs = append(pErrs, errs.NewFieldInvalid("containerPort", port.ContainerPort, ""))
		}
		if port.HostPort != 0 && !util.IsValidPortNum(port.HostPort) {
			pErrs = append(pErrs, errs.NewFieldInvalid("hostPort", port.HostPort, ""))
		}
		if len(port.Protocol) == 0 {
			port.Protocol = "TCP"
		} else if !supportedPortProtocols.Has(strings.ToUpper(string(port.Protocol))) {
			pErrs = append(pErrs, errs.NewFieldNotSupported("protocol", port.Protocol))
		}
		allErrs = append(allErrs, pErrs.PrefixIndex(i)...)
	}
	return allErrs
}

func validateEnv(vars []api.EnvVar) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	for i := range vars {
		vErrs := errs.ValidationErrorList{}
		ev := &vars[i] // so we can set default values
		if len(ev.Name) == 0 {
			vErrs = append(vErrs, errs.NewFieldRequired("name", ev.Name))
		}
		if !util.IsCIdentifier(ev.Name) {
			vErrs = append(vErrs, errs.NewFieldInvalid("name", ev.Name, ""))
		}
		allErrs = append(allErrs, vErrs.PrefixIndex(i)...)
	}
	return allErrs
}

func validateVolumeMounts(mounts []api.VolumeMount, volumes util.StringSet) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	for i := range mounts {
		mErrs := errs.ValidationErrorList{}
		mnt := &mounts[i] // so we can set default values
		if len(mnt.Name) == 0 {
			mErrs = append(mErrs, errs.NewFieldRequired("name", mnt.Name))
		} else if !volumes.Has(mnt.Name) {
			mErrs = append(mErrs, errs.NewFieldNotFound("name", mnt.Name))
		}
		if len(mnt.MountPath) == 0 {
			mErrs = append(mErrs, errs.NewFieldRequired("mountPath", mnt.MountPath))
		}
		allErrs = append(allErrs, mErrs.PrefixIndex(i)...)
	}
	return allErrs
}

// AccumulateUniquePorts runs an extraction function on each Port of each Container,
// accumulating the results and returning an error if any ports conflict.
func AccumulateUniquePorts(containers []api.Container, accumulator map[int]bool, extract func(*api.Port) int) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	for ci := range containers {
		cErrs := errs.ValidationErrorList{}
		ctr := &containers[ci]
		for pi := range ctr.Ports {
			port := extract(&ctr.Ports[pi])
			if port == 0 {
				continue
			}
			if accumulator[port] {
				cErrs = append(cErrs, errs.NewFieldDuplicate("port", port))
			} else {
				accumulator[port] = true
			}
		}
		allErrs = append(allErrs, cErrs.PrefixIndex(ci)...)
	}
	return allErrs
}

// checkHostPortConflicts checks for colliding Port.HostPort values across
// a slice of containers.
func checkHostPortConflicts(containers []api.Container) errs.ValidationErrorList {
	allPorts := map[int]bool{}
	return AccumulateUniquePorts(containers, allPorts, func(p *api.Port) int { return p.HostPort })
}

func validateExecAction(exec *api.ExecAction) errs.ValidationErrorList {
	allErrors := errs.ValidationErrorList{}
	if len(exec.Command) == 0 {
		allErrors = append(allErrors, errs.NewFieldRequired("command", exec.Command))
	}
	return allErrors
}

func validateHTTPGetAction(http *api.HTTPGetAction) errs.ValidationErrorList {
	allErrors := errs.ValidationErrorList{}
	if len(http.Path) == 0 {
		allErrors = append(allErrors, errs.NewFieldRequired("path", http.Path))
	}
	return allErrors
}

func validateHandler(handler *api.Handler) errs.ValidationErrorList {
	numHandlers := 0
	allErrors := errs.ValidationErrorList{}
	if handler.Exec != nil {
		numHandlers++
		allErrors = append(allErrors, validateExecAction(handler.Exec).Prefix("exec")...)
	}
	if handler.HTTPGet != nil {
		numHandlers++
		allErrors = append(allErrors, validateHTTPGetAction(handler.HTTPGet).Prefix("httpGet")...)
	}
	if numHandlers != 1 {
		allErrors = append(allErrors, errs.NewFieldInvalid("", handler, "exactly 1 handler type is required"))
	}
	return allErrors
}

func validateLifecycle(lifecycle *api.Lifecycle) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	if lifecycle.PostStart != nil {
		allErrs = append(allErrs, validateHandler(lifecycle.PostStart).Prefix("postStart")...)
	}
	if lifecycle.PreStop != nil {
		allErrs = append(allErrs, validateHandler(lifecycle.PreStop).Prefix("preStop")...)
	}
	return allErrs
}

func validateContainers(containers []api.Container, volumes util.StringSet) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	allNames := util.StringSet{}
	for i := range containers {
		cErrs := errs.ValidationErrorList{}
		ctr := &containers[i] // so we can set default values
		capabilities := capabilities.Get()
		if len(ctr.Name) == 0 {
			cErrs = append(cErrs, errs.NewFieldRequired("name", ctr.Name))
		} else if !util.IsDNSLabel(ctr.Name) {
			cErrs = append(cErrs, errs.NewFieldInvalid("name", ctr.Name, ""))
		} else if allNames.Has(ctr.Name) {
			cErrs = append(cErrs, errs.NewFieldDuplicate("name", ctr.Name))
		} else if ctr.Privileged && !capabilities.AllowPrivileged {
			cErrs = append(cErrs, errs.NewFieldForbidden("privileged", ctr.Privileged))
		} else {
			allNames.Insert(ctr.Name)
		}
		if len(ctr.Image) == 0 {
			cErrs = append(cErrs, errs.NewFieldRequired("image", ctr.Image))
		}
		if ctr.Lifecycle != nil {
			cErrs = append(cErrs, validateLifecycle(ctr.Lifecycle).Prefix("lifecycle")...)
		}
		cErrs = append(cErrs, validatePorts(ctr.Ports).Prefix("ports")...)
		cErrs = append(cErrs, validateEnv(ctr.Env).Prefix("env")...)
		cErrs = append(cErrs, validateVolumeMounts(ctr.VolumeMounts, volumes).Prefix("volumeMounts")...)
		allErrs = append(allErrs, cErrs.PrefixIndex(i)...)
	}
	// Check for colliding ports across all containers.
	// TODO(thockin): This really is dependent on the network config of the host (IP per pod?)
	// and the config of the new manifest.  But we have not specced that out yet, so we'll just
	// make some assumptions for now.  As of now, pods share a network namespace, which means that
	// every Port.HostPort across the whole pod must be unique.
	allErrs = append(allErrs, checkHostPortConflicts(containers)...)

	return allErrs
}

var supportedManifestVersions = util.NewStringSet("v1beta1", "v1beta2")

// ValidateManifest tests that the specified ContainerManifest has valid data.
// This includes checking formatting and uniqueness.  It also canonicalizes the
// structure by setting default values and implementing any backwards-compatibility
// tricks.
// TODO: replaced by ValidatePodSpec
func ValidateManifest(manifest *api.ContainerManifest) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	if len(manifest.Version) == 0 {
		allErrs = append(allErrs, errs.NewFieldRequired("version", manifest.Version))
	} else if !supportedManifestVersions.Has(strings.ToLower(manifest.Version)) {
		allErrs = append(allErrs, errs.NewFieldNotSupported("version", manifest.Version))
	}
	allVolumes, vErrs := validateVolumes(manifest.Volumes)
	allErrs = append(allErrs, vErrs.Prefix("volumes")...)
	allErrs = append(allErrs, validateContainers(manifest.Containers, allVolumes).Prefix("containers")...)
	allErrs = append(allErrs, validateRestartPolicy(&manifest.RestartPolicy).Prefix("restartPolicy")...)
	allErrs = append(allErrs, validateDNSPolicy(&manifest.DNSPolicy).Prefix("dnsPolicy")...)
	return allErrs
}

func validateRestartPolicy(restartPolicy *api.RestartPolicy) errs.ValidationErrorList {
	numPolicies := 0
	allErrors := errs.ValidationErrorList{}
	if restartPolicy.Always != nil {
		numPolicies++
	}
	if restartPolicy.OnFailure != nil {
		numPolicies++
	}
	if restartPolicy.Never != nil {
		numPolicies++
	}
	if numPolicies == 0 {
		restartPolicy.Always = &api.RestartPolicyAlways{}
	}
	if numPolicies > 1 {
		allErrors = append(allErrors, errs.NewFieldInvalid("", restartPolicy, "only 1 policy is allowed"))
	}
	return allErrors
}

func validateDNSPolicy(dnsPolicy *api.DNSPolicy) errs.ValidationErrorList {
	allErrors := errs.ValidationErrorList{}
	switch *dnsPolicy {
	case "":
		// TODO: move this out to standard defaulting logic, when that is ready.
		*dnsPolicy = api.DNSClusterFirst // Default value.
	case api.DNSClusterFirst, api.DNSDefault:
		break
	default:
		allErrors = append(allErrors, errs.NewFieldNotSupported("", dnsPolicy))
	}
	return allErrors
}

// ValidatePod tests if required fields in the pod are set.
func ValidatePod(pod *api.Pod) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	if len(pod.Name) == 0 {
		allErrs = append(allErrs, errs.NewFieldRequired("name", pod.Name))
	} else if !util.IsDNSSubdomain(pod.Name) {
		allErrs = append(allErrs, errs.NewFieldInvalid("name", pod.Name, ""))
	}
	if len(pod.Namespace) == 0 {
		allErrs = append(allErrs, errs.NewFieldRequired("namespace", pod.Namespace))
	} else if !util.IsDNSSubdomain(pod.Namespace) {
		allErrs = append(allErrs, errs.NewFieldInvalid("namespace", pod.Namespace, ""))
	}
	allErrs = append(allErrs, ValidatePodSpec(&pod.Spec).Prefix("spec")...)
	allErrs = append(allErrs, validateLabels(pod.Labels, "labels")...)
	return allErrs
}

// ValidatePodSpec tests that the specified PodSpec has valid data.
// This includes checking formatting and uniqueness.  It also canonicalizes the
// structure by setting default values and implementing any backwards-compatibility
// tricks.
func ValidatePodSpec(spec *api.PodSpec) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	allVolumes, vErrs := validateVolumes(spec.Volumes)
	allErrs = append(allErrs, vErrs.Prefix("volumes")...)
	allErrs = append(allErrs, validateContainers(spec.Containers, allVolumes).Prefix("containers")...)
	allErrs = append(allErrs, validateRestartPolicy(&spec.RestartPolicy).Prefix("restartPolicy")...)
	allErrs = append(allErrs, validateDNSPolicy(&spec.DNSPolicy).Prefix("dnsPolicy")...)
	allErrs = append(allErrs, validateLabels(spec.NodeSelector, "nodeSelector")...)
	return allErrs
}

func validateLabels(labels map[string]string, field string) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	for k := range labels {
		if !util.IsQualifiedName(k) {
			allErrs = append(allErrs, errs.NewFieldInvalid(field, k, ""))
		}
	}
	return allErrs
}

// ValidatePodUpdate tests to see if the update is legal
func ValidatePodUpdate(newPod, oldPod *api.Pod) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	if newPod.Name != oldPod.Name {
		allErrs = append(allErrs, errs.NewFieldInvalid("name", newPod.Name, "field is immutable"))
	}

	if len(newPod.Spec.Containers) != len(oldPod.Spec.Containers) {
		allErrs = append(allErrs, errs.NewFieldInvalid("spec.containers", newPod.Spec.Containers, "may not add or remove containers"))
		return allErrs
	}
	pod := *newPod
	// Tricky, we need to copy the container list so that we don't overwrite the update
	var newContainers []api.Container
	for ix, container := range pod.Spec.Containers {
		container.Image = oldPod.Spec.Containers[ix].Image
		newContainers = append(newContainers, container)
	}
	pod.Spec.Containers = newContainers
	if !reflect.DeepEqual(pod.Spec, oldPod.Spec) {
		// TODO: a better error would include all immutable fields explicitly.
		allErrs = append(allErrs, errs.NewFieldInvalid("spec.containers", newPod.Spec.Containers, "some fields are immutable"))
	}
	return allErrs
}

var supportedSessionAffinityType = util.NewStringSet(string(api.AffinityTypeClientIP), string(api.AffinityTypeNone))

// ValidateService tests if required fields in the service are set.
func ValidateService(service *api.Service, lister ServiceLister, ctx api.Context) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	if len(service.Name) == 0 {
		allErrs = append(allErrs, errs.NewFieldRequired("name", service.Name))
	} else if !util.IsDNS952Label(service.Name) {
		allErrs = append(allErrs, errs.NewFieldInvalid("name", service.Name, ""))
	}
	if !util.IsDNSSubdomain(service.Namespace) {
		allErrs = append(allErrs, errs.NewFieldInvalid("namespace", service.Namespace, ""))
	}
	if !util.IsValidPortNum(service.Spec.Port) {
		allErrs = append(allErrs, errs.NewFieldInvalid("spec.port", service.Spec.Port, ""))
	}
	if len(service.Spec.Protocol) == 0 {
		service.Spec.Protocol = "TCP"
	} else if !supportedPortProtocols.Has(strings.ToUpper(string(service.Spec.Protocol))) {
		allErrs = append(allErrs, errs.NewFieldNotSupported("spec.protocol", service.Spec.Protocol))
	}

	if service.Spec.Selector != nil {
		allErrs = append(allErrs, validateLabels(service.Spec.Selector, "spec.selector")...)
	}
	allErrs = append(allErrs, validateLabels(service.Labels, "labels")...)

	if service.Spec.CreateExternalLoadBalancer {
		services, err := lister.ListServices(ctx)
		if err != nil {
			allErrs = append(allErrs, errs.NewInternalError(err))
		} else {
			for i := range services.Items {
				if services.Items[i].Name != service.Name &&
					services.Items[i].Spec.CreateExternalLoadBalancer &&
					services.Items[i].Spec.Port == service.Spec.Port {
					allErrs = append(allErrs, errs.NewConflict("service", service.Name, fmt.Errorf("port: %d is already in use", service.Spec.Port)))
					break
				}
			}
		}
	}
	if service.Spec.SessionAffinity == "" {
		service.Spec.SessionAffinity = api.AffinityTypeNone
	} else if !supportedSessionAffinityType.Has(string(service.Spec.SessionAffinity)) {
		allErrs = append(allErrs, errs.NewFieldNotSupported("spec.sessionAffinity", service.Spec.SessionAffinity))
	}

	return allErrs
}

// ValidateReplicationController tests if required fields in the replication controller are set.
func ValidateReplicationController(controller *api.ReplicationController) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	if len(controller.Name) == 0 {
		allErrs = append(allErrs, errs.NewFieldRequired("name", controller.Name))
	}
	if !util.IsDNSSubdomain(controller.Namespace) {
		allErrs = append(allErrs, errs.NewFieldInvalid("namespace", controller.Namespace, ""))
	}
	allErrs = append(allErrs, ValidateReplicationControllerSpec(&controller.Spec).Prefix("spec")...)
	allErrs = append(allErrs, validateLabels(controller.Labels, "labels")...)
	return allErrs
}

// ValidateReplicationControllerSpec tests if required fields in the replication controller spec are set.
func ValidateReplicationControllerSpec(spec *api.ReplicationControllerSpec) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	selector := labels.Set(spec.Selector).AsSelector()
	if selector.Empty() {
		allErrs = append(allErrs, errs.NewFieldRequired("selector", spec.Selector))
	}
	if spec.Replicas < 0 {
		allErrs = append(allErrs, errs.NewFieldInvalid("replicas", spec.Replicas, ""))
	}

	if spec.Template == nil {
		allErrs = append(allErrs, errs.NewFieldRequired("template", spec.Template))
	} else {
		labels := labels.Set(spec.Template.Labels)
		if !selector.Matches(labels) {
			allErrs = append(allErrs, errs.NewFieldInvalid("template.labels", spec.Template.Labels, "selector does not match template"))
		}
		allErrs = append(allErrs, ValidatePodTemplateSpec(spec.Template).Prefix("template")...)
		// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec().
		if spec.Template.Spec.RestartPolicy.Always == nil {
			// TODO: should probably be Unsupported
			// TODO: api.RestartPolicy should have a String() method for nicer printing
			allErrs = append(allErrs, errs.NewFieldInvalid("template.restartPolicy", spec.Template.Spec.RestartPolicy, "must be Always"))
		}
	}
	return allErrs
}

// ValidatePodTemplateSpec validates the spec of a pod template
func ValidatePodTemplateSpec(spec *api.PodTemplateSpec) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	allErrs = append(allErrs, validateLabels(spec.Labels, "labels")...)
	allErrs = append(allErrs, ValidatePodSpec(&spec.Spec).Prefix("spec")...)
	allErrs = append(allErrs, ValidateReadOnlyPersistentDisks(spec.Spec.Volumes).Prefix("spec.volumes")...)
	return allErrs
}

func ValidateReadOnlyPersistentDisks(volumes []api.Volume) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	for _, vol := range volumes {
		if vol.Source.GCEPersistentDisk != nil {
			if vol.Source.GCEPersistentDisk.ReadOnly == false {
				allErrs = append(allErrs, errs.NewFieldInvalid("GCEPersistentDisk.ReadOnly", false, "must be true"))
			}
		}
	}
	return allErrs
}

// ValidateBoundPod tests if required fields on a bound pod are set.
func ValidateBoundPod(pod *api.BoundPod) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	if len(pod.Name) == 0 {
		allErrs = append(allErrs, errs.NewFieldRequired("name", pod.Name))
	} else if !util.IsDNSSubdomain(pod.Name) {
		allErrs = append(allErrs, errs.NewFieldInvalid("name", pod.Name, ""))
	}
	if len(pod.Name) == 0 {
		allErrs = append(allErrs, errs.NewFieldRequired("namespace", pod.Namespace))
	} else if !util.IsDNSSubdomain(pod.Namespace) {
		allErrs = append(allErrs, errs.NewFieldInvalid("namespace", pod.Namespace, ""))
	}
	allErrs = append(allErrs, ValidatePodSpec(&pod.Spec).Prefix("spec")...)
	return allErrs
}

// ValidateMinion tests if required fields in the minion are set.
func ValidateMinion(minion *api.Node) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}
	if len(minion.Namespace) != 0 {
		allErrs = append(allErrs, errs.NewFieldInvalid("namespace", minion.Namespace, ""))
	}
	if len(minion.Name) == 0 {
		allErrs = append(allErrs, errs.NewFieldRequired("name", minion.Name))
	}
	allErrs = append(allErrs, validateLabels(minion.Labels, "labels")...)
	return allErrs
}

// ValidateMinionUpdate tests to make sure a minion update can be applied.  Modifies oldMinion.
func ValidateMinionUpdate(oldMinion *api.Node, minion *api.Node) errs.ValidationErrorList {
	allErrs := errs.ValidationErrorList{}

	if !reflect.DeepEqual(minion.Status, api.NodeStatus{}) {
		allErrs = append(allErrs, errs.NewFieldInvalid("status", minion.Status, "status must be empty"))
	}

	// Allow users to update labels and capacity
	oldMinion.Labels = minion.Labels
	oldMinion.Spec.Capacity = minion.Spec.Capacity
	// Clear status
	oldMinion.Status = minion.Status

	if !reflect.DeepEqual(oldMinion, minion) {
		glog.V(4).Infof("Update failed validation %#v vs %#v", oldMinion, minion)
		allErrs = append(allErrs, fmt.Errorf("update contains more than labels or capacity changes"))
	}
	return allErrs
}


text:
package com.amazonaws.services.rds.model.transform;

import javax.xml.stream.events.XMLEvent;
import javax.annotation.Generated;

import com.amazonaws.services.rds.model.*;
import com.amazonaws.transform.Unmarshaller;

import com.amazonaws.transform.StaxUnmarshallerContext;
import com.amazonaws.transform.SimpleTypeStaxUnmarshallers.*;

/**
 * DBSecurityGroupMembership StAX Unmarshaller
 */

@Generated("com.amazonaws:aws-java-sdk-code-generator")
public class DBSecurityGroupMembershipStaxUnmarshaller implements Unmarshaller<DBSecurityGroupMembership, StaxUnmarshallerContext> {

    public DBSecurityGroupMembership unmarshall(StaxUnmarshallerContext context) throws Exception {
        DBSecurityGroupMembership dBSecurityGroupMembership = new DBSecurityGroupMembership();
        int originalDepth = context.getCurrentDepth();
        int targetDepth = originalDepth + 1;

        if (context.isStartOfDocument())
            targetDepth += 1;

        while (true) {
            XMLEvent xmlEvent = context.nextEvent();
            if (xmlEvent.isEndDocument())
                return dBSecurityGroupMembership;

            if (xmlEvent.isAttribute() || xmlEvent.isStartElement()) {

                if (context.testExpression("DBSecurityGroupName", targetDepth)) {
                    dBSecurityGroupMembership.setDBSecurityGroupName(StringStaxUnmarshaller.getInstance().unmarshall(context));
                    continue;
                }

                if (context.testExpression("Status", targetDepth)) {
                    dBSecurityGroupMembership.setStatus(StringStaxUnmarshaller.getInstance().unmarshall(context));
                    continue;
                }
            } else if (xmlEvent.isEndElement()) {
                if (context.getCurrentDepth() < originalDepth) {
                    return dBSecurityGroupMembership;
                }
            }
        }
    }

    private static DBSecurityGroupMembershipStaxUnmarshaller instance;

    public static DBSecurityGroupMembershipStaxUnmarshaller getInstance() {
        if (instance == null)
            instance = new DBSecurityGroupMembershipStaxUnmarshaller();
        return instance;
    }
}