Pseudofsize procfs(5).
This commit is contained in:
parent
3bff55e81b
commit
3a669c52a8
@ -644,19 +644,18 @@ fs/nwfs/nwfs_vfsops.c optional nwfs
|
||||
fs/nwfs/nwfs_vnops.c optional nwfs
|
||||
fs/portalfs/portal_vfsops.c optional portalfs
|
||||
fs/portalfs/portal_vnops.c optional portalfs
|
||||
fs/procfs/procfs.c optional procfs
|
||||
fs/procfs/procfs_ctl.c optional procfs
|
||||
fs/procfs/procfs_dbregs.c optional procfs
|
||||
fs/procfs/procfs_fpregs.c optional procfs
|
||||
fs/procfs/procfs_ioctl.c optional procfs
|
||||
fs/procfs/procfs_map.c optional procfs
|
||||
fs/procfs/procfs_mem.c optional procfs
|
||||
fs/procfs/procfs_note.c optional procfs
|
||||
fs/procfs/procfs_regs.c optional procfs
|
||||
fs/procfs/procfs_rlimit.c optional procfs
|
||||
fs/procfs/procfs_status.c optional procfs
|
||||
fs/procfs/procfs_subr.c optional procfs
|
||||
fs/procfs/procfs_type.c optional procfs
|
||||
fs/procfs/procfs_vfsops.c optional procfs
|
||||
fs/procfs/procfs_vnops.c optional procfs
|
||||
fs/pseudofs/pseudofs.c optional pseudofs
|
||||
fs/pseudofs/pseudofs_fileno.c optional pseudofs
|
||||
fs/pseudofs/pseudofs_vncache.c optional pseudofs
|
||||
|
198
sys/fs/procfs/procfs.c
Normal file
198
sys/fs/procfs/procfs.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Dag-Erling Smørgrav
|
||||
* Copyright (c) 1993 Jan-Simon Pendry
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry.
|
||||
*
|
||||
* 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 the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)procfs_vfsops.c 8.7 (Berkeley) 5/10/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
/*
|
||||
* Filler function for proc/pid/self
|
||||
*/
|
||||
static int
|
||||
procfs_doprocfile(PFS_FILL_ARGS)
|
||||
{
|
||||
char *fullpath = "unknown";
|
||||
char *freepath = NULL;
|
||||
|
||||
vn_fullpath(td, td->td_proc->p_textvp, &fullpath, &freepath);
|
||||
sbuf_printf(sb, "%s", fullpath);
|
||||
if (freepath)
|
||||
free(freepath, M_TEMP);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Filler function for proc/curproc
|
||||
*/
|
||||
static int
|
||||
procfs_docurproc(PFS_FILL_ARGS)
|
||||
{
|
||||
sbuf_printf(sb, "%ld", (long)td->td_proc->p_pid);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust mode for some nodes that need it
|
||||
*/
|
||||
int
|
||||
procfs_attr(PFS_ATTR_ARGS)
|
||||
{
|
||||
/* XXX inefficient, split into separate functions */
|
||||
if (strcmp(pn->pn_name, "ctl") == 0 ||
|
||||
strcmp(pn->pn_name, "note") == 0 ||
|
||||
strcmp(pn->pn_name, "notepg") == 0)
|
||||
vap->va_mode = 0200;
|
||||
else if (strcmp(pn->pn_name, "mem") == 0 ||
|
||||
strcmp(pn->pn_name, "regs") == 0 ||
|
||||
strcmp(pn->pn_name, "dbregs") == 0 ||
|
||||
strcmp(pn->pn_name, "fpregs") == 0)
|
||||
vap->va_mode = 0600;
|
||||
|
||||
/* p is locked by caller */
|
||||
vap->va_uid = p->p_ucred->cr_uid;
|
||||
vap->va_gid = p->p_ucred->cr_gid;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Visibility: some files only exist for non-system processes
|
||||
* Non-static because linprocfs uses it.
|
||||
*/
|
||||
int
|
||||
procfs_notsystem(PFS_VIS_ARGS)
|
||||
{
|
||||
return ((p->p_flag & P_SYSTEM) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Visibility: some files are only visible to process that can debug
|
||||
* the target process.
|
||||
*/
|
||||
int
|
||||
procfs_candebug(PFS_VIS_ARGS)
|
||||
{
|
||||
return ((p->p_flag & P_SYSTEM) == 0 &&
|
||||
p_candebug(td->td_proc, p) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
static int
|
||||
procfs_init(PFS_INIT_ARGS)
|
||||
{
|
||||
struct pfs_node *root;
|
||||
struct pfs_node *dir;
|
||||
struct pfs_node *node;
|
||||
|
||||
root = pi->pi_root;
|
||||
|
||||
pfs_create_link(root, "curproc", &procfs_docurproc,
|
||||
NULL, NULL, 0);
|
||||
|
||||
dir = pfs_create_dir(root, "pid",
|
||||
&procfs_attr, NULL, PFS_PROCDEP);
|
||||
pfs_create_file(dir, "cmdline", &procfs_doproccmdline,
|
||||
NULL, NULL, PFS_RD);
|
||||
pfs_create_file(dir, "ctl", &procfs_doprocctl,
|
||||
&procfs_attr, NULL, PFS_WR);
|
||||
pfs_create_file(dir, "dbregs", &procfs_doprocdbregs,
|
||||
&procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
|
||||
pfs_create_file(dir, "etype", &procfs_doproctype,
|
||||
NULL, NULL, PFS_RD);
|
||||
pfs_create_file(dir, "fpregs", &procfs_doprocfpregs,
|
||||
&procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
|
||||
pfs_create_file(dir, "map", &procfs_doprocmap,
|
||||
NULL, &procfs_notsystem, PFS_RD);
|
||||
node = pfs_create_file(dir, "mem", &procfs_doprocmem,
|
||||
&procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
|
||||
#ifdef PROCFS_DEBUG
|
||||
node->pn_ioctl = &procfs_ioctl;
|
||||
node->pn_close = &procfs_close;
|
||||
#endif
|
||||
pfs_create_file(dir, "note", &procfs_doprocnote,
|
||||
&procfs_attr, &procfs_candebug, PFS_WR);
|
||||
pfs_create_file(dir, "notepg", &procfs_doprocnote,
|
||||
&procfs_attr, &procfs_candebug, PFS_WR);
|
||||
pfs_create_file(dir, "regs", &procfs_doprocregs,
|
||||
&procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
|
||||
pfs_create_file(dir, "rlimit", &procfs_doprocrlimit,
|
||||
NULL, NULL, PFS_RD);
|
||||
pfs_create_file(dir, "status", &procfs_doprocstatus,
|
||||
NULL, NULL, PFS_RD);
|
||||
|
||||
pfs_create_link(dir, "file", &procfs_doprocfile,
|
||||
NULL, procfs_notsystem, 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destructor
|
||||
*/
|
||||
static int
|
||||
procfs_uninit(PFS_INIT_ARGS)
|
||||
{
|
||||
|
||||
/* nothing to do, pseudofs will GC */
|
||||
return (0);
|
||||
}
|
||||
|
||||
PSEUDOFS(procfs, 1);
|
@ -40,109 +40,30 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* The different types of node in a procfs filesystem
|
||||
*/
|
||||
typedef enum {
|
||||
Proot, /* the filesystem root */
|
||||
Pcurproc, /* symbolic link for curproc */
|
||||
Pproc, /* a process-specific sub-directory */
|
||||
Pfile, /* the executable file */
|
||||
Pmem, /* the process's memory image */
|
||||
Pregs, /* the process's register set */
|
||||
Pfpregs, /* the process's FP register set */
|
||||
Pdbregs, /* the process's debug register set */
|
||||
Pctl, /* process control */
|
||||
Pstatus, /* process status */
|
||||
Pnote, /* process notifier */
|
||||
Pnotepg, /* process group notifier */
|
||||
Pmap, /* memory map */
|
||||
Ptype, /* executable type */
|
||||
Pcmdline, /* command line */
|
||||
Prlimit /* resource limits */
|
||||
} pfstype;
|
||||
|
||||
/*
|
||||
* control data for the proc file system.
|
||||
*/
|
||||
struct pfsnode {
|
||||
struct pfsnode *pfs_next; /* next on list */
|
||||
struct vnode *pfs_vnode; /* vnode associated with this pfsnode */
|
||||
pfstype pfs_type; /* type of procfs node */
|
||||
pid_t pfs_pid; /* associated process */
|
||||
u_short pfs_mode; /* mode bits for stat() */
|
||||
u_long pfs_flags; /* open flags */
|
||||
u_long pfs_fileno; /* unique file id */
|
||||
pid_t pfs_lockowner; /* pfs lock owner */
|
||||
};
|
||||
|
||||
#define PROCFS_NOTELEN 64 /* max length of a note (/proc/$pid/note) */
|
||||
#define PROCFS_CTLLEN 8 /* max length of a ctl msg (/proc/$pid/ctl */
|
||||
#define PROCFS_NAMELEN 8 /* max length of a filename component */
|
||||
|
||||
/*
|
||||
* Kernel stuff follows
|
||||
*/
|
||||
#ifdef _KERNEL
|
||||
#define CNEQ(cnp, s, len) \
|
||||
((cnp)->cn_namelen == (len) && \
|
||||
(bcmp((s), (cnp)->cn_nameptr, (len)) == 0))
|
||||
|
||||
#define PROCFS_FILENO(pid, type) \
|
||||
(((type) < Pproc) ? \
|
||||
((type) + 2) : \
|
||||
((((pid)+1) << 4) + ((int) (type))))
|
||||
int procfs_doproccmdline(PFS_FILL_ARGS);
|
||||
int procfs_doprocctl(PFS_FILL_ARGS);
|
||||
int procfs_doprocdbregs(PFS_FILL_ARGS);
|
||||
int procfs_doprocfpregs(PFS_FILL_ARGS);
|
||||
int procfs_doprocmap(PFS_FILL_ARGS);
|
||||
int procfs_doprocmem(PFS_FILL_ARGS);
|
||||
int procfs_doprocnote(PFS_FILL_ARGS);
|
||||
int procfs_doprocregs(PFS_FILL_ARGS);
|
||||
int procfs_doprocrlimit(PFS_FILL_ARGS);
|
||||
int procfs_doprocstatus(PFS_FILL_ARGS);
|
||||
int procfs_doproctype(PFS_FILL_ARGS);
|
||||
int procfs_ioctl(PFS_IOCTL_ARGS);
|
||||
int procfs_close(PFS_CLOSE_ARGS);
|
||||
|
||||
/*
|
||||
* Convert between pfsnode vnode
|
||||
*/
|
||||
#define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data)
|
||||
#define PFSTOV(pfs) ((pfs)->pfs_vnode)
|
||||
/* Return 1 if process has special kernel digging privileges */
|
||||
int procfs_kmemaccess(struct proc *);
|
||||
|
||||
typedef struct vfs_namemap vfs_namemap_t;
|
||||
struct vfs_namemap {
|
||||
const char *nm_name;
|
||||
int nm_val;
|
||||
};
|
||||
/* Attributes */
|
||||
int procfs_attr(PFS_ATTR_ARGS);
|
||||
|
||||
int vfs_getuserstr __P((struct uio *, char *, int *));
|
||||
vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
|
||||
/* Visbility */
|
||||
int procfs_notsystem(PFS_VIS_ARGS);
|
||||
int procfs_candebug(PFS_VIS_ARGS);
|
||||
|
||||
/* <machine/reg.h> */
|
||||
struct reg;
|
||||
struct fpreg;
|
||||
struct dbreg;
|
||||
|
||||
#define PFIND(pid) (pfind(pid))
|
||||
|
||||
void procfs_exit __P((struct proc *));
|
||||
int procfs_freevp __P((struct vnode *));
|
||||
int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
|
||||
int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_dodbregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_docmdline __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
int procfs_dorlimit __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
|
||||
|
||||
/* functions to check whether or not files should be displayed */
|
||||
int procfs_validfile __P((struct thread *));
|
||||
int procfs_validfpregs __P((struct thread *));
|
||||
int procfs_validregs __P((struct thread *));
|
||||
int procfs_validdbregs __P((struct thread *));
|
||||
int procfs_validmap __P((struct thread *));
|
||||
int procfs_validtype __P((struct thread *));
|
||||
|
||||
#define PROCFS_LOCKED 0x01
|
||||
#define PROCFS_WANT 0x02
|
||||
|
||||
extern vop_t **procfs_vnodeop_p;
|
||||
|
||||
int procfs_root __P((struct mount *, struct vnode **));
|
||||
int procfs_rw __P((struct vop_read_args *));
|
||||
#endif /* _KERNEL */
|
||||
|
@ -44,10 +44,12 @@
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
@ -67,7 +69,12 @@
|
||||
#define PROCFS_CTL_RUN 4
|
||||
#define PROCFS_CTL_WAIT 5
|
||||
|
||||
static vfs_namemap_t ctlnames[] = {
|
||||
struct namemap {
|
||||
const char *nm_name;
|
||||
int nm_val;
|
||||
};
|
||||
|
||||
static struct namemap ctlnames[] = {
|
||||
/* special /proc commands */
|
||||
{ "attach", PROCFS_CTL_ATTACH },
|
||||
{ "detach", PROCFS_CTL_DETACH },
|
||||
@ -77,7 +84,7 @@ static vfs_namemap_t ctlnames[] = {
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static vfs_namemap_t signames[] = {
|
||||
static struct namemap signames[] = {
|
||||
/* regular signal names */
|
||||
{ "hup", SIGHUP }, { "int", SIGINT },
|
||||
{ "quit", SIGQUIT }, { "ill", SIGILL },
|
||||
@ -101,10 +108,7 @@ static vfs_namemap_t signames[] = {
|
||||
static int procfs_control __P((struct proc *curp, struct proc *p, int op));
|
||||
|
||||
static int
|
||||
procfs_control(curp, p, op)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
int op;
|
||||
procfs_control(struct proc *curp, struct proc *p, int op)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
@ -240,7 +244,6 @@ procfs_control(curp, p, op)
|
||||
* Step. Let the target process execute a single instruction.
|
||||
*/
|
||||
case PROCFS_CTL_STEP:
|
||||
_PHOLD(p);
|
||||
PROC_UNLOCK(p);
|
||||
error = proc_sstep(&p->p_thread); /* XXXKSE */
|
||||
PRELE(p);
|
||||
@ -301,26 +304,26 @@ procfs_control(curp, p, op)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_doctl(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
struct proc *p;
|
||||
static struct namemap *
|
||||
findname(struct namemap *nm, char *buf, int buflen)
|
||||
{
|
||||
|
||||
for (; nm->nm_name; nm++)
|
||||
if (bcmp(buf, nm->nm_name, buflen+1) == 0)
|
||||
return (nm);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_doprocctl(PFS_FILL_ARGS)
|
||||
{
|
||||
int xlen;
|
||||
int error;
|
||||
char msg[PROCFS_CTLLEN+1];
|
||||
vfs_namemap_t *nm;
|
||||
struct namemap *nm;
|
||||
|
||||
if (uio->uio_rw != UIO_WRITE)
|
||||
if (uio == NULL || uio->uio_rw != UIO_WRITE)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
xlen = PROCFS_CTLLEN;
|
||||
error = vfs_getuserstr(uio, msg, &xlen);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* Map signal names into signal generation
|
||||
* or debug control. Unknown commands and/or signals
|
||||
@ -332,15 +335,19 @@ procfs_doctl(curp, p, pfs, uio)
|
||||
*/
|
||||
error = EOPNOTSUPP;
|
||||
|
||||
nm = vfs_findname(ctlnames, msg, xlen);
|
||||
sbuf_trim(sb);
|
||||
sbuf_finish(sb);
|
||||
nm = findname(ctlnames, sbuf_data(sb), sbuf_len(sb));
|
||||
if (nm) {
|
||||
error = procfs_control(curp, p, nm->nm_val);
|
||||
printf("procfs: got a %s command\n", sbuf_data(sb));
|
||||
error = procfs_control(td->td_proc, p, nm->nm_val);
|
||||
} else {
|
||||
nm = vfs_findname(signames, msg, xlen);
|
||||
nm = findname(signames, sbuf_data(sb), sbuf_len(sb));
|
||||
if (nm) {
|
||||
printf("procfs: got a sig%s\n", sbuf_data(sb));
|
||||
PROC_LOCK(p);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if (TRACE_WAIT_P(curp, p)) {
|
||||
if (TRACE_WAIT_P(td->td_proc, p)) {
|
||||
p->p_xstat = nm->nm_val;
|
||||
#ifdef FIX_SSTEP
|
||||
FIX_SSTEP(&p->p_thread); /* XXXKSE */
|
||||
|
@ -49,27 +49,22 @@
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <machine/reg.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
int
|
||||
procfs_dodbregs(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doprocdbregs(PFS_FILL_ARGS)
|
||||
{
|
||||
int error;
|
||||
struct dbreg r;
|
||||
char *kv;
|
||||
int kl;
|
||||
|
||||
if (p_candebug(curp, p))
|
||||
if (p_candebug(td->td_proc, p) != 0)
|
||||
return (EPERM);
|
||||
kl = sizeof(r);
|
||||
kv = (char *) &r;
|
||||
@ -79,8 +74,6 @@ procfs_dodbregs(curp, p, pfs, uio)
|
||||
if (kl > uio->uio_resid)
|
||||
kl = uio->uio_resid;
|
||||
|
||||
PHOLD(p);
|
||||
|
||||
if (kl < 0)
|
||||
error = EINVAL;
|
||||
else
|
||||
@ -93,15 +86,7 @@ procfs_dodbregs(curp, p, pfs, uio)
|
||||
else
|
||||
error = proc_write_dbregs(&p->p_thread, &r); /* XXXKSE */
|
||||
}
|
||||
PRELE(p);
|
||||
|
||||
uio->uio_offset = 0;
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_validdbregs(struct thread *td)
|
||||
{
|
||||
|
||||
return ((td->td_proc->p_flag & P_SYSTEM) == 0);
|
||||
}
|
||||
|
@ -46,27 +46,22 @@
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <machine/reg.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
int
|
||||
procfs_dofpregs(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doprocfpregs(PFS_FILL_ARGS)
|
||||
{
|
||||
int error;
|
||||
struct fpreg r;
|
||||
char *kv;
|
||||
int kl;
|
||||
|
||||
if (p_candebug(curp, p))
|
||||
if (p_candebug(td->td_proc, p))
|
||||
return EPERM;
|
||||
kl = sizeof(r);
|
||||
kv = (char *) &r;
|
||||
@ -95,10 +90,3 @@ procfs_dofpregs(curp, p, pfs, uio)
|
||||
uio->uio_offset = 0;
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_validfpregs(struct thread *td)
|
||||
{
|
||||
|
||||
return (( td->td_proc->p_flag & P_SYSTEM) == 0);
|
||||
}
|
||||
|
132
sys/fs/procfs/procfs_ioctl.c
Normal file
132
sys/fs/procfs/procfs_ioctl.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Dag-Erling Coïdan Smørgrav
|
||||
* 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
|
||||
* in this position and unchanged.
|
||||
* 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. 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
#ifdef PROCFS_DEBUG
|
||||
/*
|
||||
* Process ioctls
|
||||
*/
|
||||
int
|
||||
procfs_ioctl(PFS_IOCTL_ARGS)
|
||||
{
|
||||
struct procfs_status *ps;
|
||||
int error, sig;
|
||||
|
||||
PROC_LOCK(p);
|
||||
error = 0;
|
||||
switch (cmd) {
|
||||
case PIOCBIS:
|
||||
p->p_stops |= *(unsigned int *)data;
|
||||
break;
|
||||
case PIOCBIC:
|
||||
p->p_stops &= ~*(unsigned int *)data;
|
||||
break;
|
||||
case PIOCSFL:
|
||||
/* ignore */
|
||||
break;
|
||||
case PIOCGFL:
|
||||
*(unsigned int *)data = 0; /* nope */
|
||||
break;
|
||||
case PIOCWAIT:
|
||||
while (p->p_step == 0) {
|
||||
/* sleep until p stops */
|
||||
error = msleep(&p->p_stype, &p->p_mtx,
|
||||
PWAIT|PCATCH, "pioctl", 0);
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
/* fall through to PIOCSTATUS */
|
||||
case PIOCSTATUS:
|
||||
ps = (struct procfs_status *)data;
|
||||
ps->state = (p->p_step == 0);
|
||||
ps->flags = 0; /* nope */
|
||||
ps->events = p->p_stops;
|
||||
ps->why = p->p_step ? p->p_stype : 0;
|
||||
ps->val = p->p_step ? p->p_xstat : 0;
|
||||
break;
|
||||
case PIOCCONT:
|
||||
if (p->p_step)
|
||||
break;
|
||||
sig = *(int *)data;
|
||||
if (!_SIG_VALID(sig)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
mtx_lock_spin(&sched_lock);
|
||||
p->p_step = 0;
|
||||
if (p->p_stat == SSTOP) {
|
||||
p->p_xstat = sig;
|
||||
setrunnable(&p->p_thread);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
} else {
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
if (sig)
|
||||
psignal(p, sig);
|
||||
}
|
||||
#else
|
||||
if (sig)
|
||||
psignal(p, sig);
|
||||
wakeup(&p->p_step);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
error = (ENOTTY);
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up on last close
|
||||
*/
|
||||
int
|
||||
procfs_close(PFS_CLOSE_ARGS)
|
||||
{
|
||||
if (p != NULL && (p->p_pfsflags & PF_LINGER) == 0) {
|
||||
p->p_pfsflags = 0;
|
||||
p->p_stops = 0;
|
||||
p->p_step = 0;
|
||||
wakeup(&p->p_step);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
@ -44,8 +44,9 @@
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
@ -68,11 +69,7 @@
|
||||
* can try a bigger buffer.
|
||||
*/
|
||||
int
|
||||
procfs_domap(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doprocmap(PFS_FILL_ARGS)
|
||||
{
|
||||
int len;
|
||||
int error;
|
||||
@ -90,7 +87,7 @@ procfs_domap(curp, p, pfs, uio)
|
||||
return (0);
|
||||
|
||||
error = 0;
|
||||
if (map != &curproc->p_vmspace->vm_map)
|
||||
if (map != &curthread->td_proc->p_vmspace->vm_map)
|
||||
vm_map_lock_read(map);
|
||||
for (entry = map->header.next;
|
||||
((uio->uio_resid > 0) && (entry != &map->header));
|
||||
@ -118,23 +115,22 @@ procfs_domap(curp, p, pfs, uio)
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
|
||||
for( lobj = tobj = obj; tobj; tobj = tobj->backing_object)
|
||||
for (lobj = tobj = obj; tobj; tobj = tobj->backing_object)
|
||||
lobj = tobj;
|
||||
|
||||
if (lobj) {
|
||||
switch(lobj->type) {
|
||||
|
||||
default:
|
||||
case OBJT_DEFAULT:
|
||||
default:
|
||||
case OBJT_DEFAULT:
|
||||
type = "default";
|
||||
break;
|
||||
case OBJT_VNODE:
|
||||
case OBJT_VNODE:
|
||||
type = "vnode";
|
||||
break;
|
||||
case OBJT_SWAP:
|
||||
case OBJT_SWAP:
|
||||
type = "swap";
|
||||
break;
|
||||
case OBJT_DEVICE:
|
||||
case OBJT_DEVICE:
|
||||
type = "device";
|
||||
break;
|
||||
}
|
||||
@ -148,13 +144,12 @@ case OBJT_DEVICE:
|
||||
ref_count = 0;
|
||||
shadow_count = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* format:
|
||||
* start, end, resident, private resident, cow, access, type.
|
||||
*/
|
||||
snprintf(mebuffer, sizeof(mebuffer),
|
||||
snprintf(mebuffer, sizeof mebuffer,
|
||||
"0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s\n",
|
||||
(u_long)entry->start, (u_long)entry->end,
|
||||
resident, privateresident, obj,
|
||||
@ -175,14 +170,8 @@ case OBJT_DEVICE:
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
if (map != &curproc->p_vmspace->vm_map)
|
||||
if (map != &curthread->td_proc->p_vmspace->vm_map)
|
||||
vm_map_unlock_read(map);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
procfs_validmap(struct thread *td)
|
||||
{
|
||||
return ((td->td_proc->p_flag & P_SYSTEM) == 0);
|
||||
return (error);
|
||||
}
|
||||
|
@ -41,14 +41,13 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
/*
|
||||
@ -58,20 +57,17 @@
|
||||
* from the kernel address space.
|
||||
*/
|
||||
int
|
||||
procfs_domem(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doprocmem(PFS_FILL_ARGS)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (uio->uio_resid == 0)
|
||||
return (0);
|
||||
|
||||
error = p_candebug(curp, p);
|
||||
error = p_candebug(td->td_proc, p);
|
||||
if (error)
|
||||
return (error);
|
||||
error = proc_rwmem(p, uio);
|
||||
|
||||
return (proc_rwmem(p, uio));
|
||||
return (error);
|
||||
}
|
||||
|
@ -40,28 +40,18 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sbuf.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
int
|
||||
procfs_donote(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doprocnote(PFS_FILL_ARGS)
|
||||
{
|
||||
int xlen;
|
||||
int error;
|
||||
char note[PROCFS_NOTELEN+1];
|
||||
|
||||
if (uio->uio_rw != UIO_WRITE)
|
||||
return (EINVAL);
|
||||
|
||||
xlen = PROCFS_NOTELEN;
|
||||
error = vfs_getuserstr(uio, note, &xlen);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
sbuf_trim(sb);
|
||||
sbuf_finish(sb);
|
||||
/* send to process's notify function */
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
@ -46,28 +46,22 @@
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <machine/reg.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
int
|
||||
procfs_doregs(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doprocregs(PFS_FILL_ARGS)
|
||||
{
|
||||
int error;
|
||||
struct reg r;
|
||||
char *kv;
|
||||
int kl;
|
||||
|
||||
if (p_candebug(curp, p))
|
||||
if (p_candebug(td->td_proc, p))
|
||||
return EPERM;
|
||||
kl = sizeof(r);
|
||||
kv = (char *) &r;
|
||||
@ -96,10 +90,3 @@ procfs_doregs(curp, p, pfs, uio)
|
||||
uio->uio_offset = 0;
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_validregs(struct thread *td)
|
||||
{
|
||||
|
||||
return ((td->td_proc->p_flag & P_SYSTEM) == 0);
|
||||
}
|
||||
|
@ -48,31 +48,18 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sbuf.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
|
||||
int
|
||||
procfs_dorlimit(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doprocrlimit(PFS_FILL_ARGS)
|
||||
{
|
||||
char *ps;
|
||||
int i;
|
||||
int xlen;
|
||||
int error;
|
||||
char psbuf[512]; /* XXX - conservative */
|
||||
|
||||
if (uio->uio_rw != UIO_READ)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
|
||||
ps = psbuf;
|
||||
|
||||
for (i = 0; i < RLIM_NLIMITS; i++) {
|
||||
|
||||
@ -80,7 +67,7 @@ procfs_dorlimit(curp, p, pfs, uio)
|
||||
* Add the rlimit ident
|
||||
*/
|
||||
|
||||
ps += sprintf(ps, "%s ", rlimit_ident[i]);
|
||||
sbuf_printf(sb, "%s ", rlimit_ident[i]);
|
||||
|
||||
/*
|
||||
* Replace RLIM_INFINITY with -1 in the string
|
||||
@ -91,9 +78,9 @@ procfs_dorlimit(curp, p, pfs, uio)
|
||||
*/
|
||||
|
||||
if (p->p_rlimit[i].rlim_cur == RLIM_INFINITY) {
|
||||
ps += sprintf(ps, "-1 ");
|
||||
sbuf_printf(sb, "-1 ");
|
||||
} else {
|
||||
ps += sprintf(ps, "%llu ",
|
||||
sbuf_printf(sb, "%llu ",
|
||||
(unsigned long long)p->p_rlimit[i].rlim_cur);
|
||||
}
|
||||
|
||||
@ -102,27 +89,13 @@ procfs_dorlimit(curp, p, pfs, uio)
|
||||
*/
|
||||
|
||||
if (p->p_rlimit[i].rlim_max == RLIM_INFINITY) {
|
||||
ps += sprintf(ps, "-1\n");
|
||||
sbuf_printf(sb, "-1\n");
|
||||
} else {
|
||||
ps += sprintf(ps, "%llu\n",
|
||||
sbuf_printf(sb, "%llu\n",
|
||||
(unsigned long long)p->p_rlimit[i].rlim_max);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This logic is rather tasty - but its from procfs_status.c, so
|
||||
* I guess I'll use it here.
|
||||
*/
|
||||
|
||||
xlen = ps - psbuf;
|
||||
xlen -= uio->uio_offset;
|
||||
ps = psbuf + uio->uio_offset;
|
||||
xlen = imin(xlen, uio->uio_resid);
|
||||
if (xlen <= 0)
|
||||
error = 0;
|
||||
else
|
||||
error = uiomove(ps, xlen, uio);
|
||||
|
||||
return (error);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -49,36 +49,26 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
#define DOCHECK() do { if (ps >= psbuf+sizeof(psbuf)) goto bailout; } while (0)
|
||||
int
|
||||
procfs_dostatus(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doprocstatus(PFS_FILL_ARGS)
|
||||
{
|
||||
struct session *sess;
|
||||
struct tty *tp;
|
||||
struct ucred *cr;
|
||||
char *ps, *pc;
|
||||
char *pc;
|
||||
char *sep;
|
||||
int pid, ppid, pgid, sid;
|
||||
int i;
|
||||
int xlen;
|
||||
int error;
|
||||
char psbuf[256]; /* XXX - conservative */
|
||||
|
||||
if (uio->uio_rw != UIO_READ)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
pid = p->p_pid;
|
||||
PROC_LOCK(p);
|
||||
@ -91,45 +81,31 @@ procfs_dostatus(curp, p, pfs, uio)
|
||||
/* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg
|
||||
euid ruid rgid,egid,groups[1 .. NGROUPS]
|
||||
*/
|
||||
KASSERT(sizeof(psbuf) > MAXCOMLEN,
|
||||
("Too short buffer for new MAXCOMLEN"));
|
||||
|
||||
ps = psbuf;
|
||||
pc = p->p_comm;
|
||||
xlen = strlen(p->p_comm);
|
||||
do {
|
||||
if (*pc < 33 || *pc > 126 || *pc == '\\')
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\\%03o",
|
||||
*pc);
|
||||
sbuf_printf(sb, "\\%03o", *pc);
|
||||
else
|
||||
*ps++ = *pc;
|
||||
DOCHECK();
|
||||
} while (++pc < p->p_comm + xlen);
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
||||
" %d %d %d %d ", pid, ppid, pgid, sid);
|
||||
DOCHECK();
|
||||
sbuf_putc(sb, *pc);
|
||||
} while (*++pc);
|
||||
sbuf_printf(sb, " %d %d %d %d ", pid, ppid, pgid, sid);
|
||||
if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp))
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
||||
"%d,%d ", major(tp->t_dev), minor(tp->t_dev));
|
||||
sbuf_printf(sb, "%d,%d ", major(tp->t_dev), minor(tp->t_dev));
|
||||
else
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
||||
"%d,%d ", -1, -1);
|
||||
DOCHECK();
|
||||
sbuf_printf(sb, "%d,%d ", -1, -1);
|
||||
|
||||
sep = "";
|
||||
if (sess->s_ttyvp) {
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "%sctty", sep);
|
||||
sbuf_printf(sb, "%sctty", sep);
|
||||
sep = ",";
|
||||
DOCHECK();
|
||||
}
|
||||
if (SESS_LEADER(p)) {
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "%ssldr", sep);
|
||||
sbuf_printf(sb, "%ssldr", sep);
|
||||
sep = ",";
|
||||
DOCHECK();
|
||||
}
|
||||
if (*sep != ',') {
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "noflags");
|
||||
DOCHECK();
|
||||
sbuf_printf(sb, "noflags");
|
||||
}
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
@ -138,92 +114,56 @@ procfs_dostatus(curp, p, pfs, uio)
|
||||
|
||||
calcru(p, &ut, &st, (struct timeval *) NULL);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
||||
" %lld,%ld %ld,%ld %ld,%ld",
|
||||
sbuf_printf(sb, " %lld,%ld %ld,%ld %ld,%ld",
|
||||
(long long)p->p_stats->p_start.tv_sec,
|
||||
p->p_stats->p_start.tv_usec,
|
||||
(long)ut.tv_sec, ut.tv_usec,
|
||||
(long)st.tv_sec, st.tv_usec);
|
||||
ut.tv_sec, ut.tv_usec,
|
||||
st.tv_sec, st.tv_usec);
|
||||
} else {
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
||||
" -1,-1 -1,-1 -1,-1");
|
||||
sbuf_printf(sb, " -1,-1 -1,-1 -1,-1");
|
||||
}
|
||||
DOCHECK();
|
||||
|
||||
if (p->p_flag & P_KSES) {
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %s",
|
||||
"-kse- ");
|
||||
sbuf_printf(sb, " %s", "-kse- ");
|
||||
} else {
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %s",
|
||||
sbuf_printf(sb, " %s",
|
||||
(p->p_thread.td_wchan && p->p_thread.td_wmesg) ?
|
||||
p->p_thread.td_wmesg : "nochan");
|
||||
}
|
||||
DOCHECK();
|
||||
|
||||
cr = p->p_ucred;
|
||||
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %lu %lu %lu",
|
||||
sbuf_printf(sb, " %lu %lu %lu",
|
||||
(u_long)cr->cr_uid,
|
||||
(u_long)cr->cr_ruid,
|
||||
(u_long)cr->cr_rgid);
|
||||
DOCHECK();
|
||||
|
||||
/* egid (cr->cr_svgid) is equal to cr_ngroups[0]
|
||||
see also getegid(2) in /sys/kern/kern_prot.c */
|
||||
|
||||
for (i = 0; i < cr->cr_ngroups; i++) {
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
||||
",%lu", (u_long)cr->cr_groups[i]);
|
||||
DOCHECK();
|
||||
sbuf_printf(sb, ",%lu", (u_long)cr->cr_groups[i]);
|
||||
}
|
||||
|
||||
if (jailed(p->p_ucred)) {
|
||||
mtx_lock(&p->p_ucred->cr_prison->pr_mtx);
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
||||
" %s", p->p_ucred->cr_prison->pr_host);
|
||||
sbuf_printf(sb, " %s", p->p_ucred->cr_prison->pr_host);
|
||||
mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
|
||||
} else {
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " -");
|
||||
sbuf_printf(sb, " -");
|
||||
}
|
||||
DOCHECK();
|
||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\n");
|
||||
DOCHECK();
|
||||
sbuf_printf(sb, "\n");
|
||||
|
||||
xlen = ps - psbuf;
|
||||
xlen -= uio->uio_offset;
|
||||
ps = psbuf + uio->uio_offset;
|
||||
xlen = imin(xlen, uio->uio_resid);
|
||||
if (xlen <= 0)
|
||||
error = 0;
|
||||
else
|
||||
error = uiomove(ps, xlen, uio);
|
||||
|
||||
return (error);
|
||||
|
||||
bailout:
|
||||
return (ENOMEM);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_docmdline(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doproccmdline(PFS_FILL_ARGS)
|
||||
{
|
||||
char *ps;
|
||||
int xlen;
|
||||
int error;
|
||||
char *buf, *bp;
|
||||
int buflen;
|
||||
struct ps_strings pstr;
|
||||
int i;
|
||||
size_t bytes_left, done;
|
||||
int error, i;
|
||||
|
||||
if (uio->uio_rw != UIO_READ)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
/*
|
||||
* If we are using the ps/cmdline caching, use that. Otherwise
|
||||
* revert back to the old way which only implements full cmdline
|
||||
@ -234,47 +174,19 @@ procfs_docmdline(curp, p, pfs, uio)
|
||||
* Linux behaviour is to return zero-length in this case.
|
||||
*/
|
||||
|
||||
if (p->p_args && (ps_argsopen || !p_cansee(curp, p))) {
|
||||
bp = p->p_args->ar_args;
|
||||
buflen = p->p_args->ar_length;
|
||||
buf = 0;
|
||||
} else if (p != curp) {
|
||||
bp = p->p_comm;
|
||||
buflen = MAXCOMLEN;
|
||||
buf = 0;
|
||||
if (p->p_args && (ps_argsopen || !p_cansee(td->td_proc, p))) {
|
||||
sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
|
||||
} else if (p != td->td_proc) {
|
||||
sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm);
|
||||
} else {
|
||||
buflen = 256;
|
||||
MALLOC(buf, char *, buflen + 1, M_TEMP, M_WAITOK);
|
||||
bp = buf;
|
||||
ps = buf;
|
||||
error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr));
|
||||
if (error) {
|
||||
FREE(buf, M_TEMP);
|
||||
if (error)
|
||||
return (error);
|
||||
for (i = 0; i < pstr.ps_nargvstr; i++) {
|
||||
sbuf_copyin(sb, pstr.ps_argvstr[i], 0);
|
||||
sbuf_printf(sb, "%c", '\0');
|
||||
}
|
||||
bytes_left = buflen;
|
||||
for (i = 0; bytes_left && (i < pstr.ps_nargvstr); i++) {
|
||||
error = copyinstr(pstr.ps_argvstr[i], ps,
|
||||
bytes_left, &done);
|
||||
/* If too long or malformed, just truncate */
|
||||
if (error) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
ps += done;
|
||||
bytes_left -= done;
|
||||
}
|
||||
buflen = ps - buf;
|
||||
}
|
||||
|
||||
buflen -= uio->uio_offset;
|
||||
ps = bp + uio->uio_offset;
|
||||
xlen = min(buflen, uio->uio_resid);
|
||||
if (xlen <= 0)
|
||||
error = 0;
|
||||
else
|
||||
error = uiomove(ps, xlen, uio);
|
||||
if (buf)
|
||||
FREE(buf, M_TEMP);
|
||||
return (error);
|
||||
return (0);
|
||||
}
|
||||
|
@ -1,413 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1993 Jan-Simon Pendry
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry.
|
||||
*
|
||||
* 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 the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
static struct pfsnode *pfshead;
|
||||
static int pfsvplock;
|
||||
|
||||
/*
|
||||
* allocate a pfsnode/vnode pair. the vnode is
|
||||
* referenced, but not locked.
|
||||
*
|
||||
* the pid, pfs_type, and mount point uniquely
|
||||
* identify a pfsnode. the mount point is needed
|
||||
* because someone might mount this filesystem
|
||||
* twice.
|
||||
*
|
||||
* all pfsnodes are maintained on a singly-linked
|
||||
* list. new nodes are only allocated when they cannot
|
||||
* be found on this list. entries on the list are
|
||||
* removed when the vfs reclaim entry is called.
|
||||
*
|
||||
* a single lock is kept for the entire list. this is
|
||||
* needed because the getnewvnode() function can block
|
||||
* waiting for a vnode to become free, in which case there
|
||||
* may be more than one process trying to get the same
|
||||
* vnode. this lock is only taken if we are going to
|
||||
* call getnewvnode, since the kernel itself is single-threaded.
|
||||
*
|
||||
* if an entry is found on the list, then call vget() to
|
||||
* take a reference. this is done because there may be
|
||||
* zero references to it and so it needs to removed from
|
||||
* the vnode free list.
|
||||
*/
|
||||
int
|
||||
procfs_allocvp(mp, vpp, pid, pfs_type)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
long pid;
|
||||
pfstype pfs_type;
|
||||
{
|
||||
struct thread *td = curthread; /* XXX */
|
||||
struct pfsnode *pfs;
|
||||
struct vnode *vp;
|
||||
struct pfsnode **pp;
|
||||
int error;
|
||||
|
||||
loop:
|
||||
for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) {
|
||||
vp = PFSTOV(pfs);
|
||||
if (pfs->pfs_pid == pid &&
|
||||
pfs->pfs_type == pfs_type &&
|
||||
vp->v_mount == mp) {
|
||||
if (vget(vp, 0, td))
|
||||
goto loop;
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* otherwise lock the vp list while we call getnewvnode
|
||||
* since that can block.
|
||||
*/
|
||||
if (pfsvplock & PROCFS_LOCKED) {
|
||||
pfsvplock |= PROCFS_WANT;
|
||||
(void) tsleep((caddr_t) &pfsvplock, PINOD, "pfsavp", 0);
|
||||
goto loop;
|
||||
}
|
||||
pfsvplock |= PROCFS_LOCKED;
|
||||
|
||||
/*
|
||||
* Do the MALLOC before the getnewvnode since doing so afterward
|
||||
* might cause a bogus v_data pointer to get dereferenced
|
||||
* elsewhere if MALLOC should block.
|
||||
*/
|
||||
MALLOC(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
|
||||
|
||||
if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) != 0) {
|
||||
FREE(pfs, M_TEMP);
|
||||
goto out;
|
||||
}
|
||||
vp = *vpp;
|
||||
|
||||
vp->v_data = pfs;
|
||||
|
||||
pfs->pfs_next = 0;
|
||||
pfs->pfs_pid = (pid_t) pid;
|
||||
pfs->pfs_type = pfs_type;
|
||||
pfs->pfs_vnode = vp;
|
||||
pfs->pfs_flags = 0;
|
||||
pfs->pfs_lockowner = 0;
|
||||
pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type);
|
||||
|
||||
switch (pfs_type) {
|
||||
case Proot: /* /proc = dr-xr-xr-x */
|
||||
pfs->pfs_mode = (VREAD|VEXEC) |
|
||||
(VREAD|VEXEC) >> 3 |
|
||||
(VREAD|VEXEC) >> 6;
|
||||
vp->v_type = VDIR;
|
||||
vp->v_flag = VROOT;
|
||||
break;
|
||||
|
||||
case Pcurproc: /* /proc/curproc = lr--r--r-- */
|
||||
pfs->pfs_mode = (VREAD) |
|
||||
(VREAD >> 3) |
|
||||
(VREAD >> 6);
|
||||
vp->v_type = VLNK;
|
||||
break;
|
||||
|
||||
case Pproc:
|
||||
pfs->pfs_mode = (VREAD|VEXEC) |
|
||||
(VREAD|VEXEC) >> 3 |
|
||||
(VREAD|VEXEC) >> 6;
|
||||
vp->v_type = VDIR;
|
||||
break;
|
||||
|
||||
case Pfile:
|
||||
pfs->pfs_mode = (VREAD|VEXEC) |
|
||||
(VREAD|VEXEC) >> 3 |
|
||||
(VREAD|VEXEC) >> 6;
|
||||
vp->v_type = VLNK;
|
||||
break;
|
||||
|
||||
case Pmem:
|
||||
pfs->pfs_mode = (VREAD|VWRITE);
|
||||
vp->v_type = VREG;
|
||||
break;
|
||||
|
||||
case Pregs:
|
||||
case Pfpregs:
|
||||
case Pdbregs:
|
||||
pfs->pfs_mode = (VREAD|VWRITE);
|
||||
vp->v_type = VREG;
|
||||
break;
|
||||
|
||||
case Pctl:
|
||||
case Pnote:
|
||||
case Pnotepg:
|
||||
pfs->pfs_mode = (VWRITE);
|
||||
vp->v_type = VREG;
|
||||
break;
|
||||
|
||||
case Ptype:
|
||||
case Pmap:
|
||||
case Pstatus:
|
||||
case Pcmdline:
|
||||
case Prlimit:
|
||||
pfs->pfs_mode = (VREAD) |
|
||||
(VREAD >> 3) |
|
||||
(VREAD >> 6);
|
||||
vp->v_type = VREG;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("procfs_allocvp");
|
||||
}
|
||||
|
||||
/* add to procfs vnode list */
|
||||
for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next)
|
||||
continue;
|
||||
*pp = pfs;
|
||||
|
||||
out:
|
||||
pfsvplock &= ~PROCFS_LOCKED;
|
||||
|
||||
if (pfsvplock & PROCFS_WANT) {
|
||||
pfsvplock &= ~PROCFS_WANT;
|
||||
wakeup((caddr_t) &pfsvplock);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_freevp(vp)
|
||||
struct vnode *vp;
|
||||
{
|
||||
struct pfsnode **pfspp;
|
||||
struct pfsnode *pfs = VTOPFS(vp);
|
||||
|
||||
for (pfspp = &pfshead; *pfspp != 0; pfspp = &(*pfspp)->pfs_next) {
|
||||
if (*pfspp == pfs) {
|
||||
*pfspp = pfs->pfs_next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FREE(vp->v_data, M_TEMP);
|
||||
vp->v_data = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_rw(ap)
|
||||
struct vop_read_args *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct uio *uio = ap->a_uio;
|
||||
struct proc *curp = uio->uio_td->td_proc;
|
||||
struct pfsnode *pfs = VTOPFS(vp);
|
||||
struct proc *p;
|
||||
int rtval;
|
||||
|
||||
p = PFIND(pfs->pfs_pid);
|
||||
if (p == NULL)
|
||||
return (EINVAL);
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
mp_fixme("pfs_lockowner needs a lock");
|
||||
while (pfs->pfs_lockowner) {
|
||||
tsleep(&pfs->pfs_lockowner, PRIBIO, "pfslck", 0);
|
||||
}
|
||||
pfs->pfs_lockowner = curproc->p_pid;
|
||||
|
||||
switch (pfs->pfs_type) {
|
||||
case Pnote:
|
||||
case Pnotepg:
|
||||
rtval = procfs_donote(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Pregs:
|
||||
rtval = procfs_doregs(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Pfpregs:
|
||||
rtval = procfs_dofpregs(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Pdbregs:
|
||||
rtval = procfs_dodbregs(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Pctl:
|
||||
rtval = procfs_doctl(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Pstatus:
|
||||
rtval = procfs_dostatus(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Pmap:
|
||||
rtval = procfs_domap(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Pmem:
|
||||
rtval = procfs_domem(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Ptype:
|
||||
rtval = procfs_dotype(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Pcmdline:
|
||||
rtval = procfs_docmdline(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
case Prlimit:
|
||||
rtval = procfs_dorlimit(curp, p, pfs, uio);
|
||||
break;
|
||||
|
||||
default:
|
||||
rtval = EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
pfs->pfs_lockowner = 0;
|
||||
wakeup(&pfs->pfs_lockowner);
|
||||
return rtval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a string from userland into (buf). Strip a trailing
|
||||
* nl character (to allow easy access from the shell).
|
||||
* The buffer should be *buflenp + 1 chars long. vfs_getuserstr
|
||||
* will automatically add a nul char at the end.
|
||||
*
|
||||
* Returns 0 on success or the following errors
|
||||
*
|
||||
* EINVAL: file offset is non-zero.
|
||||
* EMSGSIZE: message is longer than kernel buffer
|
||||
* EFAULT: user i/o buffer is not addressable
|
||||
*/
|
||||
int
|
||||
vfs_getuserstr(uio, buf, buflenp)
|
||||
struct uio *uio;
|
||||
char *buf;
|
||||
int *buflenp;
|
||||
{
|
||||
int xlen;
|
||||
int error;
|
||||
|
||||
if (uio->uio_offset != 0)
|
||||
return (EINVAL);
|
||||
|
||||
xlen = *buflenp;
|
||||
|
||||
/* must be able to read the whole string in one go */
|
||||
if (xlen < uio->uio_resid)
|
||||
return (EMSGSIZE);
|
||||
xlen = uio->uio_resid;
|
||||
|
||||
if ((error = uiomove(buf, xlen, uio)) != 0)
|
||||
return (error);
|
||||
|
||||
/* allow multiple writes without seeks */
|
||||
uio->uio_offset = 0;
|
||||
|
||||
/* cleanup string and remove trailing newline */
|
||||
buf[xlen] = '\0';
|
||||
xlen = strlen(buf);
|
||||
if (xlen > 0 && buf[xlen-1] == '\n')
|
||||
buf[--xlen] = '\0';
|
||||
*buflenp = xlen;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
vfs_namemap_t *
|
||||
vfs_findname(nm, buf, buflen)
|
||||
vfs_namemap_t *nm;
|
||||
char *buf;
|
||||
int buflen;
|
||||
{
|
||||
|
||||
for (; nm->nm_name; nm++)
|
||||
if (bcmp(buf, nm->nm_name, buflen+1) == 0)
|
||||
return (nm);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
procfs_exit(struct proc *p)
|
||||
{
|
||||
struct pfsnode *pfs;
|
||||
pid_t pid = p->p_pid;
|
||||
|
||||
/*
|
||||
* The reason for this loop is not obvious -- basicly,
|
||||
* procfs_freevp(), which is called via vgone() (eventually),
|
||||
* removes the specified procfs node from the pfshead list.
|
||||
* It does this by *pfsp = pfs->pfs_next, meaning that it
|
||||
* overwrites the node. So when we do pfs = pfs->next, we
|
||||
* end up skipping the node that replaces the one that was
|
||||
* vgone'd. Since it may have been the last one on the list,
|
||||
* it may also have been set to null -- but *our* pfs pointer,
|
||||
* here, doesn't see this. So the loop starts from the beginning
|
||||
* again.
|
||||
*
|
||||
* This is not a for() loop because the final event
|
||||
* would be "pfs = pfs->pfs_next"; in the case where
|
||||
* pfs is set to pfshead again, that would mean that
|
||||
* pfshead is skipped over.
|
||||
*
|
||||
*/
|
||||
pfs = pfshead;
|
||||
while (pfs) {
|
||||
if (pfs->pfs_pid == pid) {
|
||||
vgone(PFSTOV(pfs));
|
||||
pfs = pfshead;
|
||||
} else
|
||||
pfs = pfs->pfs_next;
|
||||
}
|
||||
}
|
@ -40,45 +40,22 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <fs/pseudofs/pseudofs.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
int
|
||||
procfs_dotype(curp, p, pfs, uio)
|
||||
struct proc *curp;
|
||||
struct proc *p;
|
||||
struct pfsnode *pfs;
|
||||
struct uio *uio;
|
||||
procfs_doproctype(PFS_FILL_ARGS)
|
||||
{
|
||||
int len;
|
||||
int error;
|
||||
/*
|
||||
* buffer for emulation type
|
||||
*/
|
||||
char mebuffer[256];
|
||||
char *none = "Not Available";
|
||||
|
||||
if (uio->uio_rw != UIO_READ)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
if (uio->uio_offset != 0)
|
||||
return (0);
|
||||
static const char *none = "Not Available";
|
||||
|
||||
if (p && p->p_sysent && p->p_sysent->sv_name) {
|
||||
len = strlen(p->p_sysent->sv_name);
|
||||
bcopy(p->p_sysent->sv_name, mebuffer, len);
|
||||
sbuf_printf(sb, p->p_sysent->sv_name);
|
||||
} else {
|
||||
len = strlen(none);
|
||||
bcopy(none, mebuffer, len);
|
||||
sbuf_printf(sb, none);
|
||||
}
|
||||
mebuffer[len++] = '\n';
|
||||
error = uiomove(mebuffer, len, uio);
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
procfs_validtype(struct thread *td)
|
||||
{
|
||||
return ((td->td_proc->p_flag & P_SYSTEM) == 0);
|
||||
sbuf_putc(sb, '\n');
|
||||
return (0);
|
||||
}
|
||||
|
@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1993 Jan-Simon Pendry
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry.
|
||||
*
|
||||
* 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 the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)procfs_vfsops.c 8.7 (Berkeley) 5/10/95
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* procfs VFS interface
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <fs/procfs/procfs.h>
|
||||
|
||||
static int procfs_mount __P((struct mount *mp, char *path, caddr_t data,
|
||||
struct nameidata *ndp, struct thread *td));
|
||||
static int procfs_statfs __P((struct mount *mp, struct statfs *sbp,
|
||||
struct thread *td));
|
||||
static int procfs_unmount __P((struct mount *mp, int mntflags,
|
||||
struct thread *td));
|
||||
|
||||
/*
|
||||
* VFS Operations.
|
||||
*
|
||||
* mount system call
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
procfs_mount(mp, path, data, ndp, td)
|
||||
struct mount *mp;
|
||||
char *path;
|
||||
caddr_t data;
|
||||
struct nameidata *ndp;
|
||||
struct thread *td;
|
||||
{
|
||||
size_t size;
|
||||
int error;
|
||||
|
||||
if (mp->mnt_flag & MNT_UPDATE)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
if (mp->mnt_vfc->vfc_refcount == 1 && (error = at_exit(procfs_exit))) {
|
||||
printf("procfs: cannot register procfs_exit with at_exit\n");
|
||||
return(error);
|
||||
}
|
||||
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_data = 0;
|
||||
vfs_getnewfsid(mp);
|
||||
|
||||
size = sizeof("procfs") - 1;
|
||||
bcopy("procfs", mp->mnt_stat.f_mntfromname, size);
|
||||
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
|
||||
(void)procfs_statfs(mp, &mp->mnt_stat, td);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* unmount system call
|
||||
*/
|
||||
static int
|
||||
procfs_unmount(mp, mntflags, td)
|
||||
struct mount *mp;
|
||||
int mntflags;
|
||||
struct thread *td;
|
||||
{
|
||||
int error;
|
||||
int flags = 0;
|
||||
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
|
||||
error = vflush(mp, 0, flags);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (mp->mnt_vfc->vfc_refcount == 1)
|
||||
rm_at_exit(procfs_exit);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
|
||||
return (procfs_allocvp(mp, vpp, 0, Proot));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get file system statistics.
|
||||
*/
|
||||
static int
|
||||
procfs_statfs(mp, sbp, td)
|
||||
struct mount *mp;
|
||||
struct statfs *sbp;
|
||||
struct thread *td;
|
||||
{
|
||||
sbp->f_bsize = PAGE_SIZE;
|
||||
sbp->f_iosize = PAGE_SIZE;
|
||||
sbp->f_blocks = 1; /* avoid divide by zero in some df's */
|
||||
sbp->f_bfree = 0;
|
||||
sbp->f_bavail = 0;
|
||||
sbp->f_files = maxproc; /* approx */
|
||||
sbp->f_ffree = maxproc - nprocs; /* approx */
|
||||
|
||||
if (sbp != &mp->mnt_stat) {
|
||||
sbp->f_type = mp->mnt_vfc->vfc_typenum;
|
||||
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
|
||||
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct vfsops procfs_vfsops = {
|
||||
procfs_mount,
|
||||
vfs_stdstart,
|
||||
procfs_unmount,
|
||||
procfs_root,
|
||||
vfs_stdquotactl,
|
||||
procfs_statfs,
|
||||
vfs_stdsync,
|
||||
vfs_stdvget,
|
||||
vfs_stdfhtovp,
|
||||
vfs_stdcheckexp,
|
||||
vfs_stdvptofh,
|
||||
vfs_stdinit,
|
||||
vfs_stduninit,
|
||||
vfs_stdextattrctl,
|
||||
};
|
||||
|
||||
VFS_SET(procfs_vfsops, procfs, VFCF_SYNTHETIC);
|
||||
MODULE_VERSION(procfs, 1);
|
File diff suppressed because it is too large
Load Diff
@ -68,7 +68,6 @@ SUBDIR= 3dfx \
|
||||
ppbus \
|
||||
ppi \
|
||||
pps \
|
||||
procfs \
|
||||
${_random} \
|
||||
rl \
|
||||
rp \
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
SUBDIR =
|
||||
SUBDIR += linprocfs
|
||||
SUBDIR += procfs
|
||||
SUBDIR += pseudofs
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
@ -1,22 +1,20 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../fs/procfs
|
||||
.PATH: ${.CURDIR}/../../../fs/procfs
|
||||
|
||||
KMOD= procfs
|
||||
SRCS= vnode_if.h \
|
||||
procfs_ctl.c \
|
||||
procfs_dbregs.c \
|
||||
procfs_fpregs.c \
|
||||
procfs_ioctl.c \
|
||||
procfs_map.c \
|
||||
procfs_mem.c \
|
||||
procfs_note.c \
|
||||
procfs_regs.c \
|
||||
procfs_rlimit.c \
|
||||
procfs_status.c \
|
||||
procfs_subr.c \
|
||||
procfs_type.c \
|
||||
procfs_vfsops.c \
|
||||
procfs_vnops.c
|
||||
NOMAN=
|
||||
procfs.c
|
||||
|
||||
.include <bsd.kmod.mk>
|
Loading…
Reference in New Issue
Block a user