Deleted Added
full compact
pseudofs_vnops.c (96886) pseudofs_vnops.c (97940)
1/*-
2 * Copyright (c) 2001 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
1/*-
2 * Copyright (c) 2001 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/fs/pseudofs/pseudofs_vnops.c 96886 2002-05-19 00:14:50Z jhb $
28 * $FreeBSD: head/sys/fs/pseudofs/pseudofs_vnops.c 97940 2002-06-06 16:59:24Z des $
29 */
30
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/systm.h>
34#include <sys/ctype.h>
35#include <sys/dirent.h>
36#include <sys/fcntl.h>

--- 33 unchanged lines hidden (view full) ---

70/*
71 * Returns non-zero if given file is visible to given process
72 */
73static int
74pfs_visible(struct thread *td, struct pfs_node *pn, pid_t pid)
75{
76 struct proc *proc;
77 int r;
29 */
30
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/systm.h>
34#include <sys/ctype.h>
35#include <sys/dirent.h>
36#include <sys/fcntl.h>

--- 33 unchanged lines hidden (view full) ---

70/*
71 * Returns non-zero if given file is visible to given process
72 */
73static int
74pfs_visible(struct thread *td, struct pfs_node *pn, pid_t pid)
75{
76 struct proc *proc;
77 int r;
78
78
79 PFS_TRACE(("%s (pid: %d, req: %d)",
80 pn->pn_name, pid, td->td_proc->p_pid));
81
82 if (pn->pn_flags & PFS_DISABLED)
83 PFS_RETURN (0);
79 PFS_TRACE(("%s (pid: %d, req: %d)",
80 pn->pn_name, pid, td->td_proc->p_pid));
81
82 if (pn->pn_flags & PFS_DISABLED)
83 PFS_RETURN (0);
84
84
85 r = 1;
86 if (pid != NO_PID) {
87 if ((proc = pfind(pid)) == NULL)
88 PFS_RETURN (0);
89 if (p_cansee(td, proc) != 0 ||
90 (pn->pn_vis != NULL && !(pn->pn_vis)(td, proc, pn)))
91 r = 0;
92 PROC_UNLOCK(proc);

--- 5 unchanged lines hidden (view full) ---

98 * Verify permissions
99 */
100static int
101pfs_access(struct vop_access_args *va)
102{
103 struct vnode *vn = va->a_vp;
104 struct vattr vattr;
105 int error;
85 r = 1;
86 if (pid != NO_PID) {
87 if ((proc = pfind(pid)) == NULL)
88 PFS_RETURN (0);
89 if (p_cansee(td, proc) != 0 ||
90 (pn->pn_vis != NULL && !(pn->pn_vis)(td, proc, pn)))
91 r = 0;
92 PROC_UNLOCK(proc);

--- 5 unchanged lines hidden (view full) ---

98 * Verify permissions
99 */
100static int
101pfs_access(struct vop_access_args *va)
102{
103 struct vnode *vn = va->a_vp;
104 struct vattr vattr;
105 int error;
106
106
107 PFS_TRACE((((struct pfs_vdata *)vn->v_data)->pvd_pn->pn_name));
107 PFS_TRACE((((struct pfs_vdata *)vn->v_data)->pvd_pn->pn_name));
108
108
109 error = VOP_GETATTR(vn, &vattr, va->a_cred, va->a_td);
110 if (error)
111 PFS_RETURN (error);
112 error = vaccess(vn->v_type, vattr.va_mode, vattr.va_uid,
113 vattr.va_gid, va->a_mode, va->a_cred, NULL);
114 PFS_RETURN (error);
115}
116

--- 17 unchanged lines hidden (view full) ---

134 */
135 if (vn->v_usecount > 1 || pn->pn_close == NULL)
136 PFS_RETURN (0);
137
138 if (pvd->pvd_pid != NO_PID)
139 proc = pfind(pvd->pvd_pid);
140 else
141 proc = NULL;
109 error = VOP_GETATTR(vn, &vattr, va->a_cred, va->a_td);
110 if (error)
111 PFS_RETURN (error);
112 error = vaccess(vn->v_type, vattr.va_mode, vattr.va_uid,
113 vattr.va_gid, va->a_mode, va->a_cred, NULL);
114 PFS_RETURN (error);
115}
116

--- 17 unchanged lines hidden (view full) ---

134 */
135 if (vn->v_usecount > 1 || pn->pn_close == NULL)
136 PFS_RETURN (0);
137
138 if (pvd->pvd_pid != NO_PID)
139 proc = pfind(pvd->pvd_pid);
140 else
141 proc = NULL;
142
142
143 error = (pn->pn_close)(va->a_td, proc, pn);
143 error = (pn->pn_close)(va->a_td, proc, pn);
144
144
145 if (proc != NULL)
146 PROC_UNLOCK(proc);
145 if (proc != NULL)
146 PROC_UNLOCK(proc);
147
147
148 PFS_RETURN (error);
149}
150
151/*
152 * Get file attributes
153 */
154static int
155pfs_getattr(struct vop_getattr_args *va)
156{
157 struct vnode *vn = va->a_vp;
158 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
159 struct pfs_node *pn = pvd->pvd_pn;
160 struct vattr *vap = va->a_vap;
161 struct proc *proc;
162 int error = 0;
163
164 PFS_TRACE((pn->pn_name));
148 PFS_RETURN (error);
149}
150
151/*
152 * Get file attributes
153 */
154static int
155pfs_getattr(struct vop_getattr_args *va)
156{
157 struct vnode *vn = va->a_vp;
158 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
159 struct pfs_node *pn = pvd->pvd_pn;
160 struct vattr *vap = va->a_vap;
161 struct proc *proc;
162 int error = 0;
163
164 PFS_TRACE((pn->pn_name));
165
165
166 VATTR_NULL(vap);
167 vap->va_type = vn->v_type;
168 vap->va_fileid = pn->pn_fileno;
169 vap->va_flags = 0;
170 vap->va_blocksize = PAGE_SIZE;
171 vap->va_bytes = vap->va_size = 0;
172 vap->va_fsid = vn->v_mount->mnt_stat.f_fsid.val[0];
173 vap->va_nlink = 1;

--- 23 unchanged lines hidden (view full) ---

197 vap->va_gid = proc->p_ucred->cr_rgid;
198 if (pn->pn_attr != NULL)
199 error = (pn->pn_attr)(va->a_td, proc, pn, vap);
200 PROC_UNLOCK(proc);
201 } else {
202 vap->va_uid = 0;
203 vap->va_gid = 0;
204 }
166 VATTR_NULL(vap);
167 vap->va_type = vn->v_type;
168 vap->va_fileid = pn->pn_fileno;
169 vap->va_flags = 0;
170 vap->va_blocksize = PAGE_SIZE;
171 vap->va_bytes = vap->va_size = 0;
172 vap->va_fsid = vn->v_mount->mnt_stat.f_fsid.val[0];
173 vap->va_nlink = 1;

--- 23 unchanged lines hidden (view full) ---

197 vap->va_gid = proc->p_ucred->cr_rgid;
198 if (pn->pn_attr != NULL)
199 error = (pn->pn_attr)(va->a_td, proc, pn, vap);
200 PROC_UNLOCK(proc);
201 } else {
202 vap->va_uid = 0;
203 vap->va_gid = 0;
204 }
205
205
206 PFS_RETURN (error);
207}
208
209/*
210 * Perform an ioctl
211 */
212static int
213pfs_ioctl(struct vop_ioctl_args *va)
214{
215 struct vnode *vn = va->a_vp;
216 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
217 struct pfs_node *pn = pvd->pvd_pn;
218 struct proc *proc = NULL;
219 int error;
220
221 PFS_TRACE(("%s: %lx", pn->pn_name, va->a_command));
206 PFS_RETURN (error);
207}
208
209/*
210 * Perform an ioctl
211 */
212static int
213pfs_ioctl(struct vop_ioctl_args *va)
214{
215 struct vnode *vn = va->a_vp;
216 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
217 struct pfs_node *pn = pvd->pvd_pn;
218 struct proc *proc = NULL;
219 int error;
220
221 PFS_TRACE(("%s: %lx", pn->pn_name, va->a_command));
222
222
223 if (vn->v_type != VREG)
224 PFS_RETURN (EINVAL);
225
226 if (pn->pn_ioctl == NULL)
227 PFS_RETURN (ENOTTY);
223 if (vn->v_type != VREG)
224 PFS_RETURN (EINVAL);
225
226 if (pn->pn_ioctl == NULL)
227 PFS_RETURN (ENOTTY);
228
228
229 /*
230 * This is necessary because either process' privileges may
231 * have changed since the open() call.
232 */
233 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
234 PFS_RETURN (EIO);
229 /*
230 * This is necessary because either process' privileges may
231 * have changed since the open() call.
232 */
233 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
234 PFS_RETURN (EIO);
235
235
236 /* XXX duplicates bits of pfs_visible() */
237 if (pvd->pvd_pid != NO_PID) {
238 if ((proc = pfind(pvd->pvd_pid)) == NULL)
239 PFS_RETURN (EIO);
240 _PHOLD(proc);
241 PROC_UNLOCK(proc);
242 }
236 /* XXX duplicates bits of pfs_visible() */
237 if (pvd->pvd_pid != NO_PID) {
238 if ((proc = pfind(pvd->pvd_pid)) == NULL)
239 PFS_RETURN (EIO);
240 _PHOLD(proc);
241 PROC_UNLOCK(proc);
242 }
243
243
244 error = (pn->pn_ioctl)(curthread, proc, pn, va->a_command, va->a_data);
245
246 if (proc != NULL)
247 PRELE(proc);
244 error = (pn->pn_ioctl)(curthread, proc, pn, va->a_command, va->a_data);
245
246 if (proc != NULL)
247 PRELE(proc);
248
248
249 PFS_RETURN (error);
250}
251
252/*
253 * Perform getextattr
254 */
255static int
256pfs_getextattr(struct vop_getextattr_args *va)
257{
258 struct vnode *vn = va->a_vp;
259 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
260 struct pfs_node *pn = pvd->pvd_pn;
261 struct proc *proc = NULL;
262 int error;
263
264 PFS_TRACE((pd->pn_name));
265
266 if (pn->pn_getextattr == NULL)
267 PFS_RETURN (EOPNOTSUPP);
249 PFS_RETURN (error);
250}
251
252/*
253 * Perform getextattr
254 */
255static int
256pfs_getextattr(struct vop_getextattr_args *va)
257{
258 struct vnode *vn = va->a_vp;
259 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
260 struct pfs_node *pn = pvd->pvd_pn;
261 struct proc *proc = NULL;
262 int error;
263
264 PFS_TRACE((pd->pn_name));
265
266 if (pn->pn_getextattr == NULL)
267 PFS_RETURN (EOPNOTSUPP);
268
268
269 /*
270 * This is necessary because either process' privileges may
271 * have changed since the open() call.
272 */
273 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
274 PFS_RETURN (EIO);
269 /*
270 * This is necessary because either process' privileges may
271 * have changed since the open() call.
272 */
273 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
274 PFS_RETURN (EIO);
275
275
276 /* XXX duplicates bits of pfs_visible() */
277 if (pvd->pvd_pid != NO_PID) {
278 if ((proc = pfind(pvd->pvd_pid)) == NULL)
279 PFS_RETURN (EIO);
280 _PHOLD(proc);
281 PROC_UNLOCK(proc);
282 }
276 /* XXX duplicates bits of pfs_visible() */
277 if (pvd->pvd_pid != NO_PID) {
278 if ((proc = pfind(pvd->pvd_pid)) == NULL)
279 PFS_RETURN (EIO);
280 _PHOLD(proc);
281 PROC_UNLOCK(proc);
282 }
283
283
284 error = (pn->pn_getextattr)(curthread, proc, pn, va->a_attrnamespace,
285 va->a_name, va->a_uio, va->a_size, va->a_cred);
286
287 if (proc != NULL)
288 PRELE(proc);
284 error = (pn->pn_getextattr)(curthread, proc, pn, va->a_attrnamespace,
285 va->a_name, va->a_uio, va->a_size, va->a_cred);
286
287 if (proc != NULL)
288 PRELE(proc);
289
289
290 PFS_RETURN (error);
291}
292
293/*
294 * Look up a file or directory
295 *
296 * XXX NOTE! pfs_lookup() has been hooked into vop_lookup_desc! This
297 * will result in a lookup operation for a vnode which may already be

--- 13 unchanged lines hidden (view full) ---

311 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
312 struct pfs_node *pd = pvd->pvd_pn;
313 struct pfs_node *pn, *pdn = NULL;
314 pid_t pid = pvd->pvd_pid;
315 char *pname;
316 int error, i, namelen;
317
318 PFS_TRACE(("%.*s", (int)cnp->cn_namelen, cnp->cn_nameptr));
290 PFS_RETURN (error);
291}
292
293/*
294 * Look up a file or directory
295 *
296 * XXX NOTE! pfs_lookup() has been hooked into vop_lookup_desc! This
297 * will result in a lookup operation for a vnode which may already be

--- 13 unchanged lines hidden (view full) ---

311 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
312 struct pfs_node *pd = pvd->pvd_pn;
313 struct pfs_node *pn, *pdn = NULL;
314 pid_t pid = pvd->pvd_pid;
315 char *pname;
316 int error, i, namelen;
317
318 PFS_TRACE(("%.*s", (int)cnp->cn_namelen, cnp->cn_nameptr));
319
319
320 if (vn->v_type != VDIR)
321 PFS_RETURN (ENOTDIR);
320 if (vn->v_type != VDIR)
321 PFS_RETURN (ENOTDIR);
322
322
323 /*
324 * Don't support DELETE or RENAME. CREATE is supported so
325 * that O_CREAT will work, but the lookup will still fail if
326 * the file does not exist.
327 */
328 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
329 PFS_RETURN (EOPNOTSUPP);
330
331 /* shortcut: check if the name is too long */
332 if (cnp->cn_namelen >= PFS_NAMELEN)
333 PFS_RETURN (ENOENT);
334
335 /* check that parent directory is visisble... */
336 if (!pfs_visible(curthread, pd, pvd->pvd_pid))
337 PFS_RETURN (ENOENT);
323 /*
324 * Don't support DELETE or RENAME. CREATE is supported so
325 * that O_CREAT will work, but the lookup will still fail if
326 * the file does not exist.
327 */
328 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
329 PFS_RETURN (EOPNOTSUPP);
330
331 /* shortcut: check if the name is too long */
332 if (cnp->cn_namelen >= PFS_NAMELEN)
333 PFS_RETURN (ENOENT);
334
335 /* check that parent directory is visisble... */
336 if (!pfs_visible(curthread, pd, pvd->pvd_pid))
337 PFS_RETURN (ENOENT);
338
338
339 /* self */
340 namelen = cnp->cn_namelen;
341 pname = cnp->cn_nameptr;
342 if (namelen == 1 && *pname == '.') {
343 pn = pd;
344 *vpp = vn;
345 VREF(vn);
346 PFS_RETURN (0);

--- 31 unchanged lines hidden (view full) ---

378 if ((pn = pdn) != NULL) {
379 pid = 0;
380 for (pid = 0, i = 0; i < namelen && isdigit(pname[i]); ++i)
381 if ((pid = pid * 10 + pname[i] - '0') > PID_MAX)
382 break;
383 if (i == cnp->cn_namelen)
384 goto got_pnode;
385 }
339 /* self */
340 namelen = cnp->cn_namelen;
341 pname = cnp->cn_nameptr;
342 if (namelen == 1 && *pname == '.') {
343 pn = pd;
344 *vpp = vn;
345 VREF(vn);
346 PFS_RETURN (0);

--- 31 unchanged lines hidden (view full) ---

378 if ((pn = pdn) != NULL) {
379 pid = 0;
380 for (pid = 0, i = 0; i < namelen && isdigit(pname[i]); ++i)
381 if ((pid = pid * 10 + pname[i] - '0') > PID_MAX)
382 break;
383 if (i == cnp->cn_namelen)
384 goto got_pnode;
385 }
386
386
387 PFS_RETURN (ENOENT);
388 got_pnode:
389 if (pn != pd->pn_parent && !pn->pn_parent)
390 pn->pn_parent = pd;
391 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
392 PFS_RETURN (ENOENT);
393 error = pfs_vncache_alloc(vn->v_mount, vpp, pn, pid);
394 if (error)

--- 18 unchanged lines hidden (view full) ---

413 int mode = va->a_mode;
414
415 PFS_TRACE(("%s (mode 0x%x)", pn->pn_name, mode));
416
417 /*
418 * check if the file is visible to the caller
419 *
420 * XXX Not sure if this is necessary, as the VFS system calls
387 PFS_RETURN (ENOENT);
388 got_pnode:
389 if (pn != pd->pn_parent && !pn->pn_parent)
390 pn->pn_parent = pd;
391 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
392 PFS_RETURN (ENOENT);
393 error = pfs_vncache_alloc(vn->v_mount, vpp, pn, pid);
394 if (error)

--- 18 unchanged lines hidden (view full) ---

413 int mode = va->a_mode;
414
415 PFS_TRACE(("%s (mode 0x%x)", pn->pn_name, mode));
416
417 /*
418 * check if the file is visible to the caller
419 *
420 * XXX Not sure if this is necessary, as the VFS system calls
421 * XXX pfs_lookup() and pfs_access() first, and pfs_lookup()
422 * XXX calls pfs_visible(). There's a race condition here, but
421 * XXX pfs_lookup() and pfs_access() first, and pfs_lookup()
422 * XXX calls pfs_visible(). There's a race condition here, but
423 * XXX calling pfs_visible() from here doesn't really close it,
424 * XXX and the only consequence of that race is an EIO further
425 * XXX down the line.
426 */
427 if (!pfs_visible(va->a_td, pn, pvd->pvd_pid))
428 PFS_RETURN (ENOENT);
423 * XXX calling pfs_visible() from here doesn't really close it,
424 * XXX and the only consequence of that race is an EIO further
425 * XXX down the line.
426 */
427 if (!pfs_visible(va->a_td, pn, pvd->pvd_pid))
428 PFS_RETURN (ENOENT);
429
429
430 /* check if the requested mode is permitted */
431 if (((mode & FREAD) && !(mode & PFS_RD)) ||
432 ((mode & FWRITE) && !(mode & PFS_WR)))
433 PFS_RETURN (EPERM);
434
435 /* we don't support locking */
436 if ((mode & O_SHLOCK) || (mode & O_EXLOCK))
437 PFS_RETURN (EOPNOTSUPP);
430 /* check if the requested mode is permitted */
431 if (((mode & FREAD) && !(mode & PFS_RD)) ||
432 ((mode & FWRITE) && !(mode & PFS_WR)))
433 PFS_RETURN (EPERM);
434
435 /* we don't support locking */
436 if ((mode & O_SHLOCK) || (mode & O_EXLOCK))
437 PFS_RETURN (EOPNOTSUPP);
438
438
439 PFS_RETURN (0);
440}
441
442/*
443 * Read from a file
444 */
445static int
446pfs_read(struct vop_read_args *va)
447{
448 struct vnode *vn = va->a_vp;
449 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
450 struct pfs_node *pn = pvd->pvd_pn;
451 struct uio *uio = va->a_uio;
452 struct proc *proc = NULL;
453 struct sbuf *sb = NULL;
454 char *ps;
455 int error, xlen;
456
457 PFS_TRACE((pn->pn_name));
439 PFS_RETURN (0);
440}
441
442/*
443 * Read from a file
444 */
445static int
446pfs_read(struct vop_read_args *va)
447{
448 struct vnode *vn = va->a_vp;
449 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
450 struct pfs_node *pn = pvd->pvd_pn;
451 struct uio *uio = va->a_uio;
452 struct proc *proc = NULL;
453 struct sbuf *sb = NULL;
454 char *ps;
455 int error, xlen;
456
457 PFS_TRACE((pn->pn_name));
458
458
459 if (vn->v_type != VREG)
460 PFS_RETURN (EINVAL);
461
462 if (!(pn->pn_flags & PFS_RD))
463 PFS_RETURN (EBADF);
464
465 if (pn->pn_func == NULL)
466 PFS_RETURN (EIO);
459 if (vn->v_type != VREG)
460 PFS_RETURN (EINVAL);
461
462 if (!(pn->pn_flags & PFS_RD))
463 PFS_RETURN (EBADF);
464
465 if (pn->pn_func == NULL)
466 PFS_RETURN (EIO);
467
467
468 /*
469 * This is necessary because either process' privileges may
470 * have changed since the open() call.
471 */
472 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
473 PFS_RETURN (EIO);
468 /*
469 * This is necessary because either process' privileges may
470 * have changed since the open() call.
471 */
472 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
473 PFS_RETURN (EIO);
474
474
475 /* XXX duplicates bits of pfs_visible() */
476 if (pvd->pvd_pid != NO_PID) {
477 if ((proc = pfind(pvd->pvd_pid)) == NULL)
478 PFS_RETURN (EIO);
479 _PHOLD(proc);
480 PROC_UNLOCK(proc);
481 }
482
483 if (pn->pn_flags & PFS_RAWRD) {
484 error = (pn->pn_func)(curthread, proc, pn, NULL, uio);
485 if (proc != NULL)
486 PRELE(proc);
487 PFS_RETURN (error);
488 }
475 /* XXX duplicates bits of pfs_visible() */
476 if (pvd->pvd_pid != NO_PID) {
477 if ((proc = pfind(pvd->pvd_pid)) == NULL)
478 PFS_RETURN (EIO);
479 _PHOLD(proc);
480 PROC_UNLOCK(proc);
481 }
482
483 if (pn->pn_flags & PFS_RAWRD) {
484 error = (pn->pn_func)(curthread, proc, pn, NULL, uio);
485 if (proc != NULL)
486 PRELE(proc);
487 PFS_RETURN (error);
488 }
489
489
490 sb = sbuf_new(sb, NULL, uio->uio_offset + uio->uio_resid, 0);
491 if (sb == NULL) {
492 if (proc != NULL)
493 PRELE(proc);
494 PFS_RETURN (EIO);
495 }
496
497 error = (pn->pn_func)(curthread, proc, pn, sb, uio);
498
499 if (proc != NULL)
500 PRELE(proc);
501
502 if (error) {
503 sbuf_delete(sb);
504 PFS_RETURN (error);
505 }
490 sb = sbuf_new(sb, NULL, uio->uio_offset + uio->uio_resid, 0);
491 if (sb == NULL) {
492 if (proc != NULL)
493 PRELE(proc);
494 PFS_RETURN (EIO);
495 }
496
497 error = (pn->pn_func)(curthread, proc, pn, sb, uio);
498
499 if (proc != NULL)
500 PRELE(proc);
501
502 if (error) {
503 sbuf_delete(sb);
504 PFS_RETURN (error);
505 }
506
506
507 /* XXX we should possibly detect and handle overflows */
508 sbuf_finish(sb);
509 ps = sbuf_data(sb) + uio->uio_offset;
510 xlen = sbuf_len(sb) - uio->uio_offset;
511 xlen = imin(xlen, uio->uio_resid);
512 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
513 sbuf_delete(sb);
514 PFS_RETURN (error);
515}
516
517/*
518 * Iterate through directory entries
519 */
520static int
521pfs_iterate(struct thread *td, pid_t pid, struct pfs_node *pd,
507 /* XXX we should possibly detect and handle overflows */
508 sbuf_finish(sb);
509 ps = sbuf_data(sb) + uio->uio_offset;
510 xlen = sbuf_len(sb) - uio->uio_offset;
511 xlen = imin(xlen, uio->uio_resid);
512 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
513 sbuf_delete(sb);
514 PFS_RETURN (error);
515}
516
517/*
518 * Iterate through directory entries
519 */
520static int
521pfs_iterate(struct thread *td, pid_t pid, struct pfs_node *pd,
522 struct pfs_node **pn, struct proc **p)
522 struct pfs_node **pn, struct proc **p)
523{
524 if ((*pn) == NULL)
525 *pn = pd->pn_nodes;
526 else
527 again:
528 if ((*pn)->pn_type != pfstype_procdir)
529 *pn = (*pn)->pn_next;
523{
524 if ((*pn) == NULL)
525 *pn = pd->pn_nodes;
526 else
527 again:
528 if ((*pn)->pn_type != pfstype_procdir)
529 *pn = (*pn)->pn_next;
530
530
531 while (*pn != NULL && (*pn)->pn_type == pfstype_procdir) {
532 if (*p == NULL)
533 *p = LIST_FIRST(&allproc);
534 else
535 *p = LIST_NEXT(*p, p_list);
536 if (*p != NULL)
537 break;
538 *pn = (*pn)->pn_next;
539 }
531 while (*pn != NULL && (*pn)->pn_type == pfstype_procdir) {
532 if (*p == NULL)
533 *p = LIST_FIRST(&allproc);
534 else
535 *p = LIST_NEXT(*p, p_list);
536 if (*p != NULL)
537 break;
538 *pn = (*pn)->pn_next;
539 }
540
540
541 if ((*pn) == NULL)
542 return (-1);
543
544 if (!pfs_visible(td, *pn, *p ? (*p)->p_pid : pid))
545 goto again;
541 if ((*pn) == NULL)
542 return (-1);
543
544 if (!pfs_visible(td, *pn, *p ? (*p)->p_pid : pid))
545 goto again;
546
546
547 return (0);
548}
549
550/*
551 * Return directory entries.
552 */
553static int
554pfs_readdir(struct vop_readdir_args *va)

--- 6 unchanged lines hidden (view full) ---

561 struct pfs_node *pn;
562 struct dirent entry;
563 struct uio *uio;
564 struct proc *p;
565 off_t offset;
566 int error, i, resid;
567
568 PFS_TRACE((pd->pn_name));
547 return (0);
548}
549
550/*
551 * Return directory entries.
552 */
553static int
554pfs_readdir(struct vop_readdir_args *va)

--- 6 unchanged lines hidden (view full) ---

561 struct pfs_node *pn;
562 struct dirent entry;
563 struct uio *uio;
564 struct proc *p;
565 off_t offset;
566 int error, i, resid;
567
568 PFS_TRACE((pd->pn_name));
569
569
570 if (vn->v_type != VDIR)
571 PFS_RETURN (ENOTDIR);
572 uio = va->a_uio;
573
574 /* check if the directory is visible to the caller */
575 if (!pfs_visible(curthread, pd, pid))
576 PFS_RETURN (ENOENT);
570 if (vn->v_type != VDIR)
571 PFS_RETURN (ENOTDIR);
572 uio = va->a_uio;
573
574 /* check if the directory is visible to the caller */
575 if (!pfs_visible(curthread, pd, pid))
576 PFS_RETURN (ENOENT);
577
577
578 /* only allow reading entire entries */
579 offset = uio->uio_offset;
580 resid = uio->uio_resid;
581 if (offset < 0 || offset % PFS_DELEN != 0 || resid < PFS_DELEN)
582 PFS_RETURN (EINVAL);
583
584 /* skip unwanted entries */
585 sx_slock(&allproc_lock);
586 for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN)
587 if (pfs_iterate(curthread, pid, pd, &pn, &p) == -1) {
588 /* nothing left... */
589 sx_sunlock(&allproc_lock);
590 PFS_RETURN (0);
591 }
578 /* only allow reading entire entries */
579 offset = uio->uio_offset;
580 resid = uio->uio_resid;
581 if (offset < 0 || offset % PFS_DELEN != 0 || resid < PFS_DELEN)
582 PFS_RETURN (EINVAL);
583
584 /* skip unwanted entries */
585 sx_slock(&allproc_lock);
586 for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN)
587 if (pfs_iterate(curthread, pid, pd, &pn, &p) == -1) {
588 /* nothing left... */
589 sx_sunlock(&allproc_lock);
590 PFS_RETURN (0);
591 }
592
592
593 /* fill in entries */
594 entry.d_reclen = PFS_DELEN;
595 while (pfs_iterate(curthread, pid, pd, &pn, &p) != -1 && resid > 0) {
596 if (!pn->pn_parent)
597 pn->pn_parent = pd;
598 if (!pn->pn_fileno)
599 pfs_fileno_alloc(pi, pn);
600 if (pid != NO_PID)

--- 54 unchanged lines hidden (view full) ---

655 struct pfs_node *pn = pvd->pvd_pn;
656 struct uio *uio = va->a_uio;
657 struct proc *proc = NULL;
658 char buf[MAXPATHLEN], *ps;
659 struct sbuf sb;
660 int error, xlen;
661
662 PFS_TRACE((pn->pn_name));
593 /* fill in entries */
594 entry.d_reclen = PFS_DELEN;
595 while (pfs_iterate(curthread, pid, pd, &pn, &p) != -1 && resid > 0) {
596 if (!pn->pn_parent)
597 pn->pn_parent = pd;
598 if (!pn->pn_fileno)
599 pfs_fileno_alloc(pi, pn);
600 if (pid != NO_PID)

--- 54 unchanged lines hidden (view full) ---

655 struct pfs_node *pn = pvd->pvd_pn;
656 struct uio *uio = va->a_uio;
657 struct proc *proc = NULL;
658 char buf[MAXPATHLEN], *ps;
659 struct sbuf sb;
660 int error, xlen;
661
662 PFS_TRACE((pn->pn_name));
663
663
664 if (vn->v_type != VLNK)
665 PFS_RETURN (EINVAL);
666
667 if (pn->pn_func == NULL)
668 PFS_RETURN (EIO);
664 if (vn->v_type != VLNK)
665 PFS_RETURN (EINVAL);
666
667 if (pn->pn_func == NULL)
668 PFS_RETURN (EIO);
669
669
670 if (pvd->pvd_pid != NO_PID) {
671 if ((proc = pfind(pvd->pvd_pid)) == NULL)
672 PFS_RETURN (EIO);
673 _PHOLD(proc);
674 PROC_UNLOCK(proc);
675 }
670 if (pvd->pvd_pid != NO_PID) {
671 if ((proc = pfind(pvd->pvd_pid)) == NULL)
672 PFS_RETURN (EIO);
673 _PHOLD(proc);
674 PROC_UNLOCK(proc);
675 }
676
676
677 /* sbuf_new() can't fail with a static buffer */
678 sbuf_new(&sb, buf, sizeof buf, 0);
679
680 error = (pn->pn_func)(curthread, proc, pn, &sb, NULL);
681
682 if (proc != NULL)
683 PRELE(proc);
677 /* sbuf_new() can't fail with a static buffer */
678 sbuf_new(&sb, buf, sizeof buf, 0);
679
680 error = (pn->pn_func)(curthread, proc, pn, &sb, NULL);
681
682 if (proc != NULL)
683 PRELE(proc);
684
684
685 if (error) {
686 sbuf_delete(&sb);
687 PFS_RETURN (error);
688 }
685 if (error) {
686 sbuf_delete(&sb);
687 PFS_RETURN (error);
688 }
689
689
690 /* XXX we should detect and handle overflows */
691 sbuf_finish(&sb);
692 ps = sbuf_data(&sb) + uio->uio_offset;
693 xlen = sbuf_len(&sb) - uio->uio_offset;
694 xlen = imin(xlen, uio->uio_resid);
695 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
696 sbuf_delete(&sb);
697 PFS_RETURN (error);

--- 31 unchanged lines hidden (view full) ---

729 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
730 struct pfs_node *pn = pvd->pvd_pn;
731 struct uio *uio = va->a_uio;
732 struct proc *proc = NULL;
733 struct sbuf sb;
734 int error;
735
736 PFS_TRACE((pn->pn_name));
690 /* XXX we should detect and handle overflows */
691 sbuf_finish(&sb);
692 ps = sbuf_data(&sb) + uio->uio_offset;
693 xlen = sbuf_len(&sb) - uio->uio_offset;
694 xlen = imin(xlen, uio->uio_resid);
695 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
696 sbuf_delete(&sb);
697 PFS_RETURN (error);

--- 31 unchanged lines hidden (view full) ---

729 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
730 struct pfs_node *pn = pvd->pvd_pn;
731 struct uio *uio = va->a_uio;
732 struct proc *proc = NULL;
733 struct sbuf sb;
734 int error;
735
736 PFS_TRACE((pn->pn_name));
737
737
738 if (vn->v_type != VREG)
739 PFS_RETURN (EINVAL);
740
741 if (!(pn->pn_flags & PFS_WR))
742 PFS_RETURN (EBADF);
743
744 if (pn->pn_func == NULL)
745 PFS_RETURN (EIO);
738 if (vn->v_type != VREG)
739 PFS_RETURN (EINVAL);
740
741 if (!(pn->pn_flags & PFS_WR))
742 PFS_RETURN (EBADF);
743
744 if (pn->pn_func == NULL)
745 PFS_RETURN (EIO);
746
746
747 /*
748 * This is necessary because either process' privileges may
749 * have changed since the open() call.
750 */
751 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
752 PFS_RETURN (EIO);
753
754 /* XXX duplicates bits of pfs_visible() */

--- 9 unchanged lines hidden (view full) ---

764 if (proc != NULL)
765 PRELE(proc);
766 PFS_RETURN (error);
767 }
768
769 sbuf_uionew(&sb, uio, &error);
770 if (error)
771 PFS_RETURN (error);
747 /*
748 * This is necessary because either process' privileges may
749 * have changed since the open() call.
750 */
751 if (!pfs_visible(curthread, pn, pvd->pvd_pid))
752 PFS_RETURN (EIO);
753
754 /* XXX duplicates bits of pfs_visible() */

--- 9 unchanged lines hidden (view full) ---

764 if (proc != NULL)
765 PRELE(proc);
766 PFS_RETURN (error);
767 }
768
769 sbuf_uionew(&sb, uio, &error);
770 if (error)
771 PFS_RETURN (error);
772
772
773 error = (pn->pn_func)(curthread, proc, pn, &sb, uio);
774
775 if (proc != NULL)
776 PRELE(proc);
773 error = (pn->pn_func)(curthread, proc, pn, &sb, uio);
774
775 if (proc != NULL)
776 PRELE(proc);
777
777
778 sbuf_delete(&sb);
779 PFS_RETURN (error);
780}
781
782/*
783 * Vnode operations
784 */
785vop_t **pfs_vnodeop_p;

--- 31 unchanged lines hidden ---
778 sbuf_delete(&sb);
779 PFS_RETURN (error);
780}
781
782/*
783 * Vnode operations
784 */
785vop_t **pfs_vnodeop_p;

--- 31 unchanged lines hidden ---