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