PR# kern/45021: Please support /emul/linux/proc/version

Add /proc/version for procfs with -o linux. The version reported depends
on the emulation type of the calling process:

$ cat /proc/version
NetBSD version 5.99.55 (netbsd@localhost) (gcc version 4.1.3 20080704 prerelease (NetBSD nb2 20081120)) NetBSD 5.99.55 (GENERIC) #39: Sun Sep  4 09:10:05 EDT 2011

$ /emul/linux/bin/cat /proc/version
Linux version 2.6.18 (linux@localhost) (gcc version 4.1.3 20080704 prerelease (NetBSD nb2 20081120)) #0 Wed Mar 3 03:03:03 PST 2010

$ /emul/linux32/bin/cat /proc/version
Linux version 2.6.18 (linux32@localhost) (gcc version 4.1.3 20080704 prerelease (NetBSD nb2 20081120)) #0 Wed Mar 3 03:03:03 PST 2010
This commit is contained in:
jmcneill 2011-09-04 17:32:10 +00:00
parent 1a6f6eba38
commit e656d3b0f6
4 changed files with 119 additions and 7 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs.h,v 1.65 2008/06/28 01:34:06 rumble Exp $ */
/* $NetBSD: procfs.h,v 1.66 2011/09/04 17:32:10 jmcneill Exp $ */
/*
* Copyright (c) 1993
@ -108,6 +108,7 @@ typedef enum {
PFScpustat, /* status info (if -o linux) */
PFSloadavg, /* load average (if -o linux) */
PFSstatm, /* process memory info (if -o linux) */
PFSversion, /* kernel version (if -o linux) */
#ifdef __HAVE_PROCFS_MACHDEP
PROCFS_MACHDEP_NODE_TYPES
#endif
@ -225,6 +226,8 @@ int procfs_domounts(struct lwp *, struct proc *, struct pfsnode *,
struct uio *);
int procfs_doemul(struct lwp *, struct proc *, struct pfsnode *,
struct uio *);
int procfs_doversion(struct lwp *, struct proc *, struct pfsnode *,
struct uio *);
void procfs_revoke_vnodes(struct proc *, void *);
void procfs_hashinit(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_linux.c,v 1.60 2011/08/28 18:48:14 jmcneill Exp $ */
/* $NetBSD: procfs_linux.c,v 1.61 2011/09/04 17:32:10 jmcneill Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.60 2011/08/28 18:48:14 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.61 2011/09/04 17:32:10 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -53,10 +53,12 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.60 2011/08/28 18:48:14 jmcneill E
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/conf.h>
#include <sys/sysctl.h>
#include <miscfs/procfs/procfs.h>
#include <compat/linux/common/linux_exec.h>
#include <compat/linux32/common/linux32_sysctl.h>
#include <uvm/uvm_extern.h>
#include <uvm/uvm.h>
@ -610,3 +612,102 @@ procfs_domounts(struct lwp *curl, struct proc *p,
return error;
}
/*
* Linux compatible /proc/version. Only active when the -o linux
* mountflag is used.
*/
int
procfs_doversion(struct lwp *curl, struct proc *p,
struct pfsnode *pfs, struct uio *uio)
{
char *bf;
char lostype[20], losrelease[20], lversion[80];
const char *postype, *posrelease, *pversion;
const char *emulname = curlwp->l_proc->p_emul->e_name;
int len;
int error = 0;
int nm[4];
size_t buflen;
CTASSERT(EMUL_LINUX_KERN_OSTYPE == EMUL_LINUX32_KERN_OSTYPE);
CTASSERT(EMUL_LINUX_KERN_OSRELEASE == EMUL_LINUX32_KERN_OSRELEASE);
CTASSERT(EMUL_LINUX_KERN_VERSION == EMUL_LINUX32_KERN_VERSION);
bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
sysctl_lock(false);
if (strncmp(emulname, "linux", 5) == 0) {
/*
* Lookup the emulation ostype, osrelease, and version.
* Since compat_linux and compat_linux32 can be built as
* modules, we use sysctl to obtain the values instead of
* using the symbols directly.
*/
if (strcmp(emulname, "linux32") == 0) {
nm[0] = CTL_EMUL;
nm[1] = EMUL_LINUX32;
nm[2] = EMUL_LINUX32_KERN;
} else {
nm[0] = CTL_EMUL;
nm[1] = EMUL_LINUX;
nm[2] = EMUL_LINUX_KERN;
}
nm[3] = EMUL_LINUX_KERN_OSTYPE;
buflen = sizeof(lostype);
error = sysctl_dispatch(nm, __arraycount(nm),
lostype, &buflen,
NULL, 0, NULL, NULL, NULL);
if (error)
goto out;
nm[3] = EMUL_LINUX_KERN_OSRELEASE;
buflen = sizeof(losrelease);
error = sysctl_dispatch(nm, __arraycount(nm),
losrelease, &buflen,
NULL, 0, NULL, NULL, NULL);
if (error)
goto out;
nm[3] = EMUL_LINUX_KERN_VERSION;
buflen = sizeof(lversion);
error = sysctl_dispatch(nm, __arraycount(nm),
lversion, &buflen,
NULL, 0, NULL, NULL, NULL);
if (error)
goto out;
postype = lostype;
posrelease = losrelease;
pversion = lversion;
} else {
postype = ostype;
posrelease = osrelease;
strlcpy(lversion, version, sizeof(lversion));
if (strchr(lversion, '\n'))
*strchr(lversion, '\n') = '\0';
pversion = lversion;
}
len = snprintf(bf, LBFSZ,
"%s version %s (%s@localhost) (gcc version %s) %s\n",
postype, posrelease, emulname,
#ifdef __VERSION__
__VERSION__,
#else
"unknown",
#endif
pversion);
if (len == 0)
goto out;
error = uiomove_frombuf(bf, len, uio);
out:
free(bf, M_TEMP);
sysctl_unlock();
return error;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_subr.c,v 1.99 2011/06/12 03:35:58 rmind Exp $ */
/* $NetBSD: procfs_subr.c,v 1.100 2011/09/04 17:32:10 jmcneill Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -102,7 +102,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.99 2011/06/12 03:35:58 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.100 2011/09/04 17:32:10 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -288,6 +288,7 @@ procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid,
case PFSmounts: /* /proc/mounts = -r--r--r-- */
case PFSloadavg: /* /proc/loadavg = -r--r--r-- */
case PFSstatm: /* /proc/N/statm = -r--r--r-- */
case PFSversion: /* /proc/version = -r--r--r-- */
pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
vp->v_type = VREG;
break;
@ -462,6 +463,10 @@ procfs_rw(void *v)
error = procfs_doemul(curl, p, pfs, uio);
break;
case PFSversion:
error = procfs_doversion(curl, p, pfs, uio);
break;
#ifdef __HAVE_PROCFS_MACHDEP
PROCFS_MACHDEP_NODETYPE_CASES
error = procfs_machdep_rw(curl, l, pfs, uio);

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_vnops.c,v 1.181 2011/06/23 17:06:38 christos Exp $ */
/* $NetBSD: procfs_vnops.c,v 1.182 2011/09/04 17:32:10 jmcneill Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -105,7 +105,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.181 2011/06/23 17:06:38 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.182 2011/09/04 17:32:10 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -196,6 +196,7 @@ static const struct proc_target proc_root_targets[] = {
{ DT_REG, N("devices"), PFSdevices, procfs_validfile_linux },
{ DT_REG, N("stat"), PFScpustat, procfs_validfile_linux },
{ DT_REG, N("loadavg"), PFSloadavg, procfs_validfile_linux },
{ DT_REG, N("version"), PFSversion, procfs_validfile_linux },
#undef N
};
static const int nproc_root_targets =
@ -736,6 +737,7 @@ procfs_getattr(void *v)
case PFSmounts:
case PFScpustat:
case PFSloadavg:
case PFSversion:
vap->va_nlink = 1;
vap->va_uid = vap->va_gid = 0;
break;
@ -845,6 +847,7 @@ procfs_getattr(void *v)
case PFScpustat:
case PFSloadavg:
case PFSstatm:
case PFSversion:
vap->va_bytes = vap->va_size = 0;
break;
case PFSmap: