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/nwfs/nwfs_vnops.c optional nwfs
|
||||||
fs/portalfs/portal_vfsops.c optional portalfs
|
fs/portalfs/portal_vfsops.c optional portalfs
|
||||||
fs/portalfs/portal_vnops.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_ctl.c optional procfs
|
||||||
fs/procfs/procfs_dbregs.c optional procfs
|
fs/procfs/procfs_dbregs.c optional procfs
|
||||||
fs/procfs/procfs_fpregs.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_map.c optional procfs
|
||||||
fs/procfs/procfs_mem.c optional procfs
|
fs/procfs/procfs_mem.c optional procfs
|
||||||
fs/procfs/procfs_note.c optional procfs
|
fs/procfs/procfs_note.c optional procfs
|
||||||
fs/procfs/procfs_regs.c optional procfs
|
fs/procfs/procfs_regs.c optional procfs
|
||||||
fs/procfs/procfs_rlimit.c optional procfs
|
fs/procfs/procfs_rlimit.c optional procfs
|
||||||
fs/procfs/procfs_status.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_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.c optional pseudofs
|
||||||
fs/pseudofs/pseudofs_fileno.c optional pseudofs
|
fs/pseudofs/pseudofs_fileno.c optional pseudofs
|
||||||
fs/pseudofs/pseudofs_vncache.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$
|
* $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
|
#ifdef _KERNEL
|
||||||
#define CNEQ(cnp, s, len) \
|
|
||||||
((cnp)->cn_namelen == (len) && \
|
|
||||||
(bcmp((s), (cnp)->cn_nameptr, (len)) == 0))
|
|
||||||
|
|
||||||
#define PROCFS_FILENO(pid, type) \
|
int procfs_doproccmdline(PFS_FILL_ARGS);
|
||||||
(((type) < Pproc) ? \
|
int procfs_doprocctl(PFS_FILL_ARGS);
|
||||||
((type) + 2) : \
|
int procfs_doprocdbregs(PFS_FILL_ARGS);
|
||||||
((((pid)+1) << 4) + ((int) (type))))
|
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);
|
||||||
|
|
||||||
/*
|
/* Return 1 if process has special kernel digging privileges */
|
||||||
* Convert between pfsnode vnode
|
int procfs_kmemaccess(struct proc *);
|
||||||
*/
|
|
||||||
#define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data)
|
|
||||||
#define PFSTOV(pfs) ((pfs)->pfs_vnode)
|
|
||||||
|
|
||||||
typedef struct vfs_namemap vfs_namemap_t;
|
/* Attributes */
|
||||||
struct vfs_namemap {
|
int procfs_attr(PFS_ATTR_ARGS);
|
||||||
const char *nm_name;
|
|
||||||
int nm_val;
|
|
||||||
};
|
|
||||||
|
|
||||||
int vfs_getuserstr __P((struct uio *, char *, int *));
|
/* Visbility */
|
||||||
vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
|
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 */
|
#endif /* _KERNEL */
|
||||||
|
@ -44,10 +44,12 @@
|
|||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
#include <sys/sbuf.h>
|
||||||
#include <sys/signalvar.h>
|
#include <sys/signalvar.h>
|
||||||
#include <sys/sx.h>
|
#include <sys/sx.h>
|
||||||
#include <sys/vnode.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
#include <fs/pseudofs/pseudofs.h>
|
||||||
#include <fs/procfs/procfs.h>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
@ -67,7 +69,12 @@
|
|||||||
#define PROCFS_CTL_RUN 4
|
#define PROCFS_CTL_RUN 4
|
||||||
#define PROCFS_CTL_WAIT 5
|
#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 */
|
/* special /proc commands */
|
||||||
{ "attach", PROCFS_CTL_ATTACH },
|
{ "attach", PROCFS_CTL_ATTACH },
|
||||||
{ "detach", PROCFS_CTL_DETACH },
|
{ "detach", PROCFS_CTL_DETACH },
|
||||||
@ -77,7 +84,7 @@ static vfs_namemap_t ctlnames[] = {
|
|||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static vfs_namemap_t signames[] = {
|
static struct namemap signames[] = {
|
||||||
/* regular signal names */
|
/* regular signal names */
|
||||||
{ "hup", SIGHUP }, { "int", SIGINT },
|
{ "hup", SIGHUP }, { "int", SIGINT },
|
||||||
{ "quit", SIGQUIT }, { "ill", SIGILL },
|
{ "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 __P((struct proc *curp, struct proc *p, int op));
|
||||||
|
|
||||||
static int
|
static int
|
||||||
procfs_control(curp, p, op)
|
procfs_control(struct proc *curp, struct proc *p, int op)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
int op;
|
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
@ -240,7 +244,6 @@ procfs_control(curp, p, op)
|
|||||||
* Step. Let the target process execute a single instruction.
|
* Step. Let the target process execute a single instruction.
|
||||||
*/
|
*/
|
||||||
case PROCFS_CTL_STEP:
|
case PROCFS_CTL_STEP:
|
||||||
_PHOLD(p);
|
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
error = proc_sstep(&p->p_thread); /* XXXKSE */
|
error = proc_sstep(&p->p_thread); /* XXXKSE */
|
||||||
PRELE(p);
|
PRELE(p);
|
||||||
@ -301,26 +304,26 @@ procfs_control(curp, p, op)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static struct namemap *
|
||||||
procfs_doctl(curp, p, pfs, uio)
|
findname(struct namemap *nm, char *buf, int buflen)
|
||||||
struct proc *curp;
|
{
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
for (; nm->nm_name; nm++)
|
||||||
struct proc *p;
|
if (bcmp(buf, nm->nm_name, buflen+1) == 0)
|
||||||
|
return (nm);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
procfs_doprocctl(PFS_FILL_ARGS)
|
||||||
{
|
{
|
||||||
int xlen;
|
|
||||||
int error;
|
int error;
|
||||||
char msg[PROCFS_CTLLEN+1];
|
struct namemap *nm;
|
||||||
vfs_namemap_t *nm;
|
|
||||||
|
|
||||||
if (uio->uio_rw != UIO_WRITE)
|
if (uio == NULL || uio->uio_rw != UIO_WRITE)
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
|
|
||||||
xlen = PROCFS_CTLLEN;
|
|
||||||
error = vfs_getuserstr(uio, msg, &xlen);
|
|
||||||
if (error)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map signal names into signal generation
|
* Map signal names into signal generation
|
||||||
* or debug control. Unknown commands and/or signals
|
* or debug control. Unknown commands and/or signals
|
||||||
@ -332,15 +335,19 @@ procfs_doctl(curp, p, pfs, uio)
|
|||||||
*/
|
*/
|
||||||
error = EOPNOTSUPP;
|
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) {
|
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 {
|
} else {
|
||||||
nm = vfs_findname(signames, msg, xlen);
|
nm = findname(signames, sbuf_data(sb), sbuf_len(sb));
|
||||||
if (nm) {
|
if (nm) {
|
||||||
|
printf("procfs: got a sig%s\n", sbuf_data(sb));
|
||||||
PROC_LOCK(p);
|
PROC_LOCK(p);
|
||||||
mtx_lock_spin(&sched_lock);
|
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;
|
p->p_xstat = nm->nm_val;
|
||||||
#ifdef FIX_SSTEP
|
#ifdef FIX_SSTEP
|
||||||
FIX_SSTEP(&p->p_thread); /* XXXKSE */
|
FIX_SSTEP(&p->p_thread); /* XXXKSE */
|
||||||
|
@ -49,27 +49,22 @@
|
|||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/vnode.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#include <machine/reg.h>
|
#include <machine/reg.h>
|
||||||
|
|
||||||
|
#include <fs/pseudofs/pseudofs.h>
|
||||||
#include <fs/procfs/procfs.h>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
#include <vm/vm.h>
|
|
||||||
|
|
||||||
int
|
int
|
||||||
procfs_dodbregs(curp, p, pfs, uio)
|
procfs_doprocdbregs(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
struct dbreg r;
|
struct dbreg r;
|
||||||
char *kv;
|
char *kv;
|
||||||
int kl;
|
int kl;
|
||||||
|
|
||||||
if (p_candebug(curp, p))
|
if (p_candebug(td->td_proc, p) != 0)
|
||||||
return (EPERM);
|
return (EPERM);
|
||||||
kl = sizeof(r);
|
kl = sizeof(r);
|
||||||
kv = (char *) &r;
|
kv = (char *) &r;
|
||||||
@ -79,8 +74,6 @@ procfs_dodbregs(curp, p, pfs, uio)
|
|||||||
if (kl > uio->uio_resid)
|
if (kl > uio->uio_resid)
|
||||||
kl = uio->uio_resid;
|
kl = uio->uio_resid;
|
||||||
|
|
||||||
PHOLD(p);
|
|
||||||
|
|
||||||
if (kl < 0)
|
if (kl < 0)
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
else
|
else
|
||||||
@ -93,15 +86,7 @@ procfs_dodbregs(curp, p, pfs, uio)
|
|||||||
else
|
else
|
||||||
error = proc_write_dbregs(&p->p_thread, &r); /* XXXKSE */
|
error = proc_write_dbregs(&p->p_thread, &r); /* XXXKSE */
|
||||||
}
|
}
|
||||||
PRELE(p);
|
|
||||||
|
|
||||||
uio->uio_offset = 0;
|
uio->uio_offset = 0;
|
||||||
return (error);
|
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/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/vnode.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#include <machine/reg.h>
|
#include <machine/reg.h>
|
||||||
|
|
||||||
|
#include <fs/pseudofs/pseudofs.h>
|
||||||
#include <fs/procfs/procfs.h>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
#include <vm/vm.h>
|
|
||||||
|
|
||||||
int
|
int
|
||||||
procfs_dofpregs(curp, p, pfs, uio)
|
procfs_doprocfpregs(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
struct fpreg r;
|
struct fpreg r;
|
||||||
char *kv;
|
char *kv;
|
||||||
int kl;
|
int kl;
|
||||||
|
|
||||||
if (p_candebug(curp, p))
|
if (p_candebug(td->td_proc, p))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
kl = sizeof(r);
|
kl = sizeof(r);
|
||||||
kv = (char *) &r;
|
kv = (char *) &r;
|
||||||
@ -95,10 +90,3 @@ procfs_dofpregs(curp, p, pfs, uio)
|
|||||||
uio->uio_offset = 0;
|
uio->uio_offset = 0;
|
||||||
return (error);
|
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/lock.h>
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/vnode.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
#include <fs/pseudofs/pseudofs.h>
|
||||||
#include <fs/procfs/procfs.h>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
@ -68,11 +69,7 @@
|
|||||||
* can try a bigger buffer.
|
* can try a bigger buffer.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
procfs_domap(curp, p, pfs, uio)
|
procfs_doprocmap(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
int error;
|
int error;
|
||||||
@ -90,7 +87,7 @@ procfs_domap(curp, p, pfs, uio)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
if (map != &curproc->p_vmspace->vm_map)
|
if (map != &curthread->td_proc->p_vmspace->vm_map)
|
||||||
vm_map_lock_read(map);
|
vm_map_lock_read(map);
|
||||||
for (entry = map->header.next;
|
for (entry = map->header.next;
|
||||||
((uio->uio_resid > 0) && (entry != &map->header));
|
((uio->uio_resid > 0) && (entry != &map->header));
|
||||||
@ -118,23 +115,22 @@ procfs_domap(curp, p, pfs, uio)
|
|||||||
addr += PAGE_SIZE;
|
addr += PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( lobj = tobj = obj; tobj; tobj = tobj->backing_object)
|
for (lobj = tobj = obj; tobj; tobj = tobj->backing_object)
|
||||||
lobj = tobj;
|
lobj = tobj;
|
||||||
|
|
||||||
if (lobj) {
|
if (lobj) {
|
||||||
switch(lobj->type) {
|
switch(lobj->type) {
|
||||||
|
default:
|
||||||
default:
|
case OBJT_DEFAULT:
|
||||||
case OBJT_DEFAULT:
|
|
||||||
type = "default";
|
type = "default";
|
||||||
break;
|
break;
|
||||||
case OBJT_VNODE:
|
case OBJT_VNODE:
|
||||||
type = "vnode";
|
type = "vnode";
|
||||||
break;
|
break;
|
||||||
case OBJT_SWAP:
|
case OBJT_SWAP:
|
||||||
type = "swap";
|
type = "swap";
|
||||||
break;
|
break;
|
||||||
case OBJT_DEVICE:
|
case OBJT_DEVICE:
|
||||||
type = "device";
|
type = "device";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -148,13 +144,12 @@ case OBJT_DEVICE:
|
|||||||
ref_count = 0;
|
ref_count = 0;
|
||||||
shadow_count = 0;
|
shadow_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* format:
|
* format:
|
||||||
* start, end, resident, private resident, cow, access, type.
|
* 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",
|
"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,
|
(u_long)entry->start, (u_long)entry->end,
|
||||||
resident, privateresident, obj,
|
resident, privateresident, obj,
|
||||||
@ -175,14 +170,8 @@ case OBJT_DEVICE:
|
|||||||
if (error)
|
if (error)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (map != &curproc->p_vmspace->vm_map)
|
if (map != &curthread->td_proc->p_vmspace->vm_map)
|
||||||
vm_map_unlock_read(map);
|
vm_map_unlock_read(map);
|
||||||
|
|
||||||
return error;
|
return (error);
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
procfs_validmap(struct thread *td)
|
|
||||||
{
|
|
||||||
return ((td->td_proc->p_flag & P_SYSTEM) == 0);
|
|
||||||
}
|
}
|
||||||
|
@ -41,14 +41,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/user.h>
|
#include <sys/uio.h>
|
||||||
#include <sys/vnode.h>
|
|
||||||
|
|
||||||
|
#include <fs/pseudofs/pseudofs.h>
|
||||||
#include <fs/procfs/procfs.h>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -58,20 +57,17 @@
|
|||||||
* from the kernel address space.
|
* from the kernel address space.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
procfs_domem(curp, p, pfs, uio)
|
procfs_doprocmem(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (uio->uio_resid == 0)
|
if (uio->uio_resid == 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
error = p_candebug(curp, p);
|
error = p_candebug(td->td_proc, p);
|
||||||
if (error)
|
if (error)
|
||||||
return (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/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>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
procfs_donote(curp, p, pfs, uio)
|
procfs_doprocnote(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
int xlen;
|
sbuf_trim(sb);
|
||||||
int error;
|
sbuf_finish(sb);
|
||||||
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);
|
|
||||||
|
|
||||||
/* send to process's notify function */
|
/* send to process's notify function */
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
@ -46,28 +46,22 @@
|
|||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/vnode.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#include <machine/reg.h>
|
#include <machine/reg.h>
|
||||||
|
|
||||||
#include <vm/vm.h>
|
#include <fs/pseudofs/pseudofs.h>
|
||||||
#include <vm/vm_extern.h>
|
|
||||||
|
|
||||||
#include <fs/procfs/procfs.h>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
procfs_doregs(curp, p, pfs, uio)
|
procfs_doprocregs(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
struct reg r;
|
struct reg r;
|
||||||
char *kv;
|
char *kv;
|
||||||
int kl;
|
int kl;
|
||||||
|
|
||||||
if (p_candebug(curp, p))
|
if (p_candebug(td->td_proc, p))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
kl = sizeof(r);
|
kl = sizeof(r);
|
||||||
kv = (char *) &r;
|
kv = (char *) &r;
|
||||||
@ -96,10 +90,3 @@ procfs_doregs(curp, p, pfs, uio)
|
|||||||
uio->uio_offset = 0;
|
uio->uio_offset = 0;
|
||||||
return (error);
|
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/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/vnode.h>
|
|
||||||
#include <sys/resourcevar.h>
|
#include <sys/resourcevar.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/types.h>
|
#include <sys/sbuf.h>
|
||||||
|
|
||||||
|
#include <fs/pseudofs/pseudofs.h>
|
||||||
#include <fs/procfs/procfs.h>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
procfs_dorlimit(curp, p, pfs, uio)
|
procfs_doprocrlimit(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
char *ps;
|
|
||||||
int i;
|
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++) {
|
for (i = 0; i < RLIM_NLIMITS; i++) {
|
||||||
|
|
||||||
@ -80,7 +67,7 @@ procfs_dorlimit(curp, p, pfs, uio)
|
|||||||
* Add the rlimit ident
|
* 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
|
* 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) {
|
if (p->p_rlimit[i].rlim_cur == RLIM_INFINITY) {
|
||||||
ps += sprintf(ps, "-1 ");
|
sbuf_printf(sb, "-1 ");
|
||||||
} else {
|
} else {
|
||||||
ps += sprintf(ps, "%llu ",
|
sbuf_printf(sb, "%llu ",
|
||||||
(unsigned long long)p->p_rlimit[i].rlim_cur);
|
(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) {
|
if (p->p_rlimit[i].rlim_max == RLIM_INFINITY) {
|
||||||
ps += sprintf(ps, "-1\n");
|
sbuf_printf(sb, "-1\n");
|
||||||
} else {
|
} else {
|
||||||
ps += sprintf(ps, "%llu\n",
|
sbuf_printf(sb, "%llu\n",
|
||||||
(unsigned long long)p->p_rlimit[i].rlim_max);
|
(unsigned long long)p->p_rlimit[i].rlim_max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
return (0);
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,36 +49,26 @@
|
|||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/resourcevar.h>
|
#include <sys/resourcevar.h>
|
||||||
|
#include <sys/sbuf.h>
|
||||||
#include <sys/tty.h>
|
#include <sys/tty.h>
|
||||||
#include <sys/vnode.h>
|
|
||||||
|
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
#include <vm/pmap.h>
|
#include <vm/pmap.h>
|
||||||
#include <vm/vm_param.h>
|
#include <vm/vm_param.h>
|
||||||
|
|
||||||
|
#include <fs/pseudofs/pseudofs.h>
|
||||||
#include <fs/procfs/procfs.h>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
#define DOCHECK() do { if (ps >= psbuf+sizeof(psbuf)) goto bailout; } while (0)
|
|
||||||
int
|
int
|
||||||
procfs_dostatus(curp, p, pfs, uio)
|
procfs_doprocstatus(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
struct session *sess;
|
struct session *sess;
|
||||||
struct tty *tp;
|
struct tty *tp;
|
||||||
struct ucred *cr;
|
struct ucred *cr;
|
||||||
char *ps, *pc;
|
char *pc;
|
||||||
char *sep;
|
char *sep;
|
||||||
int pid, ppid, pgid, sid;
|
int pid, ppid, pgid, sid;
|
||||||
int i;
|
int i;
|
||||||
int xlen;
|
|
||||||
int error;
|
|
||||||
char psbuf[256]; /* XXX - conservative */
|
|
||||||
|
|
||||||
if (uio->uio_rw != UIO_READ)
|
|
||||||
return (EOPNOTSUPP);
|
|
||||||
|
|
||||||
pid = p->p_pid;
|
pid = p->p_pid;
|
||||||
PROC_LOCK(p);
|
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
|
/* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg
|
||||||
euid ruid rgid,egid,groups[1 .. NGROUPS]
|
euid ruid rgid,egid,groups[1 .. NGROUPS]
|
||||||
*/
|
*/
|
||||||
KASSERT(sizeof(psbuf) > MAXCOMLEN,
|
|
||||||
("Too short buffer for new MAXCOMLEN"));
|
|
||||||
|
|
||||||
ps = psbuf;
|
|
||||||
pc = p->p_comm;
|
pc = p->p_comm;
|
||||||
xlen = strlen(p->p_comm);
|
|
||||||
do {
|
do {
|
||||||
if (*pc < 33 || *pc > 126 || *pc == '\\')
|
if (*pc < 33 || *pc > 126 || *pc == '\\')
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\\%03o",
|
sbuf_printf(sb, "\\%03o", *pc);
|
||||||
*pc);
|
|
||||||
else
|
else
|
||||||
*ps++ = *pc;
|
sbuf_putc(sb, *pc);
|
||||||
DOCHECK();
|
} while (*++pc);
|
||||||
} while (++pc < p->p_comm + xlen);
|
sbuf_printf(sb, " %d %d %d %d ", pid, ppid, pgid, sid);
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
|
||||||
" %d %d %d %d ", pid, ppid, pgid, sid);
|
|
||||||
DOCHECK();
|
|
||||||
if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp))
|
if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp))
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
sbuf_printf(sb, "%d,%d ", major(tp->t_dev), minor(tp->t_dev));
|
||||||
"%d,%d ", major(tp->t_dev), minor(tp->t_dev));
|
|
||||||
else
|
else
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
sbuf_printf(sb, "%d,%d ", -1, -1);
|
||||||
"%d,%d ", -1, -1);
|
|
||||||
DOCHECK();
|
|
||||||
|
|
||||||
sep = "";
|
sep = "";
|
||||||
if (sess->s_ttyvp) {
|
if (sess->s_ttyvp) {
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "%sctty", sep);
|
sbuf_printf(sb, "%sctty", sep);
|
||||||
sep = ",";
|
sep = ",";
|
||||||
DOCHECK();
|
|
||||||
}
|
}
|
||||||
if (SESS_LEADER(p)) {
|
if (SESS_LEADER(p)) {
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "%ssldr", sep);
|
sbuf_printf(sb, "%ssldr", sep);
|
||||||
sep = ",";
|
sep = ",";
|
||||||
DOCHECK();
|
|
||||||
}
|
}
|
||||||
if (*sep != ',') {
|
if (*sep != ',') {
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "noflags");
|
sbuf_printf(sb, "noflags");
|
||||||
DOCHECK();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mtx_lock_spin(&sched_lock);
|
mtx_lock_spin(&sched_lock);
|
||||||
@ -138,92 +114,56 @@ procfs_dostatus(curp, p, pfs, uio)
|
|||||||
|
|
||||||
calcru(p, &ut, &st, (struct timeval *) NULL);
|
calcru(p, &ut, &st, (struct timeval *) NULL);
|
||||||
mtx_unlock_spin(&sched_lock);
|
mtx_unlock_spin(&sched_lock);
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
sbuf_printf(sb, " %lld,%ld %ld,%ld %ld,%ld",
|
||||||
" %lld,%ld %ld,%ld %ld,%ld",
|
|
||||||
(long long)p->p_stats->p_start.tv_sec,
|
(long long)p->p_stats->p_start.tv_sec,
|
||||||
p->p_stats->p_start.tv_usec,
|
p->p_stats->p_start.tv_usec,
|
||||||
(long)ut.tv_sec, ut.tv_usec,
|
ut.tv_sec, ut.tv_usec,
|
||||||
(long)st.tv_sec, st.tv_usec);
|
st.tv_sec, st.tv_usec);
|
||||||
} else {
|
} else {
|
||||||
mtx_unlock_spin(&sched_lock);
|
mtx_unlock_spin(&sched_lock);
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
sbuf_printf(sb, " -1,-1 -1,-1 -1,-1");
|
||||||
" -1,-1 -1,-1 -1,-1");
|
|
||||||
}
|
}
|
||||||
DOCHECK();
|
|
||||||
|
|
||||||
if (p->p_flag & P_KSES) {
|
if (p->p_flag & P_KSES) {
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %s",
|
sbuf_printf(sb, " %s", "-kse- ");
|
||||||
"-kse- ");
|
|
||||||
} else {
|
} 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_wchan && p->p_thread.td_wmesg) ?
|
||||||
p->p_thread.td_wmesg : "nochan");
|
p->p_thread.td_wmesg : "nochan");
|
||||||
}
|
}
|
||||||
DOCHECK();
|
|
||||||
|
|
||||||
cr = p->p_ucred;
|
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_uid,
|
||||||
(u_long)cr->cr_ruid,
|
(u_long)cr->cr_ruid,
|
||||||
(u_long)cr->cr_rgid);
|
(u_long)cr->cr_rgid);
|
||||||
DOCHECK();
|
|
||||||
|
|
||||||
/* egid (cr->cr_svgid) is equal to cr_ngroups[0]
|
/* egid (cr->cr_svgid) is equal to cr_ngroups[0]
|
||||||
see also getegid(2) in /sys/kern/kern_prot.c */
|
see also getegid(2) in /sys/kern/kern_prot.c */
|
||||||
|
|
||||||
for (i = 0; i < cr->cr_ngroups; i++) {
|
for (i = 0; i < cr->cr_ngroups; i++) {
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
sbuf_printf(sb, ",%lu", (u_long)cr->cr_groups[i]);
|
||||||
",%lu", (u_long)cr->cr_groups[i]);
|
|
||||||
DOCHECK();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jailed(p->p_ucred)) {
|
if (jailed(p->p_ucred)) {
|
||||||
mtx_lock(&p->p_ucred->cr_prison->pr_mtx);
|
mtx_lock(&p->p_ucred->cr_prison->pr_mtx);
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
|
sbuf_printf(sb, " %s", p->p_ucred->cr_prison->pr_host);
|
||||||
" %s", p->p_ucred->cr_prison->pr_host);
|
|
||||||
mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
|
mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
|
||||||
} else {
|
} else {
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " -");
|
sbuf_printf(sb, " -");
|
||||||
}
|
}
|
||||||
DOCHECK();
|
sbuf_printf(sb, "\n");
|
||||||
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\n");
|
|
||||||
DOCHECK();
|
|
||||||
|
|
||||||
xlen = ps - psbuf;
|
return (0);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
procfs_docmdline(curp, p, pfs, uio)
|
procfs_doproccmdline(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
char *ps;
|
|
||||||
int xlen;
|
|
||||||
int error;
|
|
||||||
char *buf, *bp;
|
|
||||||
int buflen;
|
|
||||||
struct ps_strings pstr;
|
struct ps_strings pstr;
|
||||||
int i;
|
int error, i;
|
||||||
size_t bytes_left, done;
|
|
||||||
|
|
||||||
if (uio->uio_rw != UIO_READ)
|
|
||||||
return (EOPNOTSUPP);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are using the ps/cmdline caching, use that. Otherwise
|
* If we are using the ps/cmdline caching, use that. Otherwise
|
||||||
* revert back to the old way which only implements full cmdline
|
* 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.
|
* Linux behaviour is to return zero-length in this case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (p->p_args && (ps_argsopen || !p_cansee(curp, p))) {
|
if (p->p_args && (ps_argsopen || !p_cansee(td->td_proc, p))) {
|
||||||
bp = p->p_args->ar_args;
|
sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
|
||||||
buflen = p->p_args->ar_length;
|
} else if (p != td->td_proc) {
|
||||||
buf = 0;
|
sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm);
|
||||||
} else if (p != curp) {
|
|
||||||
bp = p->p_comm;
|
|
||||||
buflen = MAXCOMLEN;
|
|
||||||
buf = 0;
|
|
||||||
} else {
|
} else {
|
||||||
buflen = 256;
|
|
||||||
MALLOC(buf, char *, buflen + 1, M_TEMP, M_WAITOK);
|
|
||||||
bp = buf;
|
|
||||||
ps = buf;
|
|
||||||
error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr));
|
error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr));
|
||||||
if (error) {
|
if (error)
|
||||||
FREE(buf, M_TEMP);
|
|
||||||
return (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;
|
return (0);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
@ -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/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
|
#include <sys/sbuf.h>
|
||||||
#include <sys/sysent.h>
|
#include <sys/sysent.h>
|
||||||
#include <sys/vnode.h>
|
|
||||||
|
#include <fs/pseudofs/pseudofs.h>
|
||||||
#include <fs/procfs/procfs.h>
|
#include <fs/procfs/procfs.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
procfs_dotype(curp, p, pfs, uio)
|
procfs_doproctype(PFS_FILL_ARGS)
|
||||||
struct proc *curp;
|
|
||||||
struct proc *p;
|
|
||||||
struct pfsnode *pfs;
|
|
||||||
struct uio *uio;
|
|
||||||
{
|
{
|
||||||
int len;
|
static const char *none = "Not Available";
|
||||||
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);
|
|
||||||
|
|
||||||
if (p && p->p_sysent && p->p_sysent->sv_name) {
|
if (p && p->p_sysent && p->p_sysent->sv_name) {
|
||||||
len = strlen(p->p_sysent->sv_name);
|
sbuf_printf(sb, p->p_sysent->sv_name);
|
||||||
bcopy(p->p_sysent->sv_name, mebuffer, len);
|
|
||||||
} else {
|
} else {
|
||||||
len = strlen(none);
|
sbuf_printf(sb, none);
|
||||||
bcopy(none, mebuffer, len);
|
|
||||||
}
|
}
|
||||||
mebuffer[len++] = '\n';
|
sbuf_putc(sb, '\n');
|
||||||
error = uiomove(mebuffer, len, uio);
|
return (0);
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
procfs_validtype(struct thread *td)
|
|
||||||
{
|
|
||||||
return ((td->td_proc->p_flag & P_SYSTEM) == 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 \
|
ppbus \
|
||||||
ppi \
|
ppi \
|
||||||
pps \
|
pps \
|
||||||
procfs \
|
|
||||||
${_random} \
|
${_random} \
|
||||||
rl \
|
rl \
|
||||||
rp \
|
rp \
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
SUBDIR =
|
SUBDIR =
|
||||||
SUBDIR += linprocfs
|
SUBDIR += linprocfs
|
||||||
|
SUBDIR += procfs
|
||||||
SUBDIR += pseudofs
|
SUBDIR += pseudofs
|
||||||
|
|
||||||
.include <bsd.subdir.mk>
|
.include <bsd.subdir.mk>
|
||||||
|
@ -1,22 +1,20 @@
|
|||||||
# $FreeBSD$
|
# $FreeBSD$
|
||||||
|
|
||||||
.PATH: ${.CURDIR}/../../fs/procfs
|
.PATH: ${.CURDIR}/../../../fs/procfs
|
||||||
|
|
||||||
KMOD= procfs
|
KMOD= procfs
|
||||||
SRCS= vnode_if.h \
|
SRCS= vnode_if.h \
|
||||||
procfs_ctl.c \
|
procfs_ctl.c \
|
||||||
procfs_dbregs.c \
|
procfs_dbregs.c \
|
||||||
procfs_fpregs.c \
|
procfs_fpregs.c \
|
||||||
|
procfs_ioctl.c \
|
||||||
procfs_map.c \
|
procfs_map.c \
|
||||||
procfs_mem.c \
|
procfs_mem.c \
|
||||||
procfs_note.c \
|
procfs_note.c \
|
||||||
procfs_regs.c \
|
procfs_regs.c \
|
||||||
procfs_rlimit.c \
|
procfs_rlimit.c \
|
||||||
procfs_status.c \
|
procfs_status.c \
|
||||||
procfs_subr.c \
|
|
||||||
procfs_type.c \
|
procfs_type.c \
|
||||||
procfs_vfsops.c \
|
procfs.c
|
||||||
procfs_vnops.c
|
|
||||||
NOMAN=
|
|
||||||
|
|
||||||
.include <bsd.kmod.mk>
|
.include <bsd.kmod.mk>
|
Loading…
Reference in New Issue
Block a user