1*78b530bbSpgoyette /* $NetBSD: procfs_linux.c,v 1.90 2024/09/14 01:37:42 pgoyette Exp $ */ 24e000b75Sfvdl 34e000b75Sfvdl /* 44e000b75Sfvdl * Copyright (c) 2001 Wasabi Systems, Inc. 54e000b75Sfvdl * All rights reserved. 64e000b75Sfvdl * 74e000b75Sfvdl * Written by Frank van der Linden for Wasabi Systems, Inc. 84e000b75Sfvdl * 94e000b75Sfvdl * Redistribution and use in source and binary forms, with or without 104e000b75Sfvdl * modification, are permitted provided that the following conditions 114e000b75Sfvdl * are met: 124e000b75Sfvdl * 1. Redistributions of source code must retain the above copyright 134e000b75Sfvdl * notice, this list of conditions and the following disclaimer. 144e000b75Sfvdl * 2. Redistributions in binary form must reproduce the above copyright 154e000b75Sfvdl * notice, this list of conditions and the following disclaimer in the 164e000b75Sfvdl * documentation and/or other materials provided with the distribution. 174e000b75Sfvdl * 3. All advertising materials mentioning features or use of this software 184e000b75Sfvdl * must display the following acknowledgement: 194e000b75Sfvdl * This product includes software developed for the NetBSD Project by 204e000b75Sfvdl * Wasabi Systems, Inc. 214e000b75Sfvdl * 4. The name of Wasabi Systems, Inc. may not be used to endorse 224e000b75Sfvdl * or promote products derived from this software without specific prior 234e000b75Sfvdl * written permission. 244e000b75Sfvdl * 254e000b75Sfvdl * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 264e000b75Sfvdl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 274e000b75Sfvdl * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 284e000b75Sfvdl * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 294e000b75Sfvdl * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 304e000b75Sfvdl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 314e000b75Sfvdl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 324e000b75Sfvdl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 334e000b75Sfvdl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 344e000b75Sfvdl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 354e000b75Sfvdl * POSSIBILITY OF SUCH DAMAGE. 364e000b75Sfvdl */ 374e000b75Sfvdl 38e4b00f43Slukem #include <sys/cdefs.h> 39*78b530bbSpgoyette __KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.90 2024/09/14 01:37:42 pgoyette Exp $"); 4087f98fe2Schristos 4187f98fe2Schristos #if defined(_KERNEL_OPT) 4287f98fe2Schristos #include "opt_sysv.h" 43*78b530bbSpgoyette #include "opt_mqueue.h" 4487f98fe2Schristos #endif 45e4b00f43Slukem 464e000b75Sfvdl #include <sys/param.h> 474e000b75Sfvdl #include <sys/systm.h> 480a1cb031Smartin #include <sys/atomic.h> 494e000b75Sfvdl #include <sys/time.h> 505918ad37Smatt #include <sys/cpu.h> 514e000b75Sfvdl #include <sys/kernel.h> 524e000b75Sfvdl #include <sys/proc.h> 534e000b75Sfvdl #include <sys/vnode.h> 549897a542Schristos #include <sys/exec.h> 55210944c7Schristos #include <sys/resource.h> 56210944c7Schristos #include <sys/resourcevar.h> 57210944c7Schristos #include <sys/signal.h> 58210944c7Schristos #include <sys/signalvar.h> 59210944c7Schristos #include <sys/tty.h> 60845beaccSjdolecek #include <sys/malloc.h> 61845beaccSjdolecek #include <sys/mount.h> 62a540ef29Smanu #include <sys/conf.h> 63e656d3b0Sjmcneill #include <sys/sysctl.h> 64cab865c6Schristos #include <sys/kauth.h> 65dce4e18dSchristos #include <sys/filedesc.h> 6687f98fe2Schristos #ifdef SYSVMSG 6787f98fe2Schristos #include <sys/msg.h> 6887f98fe2Schristos #endif 6987f98fe2Schristos #ifdef SYSVSEM 7087f98fe2Schristos #include <sys/sem.h> 7187f98fe2Schristos #endif 7287f98fe2Schristos #ifdef SYSVSHM 7387f98fe2Schristos #include <sys/shm.h> 7487f98fe2Schristos #endif 75*78b530bbSpgoyette #ifdef MQUEUE 760124a941Schristos #include <sys/mqueue.h> 77*78b530bbSpgoyette #endif 784e000b75Sfvdl 794e000b75Sfvdl #include <miscfs/procfs/procfs.h> 80736a4d9bSad 819897a542Schristos #include <compat/linux/common/linux_exec.h> 82e656d3b0Sjmcneill #include <compat/linux32/common/linux32_sysctl.h> 834e000b75Sfvdl 84210944c7Schristos #include <uvm/uvm.h> 859fc45356Sriastradh #include <uvm/uvm_extern.h> 864e000b75Sfvdl 87a540ef29Smanu extern struct devsw_conv *devsw_conv; 88a540ef29Smanu extern int max_devsw_convs; 89*78b530bbSpgoyette #ifdef MQUEUE 900124a941Schristos extern u_int mq_open_max; 910124a941Schristos extern u_int mq_max_msgsize; 920124a941Schristos extern u_int mq_def_maxmsg; 930124a941Schristos extern u_int mq_max_maxmsg; 94*78b530bbSpgoyette #endif 950124a941Schristos 96a540ef29Smanu 974e000b75Sfvdl #define PGTOB(p) ((unsigned long)(p) << PAGE_SHIFT) 984e000b75Sfvdl #define PGTOKB(p) ((unsigned long)(p) << (PAGE_SHIFT - 10)) 994e000b75Sfvdl 10026bb1685Schristos #define LBFSZ (8 * 1024) 10126bb1685Schristos 1024dbe5ed7Sagc static void 10345fbe545Schs get_proc_size_info(struct proc *p, struct vm_map *map, unsigned long *stext, 10445fbe545Schs unsigned long *etext, unsigned long *sstack) 1054dbe5ed7Sagc { 1064dbe5ed7Sagc struct vm_map_entry *entry; 1074dbe5ed7Sagc 1084dbe5ed7Sagc *stext = 0; 1094dbe5ed7Sagc *etext = 0; 1104dbe5ed7Sagc *sstack = 0; 1114dbe5ed7Sagc 1124dbe5ed7Sagc vm_map_lock_read(map); 1134dbe5ed7Sagc 1144dbe5ed7Sagc for (entry = map->header.next; entry != &map->header; 1154dbe5ed7Sagc entry = entry->next) { 1164dbe5ed7Sagc if (UVM_ET_ISSUBMAP(entry)) 1174dbe5ed7Sagc continue; 1184dbe5ed7Sagc /* assume text is the first entry */ 1194dbe5ed7Sagc if (*stext == *etext) { 1204dbe5ed7Sagc *stext = entry->start; 1214dbe5ed7Sagc *etext = entry->end; 1224dbe5ed7Sagc break; 1234dbe5ed7Sagc } 1244dbe5ed7Sagc } 125c252921eSjmcneill #if defined(LINUX_USRSTACK32) && defined(USRSTACK32) 126dfdca25eSchristos if (strcmp(p->p_emul->e_name, "linux32") == 0 && 127dfdca25eSchristos LINUX_USRSTACK32 < USRSTACK32) 128dfdca25eSchristos *sstack = (unsigned long)LINUX_USRSTACK32; 129dfdca25eSchristos else 130dfdca25eSchristos #endif 1314dbe5ed7Sagc #ifdef LINUX_USRSTACK 1324dbe5ed7Sagc if (strcmp(p->p_emul->e_name, "linux") == 0 && 1334dbe5ed7Sagc LINUX_USRSTACK < USRSTACK) 1344dbe5ed7Sagc *sstack = (unsigned long)LINUX_USRSTACK; 1354dbe5ed7Sagc else 1364dbe5ed7Sagc #endif 137dfdca25eSchristos #ifdef USRSTACK32 138dfdca25eSchristos if (strstr(p->p_emul->e_name, "32") != NULL) 139dfdca25eSchristos *sstack = (unsigned long)USRSTACK32; 140dfdca25eSchristos else 141dfdca25eSchristos #endif 1424dbe5ed7Sagc *sstack = (unsigned long)USRSTACK; 1434dbe5ed7Sagc 1444dbe5ed7Sagc /* 1454dbe5ed7Sagc * jdk 1.6 compares low <= addr && addr < high 1464dbe5ed7Sagc * if we put addr == high, then the test fails 1474dbe5ed7Sagc * so eat one page. 1484dbe5ed7Sagc */ 1494dbe5ed7Sagc *sstack -= PAGE_SIZE; 1504dbe5ed7Sagc 1514dbe5ed7Sagc vm_map_unlock_read(map); 1524dbe5ed7Sagc } 1534dbe5ed7Sagc 1544e000b75Sfvdl /* 1554e000b75Sfvdl * Linux compatible /proc/meminfo. Only active when the -o linux 1564e000b75Sfvdl * mountflag is used. 1574e000b75Sfvdl */ 1584e000b75Sfvdl int 159168cd830Schristos procfs_domeminfo(struct lwp *curl, struct proc *p, 160168cd830Schristos struct pfsnode *pfs, struct uio *uio) 1614e000b75Sfvdl { 16226bb1685Schristos char *bf; 1638bcb745dSitojun int len; 16426bb1685Schristos int error = 0; 165a98966d3Sad long filepg, anonpg, execpg, freepg; 1664e000b75Sfvdl 16726bb1685Schristos bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 16826bb1685Schristos 169ba90a6baSad /* uvm_availmem() will sync the counters if needed. */ 1704b8a875aSad freepg = (long)uvm_availmem(true); 171ba90a6baSad filepg = (long)(cpu_count_get(CPU_COUNT_FILECLEAN) + 172ba90a6baSad cpu_count_get(CPU_COUNT_FILEDIRTY) + 173ba90a6baSad cpu_count_get(CPU_COUNT_FILEUNKNOWN) - 174ba90a6baSad cpu_count_get(CPU_COUNT_EXECPAGES)); 175ba90a6baSad anonpg = (long)(cpu_count_get(CPU_COUNT_ANONCLEAN) + 176ba90a6baSad cpu_count_get(CPU_COUNT_ANONDIRTY) + 177ba90a6baSad cpu_count_get(CPU_COUNT_ANONUNKNOWN)); 178a98966d3Sad execpg = (long)cpu_count_get(CPU_COUNT_EXECPAGES); 179a98966d3Sad 18026bb1685Schristos len = snprintf(bf, LBFSZ, 1814e000b75Sfvdl " total: used: free: shared: buffers: cached:\n" 1824e000b75Sfvdl "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n" 1834e000b75Sfvdl "Swap: %8lu %8lu %8lu\n" 1844e000b75Sfvdl "MemTotal: %8lu kB\n" 1854e000b75Sfvdl "MemFree: %8lu kB\n" 1864e000b75Sfvdl "MemShared: %8lu kB\n" 1874e000b75Sfvdl "Buffers: %8lu kB\n" 1884e000b75Sfvdl "Cached: %8lu kB\n" 1894e000b75Sfvdl "SwapTotal: %8lu kB\n" 1904e000b75Sfvdl "SwapFree: %8lu kB\n", 1914e000b75Sfvdl PGTOB(uvmexp.npages), 192a98966d3Sad PGTOB(uvmexp.npages - freepg), 193a98966d3Sad PGTOB(freepg), 1944e000b75Sfvdl 0L, 195a98966d3Sad PGTOB(filepg), 196a98966d3Sad PGTOB(anonpg + filepg + execpg), 1974e000b75Sfvdl PGTOB(uvmexp.swpages), 1984e000b75Sfvdl PGTOB(uvmexp.swpginuse), 1994e000b75Sfvdl PGTOB(uvmexp.swpages - uvmexp.swpginuse), 2004e000b75Sfvdl PGTOKB(uvmexp.npages), 201a98966d3Sad PGTOKB(freepg), 2024e000b75Sfvdl 0L, 203a98966d3Sad PGTOKB(freepg), 204a98966d3Sad PGTOKB(anonpg + filepg + execpg), 2054e000b75Sfvdl PGTOKB(uvmexp.swpages), 2064e000b75Sfvdl PGTOKB(uvmexp.swpages - uvmexp.swpginuse)); 2074e000b75Sfvdl 2084e000b75Sfvdl if (len == 0) 20926bb1685Schristos goto out; 2104e000b75Sfvdl 21126bb1685Schristos error = uiomove_frombuf(bf, len, uio); 21226bb1685Schristos out: 21326bb1685Schristos free(bf, M_TEMP); 21426bb1685Schristos return error; 2154e000b75Sfvdl } 2164e000b75Sfvdl 217210944c7Schristos /* 218a540ef29Smanu * Linux compatible /proc/devices. Only active when the -o linux 219a540ef29Smanu * mountflag is used. 220a540ef29Smanu */ 221a540ef29Smanu int 222168cd830Schristos procfs_dodevices(struct lwp *curl, struct proc *p, 223168cd830Schristos struct pfsnode *pfs, struct uio *uio) 224a540ef29Smanu { 22526bb1685Schristos char *bf; 226a540ef29Smanu int offset = 0; 22726bb1685Schristos int i, error = ENAMETOOLONG; 228a540ef29Smanu 229a6877176Selad /* XXX elad - may need filtering. */ 230a6877176Selad 23126bb1685Schristos bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 23226bb1685Schristos 23326bb1685Schristos offset += snprintf(&bf[offset], LBFSZ - offset, "Character devices:\n"); 23426bb1685Schristos if (offset >= LBFSZ) 23526bb1685Schristos goto out; 236a540ef29Smanu 2378583cae2Spooka mutex_enter(&device_lock); 238a540ef29Smanu for (i = 0; i < max_devsw_convs; i++) { 239a540ef29Smanu if ((devsw_conv[i].d_name == NULL) || 240a540ef29Smanu (devsw_conv[i].d_cmajor == -1)) 241a540ef29Smanu continue; 242a540ef29Smanu 24326bb1685Schristos offset += snprintf(&bf[offset], LBFSZ - offset, 244a540ef29Smanu "%3d %s\n", devsw_conv[i].d_cmajor, devsw_conv[i].d_name); 245d18c6ca4Sad if (offset >= LBFSZ) { 2468583cae2Spooka mutex_exit(&device_lock); 24726bb1685Schristos goto out; 248a540ef29Smanu } 249d18c6ca4Sad } 250a540ef29Smanu 25126bb1685Schristos offset += snprintf(&bf[offset], LBFSZ - offset, "\nBlock devices:\n"); 252d18c6ca4Sad if (offset >= LBFSZ) { 2538583cae2Spooka mutex_exit(&device_lock); 25426bb1685Schristos goto out; 255d18c6ca4Sad } 256a540ef29Smanu 257a540ef29Smanu for (i = 0; i < max_devsw_convs; i++) { 258a540ef29Smanu if ((devsw_conv[i].d_name == NULL) || 259a540ef29Smanu (devsw_conv[i].d_bmajor == -1)) 260a540ef29Smanu continue; 261a540ef29Smanu 26226bb1685Schristos offset += snprintf(&bf[offset], LBFSZ - offset, 263a540ef29Smanu "%3d %s\n", devsw_conv[i].d_bmajor, devsw_conv[i].d_name); 264d18c6ca4Sad if (offset >= LBFSZ) { 2658583cae2Spooka mutex_exit(&device_lock); 26626bb1685Schristos goto out; 267a540ef29Smanu } 268d18c6ca4Sad } 2698583cae2Spooka mutex_exit(&device_lock); 270a540ef29Smanu 27126bb1685Schristos error = uiomove_frombuf(bf, offset, uio); 27226bb1685Schristos out: 27326bb1685Schristos free(bf, M_TEMP); 27426bb1685Schristos return error; 275a540ef29Smanu } 276a540ef29Smanu 277a540ef29Smanu /* 2784dbe5ed7Sagc * Linux compatible /proc/stat. Only active when the -o linux 2794dbe5ed7Sagc * mountflag is used. 2804dbe5ed7Sagc */ 2814dbe5ed7Sagc int 2824dbe5ed7Sagc procfs_docpustat(struct lwp *curl, struct proc *p, 2834dbe5ed7Sagc struct pfsnode *pfs, struct uio *uio) 2844dbe5ed7Sagc { 2854dbe5ed7Sagc char *bf; 2864dbe5ed7Sagc int error; 2874dbe5ed7Sagc int len; 28815a3a67eSagc #if defined(MULTIPROCESSOR) 28915a3a67eSagc struct cpu_info *ci; 29015a3a67eSagc CPU_INFO_ITERATOR cii; 29115a3a67eSagc #endif 29212003e87Sagc int i; 2934dbe5ed7Sagc 2944dbe5ed7Sagc error = ENAMETOOLONG; 2954dbe5ed7Sagc bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 2964dbe5ed7Sagc 2974dbe5ed7Sagc len = snprintf(bf, LBFSZ, 298905b715aSdogcow "cpu %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 2994dbe5ed7Sagc curcpu()->ci_schedstate.spc_cp_time[CP_USER], 3004dbe5ed7Sagc curcpu()->ci_schedstate.spc_cp_time[CP_NICE], 3014dbe5ed7Sagc curcpu()->ci_schedstate.spc_cp_time[CP_SYS] /*+ [CP_INTR]*/, 3024dbe5ed7Sagc curcpu()->ci_schedstate.spc_cp_time[CP_IDLE]); 3034dbe5ed7Sagc if (len == 0) 3044dbe5ed7Sagc goto out; 3054dbe5ed7Sagc 30615a3a67eSagc #if defined(MULTIPROCESSOR) 30712003e87Sagc #define ALLCPUS CPU_INFO_FOREACH(cii, ci) 30812003e87Sagc #define CPUNAME ci 30912003e87Sagc #else 31012003e87Sagc #define ALLCPUS ; i < 1 ; 31112003e87Sagc #define CPUNAME curcpu() 31212003e87Sagc #endif 31312003e87Sagc 3144dbe5ed7Sagc i = 0; 31512003e87Sagc for (ALLCPUS) { 3164dbe5ed7Sagc len += snprintf(&bf[len], LBFSZ - len, 317905b715aSdogcow "cpu%d %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 318905b715aSdogcow "\n", i, 31912003e87Sagc CPUNAME->ci_schedstate.spc_cp_time[CP_USER], 32012003e87Sagc CPUNAME->ci_schedstate.spc_cp_time[CP_NICE], 32112003e87Sagc CPUNAME->ci_schedstate.spc_cp_time[CP_SYS], 32212003e87Sagc CPUNAME->ci_schedstate.spc_cp_time[CP_IDLE]); 3234dbe5ed7Sagc if (len >= LBFSZ) 3244dbe5ed7Sagc goto out; 3254dbe5ed7Sagc i += 1; 3264dbe5ed7Sagc } 3274dbe5ed7Sagc 328ba90a6baSad cpu_count_sync(true); 329a98966d3Sad 330d6c967bbSthorpej struct timeval btv; 331d6c967bbSthorpej getmicroboottime(&btv); 332d6c967bbSthorpej 3334dbe5ed7Sagc len += snprintf(&bf[len], LBFSZ - len, 3344dbe5ed7Sagc "disk 0 0 0 0\n" 3354dbe5ed7Sagc "page %u %u\n" 3364dbe5ed7Sagc "swap %u %u\n" 337a98966d3Sad "intr %"PRId64"\n" 338a98966d3Sad "ctxt %"PRId64"\n" 3396a66466fSmatt "btime %"PRId64"\n", 3404dbe5ed7Sagc uvmexp.pageins, uvmexp.pdpageouts, 3414dbe5ed7Sagc uvmexp.pgswapin, uvmexp.pgswapout, 342a98966d3Sad cpu_count_get(CPU_COUNT_NINTR), 343a98966d3Sad cpu_count_get(CPU_COUNT_NSWTCH), 344d6c967bbSthorpej btv.tv_sec); 3454dbe5ed7Sagc if (len >= LBFSZ) 3464dbe5ed7Sagc goto out; 3474dbe5ed7Sagc 3484dbe5ed7Sagc error = uiomove_frombuf(bf, len, uio); 3494dbe5ed7Sagc out: 3504dbe5ed7Sagc free(bf, M_TEMP); 3514dbe5ed7Sagc return error; 3524dbe5ed7Sagc } 3534dbe5ed7Sagc 3544dbe5ed7Sagc /* 3554dbe5ed7Sagc * Linux compatible /proc/loadavg. Only active when the -o linux 3564dbe5ed7Sagc * mountflag is used. 3574dbe5ed7Sagc */ 3584dbe5ed7Sagc int 3594dbe5ed7Sagc procfs_doloadavg(struct lwp *curl, struct proc *p, 3604dbe5ed7Sagc struct pfsnode *pfs, struct uio *uio) 3614dbe5ed7Sagc { 3624dbe5ed7Sagc char *bf; 3634dbe5ed7Sagc int error; 3644dbe5ed7Sagc int len; 3654dbe5ed7Sagc 3664dbe5ed7Sagc error = ENAMETOOLONG; 3674dbe5ed7Sagc bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 3684dbe5ed7Sagc 3694dbe5ed7Sagc averunnable.fscale = FSCALE; 3704dbe5ed7Sagc len = snprintf(bf, LBFSZ, 3714dbe5ed7Sagc "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 3724dbe5ed7Sagc (int)(averunnable.ldavg[0] / averunnable.fscale), 3734dbe5ed7Sagc (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 3744dbe5ed7Sagc (int)(averunnable.ldavg[1] / averunnable.fscale), 3754dbe5ed7Sagc (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 3764dbe5ed7Sagc (int)(averunnable.ldavg[2] / averunnable.fscale), 3774dbe5ed7Sagc (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 3784dbe5ed7Sagc 1, /* number of ONPROC processes */ 379a29147faSthorpej atomic_load_relaxed(&nprocs), 3804dbe5ed7Sagc 30000); /* last pid */ 3814dbe5ed7Sagc if (len == 0) 3824dbe5ed7Sagc goto out; 3834dbe5ed7Sagc 3844dbe5ed7Sagc error = uiomove_frombuf(bf, len, uio); 3854dbe5ed7Sagc out: 3864dbe5ed7Sagc free(bf, M_TEMP); 3874dbe5ed7Sagc return error; 3884dbe5ed7Sagc } 3894dbe5ed7Sagc 3904dbe5ed7Sagc /* 3914dbe5ed7Sagc * Linux compatible /proc/<pid>/statm. Only active when the -o linux 3924dbe5ed7Sagc * mountflag is used. 3934dbe5ed7Sagc */ 3944dbe5ed7Sagc int 3954dbe5ed7Sagc procfs_do_pid_statm(struct lwp *curl, struct lwp *l, 3964dbe5ed7Sagc struct pfsnode *pfs, struct uio *uio) 3974dbe5ed7Sagc { 39815a3a67eSagc struct vmspace *vm; 3994dbe5ed7Sagc struct proc *p = l->l_proc; 4004dbe5ed7Sagc char *bf; 4014dbe5ed7Sagc int error; 4024dbe5ed7Sagc int len; 4033bb28e76Smlelstv struct kinfo_proc2 ki; 4044dbe5ed7Sagc 4054dbe5ed7Sagc bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 4064dbe5ed7Sagc 40715a3a67eSagc /* XXX - we use values from vmspace, since dsl says that ru figures 40815a3a67eSagc are always 0 except for zombies. See kvm_proc.c::kvm_getproc2() */ 40915a3a67eSagc if ((error = proc_vmspace_getref(p, &vm)) != 0) { 410f1a59086Sagc goto out; 41115a3a67eSagc } 4124dbe5ed7Sagc 4130eaaa024Sad mutex_enter(&proc_lock); 4143bb28e76Smlelstv mutex_enter(p->p_lock); 4153bb28e76Smlelstv 4163bb28e76Smlelstv /* retrieve RSS size */ 4173fb8db10Smaxv memset(&ki, 0, sizeof(ki)); 418dea54605Schristos fill_kproc2(p, &ki, false, false); 4193bb28e76Smlelstv 4203bb28e76Smlelstv mutex_exit(p->p_lock); 4210eaaa024Sad mutex_exit(&proc_lock); 42215a3a67eSagc 423a501df5aSdholland uvmspace_free(vm); 424a501df5aSdholland 4253bb28e76Smlelstv len = snprintf(bf, LBFSZ, 4263bb28e76Smlelstv "%lu %lu %lu %lu %lu %lu %lu\n", 4273bb28e76Smlelstv (unsigned long)(ki.p_vm_msize), /* size */ 4283bb28e76Smlelstv (unsigned long)(ki.p_vm_rssize),/* resident */ 4293bb28e76Smlelstv (unsigned long)(ki.p_uru_ixrss),/* shared */ 4303bb28e76Smlelstv (unsigned long)(ki.p_vm_tsize), /* text */ 4313bb28e76Smlelstv (unsigned long) 0, /* library (unused) */ 4323bb28e76Smlelstv (unsigned long)(ki.p_vm_dsize + ki.p_vm_ssize), /* data+stack */ 4333bb28e76Smlelstv (unsigned long) 0); /* dirty */ 4343bb28e76Smlelstv 4354dbe5ed7Sagc if (len == 0) 4364dbe5ed7Sagc goto out; 4374dbe5ed7Sagc 4384dbe5ed7Sagc error = uiomove_frombuf(bf, len, uio); 4394dbe5ed7Sagc out: 4404dbe5ed7Sagc free(bf, M_TEMP); 4414dbe5ed7Sagc return error; 4424dbe5ed7Sagc } 4434dbe5ed7Sagc 444684c8bf8Snjoly #define UTIME2TICKS(s,u) (((uint64_t)(s) * 1000000 + (u)) / 10000) 44515a3a67eSagc 4464dbe5ed7Sagc /* 447210944c7Schristos * Linux compatible /proc/<pid>/stat. Only active when the -o linux 448210944c7Schristos * mountflag is used. 449210944c7Schristos */ 450210944c7Schristos int 451168cd830Schristos procfs_do_pid_stat(struct lwp *curl, struct lwp *l, 452168cd830Schristos struct pfsnode *pfs, struct uio *uio) 453210944c7Schristos { 45426bb1685Schristos char *bf; 455f36aa0cdSchristos struct proc *p = l->l_proc; 4568bcb745dSitojun int len; 457210944c7Schristos struct rusage *cru = &p->p_stats->p_cru; 458210944c7Schristos unsigned long stext = 0, etext = 0, sstack = 0; 459b07ec3fcSad struct timeval rt; 460f1a59086Sagc struct vmspace *vm; 461684c8bf8Snjoly struct kinfo_proc2 ki; 4626647020bSmaxv int error; 46326bb1685Schristos 46426bb1685Schristos bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 465210944c7Schristos 466f1a59086Sagc if ((error = proc_vmspace_getref(p, &vm)) != 0) { 467f1a59086Sagc goto out; 468f1a59086Sagc } 469f1a59086Sagc 47045fbe545Schs get_proc_size_info(p, &vm->vm_map, &stext, &etext, &sstack); 471b07ec3fcSad 4720eaaa024Sad mutex_enter(&proc_lock); 473284c2b9aSad mutex_enter(p->p_lock); 474b07ec3fcSad 4753fb8db10Smaxv memset(&ki, 0, sizeof(ki)); 476dea54605Schristos fill_kproc2(p, &ki, false, false); 477b07ec3fcSad calcru(p, NULL, NULL, NULL, &rt); 478210944c7Schristos 47926bb1685Schristos len = snprintf(bf, LBFSZ, 480684c8bf8Snjoly "%d (%s) %c %d %d %d %u %d " 481210944c7Schristos "%u " 482684c8bf8Snjoly "%"PRIu64" %lu %"PRIu64" %lu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" " 483684c8bf8Snjoly "%d %d %"PRIu64" " 484684c8bf8Snjoly "%lld %"PRIu64" %"PRId64" %lu %"PRIu64" " 485210944c7Schristos "%lu %lu %lu " 486210944c7Schristos "%u %u " 487210944c7Schristos "%u %u %u %u " 488684c8bf8Snjoly "%"PRIu64" %"PRIu64" %"PRIu64" %d %"PRIu64"\n", 489210944c7Schristos 490684c8bf8Snjoly ki.p_pid, /* 1 pid */ 491684c8bf8Snjoly ki.p_comm, /* 2 tcomm */ 492684c8bf8Snjoly "0RRSTZXR8"[(ki.p_stat > 8) ? 0 : (int)ki.p_stat], /* 3 state */ 493684c8bf8Snjoly ki.p_ppid, /* 4 ppid */ 494684c8bf8Snjoly ki.p__pgid, /* 5 pgrp */ 495684c8bf8Snjoly ki.p_sid, /* 6 sid */ 496684c8bf8Snjoly (ki.p_tdev != (uint32_t)NODEV) ? ki.p_tdev : 0, /* 7 tty_nr */ 497684c8bf8Snjoly ki.p_tpgid, /* 8 tty_pgrp */ 498210944c7Schristos 499684c8bf8Snjoly ki.p_flag, /* 9 flags */ 500210944c7Schristos 501684c8bf8Snjoly ki.p_uru_minflt, /* 10 min_flt */ 502210944c7Schristos cru->ru_minflt, 503684c8bf8Snjoly ki.p_uru_majflt, /* 12 maj_flt */ 504210944c7Schristos cru->ru_majflt, 505684c8bf8Snjoly UTIME2TICKS(ki.p_uutime_sec, ki.p_uutime_usec), /* 14 utime */ 506684c8bf8Snjoly UTIME2TICKS(ki.p_ustime_sec, ki.p_ustime_usec), /* 15 stime */ 507684c8bf8Snjoly UTIME2TICKS(cru->ru_utime.tv_sec, cru->ru_utime.tv_usec), /* 16 cutime */ 508684c8bf8Snjoly UTIME2TICKS(cru->ru_stime.tv_sec, cru->ru_stime.tv_usec), /* 17 cstime */ 509210944c7Schristos 510684c8bf8Snjoly ki.p_priority, /* XXX: 18 priority */ 511684c8bf8Snjoly ki.p_nice - NZERO, /* 19 nice */ 512684c8bf8Snjoly ki.p_nlwps, /* 20 num_threads */ 513210944c7Schristos 514461a86f9Schristos (long long)rt.tv_sec, 515684c8bf8Snjoly UTIME2TICKS(ki.p_ustart_sec, ki.p_ustart_usec), /* 22 start_time */ 516684c8bf8Snjoly ki.p_vm_msize, /* 23 vsize */ 517684c8bf8Snjoly PGTOKB(ki.p_vm_rssize), /* 24 rss */ 518684c8bf8Snjoly p->p_rlimit[RLIMIT_RSS].rlim_cur, /* 25 rsslim */ 519210944c7Schristos 520684c8bf8Snjoly stext, /* 26 start_code */ 521684c8bf8Snjoly etext, /* 27 end_code */ 522684c8bf8Snjoly sstack, /* 28 start_stack */ 523210944c7Schristos 524684c8bf8Snjoly 0, /* XXX: 29 esp */ 525684c8bf8Snjoly 0, /* XXX: 30 eip */ 526684c8bf8Snjoly 527684c8bf8Snjoly ki.p_siglist.__bits[0], /* XXX: 31 pending */ 528684c8bf8Snjoly 0, /* XXX: 32 blocked */ 529684c8bf8Snjoly ki.p_sigignore.__bits[0], /* 33 sigign */ 530684c8bf8Snjoly ki.p_sigcatch.__bits[0], /* 34 sigcatch */ 531684c8bf8Snjoly 532684c8bf8Snjoly ki.p_wchan, /* 35 wchan */ 533684c8bf8Snjoly ki.p_uru_nvcsw, 534684c8bf8Snjoly ki.p_uru_nivcsw, 535684c8bf8Snjoly ki.p_exitsig, /* 38 exit_signal */ 536684c8bf8Snjoly ki.p_cpuid); /* 39 task_cpu */ 537210944c7Schristos 538284c2b9aSad mutex_exit(p->p_lock); 5390eaaa024Sad mutex_exit(&proc_lock); 540b07ec3fcSad 541a501df5aSdholland uvmspace_free(vm); 542a501df5aSdholland 543210944c7Schristos if (len == 0) 54426bb1685Schristos goto out; 545210944c7Schristos 54626bb1685Schristos error = uiomove_frombuf(bf, len, uio); 54726bb1685Schristos out: 54826bb1685Schristos free(bf, M_TEMP); 54926bb1685Schristos return error; 550210944c7Schristos } 551210944c7Schristos 5524e000b75Sfvdl int 553168cd830Schristos procfs_docpuinfo(struct lwp *curl, struct proc *p, 554168cd830Schristos struct pfsnode *pfs, struct uio *uio) 5554e000b75Sfvdl { 55616c9d42fSchristos size_t len = LBFSZ; 55716c9d42fSchristos char *bf = NULL; 5581a63592aSchristos int error; 5591a63592aSchristos 56016c9d42fSchristos do { 56116c9d42fSchristos if (bf) 56216c9d42fSchristos free(bf, M_TEMP); 56316c9d42fSchristos bf = malloc(len, M_TEMP, M_WAITOK); 56416c9d42fSchristos } while (procfs_getcpuinfstr(bf, &len) < 0); 5654e000b75Sfvdl 5661a63592aSchristos if (len == 0) { 5671a63592aSchristos error = 0; 5681a63592aSchristos goto done; 5691a63592aSchristos } 5704e000b75Sfvdl 571c107ef9eSchristos error = uiomove_frombuf(bf, len, uio); 5721a63592aSchristos done: 573c107ef9eSchristos free(bf, M_TEMP); 5741a63592aSchristos return error; 5754e000b75Sfvdl } 576a2d850baSjrf 577a2d850baSjrf int 578168cd830Schristos procfs_douptime(struct lwp *curl, struct proc *p, 579168cd830Schristos struct pfsnode *pfs, struct uio *uio) 580a2d850baSjrf { 58126bb1685Schristos char *bf; 5828bcb745dSitojun int len; 583a2d850baSjrf struct timeval runtime; 584a2d850baSjrf u_int64_t idle; 58526bb1685Schristos int error = 0; 58626bb1685Schristos 58726bb1685Schristos bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 588a2d850baSjrf 5892294b0bcSyamt microuptime(&runtime); 590a2d850baSjrf idle = curcpu()->ci_schedstate.spc_cp_time[CP_IDLE]; 59126bb1685Schristos len = snprintf(bf, LBFSZ, 592461a86f9Schristos "%lld.%02lu %" PRIu64 ".%02" PRIu64 "\n", 593461a86f9Schristos (long long)runtime.tv_sec, (long)runtime.tv_usec / 10000, 594a2d850baSjrf idle / hz, (((idle % hz) * 100) / hz) % 100); 595a2d850baSjrf 596a2d850baSjrf if (len == 0) 59726bb1685Schristos goto out; 598a2d850baSjrf 59926bb1685Schristos error = uiomove_frombuf(bf, len, uio); 60026bb1685Schristos out: 60126bb1685Schristos free(bf, M_TEMP); 60226bb1685Schristos return error; 603a2d850baSjrf } 604845beaccSjdolecek 605dce4e18dSchristos static int 606dce4e18dSchristos procfs_format_sfs(char **mtab, size_t *mlen, char *buf, size_t blen, 607dce4e18dSchristos const struct statvfs *sfs, struct lwp *curl, int suser) 608845beaccSjdolecek { 609845beaccSjdolecek const char *fsname; 610845beaccSjdolecek 611845beaccSjdolecek /* Linux uses different names for some filesystems */ 612dce4e18dSchristos fsname = sfs->f_fstypename; 613845beaccSjdolecek if (strcmp(fsname, "procfs") == 0) 614845beaccSjdolecek fsname = "proc"; 615845beaccSjdolecek else if (strcmp(fsname, "ext2fs") == 0) 616845beaccSjdolecek fsname = "ext2"; 617845beaccSjdolecek 618dce4e18dSchristos blen = snprintf(buf, blen, "%s %s %s %s%s%s%s%s%s 0 0\n", 619dce4e18dSchristos sfs->f_mntfromname, sfs->f_mntonname, fsname, 620dce4e18dSchristos (sfs->f_flag & ST_RDONLY) ? "ro" : "rw", 621dce4e18dSchristos (sfs->f_flag & ST_NOSUID) ? ",nosuid" : "", 622dce4e18dSchristos (sfs->f_flag & ST_NOEXEC) ? ",noexec" : "", 623dce4e18dSchristos (sfs->f_flag & ST_NODEV) ? ",nodev" : "", 624dce4e18dSchristos (sfs->f_flag & ST_SYNCHRONOUS) ? ",sync" : "", 625dce4e18dSchristos (sfs->f_flag & ST_NOATIME) ? ",noatime" : ""); 626845beaccSjdolecek 627dce4e18dSchristos *mtab = realloc(*mtab, *mlen + blen, M_TEMP, M_WAITOK); 628dce4e18dSchristos memcpy(*mtab + *mlen, buf, blen); 629dce4e18dSchristos *mlen += blen; 630dce4e18dSchristos return sfs->f_mntonname[0] == '/' && sfs->f_mntonname[1] == '\0'; 631dce4e18dSchristos } 632dce4e18dSchristos 633dce4e18dSchristos int 634dce4e18dSchristos procfs_domounts(struct lwp *curl, struct proc *p, 635dce4e18dSchristos struct pfsnode *pfs, struct uio *uio) 636dce4e18dSchristos { 637dce4e18dSchristos char *bf, *mtab = NULL; 638dce4e18dSchristos size_t mtabsz = 0; 639769f0c92Shannken mount_iterator_t *iter; 640769f0c92Shannken struct mount *mp; 6418ddb33d2Schristos int error = 0, root = 0; 642dce4e18dSchristos struct cwdinfo *cwdi = curl->l_proc->p_cwdi; 64346b290a0Srin struct statvfs *sfs; 644dce4e18dSchristos 645dce4e18dSchristos bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 646dce4e18dSchristos 64746b290a0Srin sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK); 648769f0c92Shannken mountlist_iterator_init(&iter); 649769f0c92Shannken while ((mp = mountlist_iterator_next(iter)) != NULL) { 65046b290a0Srin if ((error = dostatvfs(mp, sfs, curl, MNT_WAIT, 0)) == 0) 651dce4e18dSchristos root |= procfs_format_sfs(&mtab, &mtabsz, bf, LBFSZ, 65246b290a0Srin sfs, curl, 0); 653845beaccSjdolecek } 654769f0c92Shannken mountlist_iterator_destroy(iter); 65546b290a0Srin free(sfs, M_TEMP); 656dce4e18dSchristos 657dce4e18dSchristos /* 658dce4e18dSchristos * If we are inside a chroot that is not itself a mount point, 659dce4e18dSchristos * fake a root entry. 660dce4e18dSchristos */ 661dce4e18dSchristos if (!root && cwdi->cwdi_rdir) 662dce4e18dSchristos (void)procfs_format_sfs(&mtab, &mtabsz, bf, LBFSZ, 663dce4e18dSchristos &cwdi->cwdi_rdir->v_mount->mnt_stat, curl, 1); 664dce4e18dSchristos 66526bb1685Schristos free(bf, M_TEMP); 666845beaccSjdolecek 667845beaccSjdolecek if (mtabsz > 0) { 668845beaccSjdolecek error = uiomove_frombuf(mtab, mtabsz, uio); 669845beaccSjdolecek free(mtab, M_TEMP); 670845beaccSjdolecek } 671845beaccSjdolecek 672845beaccSjdolecek return error; 673845beaccSjdolecek } 674e656d3b0Sjmcneill 675e656d3b0Sjmcneill /* 676e656d3b0Sjmcneill * Linux compatible /proc/version. Only active when the -o linux 677e656d3b0Sjmcneill * mountflag is used. 678e656d3b0Sjmcneill */ 679e656d3b0Sjmcneill int 680e656d3b0Sjmcneill procfs_doversion(struct lwp *curl, struct proc *p, 681e656d3b0Sjmcneill struct pfsnode *pfs, struct uio *uio) 682e656d3b0Sjmcneill { 683e656d3b0Sjmcneill char *bf; 684e656d3b0Sjmcneill char lostype[20], losrelease[20], lversion[80]; 685e656d3b0Sjmcneill const char *postype, *posrelease, *pversion; 686e656d3b0Sjmcneill const char *emulname = curlwp->l_proc->p_emul->e_name; 687e656d3b0Sjmcneill int len; 688e656d3b0Sjmcneill int error = 0; 689e656d3b0Sjmcneill int nm[4]; 690e656d3b0Sjmcneill size_t buflen; 691e656d3b0Sjmcneill 692e656d3b0Sjmcneill CTASSERT(EMUL_LINUX_KERN_OSTYPE == EMUL_LINUX32_KERN_OSTYPE); 693e656d3b0Sjmcneill CTASSERT(EMUL_LINUX_KERN_OSRELEASE == EMUL_LINUX32_KERN_OSRELEASE); 694e656d3b0Sjmcneill CTASSERT(EMUL_LINUX_KERN_VERSION == EMUL_LINUX32_KERN_VERSION); 695e656d3b0Sjmcneill 696e656d3b0Sjmcneill bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 697e656d3b0Sjmcneill 698e656d3b0Sjmcneill sysctl_lock(false); 699e656d3b0Sjmcneill 700e656d3b0Sjmcneill if (strncmp(emulname, "linux", 5) == 0) { 701e656d3b0Sjmcneill /* 702e656d3b0Sjmcneill * Lookup the emulation ostype, osrelease, and version. 703e656d3b0Sjmcneill * Since compat_linux and compat_linux32 can be built as 704e656d3b0Sjmcneill * modules, we use sysctl to obtain the values instead of 705e656d3b0Sjmcneill * using the symbols directly. 706e656d3b0Sjmcneill */ 707e656d3b0Sjmcneill 708e656d3b0Sjmcneill if (strcmp(emulname, "linux32") == 0) { 709e656d3b0Sjmcneill nm[0] = CTL_EMUL; 710e656d3b0Sjmcneill nm[1] = EMUL_LINUX32; 711e656d3b0Sjmcneill nm[2] = EMUL_LINUX32_KERN; 712e656d3b0Sjmcneill } else { 713e656d3b0Sjmcneill nm[0] = CTL_EMUL; 714e656d3b0Sjmcneill nm[1] = EMUL_LINUX; 715e656d3b0Sjmcneill nm[2] = EMUL_LINUX_KERN; 716e656d3b0Sjmcneill } 717e656d3b0Sjmcneill 718e656d3b0Sjmcneill nm[3] = EMUL_LINUX_KERN_OSTYPE; 719e656d3b0Sjmcneill buflen = sizeof(lostype); 720e656d3b0Sjmcneill error = sysctl_dispatch(nm, __arraycount(nm), 721e656d3b0Sjmcneill lostype, &buflen, 722e656d3b0Sjmcneill NULL, 0, NULL, NULL, NULL); 723e656d3b0Sjmcneill if (error) 724e656d3b0Sjmcneill goto out; 725e656d3b0Sjmcneill 726e656d3b0Sjmcneill nm[3] = EMUL_LINUX_KERN_OSRELEASE; 727e656d3b0Sjmcneill buflen = sizeof(losrelease); 728e656d3b0Sjmcneill error = sysctl_dispatch(nm, __arraycount(nm), 729e656d3b0Sjmcneill losrelease, &buflen, 730e656d3b0Sjmcneill NULL, 0, NULL, NULL, NULL); 731e656d3b0Sjmcneill if (error) 732e656d3b0Sjmcneill goto out; 733e656d3b0Sjmcneill 734e656d3b0Sjmcneill nm[3] = EMUL_LINUX_KERN_VERSION; 735e656d3b0Sjmcneill buflen = sizeof(lversion); 736e656d3b0Sjmcneill error = sysctl_dispatch(nm, __arraycount(nm), 737e656d3b0Sjmcneill lversion, &buflen, 738e656d3b0Sjmcneill NULL, 0, NULL, NULL, NULL); 739e656d3b0Sjmcneill if (error) 740e656d3b0Sjmcneill goto out; 741e656d3b0Sjmcneill 742e656d3b0Sjmcneill postype = lostype; 743e656d3b0Sjmcneill posrelease = losrelease; 744e656d3b0Sjmcneill pversion = lversion; 745e656d3b0Sjmcneill } else { 746e656d3b0Sjmcneill postype = ostype; 747e656d3b0Sjmcneill posrelease = osrelease; 748e656d3b0Sjmcneill strlcpy(lversion, version, sizeof(lversion)); 749e656d3b0Sjmcneill if (strchr(lversion, '\n')) 750e656d3b0Sjmcneill *strchr(lversion, '\n') = '\0'; 751e656d3b0Sjmcneill pversion = lversion; 752e656d3b0Sjmcneill } 753e656d3b0Sjmcneill 754e656d3b0Sjmcneill len = snprintf(bf, LBFSZ, 755e656d3b0Sjmcneill "%s version %s (%s@localhost) (gcc version %s) %s\n", 756e656d3b0Sjmcneill postype, posrelease, emulname, 757e656d3b0Sjmcneill #ifdef __VERSION__ 758e656d3b0Sjmcneill __VERSION__, 759e656d3b0Sjmcneill #else 760e656d3b0Sjmcneill "unknown", 761e656d3b0Sjmcneill #endif 762e656d3b0Sjmcneill pversion); 763e656d3b0Sjmcneill 764e656d3b0Sjmcneill if (len == 0) 765e656d3b0Sjmcneill goto out; 766e656d3b0Sjmcneill 767e656d3b0Sjmcneill error = uiomove_frombuf(bf, len, uio); 768e656d3b0Sjmcneill out: 769e656d3b0Sjmcneill free(bf, M_TEMP); 770e656d3b0Sjmcneill sysctl_unlock(); 771e656d3b0Sjmcneill return error; 772e656d3b0Sjmcneill } 77387f98fe2Schristos 77487f98fe2Schristos int 77587f98fe2Schristos procfs_dosysvipc_msg(struct lwp *curl, struct proc *p, 77687f98fe2Schristos struct pfsnode *pfs, struct uio *uio) 77787f98fe2Schristos { 77887f98fe2Schristos char *bf; 77987f98fe2Schristos int offset = 0; 78087f98fe2Schristos int error = EFBIG; 78187f98fe2Schristos 78287f98fe2Schristos bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 78387f98fe2Schristos 78487f98fe2Schristos offset += snprintf(bf, LBFSZ, 78587f98fe2Schristos "%10s %10s %4s %10s %10s %5s %5s %5s %5s %5s %5s %10s %10s %10s\n", 78687f98fe2Schristos "key", "msqid", "perms", "cbytes", "qnum", "lspid", "lrpid", 78787f98fe2Schristos "uid", "gid", "cuid", "cgid", "stime", "rtime", "ctime"); 78887f98fe2Schristos if (offset >= LBFSZ) 78987f98fe2Schristos goto out; 79087f98fe2Schristos 79187f98fe2Schristos #ifdef SYSVMSG 79287f98fe2Schristos for (int id = 0; id < msginfo.msgmni; id++) 79387f98fe2Schristos if (msqs[id].msq_u.msg_qbytes > 0) { 79487f98fe2Schristos offset += snprintf(&bf[offset], LBFSZ - offset, 79587f98fe2Schristos "%10d %10d %4o %10zu %10lu %5u %5u %5u %5u %5u %5u %10lld %10lld %10lld\n", 79687f98fe2Schristos (int) msqs[id].msq_u.msg_perm._key, 79787f98fe2Schristos IXSEQ_TO_IPCID(id, msqs[id].msq_u.msg_perm), 79887f98fe2Schristos msqs[id].msq_u.msg_perm.mode, 79987f98fe2Schristos msqs[id].msq_u._msg_cbytes, 80087f98fe2Schristos msqs[id].msq_u.msg_qnum, 80187f98fe2Schristos msqs[id].msq_u.msg_lspid, 80287f98fe2Schristos msqs[id].msq_u.msg_lrpid, 80387f98fe2Schristos msqs[id].msq_u.msg_perm.uid, 80487f98fe2Schristos msqs[id].msq_u.msg_perm.gid, 80587f98fe2Schristos msqs[id].msq_u.msg_perm.cuid, 80687f98fe2Schristos msqs[id].msq_u.msg_perm.cgid, 80787f98fe2Schristos (long long)msqs[id].msq_u.msg_stime, 80887f98fe2Schristos (long long)msqs[id].msq_u.msg_rtime, 80987f98fe2Schristos (long long)msqs[id].msq_u.msg_ctime); 81087f98fe2Schristos if (offset >= LBFSZ) 81187f98fe2Schristos goto out; 81287f98fe2Schristos } 81387f98fe2Schristos #endif 81487f98fe2Schristos 81587f98fe2Schristos error = uiomove_frombuf(bf, offset, uio); 81687f98fe2Schristos out: 81787f98fe2Schristos free(bf, M_TEMP); 81887f98fe2Schristos return error; 81987f98fe2Schristos } 82087f98fe2Schristos 82187f98fe2Schristos int 82287f98fe2Schristos procfs_dosysvipc_sem(struct lwp *curl, struct proc *p, 82387f98fe2Schristos struct pfsnode *pfs, struct uio *uio) 82487f98fe2Schristos { 82587f98fe2Schristos char *bf; 82687f98fe2Schristos int offset = 0; 82787f98fe2Schristos int error = EFBIG; 82887f98fe2Schristos 82987f98fe2Schristos bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 83087f98fe2Schristos 83187f98fe2Schristos offset += snprintf(bf, LBFSZ, 83287f98fe2Schristos "%10s %10s %4s %10s %5s %5s %5s %5s %10s %10s\n", 83387f98fe2Schristos "key", "semid", "perms", "nsems", "uid", "gid", "cuid", "cgid", 83487f98fe2Schristos "otime", "ctime"); 83587f98fe2Schristos if (offset >= LBFSZ) 83687f98fe2Schristos goto out; 83787f98fe2Schristos 83887f98fe2Schristos #ifdef SYSVSEM 83987f98fe2Schristos for (int id = 0; id < seminfo.semmni; id++) 84087f98fe2Schristos if ((sema[id].sem_perm.mode & SEM_ALLOC) != 0) { 84187f98fe2Schristos offset += snprintf(&bf[offset], LBFSZ - offset, 84287f98fe2Schristos "%10d %10d %4o %10u %5u %5u %5u %5u %10lld %10lld\n", 84387f98fe2Schristos (int) sema[id].sem_perm._key, 84487f98fe2Schristos IXSEQ_TO_IPCID(id, sema[id].sem_perm), 84587f98fe2Schristos sema[id].sem_perm.mode, 84687f98fe2Schristos sema[id].sem_nsems, 84787f98fe2Schristos sema[id].sem_perm.uid, 84887f98fe2Schristos sema[id].sem_perm.gid, 84987f98fe2Schristos sema[id].sem_perm.cuid, 85087f98fe2Schristos sema[id].sem_perm.cgid, 85187f98fe2Schristos (long long)sema[id].sem_otime, 85287f98fe2Schristos (long long)sema[id].sem_ctime); 85387f98fe2Schristos if (offset >= LBFSZ) 85487f98fe2Schristos goto out; 85587f98fe2Schristos } 85687f98fe2Schristos #endif 85787f98fe2Schristos 85887f98fe2Schristos error = uiomove_frombuf(bf, offset, uio); 85987f98fe2Schristos out: 86087f98fe2Schristos free(bf, M_TEMP); 86187f98fe2Schristos return error; 86287f98fe2Schristos } 86387f98fe2Schristos 86487f98fe2Schristos int 86587f98fe2Schristos procfs_dosysvipc_shm(struct lwp *curl, struct proc *p, 86687f98fe2Schristos struct pfsnode *pfs, struct uio *uio) 86787f98fe2Schristos { 86887f98fe2Schristos char *bf; 86987f98fe2Schristos int offset = 0; 87087f98fe2Schristos int error = EFBIG; 87187f98fe2Schristos 87287f98fe2Schristos bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 87387f98fe2Schristos 87487f98fe2Schristos offset += snprintf(bf, LBFSZ, 87587f98fe2Schristos "%10s %10s %s %21s %5s %5s %5s %5s %5s %5s %5s %10s %10s %10s %21s %21s\n", 87687f98fe2Schristos "key", "shmid", "perms", "size", "cpid", "lpid", "nattch", "uid", 87787f98fe2Schristos "gid", "cuid", "cgid", "atime", "dtime", "ctime", "rss", "swap"); 87887f98fe2Schristos if (offset >= LBFSZ) 87987f98fe2Schristos goto out; 88087f98fe2Schristos 88187f98fe2Schristos #ifdef SYSVSHM 88287f98fe2Schristos for (unsigned int id = 0; id < shminfo.shmmni; id++) 88387f98fe2Schristos if ((shmsegs[id].shm_perm.mode & SHMSEG_ALLOCATED) != 0) { 88487f98fe2Schristos offset += snprintf(&bf[offset], LBFSZ - offset, 88587f98fe2Schristos "%10d %10d %4o %21zu %5u %5u %5u %5u %5u %5u %5u %10lld %10lld %10lld %21d %21d\n", 88687f98fe2Schristos (int) shmsegs[id].shm_perm._key, 88787f98fe2Schristos IXSEQ_TO_IPCID(id, shmsegs[id].shm_perm), 88887f98fe2Schristos shmsegs[id].shm_perm.mode, 88987f98fe2Schristos shmsegs[id].shm_segsz, 89087f98fe2Schristos shmsegs[id].shm_cpid, 89187f98fe2Schristos shmsegs[id].shm_lpid, 89287f98fe2Schristos shmsegs[id].shm_nattch, 89387f98fe2Schristos shmsegs[id].shm_perm.uid, 89487f98fe2Schristos shmsegs[id].shm_perm.gid, 89587f98fe2Schristos shmsegs[id].shm_perm.cuid, 89687f98fe2Schristos shmsegs[id].shm_perm.cgid, 89787f98fe2Schristos (long long)shmsegs[id].shm_atime, 89887f98fe2Schristos (long long)shmsegs[id].shm_dtime, 89987f98fe2Schristos (long long)shmsegs[id].shm_ctime, 90087f98fe2Schristos 0, 0); /* XXX rss & swp are not supported */ 90187f98fe2Schristos if (offset >= LBFSZ) 90287f98fe2Schristos goto out; 90387f98fe2Schristos } 90487f98fe2Schristos #endif 90587f98fe2Schristos 90687f98fe2Schristos error = uiomove_frombuf(bf, offset, uio); 90787f98fe2Schristos out: 90887f98fe2Schristos free(bf, M_TEMP); 90987f98fe2Schristos return error; 91087f98fe2Schristos } 9110124a941Schristos 912*78b530bbSpgoyette #ifdef MQUEUE 913*78b530bbSpgoyette #define print_uint(value, uio) PFS_print_uint(value, uio); 914*78b530bbSpgoyette 9150124a941Schristos static int 916*78b530bbSpgoyette PFS_print_uint(unsigned int value, struct uio *uio) 9170124a941Schristos { 9180124a941Schristos char *bf; 9190124a941Schristos int offset = 0; 9200124a941Schristos int error = EFBIG; 9210124a941Schristos 9220124a941Schristos bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 9230124a941Schristos offset += snprintf(bf, LBFSZ, "%u\n", value); 9240124a941Schristos if (offset >= LBFSZ) 9250124a941Schristos goto out; 9260124a941Schristos 9270124a941Schristos error = uiomove_frombuf(bf, offset, uio); 9280124a941Schristos out: 9290124a941Schristos free(bf, M_TEMP); 9300124a941Schristos return error; 9310124a941Schristos } 932*78b530bbSpgoyette #else 933*78b530bbSpgoyette 934*78b530bbSpgoyette #define print_uint(value, uio) EINVAL 935*78b530bbSpgoyette 936*78b530bbSpgoyette #endif 9370124a941Schristos 9380124a941Schristos int 9390124a941Schristos procfs_domq_msg_def(struct lwp *curl, struct proc *p, 9400124a941Schristos struct pfsnode *pfs, struct uio *uio) 9410124a941Schristos { 9420124a941Schristos return print_uint(mq_def_maxmsg, uio); 9430124a941Schristos } 9440124a941Schristos 9450124a941Schristos int 9460124a941Schristos procfs_domq_msg_max(struct lwp *curl, struct proc *p, 9470124a941Schristos struct pfsnode *pfs, struct uio *uio) 9480124a941Schristos { 9490124a941Schristos return print_uint(mq_max_maxmsg, uio); 9500124a941Schristos } 9510124a941Schristos 9520124a941Schristos int 9530124a941Schristos procfs_domq_siz_def(struct lwp *curl, struct proc *p, 9540124a941Schristos struct pfsnode *pfs, struct uio *uio) 9550124a941Schristos { 9560124a941Schristos return print_uint(MQ_DEF_MSGSIZE, uio); 9570124a941Schristos } 9580124a941Schristos 9590124a941Schristos int 9600124a941Schristos procfs_domq_siz_max(struct lwp *curl, struct proc *p, 9610124a941Schristos struct pfsnode *pfs, struct uio *uio) 9620124a941Schristos { 9630124a941Schristos return print_uint(mq_max_msgsize, uio); 9640124a941Schristos } 9650124a941Schristos 9660124a941Schristos int 9670124a941Schristos procfs_domq_qmax(struct lwp *curl, struct proc *p, 9680124a941Schristos struct pfsnode *pfs, struct uio *uio) 9690124a941Schristos { 9700124a941Schristos return print_uint(mq_open_max, uio); 9710124a941Schristos } 972