Annotation of src/sys/miscfs/procfs/procfs_vnops.c, Revision 1.163.6.2
1.163.6.1 bouyer 1: /* $NetBSD$ */
1.145 ad 2:
3: /*-
1.147 ad 4: * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
1.145 ad 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Andrew Doran.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
1.24 cgd 38:
1.1 pk 39: /*
1.53 fvdl 40: * Copyright (c) 1993, 1995
1.21 mycroft 41: * The Regents of the University of California. All rights reserved.
1.2 pk 42: *
1.9 cgd 43: * This code is derived from software contributed to Berkeley by
44: * Jan-Simon Pendry.
45: *
1.2 pk 46: * Redistribution and use in source and binary forms, with or without
47: * modification, are permitted provided that the following conditions
48: * are met:
49: * 1. Redistributions of source code must retain the above copyright
50: * notice, this list of conditions and the following disclaimer.
51: * 2. Redistributions in binary form must reproduce the above copyright
52: * notice, this list of conditions and the following disclaimer in the
53: * documentation and/or other materials provided with the distribution.
1.107 agc 54: * 3. Neither the name of the University nor the names of its contributors
55: * may be used to endorse or promote products derived from this software
56: * without specific prior written permission.
57: *
58: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68: * SUCH DAMAGE.
69: *
70: * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
71: */
72:
73: /*
74: * Copyright (c) 1993 Jan-Simon Pendry
75: *
76: * This code is derived from software contributed to Berkeley by
77: * Jan-Simon Pendry.
78: *
79: * Redistribution and use in source and binary forms, with or without
80: * modification, are permitted provided that the following conditions
81: * are met:
82: * 1. Redistributions of source code must retain the above copyright
83: * notice, this list of conditions and the following disclaimer.
84: * 2. Redistributions in binary form must reproduce the above copyright
85: * notice, this list of conditions and the following disclaimer in the
86: * documentation and/or other materials provided with the distribution.
1.2 pk 87: * 3. All advertising materials mentioning features or use of this software
88: * must display the following acknowledgement:
1.9 cgd 89: * This product includes software developed by the University of
90: * California, Berkeley and its contributors.
91: * 4. Neither the name of the University nor the names of its contributors
92: * may be used to endorse or promote products derived from this software
93: * without specific prior written permission.
94: *
95: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
96: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
97: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
98: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
99: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
100: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
101: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
102: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
103: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
104: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
105: * SUCH DAMAGE.
1.2 pk 106: *
1.53 fvdl 107: * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
1.2 pk 108: */
109:
110: /*
1.9 cgd 111: * procfs vnode interface
1.1 pk 112: */
1.85 lukem 113:
114: #include <sys/cdefs.h>
1.163.6.1 bouyer 115: __KERNEL_RCSID(0, "$NetBSD$");
1.1 pk 116:
1.8 mycroft 117: #include <sys/param.h>
118: #include <sys/systm.h>
119: #include <sys/time.h>
120: #include <sys/kernel.h>
121: #include <sys/file.h>
1.91 christos 122: #include <sys/filedesc.h>
1.8 mycroft 123: #include <sys/proc.h>
124: #include <sys/vnode.h>
125: #include <sys/namei.h>
1.9 cgd 126: #include <sys/malloc.h>
1.76 fvdl 127: #include <sys/mount.h>
1.21 mycroft 128: #include <sys/dirent.h>
1.8 mycroft 129: #include <sys/resourcevar.h>
1.48 mycroft 130: #include <sys/stat.h>
1.89 thorpej 131: #include <sys/ptrace.h>
1.130 elad 132: #include <sys/kauth.h>
1.48 mycroft 133:
1.71 mrg 134: #include <uvm/uvm_extern.h> /* for PAGE_SIZE */
1.48 mycroft 135:
1.21 mycroft 136: #include <machine/reg.h>
1.41 mycroft 137:
138: #include <miscfs/genfs/genfs.h>
1.9 cgd 139: #include <miscfs/procfs/procfs.h>
1.11 cgd 140:
1.9 cgd 141: /*
142: * Vnode Operations.
143: *
144: */
1.1 pk 145:
1.128 christos 146: static int procfs_validfile_linux(struct lwp *, struct mount *);
1.117 yamt 147: static int procfs_root_readdir_callback(struct proc *, void *);
1.162 christos 148: static void procfs_dir(pfstype, struct lwp *, struct proc *, char **, char *,
149: size_t);
1.74 tv 150:
1.1 pk 151: /*
1.9 cgd 152: * This is a list of the valid names in the
153: * process-specific sub-directories. It is
154: * used in procfs_lookup and procfs_readdir
155: */
1.97 jdolecek 156: static const struct proc_target {
1.32 mycroft 157: u_char pt_type;
158: u_char pt_namlen;
1.97 jdolecek 159: const char *pt_name;
1.32 mycroft 160: pfstype pt_pfstype;
1.128 christos 161: int (*pt_valid)(struct lwp *, struct mount *);
1.32 mycroft 162: } proc_targets[] = {
1.9 cgd 163: #define N(s) sizeof(s)-1, s
1.32 mycroft 164: /* name type validp */
1.136 christos 165: { DT_DIR, N("."), PFSproc, NULL },
166: { DT_DIR, N(".."), PFSroot, NULL },
1.109 darcy 167: { DT_DIR, N("fd"), PFSfd, NULL },
1.136 christos 168: { DT_REG, N("file"), PFSfile, procfs_validfile },
1.109 darcy 169: { DT_REG, N("mem"), PFSmem, NULL },
1.136 christos 170: { DT_REG, N("regs"), PFSregs, procfs_validregs },
1.109 darcy 171: { DT_REG, N("fpregs"), PFSfpregs, procfs_validfpregs },
172: { DT_REG, N("ctl"), PFSctl, NULL },
1.136 christos 173: { DT_REG, N("stat"), PFSstat, procfs_validfile_linux },
1.109 darcy 174: { DT_REG, N("status"), PFSstatus, NULL },
1.136 christos 175: { DT_REG, N("note"), PFSnote, NULL },
1.109 darcy 176: { DT_REG, N("notepg"), PFSnotepg, NULL },
177: { DT_REG, N("map"), PFSmap, procfs_validmap },
1.136 christos 178: { DT_REG, N("maps"), PFSmaps, procfs_validmap },
1.109 darcy 179: { DT_REG, N("cmdline"), PFScmdline, NULL },
1.139 skrll 180: { DT_REG, N("exe"), PFSexe, procfs_validfile },
1.126 atatat 181: { DT_LNK, N("cwd"), PFScwd, NULL },
182: { DT_LNK, N("root"), PFSchroot, NULL },
1.137 christos 183: { DT_LNK, N("emul"), PFSemul, NULL },
1.157 agc 184: { DT_REG, N("statm"), PFSstatm, procfs_validfile_linux },
1.86 thorpej 185: #ifdef __HAVE_PROCFS_MACHDEP
186: PROCFS_MACHDEP_NODETYPE_DEFNS
187: #endif
1.9 cgd 188: #undef N
1.1 pk 189: };
1.97 jdolecek 190: static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
1.1 pk 191:
1.76 fvdl 192: /*
193: * List of files in the root directory. Note: the validate function will
194: * be called with p == NULL for these ones.
195: */
1.97 jdolecek 196: static const struct proc_target proc_root_targets[] = {
1.76 fvdl 197: #define N(s) sizeof(s)-1, s
198: /* name type validp */
1.109 darcy 199: { DT_REG, N("meminfo"), PFSmeminfo, procfs_validfile_linux },
200: { DT_REG, N("cpuinfo"), PFScpuinfo, procfs_validfile_linux },
201: { DT_REG, N("uptime"), PFSuptime, procfs_validfile_linux },
1.114 jdolecek 202: { DT_REG, N("mounts"), PFSmounts, procfs_validfile_linux },
1.134 manu 203: { DT_REG, N("devices"), PFSdevices, procfs_validfile_linux },
1.157 agc 204: { DT_REG, N("stat"), PFScpustat, procfs_validfile_linux },
205: { DT_REG, N("loadavg"), PFSloadavg, procfs_validfile_linux },
1.76 fvdl 206: #undef N
207: };
1.97 jdolecek 208: static const int nproc_root_targets =
1.76 fvdl 209: sizeof(proc_root_targets) / sizeof(proc_root_targets[0]);
210:
1.124 xtraeme 211: int procfs_lookup(void *);
1.96 jdolecek 212: #define procfs_create genfs_eopnotsupp
213: #define procfs_mknod genfs_eopnotsupp
1.124 xtraeme 214: int procfs_open(void *);
215: int procfs_close(void *);
216: int procfs_access(void *);
217: int procfs_getattr(void *);
218: int procfs_setattr(void *);
1.37 christos 219: #define procfs_read procfs_rw
220: #define procfs_write procfs_rw
1.65 wrstuden 221: #define procfs_fcntl genfs_fcntl
1.57 matthias 222: #define procfs_ioctl genfs_enoioctl
1.42 mycroft 223: #define procfs_poll genfs_poll
1.53 fvdl 224: #define procfs_revoke genfs_revoke
1.41 mycroft 225: #define procfs_fsync genfs_nullop
226: #define procfs_seek genfs_nullop
1.96 jdolecek 227: #define procfs_remove genfs_eopnotsupp
1.124 xtraeme 228: int procfs_link(void *);
1.96 jdolecek 229: #define procfs_rename genfs_eopnotsupp
230: #define procfs_mkdir genfs_eopnotsupp
231: #define procfs_rmdir genfs_eopnotsupp
1.124 xtraeme 232: int procfs_symlink(void *);
233: int procfs_readdir(void *);
234: int procfs_readlink(void *);
1.41 mycroft 235: #define procfs_abortop genfs_abortop
1.124 xtraeme 236: int procfs_inactive(void *);
237: int procfs_reclaim(void *);
1.62 wrstuden 238: #define procfs_lock genfs_lock
239: #define procfs_unlock genfs_unlock
1.82 chs 240: #define procfs_bmap genfs_badop
1.41 mycroft 241: #define procfs_strategy genfs_badop
1.124 xtraeme 242: int procfs_print(void *);
243: int procfs_pathconf(void *);
1.62 wrstuden 244: #define procfs_islocked genfs_islocked
1.58 kleink 245: #define procfs_advlock genfs_einval
1.41 mycroft 246: #define procfs_bwrite genfs_eopnotsupp
1.87 chs 247: #define procfs_putpages genfs_null_putpages
1.37 christos 248:
1.124 xtraeme 249: static int atoi(const char *, size_t);
1.37 christos 250:
251: /*
252: * procfs vnode operations.
253: */
1.124 xtraeme 254: int (**procfs_vnodeop_p)(void *);
1.77 jdolecek 255: const struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
1.37 christos 256: { &vop_default_desc, vn_default_error },
257: { &vop_lookup_desc, procfs_lookup }, /* lookup */
258: { &vop_create_desc, procfs_create }, /* create */
259: { &vop_mknod_desc, procfs_mknod }, /* mknod */
260: { &vop_open_desc, procfs_open }, /* open */
261: { &vop_close_desc, procfs_close }, /* close */
262: { &vop_access_desc, procfs_access }, /* access */
263: { &vop_getattr_desc, procfs_getattr }, /* getattr */
264: { &vop_setattr_desc, procfs_setattr }, /* setattr */
265: { &vop_read_desc, procfs_read }, /* read */
266: { &vop_write_desc, procfs_write }, /* write */
1.65 wrstuden 267: { &vop_fcntl_desc, procfs_fcntl }, /* fcntl */
1.37 christos 268: { &vop_ioctl_desc, procfs_ioctl }, /* ioctl */
1.42 mycroft 269: { &vop_poll_desc, procfs_poll }, /* poll */
1.53 fvdl 270: { &vop_revoke_desc, procfs_revoke }, /* revoke */
1.37 christos 271: { &vop_fsync_desc, procfs_fsync }, /* fsync */
272: { &vop_seek_desc, procfs_seek }, /* seek */
273: { &vop_remove_desc, procfs_remove }, /* remove */
274: { &vop_link_desc, procfs_link }, /* link */
275: { &vop_rename_desc, procfs_rename }, /* rename */
276: { &vop_mkdir_desc, procfs_mkdir }, /* mkdir */
277: { &vop_rmdir_desc, procfs_rmdir }, /* rmdir */
278: { &vop_symlink_desc, procfs_symlink }, /* symlink */
279: { &vop_readdir_desc, procfs_readdir }, /* readdir */
280: { &vop_readlink_desc, procfs_readlink }, /* readlink */
281: { &vop_abortop_desc, procfs_abortop }, /* abortop */
282: { &vop_inactive_desc, procfs_inactive }, /* inactive */
283: { &vop_reclaim_desc, procfs_reclaim }, /* reclaim */
284: { &vop_lock_desc, procfs_lock }, /* lock */
285: { &vop_unlock_desc, procfs_unlock }, /* unlock */
286: { &vop_bmap_desc, procfs_bmap }, /* bmap */
287: { &vop_strategy_desc, procfs_strategy }, /* strategy */
288: { &vop_print_desc, procfs_print }, /* print */
289: { &vop_islocked_desc, procfs_islocked }, /* islocked */
290: { &vop_pathconf_desc, procfs_pathconf }, /* pathconf */
291: { &vop_advlock_desc, procfs_advlock }, /* advlock */
1.87 chs 292: { &vop_putpages_desc, procfs_putpages }, /* putpages */
1.82 chs 293: { NULL, NULL }
1.37 christos 294: };
1.77 jdolecek 295: const struct vnodeopv_desc procfs_vnodeop_opv_desc =
1.37 christos 296: { &procfs_vnodeop_p, procfs_vnodeop_entries };
297: /*
1.9 cgd 298: * set things up for doing i/o on
299: * the pfsnode (vp). (vp) is locked
300: * on entry, and should be left locked
301: * on exit.
1.1 pk 302: *
1.9 cgd 303: * for procfs we don't need to do anything
304: * in particular for i/o. all that is done
305: * is to support exclusive open on process
306: * memory images.
1.1 pk 307: */
1.37 christos 308: int
309: procfs_open(v)
310: void *v;
311: {
1.22 mycroft 312: struct vop_open_args /* {
313: struct vnode *a_vp;
314: int a_mode;
1.130 elad 315: kauth_cred_t a_cred;
1.37 christos 316: } */ *ap = v;
1.21 mycroft 317: struct pfsnode *pfs = VTOPFS(ap->a_vp);
1.128 christos 318: struct lwp *l1;
319: struct proc *p2;
1.88 christos 320: int error;
1.50 thorpej 321:
1.145 ad 322: if ((error = procfs_proc_lock(pfs->pfs_pid, &p2, ENOENT)) != 0)
323: return error;
324:
1.163 pooka 325: l1 = curlwp; /* tracer */
1.140 elad 326:
1.144 elad 327: #define M2K(m) (((m) & FREAD) && ((m) & FWRITE) ? \
1.163.6.2! bouyer 328: KAUTH_REQ_PROCESS_PROCFS_RW : \
! 329: (m) & FWRITE ? KAUTH_REQ_PROCESS_PROCFS_WRITE : \
! 330: KAUTH_REQ_PROCESS_PROCFS_READ)
1.144 elad 331:
1.145 ad 332: mutex_enter(&p2->p_mutex);
1.163.6.2! bouyer 333: error = kauth_authorize_process(l1->l_cred, KAUTH_PROCESS_PROCFS,
1.144 elad 334: p2, pfs, KAUTH_ARG(M2K(ap->a_mode)), NULL);
1.145 ad 335: mutex_exit(&p2->p_mutex);
1.161 ad 336: if (error) {
337: procfs_proc_unlock(p2);
1.144 elad 338: return (error);
1.161 ad 339: }
1.144 elad 340:
341: #undef M2K
342:
1.9 cgd 343: switch (pfs->pfs_type) {
1.109 darcy 344: case PFSmem:
1.37 christos 345: if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
1.145 ad 346: ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) {
347: error = EBUSY;
348: break;
349: }
1.50 thorpej 350:
1.161 ad 351: if (!proc_isunder(p2, l1)) {
352: error = EPERM;
353: break;
354: }
1.141 elad 355:
1.21 mycroft 356: if (ap->a_mode & FWRITE)
357: pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
1.1 pk 358:
1.144 elad 359: break;
360:
361: case PFSregs:
362: case PFSfpregs:
1.161 ad 363: if (!proc_isunder(p2, l1)) {
364: error = EPERM;
365: break;
366: }
1.144 elad 367: break;
1.1 pk 368:
1.9 cgd 369: default:
370: break;
371: }
1.1 pk 372:
1.145 ad 373: procfs_proc_unlock(p2);
374: return (error);
1.1 pk 375: }
376:
377: /*
1.9 cgd 378: * close the pfsnode (vp) after doing i/o.
379: * (vp) is not locked on entry or exit.
380: *
381: * nothing to do for procfs other than undo
382: * any exclusive open flag (see _open above).
1.1 pk 383: */
1.37 christos 384: int
385: procfs_close(v)
386: void *v;
387: {
1.22 mycroft 388: struct vop_close_args /* {
389: struct vnode *a_vp;
390: int a_fflag;
1.130 elad 391: kauth_cred_t a_cred;
1.37 christos 392: } */ *ap = v;
1.21 mycroft 393: struct pfsnode *pfs = VTOPFS(ap->a_vp);
1.1 pk 394:
1.9 cgd 395: switch (pfs->pfs_type) {
1.109 darcy 396: case PFSmem:
1.21 mycroft 397: if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL))
1.9 cgd 398: pfs->pfs_flags &= ~(FWRITE|O_EXCL);
399: break;
1.46 mycroft 400:
401: default:
1.37 christos 402: break;
1.9 cgd 403: }
1.1 pk 404:
405: return (0);
406: }
407:
408: /*
1.9 cgd 409: * _inactive is called when the pfsnode
410: * is vrele'd and the reference count goes
411: * to zero. (vp) will be on the vnode free
412: * list, so to get it back vget() must be
413: * used.
414: *
1.62 wrstuden 415: * (vp) is locked on entry, but must be unlocked on exit.
1.1 pk 416: */
1.37 christos 417: int
418: procfs_inactive(v)
419: void *v;
420: {
1.22 mycroft 421: struct vop_inactive_args /* {
422: struct vnode *a_vp;
1.161 ad 423: bool *a_recycle;
1.37 christos 424: } */ *ap = v;
1.122 christos 425: struct vnode *vp = ap->a_vp;
426: struct pfsnode *pfs = VTOPFS(vp);
1.161 ad 427:
428: mutex_enter(&proclist_lock);
1.163.6.1 bouyer 429: *ap->a_recycle = (p_find(pfs->pfs_pid, PFIND_LOCKED) == NULL);
1.161 ad 430: mutex_exit(&proclist_lock);
1.1 pk 431:
1.122 christos 432: VOP_UNLOCK(vp, 0);
1.145 ad 433:
1.9 cgd 434: return (0);
1.1 pk 435: }
436:
437: /*
1.9 cgd 438: * _reclaim is called when getnewvnode()
439: * wants to make use of an entry on the vnode
440: * free list. at this time the filesystem needs
441: * to free any private data and remove the node
442: * from any private lists.
1.1 pk 443: */
1.37 christos 444: int
445: procfs_reclaim(v)
446: void *v;
447: {
1.22 mycroft 448: struct vop_reclaim_args /* {
449: struct vnode *a_vp;
1.37 christos 450: } */ *ap = v;
1.21 mycroft 451:
452: return (procfs_freevp(ap->a_vp));
453: }
454:
455: /*
456: * Return POSIX pathconf information applicable to special devices.
457: */
1.37 christos 458: int
459: procfs_pathconf(v)
460: void *v;
461: {
1.21 mycroft 462: struct vop_pathconf_args /* {
463: struct vnode *a_vp;
464: int a_name;
1.26 cgd 465: register_t *a_retval;
1.37 christos 466: } */ *ap = v;
1.1 pk 467:
1.21 mycroft 468: switch (ap->a_name) {
469: case _PC_LINK_MAX:
470: *ap->a_retval = LINK_MAX;
471: return (0);
472: case _PC_MAX_CANON:
473: *ap->a_retval = MAX_CANON;
474: return (0);
475: case _PC_MAX_INPUT:
476: *ap->a_retval = MAX_INPUT;
477: return (0);
478: case _PC_PIPE_BUF:
479: *ap->a_retval = PIPE_BUF;
480: return (0);
481: case _PC_CHOWN_RESTRICTED:
482: *ap->a_retval = 1;
483: return (0);
484: case _PC_VDISABLE:
485: *ap->a_retval = _POSIX_VDISABLE;
1.55 kleink 486: return (0);
487: case _PC_SYNC_IO:
488: *ap->a_retval = 1;
1.21 mycroft 489: return (0);
490: default:
491: return (EINVAL);
492: }
493: /* NOTREACHED */
1.1 pk 494: }
495:
496: /*
1.9 cgd 497: * _print is used for debugging.
498: * just print a readable description
499: * of (vp).
1.1 pk 500: */
1.37 christos 501: int
502: procfs_print(v)
503: void *v;
504: {
1.22 mycroft 505: struct vop_print_args /* {
506: struct vnode *a_vp;
1.37 christos 507: } */ *ap = v;
1.21 mycroft 508: struct pfsnode *pfs = VTOPFS(ap->a_vp);
1.5 pk 509:
1.44 christos 510: printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n",
1.21 mycroft 511: pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
1.37 christos 512: return 0;
1.36 mycroft 513: }
514:
515: int
1.121 perry 516: procfs_link(v)
1.37 christos 517: void *v;
518: {
1.36 mycroft 519: struct vop_link_args /* {
520: struct vnode *a_dvp;
1.121 perry 521: struct vnode *a_vp;
1.36 mycroft 522: struct componentname *a_cnp;
1.37 christos 523: } */ *ap = v;
1.121 perry 524:
1.36 mycroft 525: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
526: vput(ap->a_dvp);
527: return (EROFS);
528: }
529:
530: int
1.37 christos 531: procfs_symlink(v)
532: void *v;
533: {
1.36 mycroft 534: struct vop_symlink_args /* {
535: struct vnode *a_dvp;
536: struct vnode **a_vpp;
537: struct componentname *a_cnp;
538: struct vattr *a_vap;
539: char *a_target;
1.37 christos 540: } */ *ap = v;
1.121 perry 541:
1.36 mycroft 542: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
543: vput(ap->a_dvp);
544: return (EROFS);
1.1 pk 545: }
546:
547: /*
1.126 atatat 548: * Works out the path to (and vnode of) the target process's current
549: * working directory or chroot. If the caller is in a chroot and
550: * can't "reach" the target's cwd or root (or some other error
551: * occurs), a "/" is returned for the path and a NULL pointer is
552: * returned for the vnode.
553: */
1.161 ad 554: static void
1.162 christos 555: procfs_dir(pfstype t, struct lwp *caller, struct proc *target, char **bpp,
556: char *path, size_t len)
1.126 atatat 557: {
1.161 ad 558: struct cwdinfo *cwdi;
559: struct vnode *vp, *rvp;
1.126 atatat 560: char *bp;
561:
1.161 ad 562: cwdi = caller->l_proc->p_cwdi;
563: rw_enter(&cwdi->cwdi_lock, RW_READER);
1.145 ad 564:
1.161 ad 565: rvp = cwdi->cwdi_rdir;
1.126 atatat 566: bp = bpp ? *bpp : NULL;
567:
568: switch (t) {
569: case PFScwd:
570: vp = target->p_cwdi->cwdi_cdir;
571: break;
572: case PFSchroot:
573: vp = target->p_cwdi->cwdi_rdir;
574: break;
1.136 christos 575: case PFSexe:
576: vp = target->p_textvp;
577: break;
1.126 atatat 578: default:
1.161 ad 579: rw_exit(&cwdi->cwdi_lock);
580: return;
1.126 atatat 581: }
582:
1.158 pooka 583: /*
584: * XXX: this horrible kludge avoids locking panics when
585: * attempting to lookup links that point to within procfs
586: */
587: if (vp != NULL && vp->v_tag == VT_PROCFS) {
588: if (bpp) {
589: *--bp = '/';
590: *bpp = bp;
591: }
1.161 ad 592: rw_exit(&cwdi->cwdi_lock);
593: return;
1.158 pooka 594: }
595:
1.126 atatat 596: if (rvp == NULL)
597: rvp = rootvnode;
598: if (vp == NULL || getcwd_common(vp, rvp, bp ? &bp : NULL, path,
599: len / 2, 0, caller) != 0) {
600: vp = NULL;
601: if (bpp) {
1.153 christos 602: /*
603: if (t == PFSexe) {
604: snprintf(path, len, "%s/%d/file"
605: mp->mnt_stat.f_mntonname, pfs->pfs_pid);
606: } else */ {
607: bp = *bpp;
608: *--bp = '/';
609: }
1.126 atatat 610: }
611: }
612:
613: if (bpp)
614: *bpp = bp;
615:
1.161 ad 616: rw_exit(&cwdi->cwdi_lock);
1.126 atatat 617: }
618:
619: /*
1.9 cgd 620: * Invent attributes for pfsnode (vp) and store
621: * them in (vap).
622: * Directories lengths are returned as zero since
623: * any real length would require the genuine size
624: * to be computed, and nothing cares anyway.
625: *
626: * this is relatively minimal for procfs.
1.1 pk 627: */
1.37 christos 628: int
629: procfs_getattr(v)
630: void *v;
631: {
1.22 mycroft 632: struct vop_getattr_args /* {
633: struct vnode *a_vp;
634: struct vattr *a_vap;
1.130 elad 635: kauth_cred_t a_cred;
1.37 christos 636: } */ *ap = v;
1.21 mycroft 637: struct pfsnode *pfs = VTOPFS(ap->a_vp);
638: struct vattr *vap = ap->a_vap;
1.1 pk 639: struct proc *procp;
1.145 ad 640: char *path;
1.9 cgd 641: int error;
1.1 pk 642:
1.21 mycroft 643: /* first check the process still exists */
644: switch (pfs->pfs_type) {
1.109 darcy 645: case PFSroot:
646: case PFScurproc:
647: case PFSself:
1.145 ad 648: procp = NULL;
649: break;
650:
651: default:
652: error = procfs_proc_lock(pfs->pfs_pid, &procp, ENOENT);
653: if (error != 0)
654: return (error);
655: break;
656: }
657:
658: switch (pfs->pfs_type) {
659: case PFScwd:
660: case PFSchroot:
661: case PFSexe:
662: MALLOC(path, char *, MAXPATHLEN + 4, M_TEMP,
663: M_WAITOK|M_CANFAIL);
1.146 ad 664: if (path == NULL && procp != NULL) {
1.145 ad 665: procfs_proc_unlock(procp);
666: return (ENOMEM);
667: }
1.21 mycroft 668: break;
669:
670: default:
1.145 ad 671: path = NULL;
1.46 mycroft 672: break;
1.21 mycroft 673: }
674:
1.125 elad 675: if (procp != NULL) {
1.145 ad 676: mutex_enter(&procp->p_mutex);
1.146 ad 677: error = kauth_authorize_process(kauth_cred_get(),
1.163.6.2! bouyer 678: KAUTH_PROCESS_CANSEE, procp,
! 679: KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
1.146 ad 680: mutex_exit(&procp->p_mutex);
681: if (error != 0) {
1.145 ad 682: procfs_proc_unlock(procp);
683: if (path != NULL)
684: free(path, M_TEMP);
1.125 elad 685: return (ENOENT);
1.145 ad 686: }
1.125 elad 687: }
688:
1.21 mycroft 689: error = 0;
690:
1.9 cgd 691: /* start by zeroing out the attributes */
1.1 pk 692: VATTR_NULL(vap);
1.9 cgd 693:
694: /* next do all the common fields */
1.21 mycroft 695: vap->va_type = ap->a_vp->v_type;
1.9 cgd 696: vap->va_mode = pfs->pfs_mode;
697: vap->va_fileid = pfs->pfs_fileno;
698: vap->va_flags = 0;
1.19 cgd 699: vap->va_blocksize = PAGE_SIZE;
1.9 cgd 700:
701: /*
1.131 kardel 702: * Make all times be current TOD.
1.90 simonb 703: *
1.9 cgd 704: * It would be possible to get the process start
1.126 atatat 705: * time from the p_stats structure, but there's
1.9 cgd 706: * no "file creation" time stamp anyway, and the
1.126 atatat 707: * p_stats structure is not addressable if u. gets
1.9 cgd 708: * swapped out for that process.
709: */
1.131 kardel 710: getnanotime(&vap->va_ctime);
1.9 cgd 711: vap->va_atime = vap->va_mtime = vap->va_ctime;
1.126 atatat 712: if (procp)
713: TIMEVAL_TO_TIMESPEC(&procp->p_stats->p_start,
714: &vap->va_birthtime);
715: else
1.131 kardel 716: getnanotime(&vap->va_birthtime);
1.9 cgd 717:
1.21 mycroft 718: switch (pfs->pfs_type) {
1.109 darcy 719: case PFSmem:
720: case PFSregs:
721: case PFSfpregs:
1.86 thorpej 722: #if defined(__HAVE_PROCFS_MACHDEP) && defined(PROCFS_MACHDEP_PROTECT_CASES)
723: PROCFS_MACHDEP_PROTECT_CASES
724: #endif
1.47 mycroft 725: /*
726: * If the process has exercised some setuid or setgid
727: * privilege, then rip away read/write permission so
728: * that only root can gain access.
729: */
1.149 pavel 730: if (procp->p_flag & PK_SUGID)
1.47 mycroft 731: vap->va_mode &= ~(S_IRUSR|S_IWUSR);
1.46 mycroft 732: /* FALLTHROUGH */
1.109 darcy 733: case PFSctl:
734: case PFSstatus:
735: case PFSstat:
736: case PFSnote:
737: case PFSnotepg:
738: case PFSmap:
739: case PFSmaps:
740: case PFScmdline:
1.137 christos 741: case PFSemul:
1.157 agc 742: case PFSstatm:
1.12 ws 743: vap->va_nlink = 1;
1.130 elad 744: vap->va_uid = kauth_cred_geteuid(procp->p_cred);
745: vap->va_gid = kauth_cred_getegid(procp->p_cred);
1.21 mycroft 746: break;
1.109 darcy 747: case PFSmeminfo:
1.134 manu 748: case PFSdevices:
1.109 darcy 749: case PFScpuinfo:
750: case PFSuptime:
1.114 jdolecek 751: case PFSmounts:
1.157 agc 752: case PFScpustat:
753: case PFSloadavg:
1.76 fvdl 754: vap->va_nlink = 1;
755: vap->va_uid = vap->va_gid = 0;
756: break;
1.46 mycroft 757:
758: default:
1.37 christos 759: break;
1.12 ws 760: }
761:
1.9 cgd 762: /*
763: * now do the object specific fields
764: *
765: * The size could be set from struct reg, but it's hardly
766: * worth the trouble, and it puts some (potentially) machine
767: * dependent data into this machine-independent code. If it
768: * becomes important then this function should break out into
769: * a per-file stat function in the corresponding .c file.
770: */
1.1 pk 771:
1.9 cgd 772: switch (pfs->pfs_type) {
1.109 darcy 773: case PFSroot:
1.21 mycroft 774: /*
775: * Set nlink to 1 to tell fts(3) we don't actually know.
776: */
777: vap->va_nlink = 1;
778: vap->va_uid = 0;
779: vap->va_gid = 0;
1.46 mycroft 780: vap->va_bytes = vap->va_size = DEV_BSIZE;
1.21 mycroft 781: break;
782:
1.129 christos 783: case PFSself:
1.109 darcy 784: case PFScurproc: {
1.123 christos 785: char bf[16]; /* should be enough */
1.21 mycroft 786: vap->va_nlink = 1;
787: vap->va_uid = 0;
788: vap->va_gid = 0;
1.46 mycroft 789: vap->va_bytes = vap->va_size =
1.123 christos 790: snprintf(bf, sizeof(bf), "%ld", (long)curproc->p_pid);
1.9 cgd 791: break;
1.21 mycroft 792: }
1.9 cgd 793:
1.109 darcy 794: case PFSfd:
1.91 christos 795: if (pfs->pfs_fd != -1) {
796: struct file *fp;
1.98 jdolecek 797:
1.145 ad 798: fp = fd_getfile(procp->p_fd, pfs->pfs_fd);
799: if (fp == NULL) {
800: error = EBADF;
801: break;
802: }
1.98 jdolecek 803: FILE_USE(fp);
1.91 christos 804: vap->va_nlink = 1;
1.130 elad 805: vap->va_uid = kauth_cred_geteuid(fp->f_cred);
806: vap->va_gid = kauth_cred_getegid(fp->f_cred);
1.91 christos 807: switch (fp->f_type) {
808: case DTYPE_VNODE:
809: vap->va_bytes = vap->va_size =
810: ((struct vnode *)fp->f_data)->v_size;
811: break;
812: default:
813: vap->va_bytes = vap->va_size = 0;
814: break;
815: }
1.145 ad 816: FILE_UNUSE(fp, curlwp);
1.91 christos 817: break;
818: }
819: /*FALLTHROUGH*/
1.109 darcy 820: case PFSproc:
1.9 cgd 821: vap->va_nlink = 2;
1.130 elad 822: vap->va_uid = kauth_cred_geteuid(procp->p_cred);
823: vap->va_gid = kauth_cred_getegid(procp->p_cred);
1.46 mycroft 824: vap->va_bytes = vap->va_size = DEV_BSIZE;
1.21 mycroft 825: break;
826:
1.109 darcy 827: case PFSfile:
1.21 mycroft 828: error = EOPNOTSUPP;
1.9 cgd 829: break;
830:
1.109 darcy 831: case PFSmem:
1.9 cgd 832: vap->va_bytes = vap->va_size =
833: ctob(procp->p_vmspace->vm_tsize +
834: procp->p_vmspace->vm_dsize +
835: procp->p_vmspace->vm_ssize);
836: break;
837:
1.18 cgd 838: #if defined(PT_GETREGS) || defined(PT_SETREGS)
1.109 darcy 839: case PFSregs:
1.11 cgd 840: vap->va_bytes = vap->va_size = sizeof(struct reg);
1.18 cgd 841: break;
1.14 cgd 842: #endif
843:
1.18 cgd 844: #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
1.109 darcy 845: case PFSfpregs:
1.14 cgd 846: vap->va_bytes = vap->va_size = sizeof(struct fpreg);
1.18 cgd 847: break;
1.14 cgd 848: #endif
1.12 ws 849:
1.109 darcy 850: case PFSctl:
851: case PFSstatus:
852: case PFSstat:
853: case PFSnote:
854: case PFSnotepg:
855: case PFScmdline:
856: case PFSmeminfo:
1.134 manu 857: case PFSdevices:
1.109 darcy 858: case PFScpuinfo:
859: case PFSuptime:
1.114 jdolecek 860: case PFSmounts:
1.157 agc 861: case PFScpustat:
862: case PFSloadavg:
863: case PFSstatm:
1.46 mycroft 864: vap->va_bytes = vap->va_size = 0;
1.79 fvdl 865: break;
1.109 darcy 866: case PFSmap:
867: case PFSmaps:
1.79 fvdl 868: /*
869: * Advise a larger blocksize for the map files, so that
870: * they may be read in one pass.
871: */
1.80 fvdl 872: vap->va_blocksize = 4 * PAGE_SIZE;
1.83 chs 873: vap->va_bytes = vap->va_size = 0;
1.9 cgd 874: break;
1.86 thorpej 875:
1.126 atatat 876: case PFScwd:
1.136 christos 877: case PFSchroot:
878: case PFSexe: {
1.145 ad 879: char *bp;
1.126 atatat 880:
881: vap->va_nlink = 1;
882: vap->va_uid = 0;
883: vap->va_gid = 0;
884: bp = path + MAXPATHLEN;
885: *--bp = '\0';
1.161 ad 886: procfs_dir(pfs->pfs_type, curlwp, procp, &bp, path,
1.126 atatat 887: MAXPATHLEN);
888: vap->va_bytes = vap->va_size = strlen(bp);
889: break;
890: }
891:
1.137 christos 892: case PFSemul:
893: vap->va_bytes = vap->va_size = strlen(procp->p_emul->e_name);
894: break;
895:
1.86 thorpej 896: #ifdef __HAVE_PROCFS_MACHDEP
897: PROCFS_MACHDEP_NODETYPE_CASES
898: error = procfs_machdep_getattr(ap->a_vp, vap, procp);
899: break;
900: #endif
1.1 pk 901:
1.9 cgd 902: default:
1.21 mycroft 903: panic("procfs_getattr");
1.1 pk 904: }
905:
1.146 ad 906: if (procp != NULL)
1.145 ad 907: procfs_proc_unlock(procp);
908: if (path != NULL)
909: free(path, M_TEMP);
910:
1.9 cgd 911: return (error);
1.1 pk 912: }
913:
1.37 christos 914: /*ARGSUSED*/
915: int
1.138 christos 916: procfs_setattr(void *v)
1.5 pk 917: {
918: /*
1.9 cgd 919: * just fake out attribute setting
920: * it's not good to generate an error
921: * return, otherwise things like creat()
922: * will fail when they try to set the
923: * file length to 0. worse, this means
924: * that echo $note > /proc/$pid/note will fail.
1.5 pk 925: */
926:
1.9 cgd 927: return (0);
1.5 pk 928: }
929:
1.9 cgd 930: /*
931: * implement access checking.
932: *
933: * actually, the check for super-user is slightly
934: * broken since it will allow read access to write-only
935: * objects. this doesn't cause any particular trouble
936: * but does mean that the i/o entry points need to check
937: * that the operation really does make sense.
938: */
1.37 christos 939: int
940: procfs_access(v)
941: void *v;
942: {
1.22 mycroft 943: struct vop_access_args /* {
944: struct vnode *a_vp;
945: int a_mode;
1.130 elad 946: kauth_cred_t a_cred;
1.37 christos 947: } */ *ap = v;
1.31 mycroft 948: struct vattr va;
1.1 pk 949: int error;
950:
1.163 pooka 951: if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0)
1.1 pk 952: return (error);
1.9 cgd 953:
1.49 mycroft 954: return (vaccess(va.va_type, va.va_mode,
955: va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
1.1 pk 956: }
957:
958: /*
1.9 cgd 959: * lookup. this is incredibly complicated in the
960: * general case, however for most pseudo-filesystems
961: * very little needs to be done.
962: *
1.62 wrstuden 963: * Locking isn't hard here, just poorly documented.
964: *
1.121 perry 965: * If we're looking up ".", just vref the parent & return it.
1.62 wrstuden 966: *
967: * If we're looking up "..", unlock the parent, and lock "..". If everything
968: * went ok, and we're on the last component and the caller requested the
969: * parent locked, try to re-lock the parent. We do this to prevent lock
970: * races.
971: *
972: * For anything else, get the needed node. Then unlock the parent if not
973: * the last component or not LOCKPARENT (i.e. if we wouldn't re-lock the
974: * parent in the .. case).
975: *
976: * We try to exit with the parent locked in error cases.
1.9 cgd 977: */
1.37 christos 978: int
979: procfs_lookup(v)
980: void *v;
981: {
1.22 mycroft 982: struct vop_lookup_args /* {
983: struct vnode * a_dvp;
984: struct vnode ** a_vpp;
985: struct componentname * a_cnp;
1.37 christos 986: } */ *ap = v;
1.21 mycroft 987: struct componentname *cnp = ap->a_cnp;
988: struct vnode **vpp = ap->a_vpp;
989: struct vnode *dvp = ap->a_dvp;
1.45 cgd 990: const char *pname = cnp->cn_nameptr;
1.78 jdolecek 991: const struct proc_target *pt = NULL;
1.32 mycroft 992: struct vnode *fvp;
1.146 ad 993: pid_t pid, vnpid;
1.9 cgd 994: struct pfsnode *pfs;
1.76 fvdl 995: struct proc *p = NULL;
1.128 christos 996: struct lwp *l = NULL;
1.146 ad 997: int i, error;
998: pfstype type;
1.1 pk 999:
1.32 mycroft 1000: *vpp = NULL;
1001:
1002: if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
1003: return (EROFS);
1004:
1.21 mycroft 1005: if (cnp->cn_namelen == 1 && *pname == '.') {
1006: *vpp = dvp;
1.9 cgd 1007: VREF(dvp);
1008: return (0);
1009: }
1.1 pk 1010:
1.9 cgd 1011: pfs = VTOPFS(dvp);
1012: switch (pfs->pfs_type) {
1.109 darcy 1013: case PFSroot:
1.62 wrstuden 1014: /*
1015: * Shouldn't get here with .. in the root node.
1016: */
1.121 perry 1017: if (cnp->cn_flags & ISDOTDOT)
1.9 cgd 1018: return (EIO);
1019:
1.76 fvdl 1020: for (i = 0; i < nproc_root_targets; i++) {
1021: pt = &proc_root_targets[i];
1.150 pooka 1022: /*
1023: * check for node match. proc is always NULL here,
1024: * so call pt_valid with constant NULL lwp.
1025: */
1.76 fvdl 1026: if (cnp->cn_namelen == pt->pt_namlen &&
1027: memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
1.150 pooka 1028: (pt->pt_valid == NULL ||
1029: (*pt->pt_valid)(NULL, dvp->v_mount)))
1.76 fvdl 1030: break;
1031: }
1032:
1033: if (i != nproc_root_targets) {
1034: error = procfs_allocvp(dvp->v_mount, vpp, 0,
1.145 ad 1035: pt->pt_pfstype, -1, NULL);
1.76 fvdl 1036: return (error);
1037: }
1038:
1.146 ad 1039: if (CNEQ(cnp, "curproc", 7)) {
1040: pid = curproc->p_pid;
1041: vnpid = 0;
1042: type = PFScurproc;
1043: } else if (CNEQ(cnp, "self", 4)) {
1044: pid = curproc->p_pid;
1045: vnpid = 0;
1046: type = PFSself;
1047: } else {
1048: pid = (pid_t)atoi(pname, cnp->cn_namelen);
1049: vnpid = pid;
1050: type = PFSproc;
1051: }
1.9 cgd 1052:
1.145 ad 1053: if (procfs_proc_lock(pid, &p, ESRCH) != 0)
1.32 mycroft 1054: break;
1.146 ad 1055: error = procfs_allocvp(dvp->v_mount, vpp, vnpid, type, -1, p);
1.145 ad 1056: procfs_proc_unlock(p);
1.62 wrstuden 1057: return (error);
1.9 cgd 1058:
1.109 darcy 1059: case PFSproc:
1.62 wrstuden 1060: /*
1061: * do the .. dance. We unlock the directory, and then
1062: * get the root dir. That will automatically return ..
1063: * locked. Then if the caller wanted dvp locked, we
1064: * re-lock.
1065: */
1066: if (cnp->cn_flags & ISDOTDOT) {
1067: VOP_UNLOCK(dvp, 0);
1.105 thorpej 1068: error = procfs_root(dvp->v_mount, vpp);
1.143 chs 1069: vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
1.62 wrstuden 1070: return (error);
1071: }
1.1 pk 1072:
1.145 ad 1073: if (procfs_proc_lock(pfs->pfs_pid, &p, ESRCH) != 0)
1.32 mycroft 1074: break;
1075:
1076: for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
1.151 pooka 1077: struct lwp *plwp;
1078: int found;
1079:
1080: mutex_enter(&p->p_smutex);
1081: plwp = proc_representative_lwp(p, NULL, 1);
1082: lwp_addref(plwp);
1083: mutex_exit(&p->p_smutex);
1084: found = cnp->cn_namelen == pt->pt_namlen &&
1.56 perry 1085: memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
1.151 pooka 1086: (pt->pt_valid == NULL
1087: || (*pt->pt_valid)(plwp, dvp->v_mount));
1088: lwp_delref(plwp);
1089: if (found)
1.145 ad 1090: break;
1.9 cgd 1091: }
1.146 ad 1092: if (i == nproc_targets) {
1093: procfs_proc_unlock(p);
1.145 ad 1094: break;
1.146 ad 1095: }
1.109 darcy 1096: if (pt->pt_pfstype == PFSfile) {
1.75 chs 1097: fvp = p->p_textvp;
1.23 mycroft 1098: /* We already checked that it exists. */
1.32 mycroft 1099: VREF(fvp);
1.161 ad 1100: procfs_proc_unlock(p);
1.53 fvdl 1101: vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY);
1.32 mycroft 1102: *vpp = fvp;
1.21 mycroft 1103: return (0);
1104: }
1.1 pk 1105:
1.62 wrstuden 1106: error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1.145 ad 1107: pt->pt_pfstype, -1, p);
1108: procfs_proc_unlock(p);
1.62 wrstuden 1109: return (error);
1.1 pk 1110:
1.109 darcy 1111: case PFSfd: {
1.91 christos 1112: int fd;
1113: struct file *fp;
1.145 ad 1114:
1115: if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ENOENT)) != 0)
1116: return error;
1117:
1.91 christos 1118: /*
1119: * do the .. dance. We unlock the directory, and then
1120: * get the proc dir. That will automatically return ..
1.143 chs 1121: * locked. Then re-lock the directory.
1.91 christos 1122: */
1123: if (cnp->cn_flags & ISDOTDOT) {
1124: VOP_UNLOCK(dvp, 0);
1125: error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1.145 ad 1126: PFSproc, -1, p);
1.161 ad 1127: procfs_proc_unlock(p);
1.146 ad 1128: vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
1.91 christos 1129: return (error);
1130: }
1131: fd = atoi(pname, cnp->cn_namelen);
1.145 ad 1132:
1133: fp = fd_getfile(p->p_fd, fd);
1134: if (fp == NULL) {
1135: procfs_proc_unlock(p);
1.91 christos 1136: return ENOENT;
1.145 ad 1137: }
1138:
1.99 jdolecek 1139: FILE_USE(fp);
1.161 ad 1140: fvp = (struct vnode *)fp->f_data;
1.99 jdolecek 1141:
1.161 ad 1142: /* Don't show directories */
1143: if (fp->f_type == DTYPE_VNODE && fvp->v_type != VDIR) {
1.91 christos 1144: VREF(fvp);
1.128 christos 1145: FILE_UNUSE(fp, l);
1.161 ad 1146: procfs_proc_unlock(p);
1.121 perry 1147: vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY |
1.92 christos 1148: (p == curproc ? LK_CANRECURSE : 0));
1.91 christos 1149: *vpp = fvp;
1.161 ad 1150: return 0;
1.91 christos 1151: }
1.161 ad 1152:
1153: FILE_UNUSE(fp, l);
1154: error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1155: PFSfd, fd, p);
1.145 ad 1156: procfs_proc_unlock(p);
1.91 christos 1157: return error;
1158: }
1.9 cgd 1159: default:
1160: return (ENOTDIR);
1.1 pk 1161: }
1.32 mycroft 1162:
1163: return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
1.1 pk 1164: }
1165:
1.18 cgd 1166: int
1.138 christos 1167: procfs_validfile(struct lwp *l, struct mount *mp)
1.18 cgd 1168: {
1.136 christos 1169: return l != NULL && l->l_proc != NULL && l->l_proc->p_textvp != NULL;
1.74 tv 1170: }
1.21 mycroft 1171:
1.74 tv 1172: static int
1.128 christos 1173: procfs_validfile_linux(l, mp)
1174: struct lwp *l;
1.76 fvdl 1175: struct mount *mp;
1.74 tv 1176: {
1.76 fvdl 1177: int flags;
1178:
1179: flags = VFSTOPROC(mp)->pmnt_flags;
1.142 christos 1180: return (flags & PROCFSMNT_LINUXCOMPAT) &&
1181: (l == NULL || l->l_proc == NULL || procfs_validfile(l, mp));
1.18 cgd 1182: }
1183:
1.117 yamt 1184: struct procfs_root_readdir_ctx {
1185: struct uio *uiop;
1186: off_t *cookies;
1187: int ncookies;
1.120 yamt 1188: off_t off;
1189: off_t startoff;
1.117 yamt 1190: int error;
1191: };
1192:
1193: static int
1194: procfs_root_readdir_callback(struct proc *p, void *arg)
1195: {
1196: struct procfs_root_readdir_ctx *ctxp = arg;
1197: struct dirent d;
1198: struct uio *uiop;
1199: int error;
1200:
1201: uiop = ctxp->uiop;
1202: if (uiop->uio_resid < UIO_MX)
1203: return -1; /* no space */
1204:
1.120 yamt 1205: if (ctxp->off < ctxp->startoff) {
1206: ctxp->off++;
1.117 yamt 1207: return 0;
1208: }
1209:
1.133 yamt 1210: if (kauth_authorize_process(kauth_cred_get(),
1.163.6.2! bouyer 1211: KAUTH_PROCESS_CANSEE, p,
! 1212: KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL) != 0)
1.133 yamt 1213: return 0;
1.125 elad 1214:
1.117 yamt 1215: memset(&d, 0, UIO_MX);
1216: d.d_reclen = UIO_MX;
1217: d.d_fileno = PROCFS_FILENO(p->p_pid, PFSproc, -1);
1218: d.d_namlen = snprintf(d.d_name,
1219: UIO_MX - offsetof(struct dirent, d_name), "%ld", (long)p->p_pid);
1220: d.d_type = DT_DIR;
1221:
1.154 ad 1222: mutex_exit(&proclist_lock);
1.117 yamt 1223: error = uiomove(&d, UIO_MX, uiop);
1.154 ad 1224: mutex_enter(&proclist_lock);
1.117 yamt 1225: if (error) {
1226: ctxp->error = error;
1227: return -1;
1228: }
1229:
1230: ctxp->ncookies++;
1231: if (ctxp->cookies)
1.120 yamt 1232: *(ctxp->cookies)++ = ctxp->off + 1;
1233: ctxp->off++;
1.117 yamt 1234:
1235: return 0;
1236: }
1237:
1.9 cgd 1238: /*
1239: * readdir returns directory entries from pfsnode (vp).
1240: *
1241: * the strategy here with procfs is to generate a single
1.34 mycroft 1242: * directory entry at a time (struct dirent) and then
1.9 cgd 1243: * copy that out to userland using uiomove. a more efficent
1244: * though more complex implementation, would try to minimize
1245: * the number of calls to uiomove(). for procfs, this is
1246: * hardly worth the added code complexity.
1247: *
1248: * this should just be done through read()
1249: */
1.37 christos 1250: int
1251: procfs_readdir(v)
1252: void *v;
1253: {
1.22 mycroft 1254: struct vop_readdir_args /* {
1255: struct vnode *a_vp;
1256: struct uio *a_uio;
1.130 elad 1257: kauth_cred_t a_cred;
1.22 mycroft 1258: int *a_eofflag;
1.53 fvdl 1259: off_t **a_cookies;
1260: int *a_ncookies;
1.37 christos 1261: } */ *ap = v;
1.21 mycroft 1262: struct uio *uio = ap->a_uio;
1.34 mycroft 1263: struct dirent d;
1.9 cgd 1264: struct pfsnode *pfs;
1.68 sommerfe 1265: off_t i;
1.9 cgd 1266: int error;
1.53 fvdl 1267: off_t *cookies = NULL;
1.117 yamt 1268: int ncookies;
1.76 fvdl 1269: struct vnode *vp;
1.78 jdolecek 1270: const struct proc_target *pt;
1.117 yamt 1271: struct procfs_root_readdir_ctx ctx;
1.145 ad 1272: struct lwp *l;
1.161 ad 1273: int nfd;
1.9 cgd 1274:
1.76 fvdl 1275: vp = ap->a_vp;
1276: pfs = VTOPFS(vp);
1.1 pk 1277:
1.9 cgd 1278: if (uio->uio_resid < UIO_MX)
1279: return (EINVAL);
1.35 mycroft 1280: if (uio->uio_offset < 0)
1.1 pk 1281: return (EINVAL);
1282:
1.9 cgd 1283: error = 0;
1.35 mycroft 1284: i = uio->uio_offset;
1.113 jrf 1285: memset(&d, 0, UIO_MX);
1.34 mycroft 1286: d.d_reclen = UIO_MX;
1.53 fvdl 1287: ncookies = uio->uio_resid / UIO_MX;
1.9 cgd 1288:
1289: switch (pfs->pfs_type) {
1290: /*
1291: * this is for the process-specific sub-directories.
1292: * all that is needed to is copy out all the entries
1293: * from the procent[] table (top of this file).
1294: */
1.109 darcy 1295: case PFSproc: {
1.32 mycroft 1296: struct proc *p;
1.66 christos 1297:
1298: if (i >= nproc_targets)
1.67 sommerfe 1299: return 0;
1.9 cgd 1300:
1.145 ad 1301: if (procfs_proc_lock(pfs->pfs_pid, &p, ESRCH) != 0)
1.32 mycroft 1302: break;
1303:
1.53 fvdl 1304: if (ap->a_ncookies) {
1305: ncookies = min(ncookies, (nproc_targets - i));
1.72 thorpej 1306: cookies = malloc(ncookies * sizeof (off_t),
1.53 fvdl 1307: M_TEMP, M_WAITOK);
1308: *ap->a_cookies = cookies;
1309: }
1310:
1.32 mycroft 1311: for (pt = &proc_targets[i];
1312: uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) {
1.145 ad 1313: if (pt->pt_valid) {
1.161 ad 1314: /* XXX LWP can disappear */
1.145 ad 1315: mutex_enter(&p->p_smutex);
1316: l = proc_representative_lwp(p, NULL, 1);
1317: mutex_exit(&p->p_smutex);
1318: if ((*pt->pt_valid)(l, vp->v_mount) == 0)
1319: continue;
1320: }
1.121 perry 1321:
1.91 christos 1322: d.d_fileno = PROCFS_FILENO(pfs->pfs_pid,
1323: pt->pt_pfstype, -1);
1.34 mycroft 1324: d.d_namlen = pt->pt_namlen;
1.56 perry 1325: memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1.34 mycroft 1326: d.d_type = pt->pt_type;
1.15 ws 1327:
1.113 jrf 1328: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.9 cgd 1329: break;
1.53 fvdl 1330: if (cookies)
1.35 mycroft 1331: *cookies++ = i + 1;
1.6 ws 1332: }
1.9 cgd 1333:
1.145 ad 1334: procfs_proc_unlock(p);
1.9 cgd 1335: break;
1.34 mycroft 1336: }
1.109 darcy 1337: case PFSfd: {
1.91 christos 1338: struct proc *p;
1339: struct filedesc *fdp;
1.111 jdolecek 1340: struct file *fp;
1.110 simonb 1341: int lim, nc = 0;
1.91 christos 1342:
1.145 ad 1343: if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ESRCH)) != 0)
1344: return error;
1.91 christos 1345:
1.163.6.2! bouyer 1346: /* XXX Should this be by file as well? */
1.133 yamt 1347: if (kauth_authorize_process(kauth_cred_get(),
1.163.6.2! bouyer 1348: KAUTH_PROCESS_CANSEE, p,
! 1349: KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_OPENFILES), NULL,
! 1350: NULL) != 0) {
1.145 ad 1351: procfs_proc_unlock(p);
1.133 yamt 1352: return ESRCH;
1.145 ad 1353: }
1.125 elad 1354:
1.161 ad 1355: fdp = p->p_fd;
1356: nfd = fdp->fd_nfiles;
1.91 christos 1357:
1358: lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1.145 ad 1359: if (i >= lim) {
1360: procfs_proc_unlock(p);
1.91 christos 1361: return 0;
1.145 ad 1362: }
1.91 christos 1363:
1364: if (ap->a_ncookies) {
1.161 ad 1365: ncookies = min(ncookies, (nfd + 2 - i));
1.91 christos 1366: cookies = malloc(ncookies * sizeof (off_t),
1367: M_TEMP, M_WAITOK);
1368: *ap->a_cookies = cookies;
1369: }
1370:
1371: for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1372: pt = &proc_targets[i];
1373: d.d_namlen = pt->pt_namlen;
1374: d.d_fileno = PROCFS_FILENO(pfs->pfs_pid,
1375: pt->pt_pfstype, -1);
1376: (void)memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1377: d.d_type = pt->pt_type;
1.113 jrf 1378: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.91 christos 1379: break;
1380: if (cookies)
1381: *cookies++ = i + 1;
1382: nc++;
1383: }
1384: if (error) {
1385: ncookies = nc;
1386: break;
1387: }
1.161 ad 1388: for (; uio->uio_resid >= UIO_MX && i < nfd; i++) {
1.111 jdolecek 1389: /* check the descriptor exists */
1390: if ((fp = fd_getfile(fdp, i - 2)) == NULL)
1.100 jdolecek 1391: continue;
1.159 ad 1392: mutex_exit(&fp->f_lock);
1.111 jdolecek 1393:
1.109 darcy 1394: d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, PFSfd, i - 2);
1.91 christos 1395: d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1.93 martin 1396: "%lld", (long long)(i - 2));
1.91 christos 1397: d.d_type = VREG;
1.113 jrf 1398: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.91 christos 1399: break;
1400: if (cookies)
1401: *cookies++ = i + 1;
1402: nc++;
1403: }
1404: ncookies = nc;
1.145 ad 1405: procfs_proc_unlock(p);
1.91 christos 1406: break;
1407: }
1.9 cgd 1408:
1409: /*
1410: * this is for the root of the procfs filesystem
1.69 thorpej 1411: * what is needed are special entries for "curproc"
1412: * and "self" followed by an entry for each process
1.117 yamt 1413: * on allproc.
1.9 cgd 1414: */
1415:
1.109 darcy 1416: case PFSroot: {
1.117 yamt 1417: int nc = 0;
1.9 cgd 1418:
1.53 fvdl 1419: if (ap->a_ncookies) {
1420: /*
1421: * XXX Potentially allocating too much space here,
1422: * but I'm lazy. This loop needs some work.
1423: */
1.72 thorpej 1424: cookies = malloc(ncookies * sizeof (off_t),
1.53 fvdl 1425: M_TEMP, M_WAITOK);
1426: *ap->a_cookies = cookies;
1427: }
1.117 yamt 1428: error = 0;
1429: /* 0 ... 3 are static entries. */
1430: for (; i <= 3 && uio->uio_resid >= UIO_MX; i++) {
1.9 cgd 1431: switch (i) {
1.12 ws 1432: case 0: /* `.' */
1433: case 1: /* `..' */
1.109 darcy 1434: d.d_fileno = PROCFS_FILENO(0, PFSroot, -1);
1.34 mycroft 1435: d.d_namlen = i + 1;
1.56 perry 1436: memcpy(d.d_name, "..", d.d_namlen);
1.34 mycroft 1437: d.d_name[i + 1] = '\0';
1438: d.d_type = DT_DIR;
1.12 ws 1439: break;
1.21 mycroft 1440:
1.12 ws 1441: case 2:
1.109 darcy 1442: d.d_fileno = PROCFS_FILENO(0, PFScurproc, -1);
1.69 thorpej 1443: d.d_namlen = sizeof("curproc") - 1;
1444: memcpy(d.d_name, "curproc", sizeof("curproc"));
1445: d.d_type = DT_LNK;
1446: break;
1447:
1448: case 3:
1.109 darcy 1449: d.d_fileno = PROCFS_FILENO(0, PFSself, -1);
1.69 thorpej 1450: d.d_namlen = sizeof("self") - 1;
1451: memcpy(d.d_name, "self", sizeof("self"));
1.34 mycroft 1452: d.d_type = DT_LNK;
1.9 cgd 1453: break;
1.1 pk 1454: }
1.21 mycroft 1455:
1.113 jrf 1456: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.9 cgd 1457: break;
1.53 fvdl 1458: nc++;
1459: if (cookies)
1.35 mycroft 1460: *cookies++ = i + 1;
1.1 pk 1461: }
1.117 yamt 1462: /* 4 ... are process entries. */
1463: ctx.uiop = uio;
1464: ctx.error = 0;
1.120 yamt 1465: ctx.off = 4;
1466: ctx.startoff = i;
1.117 yamt 1467: ctx.cookies = cookies;
1468: ctx.ncookies = nc;
1469: proclist_foreach_call(&allproc,
1470: procfs_root_readdir_callback, &ctx);
1471: cookies = ctx.cookies;
1472: nc = ctx.ncookies;
1473: error = ctx.error;
1474: if (error)
1475: break;
1.76 fvdl 1476:
1.117 yamt 1477: /* misc entries. */
1.120 yamt 1478: if (i < ctx.off)
1479: i = ctx.off;
1480: if (i >= ctx.off + nproc_root_targets)
1.76 fvdl 1481: break;
1.120 yamt 1482: for (pt = &proc_root_targets[i - ctx.off];
1.117 yamt 1483: uio->uio_resid >= UIO_MX &&
1484: pt < &proc_root_targets[nproc_root_targets];
1485: pt++, i++) {
1.76 fvdl 1486: if (pt->pt_valid &&
1487: (*pt->pt_valid)(NULL, vp->v_mount) == 0)
1488: continue;
1.91 christos 1489: d.d_fileno = PROCFS_FILENO(0, pt->pt_pfstype, -1);
1.76 fvdl 1490: d.d_namlen = pt->pt_namlen;
1491: memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1492: d.d_type = pt->pt_type;
1493:
1.113 jrf 1494: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.76 fvdl 1495: break;
1496: nc++;
1497: if (cookies)
1498: *cookies++ = i + 1;
1499: }
1500:
1.53 fvdl 1501: ncookies = nc;
1.9 cgd 1502: break;
1.34 mycroft 1503: }
1.9 cgd 1504:
1505: default:
1506: error = ENOTDIR;
1507: break;
1.1 pk 1508: }
1.9 cgd 1509:
1.53 fvdl 1510: if (ap->a_ncookies) {
1511: if (error) {
1.54 fvdl 1512: if (cookies)
1.72 thorpej 1513: free(*ap->a_cookies, M_TEMP);
1.53 fvdl 1514: *ap->a_ncookies = 0;
1515: *ap->a_cookies = NULL;
1516: } else
1517: *ap->a_ncookies = ncookies;
1518: }
1.35 mycroft 1519: uio->uio_offset = i;
1.9 cgd 1520: return (error);
1.12 ws 1521: }
1522:
1523: /*
1.126 atatat 1524: * readlink reads the link of `curproc' and others
1.12 ws 1525: */
1.37 christos 1526: int
1527: procfs_readlink(v)
1528: void *v;
1.12 ws 1529: {
1.37 christos 1530: struct vop_readlink_args *ap = v;
1.123 christos 1531: char bf[16]; /* should be enough */
1532: char *bp = bf;
1.102 christos 1533: char *path = NULL;
1.161 ad 1534: int len = 0;
1.102 christos 1535: int error = 0;
1536: struct pfsnode *pfs = VTOPFS(ap->a_vp);
1.126 atatat 1537: struct proc *pown;
1.12 ws 1538:
1.109 darcy 1539: if (pfs->pfs_fileno == PROCFS_FILENO(0, PFScurproc, -1))
1.123 christos 1540: len = snprintf(bf, sizeof(bf), "%ld", (long)curproc->p_pid);
1.109 darcy 1541: else if (pfs->pfs_fileno == PROCFS_FILENO(0, PFSself, -1))
1.123 christos 1542: len = snprintf(bf, sizeof(bf), "%s", "curproc");
1.136 christos 1543: else if (pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFScwd, -1) ||
1544: pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFSchroot, -1) ||
1545: pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFSexe, -1)) {
1.145 ad 1546: if ((error = procfs_proc_lock(pfs->pfs_pid, &pown, ESRCH)) != 0)
1547: return error;
1.126 atatat 1548: MALLOC(path, char *, MAXPATHLEN + 4, M_TEMP,
1549: M_WAITOK|M_CANFAIL);
1.145 ad 1550: if (path == NULL) {
1551: procfs_proc_unlock(pown);
1.126 atatat 1552: return (ENOMEM);
1.145 ad 1553: }
1.126 atatat 1554: bp = path + MAXPATHLEN;
1555: *--bp = '\0';
1.161 ad 1556: procfs_dir(PROCFS_TYPE(pfs->pfs_fileno), curlwp, pown,
1.136 christos 1557: &bp, path, MAXPATHLEN);
1.145 ad 1558: procfs_proc_unlock(pown);
1.126 atatat 1559: len = strlen(bp);
1.136 christos 1560: } else {
1.102 christos 1561: struct file *fp;
1562: struct vnode *vxp, *vp;
1563:
1.145 ad 1564: if ((error = procfs_proc_lock(pfs->pfs_pid, &pown, ESRCH)) != 0)
1.102 christos 1565: return error;
1.155 rmind 1566:
1.145 ad 1567: fp = fd_getfile(pown->p_fd, pfs->pfs_fd);
1.156 rmind 1568: if (fp == NULL) {
1569: procfs_proc_unlock(pown);
1.155 rmind 1570: return EBADF;
1.156 rmind 1571: }
1.155 rmind 1572:
1.102 christos 1573: FILE_USE(fp);
1574: switch (fp->f_type) {
1575: case DTYPE_VNODE:
1576: vxp = (struct vnode *)fp->f_data;
1577: if (vxp->v_type != VDIR) {
1.145 ad 1578: FILE_UNUSE(fp, curlwp);
1579: error = EINVAL;
1580: break;
1.102 christos 1581: }
1582: if ((path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK))
1583: == NULL) {
1.145 ad 1584: FILE_UNUSE(fp, curlwp);
1585: error = ENOMEM;
1586: break;
1.102 christos 1587: }
1588: bp = path + MAXPATHLEN;
1589: *--bp = '\0';
1.158 pooka 1590:
1591: /*
1592: * XXX: kludge to avoid locking against ourselves
1593: * in getcwd()
1594: */
1595: if (vxp->v_tag == VT_PROCFS) {
1596: *--bp = '/';
1597: } else {
1.161 ad 1598: rw_enter(&curproc->p_cwdi->cwdi_lock, RW_READER);
1599: vp = curproc->p_cwdi->cwdi_rdir;
1.158 pooka 1600: if (vp == NULL)
1601: vp = rootvnode;
1602: error = getcwd_common(vxp, vp, &bp, path,
1603: MAXPATHLEN / 2, 0, curlwp);
1.161 ad 1604: rw_exit(&curproc->p_cwdi->cwdi_lock);
1.158 pooka 1605: }
1.145 ad 1606: if (error)
1607: break;
1.102 christos 1608: len = strlen(bp);
1609: break;
1610:
1611: case DTYPE_MISC:
1.123 christos 1612: len = snprintf(bf, sizeof(bf), "%s", "[misc]");
1.102 christos 1613: break;
1614:
1615: case DTYPE_KQUEUE:
1.123 christos 1616: len = snprintf(bf, sizeof(bf), "%s", "[kqueue]");
1.102 christos 1617: break;
1618:
1619: default:
1.145 ad 1620: error = EINVAL;
1621: break;
1622: }
1.161 ad 1623: FILE_UNUSE(fp, curlwp);
1.145 ad 1624: procfs_proc_unlock(pown);
1.102 christos 1625: }
1.12 ws 1626:
1.145 ad 1627: if (error == 0)
1628: error = uiomove(bp, len, ap->a_uio);
1.102 christos 1629: if (path)
1630: free(path, M_TEMP);
1631: return error;
1.1 pk 1632: }
1633:
1634: /*
1.91 christos 1635: * convert decimal ascii to int
1.1 pk 1636: */
1.91 christos 1637: static int
1638: atoi(b, len)
1.9 cgd 1639: const char *b;
1.91 christos 1640: size_t len;
1.1 pk 1641: {
1.91 christos 1642: int p = 0;
1.1 pk 1643:
1644: while (len--) {
1.9 cgd 1645: char c = *b++;
1.1 pk 1646: if (c < '0' || c > '9')
1.91 christos 1647: return -1;
1.9 cgd 1648: p = 10 * p + (c - '0');
1.1 pk 1649: }
1.9 cgd 1650:
1.91 christos 1651: return p;
1.1 pk 1652: }
CVSweb <webmaster@jp.NetBSD.org>