Annotation of src/sys/compat/netbsd32/netbsd32_fs.c, Revision 1.36.2.2
1.36.2.2! ad 1: /* $NetBSD: netbsd32_fs.c,v 1.36.2.1 2007/03/13 16:50:19 ad Exp $ */
1.1 mrg 2:
3: /*
4: * Copyright (c) 1998, 2001 Matthew R. Green
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. The name of the author may not be used to endorse or promote products
16: * derived from this software without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28: * SUCH DAMAGE.
29: */
1.7 lukem 30:
31: #include <sys/cdefs.h>
1.36.2.2! ad 32: __KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.36.2.1 2007/03/13 16:50:19 ad Exp $");
1.1 mrg 33:
1.5 mrg 34: #if defined(_KERNEL_OPT)
1.1 mrg 35: #include "opt_ktrace.h"
36: #endif
37:
38: #include <sys/param.h>
39: #include <sys/systm.h>
40: #include <sys/malloc.h>
41: #include <sys/mount.h>
42: #include <sys/socket.h>
43: #include <sys/socketvar.h>
44: #include <sys/stat.h>
45: #include <sys/time.h>
46: #include <sys/ktrace.h>
47: #include <sys/resourcevar.h>
48: #include <sys/vnode.h>
49: #include <sys/file.h>
50: #include <sys/filedesc.h>
51: #include <sys/namei.h>
1.18 cube 52: #include <sys/statvfs.h>
1.1 mrg 53: #include <sys/syscallargs.h>
54: #include <sys/proc.h>
1.22 christos 55: #include <sys/dirent.h>
1.27 elad 56: #include <sys/kauth.h>
1.36.2.1 ad 57: #include <sys/vfs_syscalls.h>
1.1 mrg 58:
59: #include <compat/netbsd32/netbsd32.h>
60: #include <compat/netbsd32/netbsd32_syscallargs.h>
61: #include <compat/netbsd32/netbsd32_conv.h>
1.28 martin 62: #include <compat/sys/mount.h>
1.1 mrg 63:
64:
1.23 christos 65: static int dofilereadv32 __P((struct lwp *, int, struct file *, struct netbsd32_iovec *,
1.1 mrg 66: int, off_t *, int, register_t *));
1.23 christos 67: static int dofilewritev32 __P((struct lwp *, int, struct file *, struct netbsd32_iovec *,
1.1 mrg 68: int, off_t *, int, register_t *));
1.23 christos 69: static int change_utimes32 __P((struct vnode *, netbsd32_timevalp_t, struct lwp *));
1.1 mrg 70:
71: int
1.11 thorpej 72: netbsd32_readv(l, v, retval)
73: struct lwp *l;
1.1 mrg 74: void *v;
75: register_t *retval;
76: {
77: struct netbsd32_readv_args /* {
78: syscallarg(int) fd;
79: syscallarg(const netbsd32_iovecp_t) iovp;
80: syscallarg(int) iovcnt;
81: } */ *uap = v;
82: int fd = SCARG(uap, fd);
1.11 thorpej 83: struct proc *p = l->l_proc;
1.1 mrg 84: struct file *fp;
85: struct filedesc *fdp = p->p_fd;
86:
1.6 thorpej 87: if ((fp = fd_getfile(fdp, fd)) == NULL)
88: return (EBADF);
89:
90: if ((fp->f_flag & FREAD) == 0)
1.1 mrg 91: return (EBADF);
92:
1.9 jdolecek 93: FILE_USE(fp);
94:
1.23 christos 95: return (dofilereadv32(l, fd, fp,
1.19 perry 96: (struct netbsd32_iovec *)NETBSD32PTR64(SCARG(uap, iovp)),
1.10 scw 97: SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval));
1.1 mrg 98: }
99:
100: /* Damn thing copies in the iovec! */
101: int
1.23 christos 102: dofilereadv32(l, fd, fp, iovp, iovcnt, offset, flags, retval)
103: struct lwp *l;
1.1 mrg 104: int fd;
105: struct file *fp;
106: struct netbsd32_iovec *iovp;
107: int iovcnt;
108: off_t *offset;
109: int flags;
110: register_t *retval;
111: {
112: struct uio auio;
113: struct iovec *iov;
114: struct iovec *needfree;
115: struct iovec aiov[UIO_SMALLIOV];
116: long i, cnt, error = 0;
117: u_int iovlen;
118: #ifdef KTRACE
119: struct iovec *ktriov = NULL;
120: #endif
121:
122: /* note: can't use iovlen until iovcnt is validated */
123: iovlen = iovcnt * sizeof(struct iovec);
124: if ((u_int)iovcnt > UIO_SMALLIOV) {
1.9 jdolecek 125: if ((u_int)iovcnt > IOV_MAX) {
126: error = EINVAL;
127: goto out;
128: }
129: iov = malloc(iovlen, M_IOV, M_WAITOK);
1.1 mrg 130: needfree = iov;
131: } else if ((u_int)iovcnt > 0) {
132: iov = aiov;
133: needfree = NULL;
1.9 jdolecek 134: } else {
135: error = EINVAL;
136: goto out;
137: }
1.1 mrg 138:
139: auio.uio_iov = iov;
140: auio.uio_iovcnt = iovcnt;
141: auio.uio_rw = UIO_READ;
1.24 yamt 142: auio.uio_vmspace = l->l_proc->p_vmspace;
1.1 mrg 143: error = netbsd32_to_iovecin(iovp, iov, iovcnt);
144: if (error)
145: goto done;
146: auio.uio_resid = 0;
147: for (i = 0; i < iovcnt; i++) {
148: auio.uio_resid += iov->iov_len;
149: /*
150: * Reads return ssize_t because -1 is returned on error.
151: * Therefore we must restrict the length to SSIZE_MAX to
152: * avoid garbage return values.
153: */
154: if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
155: error = EINVAL;
156: goto done;
157: }
158: iov++;
159: }
160: #ifdef KTRACE
161: /*
162: * if tracing, save a copy of iovec
163: */
1.23 christos 164: if (KTRPOINT(l->l_proc, KTR_GENIO)) {
1.9 jdolecek 165: ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
1.36 christos 166: memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
1.1 mrg 167: }
168: #endif
169: cnt = auio.uio_resid;
170: error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred, flags);
171: if (error)
172: if (auio.uio_resid != cnt && (error == ERESTART ||
173: error == EINTR || error == EWOULDBLOCK))
174: error = 0;
175: cnt -= auio.uio_resid;
176: #ifdef KTRACE
1.23 christos 177: if (KTRPOINT(l->l_proc, KTR_GENIO))
1.1 mrg 178: if (error == 0) {
1.23 christos 179: ktrgenio(l, fd, UIO_READ, ktriov, cnt,
1.1 mrg 180: error);
1.9 jdolecek 181: free(ktriov, M_TEMP);
1.1 mrg 182: }
183: #endif
184: *retval = cnt;
185: done:
186: if (needfree)
1.9 jdolecek 187: free(needfree, M_IOV);
188: out:
1.23 christos 189: FILE_UNUSE(fp, l);
1.1 mrg 190: return (error);
191: }
192:
193: int
1.11 thorpej 194: netbsd32_writev(l, v, retval)
195: struct lwp *l;
1.1 mrg 196: void *v;
197: register_t *retval;
198: {
199: struct netbsd32_writev_args /* {
200: syscallarg(int) fd;
201: syscallarg(const netbsd32_iovecp_t) iovp;
202: syscallarg(int) iovcnt;
203: } */ *uap = v;
204: int fd = SCARG(uap, fd);
205: struct file *fp;
1.11 thorpej 206: struct proc *p = l->l_proc;
1.1 mrg 207: struct filedesc *fdp = p->p_fd;
208:
1.6 thorpej 209: if ((fp = fd_getfile(fdp, fd)) == NULL)
210: return (EBADF);
211:
212: if ((fp->f_flag & FWRITE) == 0)
1.1 mrg 213: return (EBADF);
214:
1.9 jdolecek 215: FILE_USE(fp);
216:
1.23 christos 217: return (dofilewritev32(l, fd, fp,
1.10 scw 218: (struct netbsd32_iovec *)NETBSD32PTR64(SCARG(uap, iovp)),
219: SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval));
1.1 mrg 220: }
221:
222: int
1.23 christos 223: dofilewritev32(l, fd, fp, iovp, iovcnt, offset, flags, retval)
224: struct lwp *l;
1.1 mrg 225: int fd;
226: struct file *fp;
227: struct netbsd32_iovec *iovp;
228: int iovcnt;
229: off_t *offset;
230: int flags;
231: register_t *retval;
232: {
233: struct uio auio;
234: struct iovec *iov;
235: struct iovec *needfree;
236: struct iovec aiov[UIO_SMALLIOV];
1.23 christos 237: struct proc *p = l->l_proc;
1.1 mrg 238: long i, cnt, error = 0;
239: u_int iovlen;
240: #ifdef KTRACE
241: struct iovec *ktriov = NULL;
242: #endif
243:
244: /* note: can't use iovlen until iovcnt is validated */
245: iovlen = iovcnt * sizeof(struct iovec);
246: if ((u_int)iovcnt > UIO_SMALLIOV) {
1.9 jdolecek 247: if ((u_int)iovcnt > IOV_MAX) {
248: error = EINVAL;
249: goto out;
250: }
251: iov = malloc(iovlen, M_IOV, M_WAITOK);
1.1 mrg 252: needfree = iov;
253: } else if ((u_int)iovcnt > 0) {
254: iov = aiov;
255: needfree = NULL;
1.9 jdolecek 256: } else {
257: error = EINVAL;
258: goto out;
259: }
1.1 mrg 260:
261: auio.uio_iov = iov;
262: auio.uio_iovcnt = iovcnt;
263: auio.uio_rw = UIO_WRITE;
1.24 yamt 264: auio.uio_vmspace = l->l_proc->p_vmspace;
1.1 mrg 265: error = netbsd32_to_iovecin(iovp, iov, iovcnt);
266: if (error)
267: goto done;
268: auio.uio_resid = 0;
269: for (i = 0; i < iovcnt; i++) {
270: auio.uio_resid += iov->iov_len;
271: /*
272: * Writes return ssize_t because -1 is returned on error.
273: * Therefore we must restrict the length to SSIZE_MAX to
274: * avoid garbage return values.
275: */
276: if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
277: error = EINVAL;
278: goto done;
279: }
280: iov++;
281: }
282: #ifdef KTRACE
283: /*
284: * if tracing, save a copy of iovec
285: */
1.14 fvdl 286: if (KTRPOINT(p, KTR_GENIO)) {
1.9 jdolecek 287: ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
1.36 christos 288: memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
1.1 mrg 289: }
290: #endif
291: cnt = auio.uio_resid;
292: error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred, flags);
293: if (error) {
294: if (auio.uio_resid != cnt && (error == ERESTART ||
295: error == EINTR || error == EWOULDBLOCK))
296: error = 0;
297: if (error == EPIPE)
1.14 fvdl 298: psignal(p, SIGPIPE);
1.1 mrg 299: }
300: cnt -= auio.uio_resid;
301: #ifdef KTRACE
1.14 fvdl 302: if (KTRPOINT(p, KTR_GENIO))
1.1 mrg 303: if (error == 0) {
1.23 christos 304: ktrgenio(l, fd, UIO_WRITE, ktriov, cnt,
1.1 mrg 305: error);
1.9 jdolecek 306: free(ktriov, M_TEMP);
1.1 mrg 307: }
308: #endif
309: *retval = cnt;
310: done:
311: if (needfree)
1.9 jdolecek 312: free(needfree, M_IOV);
313: out:
1.23 christos 314: FILE_UNUSE(fp, l);
1.1 mrg 315: return (error);
316: }
317:
318: int
1.11 thorpej 319: netbsd32_utimes(l, v, retval)
320: struct lwp *l;
1.1 mrg 321: void *v;
322: register_t *retval;
323: {
324: struct netbsd32_utimes_args /* {
325: syscallarg(const netbsd32_charp) path;
326: syscallarg(const netbsd32_timevalp_t) tptr;
327: } */ *uap = v;
328: int error;
329: struct nameidata nd;
330:
1.10 scw 331: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE,
1.23 christos 332: (char *)NETBSD32PTR64(SCARG(uap, path)), l);
1.1 mrg 333: if ((error = namei(&nd)) != 0)
334: return (error);
335:
1.23 christos 336: error = change_utimes32(nd.ni_vp, SCARG(uap, tptr), l);
1.1 mrg 337:
338: vrele(nd.ni_vp);
339: return (error);
340: }
341:
342: /*
343: * Common routine to set access and modification times given a vnode.
344: */
345: static int
1.23 christos 346: change_utimes32(vp, tptr, l)
1.1 mrg 347: struct vnode *vp;
348: netbsd32_timevalp_t tptr;
1.23 christos 349: struct lwp *l;
1.1 mrg 350: {
351: struct netbsd32_timeval tv32[2];
352: struct timeval tv[2];
353: struct vattr vattr;
354: int error;
355:
356: VATTR_NULL(&vattr);
1.15 fvdl 357: if (tptr == 0) {
1.1 mrg 358: microtime(&tv[0]);
359: tv[1] = tv[0];
360: vattr.va_vaflags |= VA_UTIMES_NULL;
361: } else {
1.36 christos 362: error = copyin((void *)NETBSD32PTR64(tptr), tv32,
1.10 scw 363: sizeof(tv32));
1.1 mrg 364: if (error)
365: return (error);
366: netbsd32_to_timeval(&tv32[0], &tv[0]);
367: netbsd32_to_timeval(&tv32[1], &tv[1]);
368: }
1.31 ad 369: VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
1.1 mrg 370: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
371: vattr.va_atime.tv_sec = tv[0].tv_sec;
372: vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
373: vattr.va_mtime.tv_sec = tv[1].tv_sec;
374: vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
1.31 ad 375: error = VOP_SETATTR(vp, &vattr, l->l_cred, l);
1.1 mrg 376: VOP_UNLOCK(vp, 0);
377: return (error);
378: }
379:
380: int
1.18 cube 381: netbsd32_statvfs1(l, v, retval)
1.11 thorpej 382: struct lwp *l;
1.1 mrg 383: void *v;
384: register_t *retval;
385: {
1.18 cube 386: struct netbsd32_statvfs1_args /* {
1.1 mrg 387: syscallarg(const netbsd32_charp) path;
1.18 cube 388: syscallarg(netbsd32_statvfsp_t) buf;
389: syscallarg(int) flags;
1.1 mrg 390: } */ *uap = v;
391: struct mount *mp;
1.18 cube 392: struct statvfs *sbuf;
393: struct netbsd32_statvfs *s32;
394: struct nameidata nd;
1.1 mrg 395: int error;
396:
1.10 scw 397: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE,
1.23 christos 398: (char *)NETBSD32PTR64(SCARG(uap, path)), l);
1.1 mrg 399: if ((error = namei(&nd)) != 0)
400: return (error);
1.18 cube 401: /* Allocating on the stack would blow it up */
402: sbuf = (struct statvfs *)malloc(sizeof(struct statvfs), M_TEMP,
403: M_WAITOK);
1.1 mrg 404: mp = nd.ni_vp->v_mount;
405: vrele(nd.ni_vp);
1.23 christos 406: if ((error = dostatvfs(mp, sbuf, l, SCARG(uap, flags), 1)) != 0)
1.18 cube 407: goto out;
408: s32 = (struct netbsd32_statvfs *)
409: malloc(sizeof(struct netbsd32_statvfs), M_TEMP, M_WAITOK);
410: netbsd32_from_statvfs(sbuf, s32);
1.36 christos 411: error = copyout(s32, (void *)NETBSD32PTR64(SCARG(uap, buf)),
1.18 cube 412: sizeof(struct netbsd32_statvfs));
413: free(s32, M_TEMP);
414: out:
415: free(sbuf, M_TEMP);
416: return (error);
1.1 mrg 417: }
418:
419: int
1.18 cube 420: netbsd32_fstatvfs1(l, v, retval)
1.11 thorpej 421: struct lwp *l;
1.1 mrg 422: void *v;
423: register_t *retval;
424: {
1.18 cube 425: struct netbsd32_fstatvfs1_args /* {
1.1 mrg 426: syscallarg(int) fd;
1.18 cube 427: syscallarg(netbsd32_statvfsp_t) buf;
428: syscallarg(int) flags;
1.1 mrg 429: } */ *uap = v;
1.18 cube 430: struct proc *p = l->l_proc;
1.1 mrg 431: struct file *fp;
432: struct mount *mp;
1.18 cube 433: struct statvfs *sbuf;
434: struct netbsd32_statvfs *s32;
1.1 mrg 435: int error;
436:
437: /* getvnode() will use the descriptor for us */
1.14 fvdl 438: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.1 mrg 439: return (error);
440: mp = ((struct vnode *)fp->f_data)->v_mount;
1.18 cube 441: sbuf = (struct statvfs *)malloc(sizeof(struct statvfs), M_TEMP,
442: M_WAITOK);
1.23 christos 443: if ((error = dostatvfs(mp, sbuf, l, SCARG(uap, flags), 1)) != 0)
1.1 mrg 444: goto out;
1.18 cube 445: s32 = (struct netbsd32_statvfs *)
446: malloc(sizeof(struct netbsd32_statvfs), M_TEMP, M_WAITOK);
447: netbsd32_from_statvfs(sbuf, s32);
1.36 christos 448: error = copyout(s32, (void *)NETBSD32PTR64(SCARG(uap, buf)),
1.18 cube 449: sizeof(struct netbsd32_statvfs));
450: free(s32, M_TEMP);
1.1 mrg 451: out:
1.18 cube 452: free(sbuf, M_TEMP);
1.23 christos 453: FILE_UNUSE(fp, l);
1.18 cube 454: return error;
455: }
456:
457: int
458: netbsd32_getvfsstat(l, v, retval)
459: struct lwp *l;
460: void *v;
461: register_t *retval;
462: {
463: struct netbsd32_getvfsstat_args /* {
464: syscallarg(netbsd32_statvfsp_t) buf;
465: syscallarg(netbsd32_size_t) bufsize;
466: syscallarg(int) flags;
467: } */ *uap = v;
468: int root = 0;
469: struct proc *p = l->l_proc;
470: struct mount *mp, *nmp;
471: struct statvfs *sbuf;
472: struct netbsd32_statvfs *sfsp;
473: struct netbsd32_statvfs *s32;
474: size_t count, maxcount;
475: int error = 0;
476:
477: maxcount = SCARG(uap, bufsize) / sizeof(struct netbsd32_statvfs);
478: sfsp = (struct netbsd32_statvfs *)NETBSD32PTR64(SCARG(uap, buf));
479: sbuf = (struct statvfs *)malloc(sizeof(struct statvfs), M_TEMP,
480: M_WAITOK);
481: s32 = (struct netbsd32_statvfs *)
482: malloc(sizeof(struct netbsd32_statvfs), M_TEMP, M_WAITOK);
1.36.2.2! ad 483: mutex_enter(&mountlist_lock);
1.25 cube 484: count = 0;
1.18 cube 485: for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
486: mp = nmp) {
1.36.2.2! ad 487: if (vfs_busy(mp, LK_NOWAIT, &mountlist_lock)) {
1.18 cube 488: nmp = CIRCLEQ_NEXT(mp, mnt_list);
489: continue;
490: }
491: if (sfsp && count < maxcount) {
1.23 christos 492: error = dostatvfs(mp, sbuf, l, SCARG(uap, flags), 0);
1.18 cube 493: if (error) {
1.36.2.2! ad 494: mutex_enter(&mountlist_lock);
1.18 cube 495: nmp = CIRCLEQ_NEXT(mp, mnt_list);
496: vfs_unbusy(mp);
497: continue;
498: }
499: netbsd32_from_statvfs(sbuf, s32);
500: error = copyout(s32, sfsp, sizeof(*sfsp));
501: if (error) {
502: vfs_unbusy(mp);
503: goto out;
504: }
505: sfsp++;
506: root |= strcmp(sbuf->f_mntonname, "/") == 0;
507: }
508: count++;
1.36.2.2! ad 509: mutex_enter(&mountlist_lock);
1.18 cube 510: nmp = CIRCLEQ_NEXT(mp, mnt_list);
511: vfs_unbusy(mp);
512: }
1.36.2.2! ad 513: mutex_exit(&mountlist_lock);
1.18 cube 514: if (root == 0 && p->p_cwdi->cwdi_rdir) {
515: /*
516: * fake a root entry
517: */
1.23 christos 518: if ((error = dostatvfs(p->p_cwdi->cwdi_rdir->v_mount, sbuf, l,
1.18 cube 519: SCARG(uap, flags), 1)) != 0)
520: goto out;
521: if (sfsp) {
522: netbsd32_from_statvfs(sbuf, s32);
523: error = copyout(s32, sfsp, sizeof(*sfsp));
524: }
525: count++;
526: }
527: if (sfsp && count > maxcount)
528: *retval = maxcount;
529: else
530: *retval = count;
531:
532: out:
533: free(s32, M_TEMP);
534: free(sbuf, M_TEMP);
535: return (error);
536: }
537:
538: int
1.32 martin 539: netbsd32___fhstatvfs140(l, v, retval)
1.18 cube 540: struct lwp *l;
541: void *v;
542: register_t *retval;
543: {
1.32 martin 544: struct netbsd32___fhstatvfs140_args /* {
545: syscallarg(const netbsd32_pointer_t) fhp;
546: syscallarg(netbsd32_size_t) fh_size;
1.18 cube 547: syscallarg(netbsd32_statvfsp_t) buf;
548: syscallarg(int) flags;
549: } */ *uap = v;
550: struct statvfs *sbuf;
551: struct netbsd32_statvfs *s32;
1.29 martin 552: fhandle_t *fh;
1.18 cube 553: struct vnode *vp;
554: int error;
555:
556: /*
557: * Must be super user
558: */
1.34 elad 559: if ((error = kauth_authorize_system(l->l_cred,
560: KAUTH_SYSTEM_FILEHANDLE, 0, NULL, NULL, NULL)) != 0)
1.18 cube 561: return error;
562:
1.33 yamt 563: if ((error = vfs_copyinfh_alloc(NETBSD32PTR64(SCARG(uap, fhp)),
1.32 martin 564: SCARG(uap, fh_size), &fh)) != 0)
1.29 martin 565: goto bad;
566: if ((error = vfs_fhtovp(fh, &vp)) != 0)
567: goto bad;
1.18 cube 568:
569: sbuf = (struct statvfs *)malloc(sizeof(struct statvfs), M_TEMP,
570: M_WAITOK);
1.29 martin 571: error = dostatvfs(vp->v_mount, sbuf, l, SCARG(uap, flags), 1);
572: vput(vp);
573: if (error != 0)
1.18 cube 574: goto out;
575:
576: s32 = (struct netbsd32_statvfs *)
577: malloc(sizeof(struct netbsd32_statvfs), M_TEMP, M_WAITOK);
578: netbsd32_from_statvfs(sbuf, s32);
1.36 christos 579: error = copyout(s32, (void *)NETBSD32PTR64(SCARG(uap, buf)),
1.18 cube 580: sizeof(struct netbsd32_statvfs));
581: free(s32, M_TEMP);
582:
583: out:
584: free(sbuf, M_TEMP);
1.29 martin 585: bad:
586: vfs_copyinfh_free(fh);
1.1 mrg 587: return (error);
588: }
589:
590: int
1.11 thorpej 591: netbsd32_futimes(l, v, retval)
592: struct lwp *l;
1.1 mrg 593: void *v;
594: register_t *retval;
595: {
596: struct netbsd32_futimes_args /* {
597: syscallarg(int) fd;
598: syscallarg(const netbsd32_timevalp_t) tptr;
599: } */ *uap = v;
600: int error;
601: struct file *fp;
1.14 fvdl 602: struct proc *p = l->l_proc;
1.1 mrg 603:
604: /* getvnode() will use the descriptor for us */
1.14 fvdl 605: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.1 mrg 606: return (error);
607:
1.19 perry 608: error = change_utimes32((struct vnode *)fp->f_data,
1.23 christos 609: SCARG(uap, tptr), l);
610: FILE_UNUSE(fp, l);
1.1 mrg 611: return (error);
612: }
613:
614: int
1.22 christos 615: netbsd32_sys___getdents30(l, v, retval)
1.11 thorpej 616: struct lwp *l;
1.1 mrg 617: void *v;
618: register_t *retval;
619: {
1.22 christos 620: struct netbsd32_sys___getdents30_args /* {
1.1 mrg 621: syscallarg(int) fd;
622: syscallarg(netbsd32_charp) buf;
623: syscallarg(netbsd32_size_t) count;
624: } */ *uap = v;
625: struct file *fp;
626: int error, done;
1.11 thorpej 627: struct proc *p = l->l_proc;
1.1 mrg 628:
629: /* getvnode() will use the descriptor for us */
630: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
631: return (error);
632: if ((fp->f_flag & FREAD) == 0) {
633: error = EBADF;
634: goto out;
635: }
1.36 christos 636: error = vn_readdir(fp, (void *)NETBSD32PTR64(SCARG(uap, buf)),
1.23 christos 637: UIO_USERSPACE, SCARG(uap, count), &done, l, 0, 0);
1.1 mrg 638: *retval = done;
639: out:
1.23 christos 640: FILE_UNUSE(fp, l);
1.1 mrg 641: return (error);
642: }
643:
644: int
1.11 thorpej 645: netbsd32_lutimes(l, v, retval)
646: struct lwp *l;
1.1 mrg 647: void *v;
648: register_t *retval;
649: {
650: struct netbsd32_lutimes_args /* {
651: syscallarg(const netbsd32_charp) path;
652: syscallarg(const netbsd32_timevalp_t) tptr;
653: } */ *uap = v;
654: int error;
655: struct nameidata nd;
656:
1.10 scw 657: NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE,
1.36 christos 658: (void *)NETBSD32PTR64(SCARG(uap, path)), l);
1.1 mrg 659: if ((error = namei(&nd)) != 0)
660: return (error);
661:
1.23 christos 662: error = change_utimes32(nd.ni_vp, SCARG(uap, tptr), l);
1.1 mrg 663:
664: vrele(nd.ni_vp);
665: return (error);
666: }
667:
668: int
1.22 christos 669: netbsd32_sys___stat30(l, v, retval)
1.11 thorpej 670: struct lwp *l;
1.1 mrg 671: void *v;
672: register_t *retval;
673: {
1.22 christos 674: struct netbsd32_sys___stat30_args /* {
1.1 mrg 675: syscallarg(const netbsd32_charp) path;
676: syscallarg(netbsd32_statp_t) ub;
677: } */ *uap = v;
678: struct netbsd32_stat sb32;
679: struct stat sb;
680: int error;
1.36 christos 681: void *sg;
1.1 mrg 682: const char *path;
1.14 fvdl 683: struct proc *p = l->l_proc;
1.1 mrg 684:
1.10 scw 685: path = (char *)NETBSD32PTR64(SCARG(uap, path));
1.14 fvdl 686: sg = stackgap_init(p, 0);
1.23 christos 687: CHECK_ALT_EXIST(l, &sg, path);
1.1 mrg 688:
1.36.2.1 ad 689: error = do_sys_stat(l, path, FOLLOW, &sb);
1.22 christos 690: netbsd32_from___stat30(&sb, &sb32);
1.36 christos 691: error = copyout(&sb32, (void *)NETBSD32PTR64(SCARG(uap, ub)),
1.10 scw 692: sizeof(sb32));
1.1 mrg 693: return (error);
694: }
695:
696: int
1.22 christos 697: netbsd32_sys___fstat30(l, v, retval)
1.11 thorpej 698: struct lwp *l;
1.1 mrg 699: void *v;
700: register_t *retval;
701: {
1.22 christos 702: struct netbsd32_sys___fstat30_args /* {
1.1 mrg 703: syscallarg(int) fd;
704: syscallarg(netbsd32_statp_t) sb;
705: } */ *uap = v;
706: int fd = SCARG(uap, fd);
1.14 fvdl 707: struct proc *p = l->l_proc;
708: struct filedesc *fdp = p->p_fd;
1.1 mrg 709: struct file *fp;
710: struct netbsd32_stat sb32;
711: struct stat ub;
712: int error = 0;
713:
1.6 thorpej 714: if ((fp = fd_getfile(fdp, fd)) == NULL)
1.1 mrg 715: return (EBADF);
716:
1.3 jdolecek 717: FILE_USE(fp);
1.23 christos 718: error = (*fp->f_ops->fo_stat)(fp, &ub, l);
719: FILE_UNUSE(fp, l);
1.3 jdolecek 720:
1.1 mrg 721: if (error == 0) {
1.22 christos 722: netbsd32_from___stat30(&ub, &sb32);
1.36 christos 723: error = copyout(&sb32, (void *)NETBSD32PTR64(SCARG(uap, sb)),
1.10 scw 724: sizeof(sb32));
1.1 mrg 725: }
726: return (error);
727: }
728:
729: int
1.22 christos 730: netbsd32_sys___lstat30(l, v, retval)
1.11 thorpej 731: struct lwp *l;
1.1 mrg 732: void *v;
733: register_t *retval;
734: {
1.22 christos 735: struct netbsd32_sys___lstat30_args /* {
1.1 mrg 736: syscallarg(const netbsd32_charp) path;
737: syscallarg(netbsd32_statp_t) ub;
738: } */ *uap = v;
739: struct netbsd32_stat sb32;
740: struct stat sb;
741: int error;
1.36 christos 742: void *sg;
1.1 mrg 743: const char *path;
1.14 fvdl 744: struct proc *p = l->l_proc;
1.1 mrg 745:
1.10 scw 746: path = (char *)NETBSD32PTR64(SCARG(uap, path));
1.14 fvdl 747: sg = stackgap_init(p, 0);
1.23 christos 748: CHECK_ALT_EXIST(l, &sg, path);
1.1 mrg 749:
1.36.2.1 ad 750: error = do_sys_stat(l, path, NOFOLLOW, &sb);
1.1 mrg 751: if (error)
752: return (error);
1.22 christos 753: netbsd32_from___stat30(&sb, &sb32);
1.36 christos 754: error = copyout(&sb32, (void *)NETBSD32PTR64(SCARG(uap, ub)),
1.10 scw 755: sizeof(sb32));
1.1 mrg 756: return (error);
757: }
758:
1.32 martin 759: int netbsd32___fhstat40(l, v, retval)
1.26 cube 760: struct lwp *l;
761: void *v;
762: register_t *retval;
763: {
1.32 martin 764: struct netbsd32___fhstat40_args /* {
765: syscallarg(const netbsd32_pointer_t) fhp;
766: syscallarg(netbsd32_size_t) fh_size;
1.26 cube 767: syscallarg(netbsd32_statp_t) sb;
768: } */ *uap = v;
769: struct stat sb;
770: struct netbsd32_stat sb32;
771: int error;
1.29 martin 772: fhandle_t *fh;
1.26 cube 773: struct vnode *vp;
774:
775: /*
776: * Must be super user
777: */
1.34 elad 778: if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE,
779: 0, NULL, NULL, NULL)))
1.29 martin 780: return error;
781:
1.33 yamt 782: if ((error = vfs_copyinfh_alloc(NETBSD32PTR64(SCARG(uap, fhp)),
783: SCARG(uap, fh_size), &fh)) != 0)
1.29 martin 784: goto bad;
1.26 cube 785:
1.29 martin 786: if ((error = vfs_fhtovp(fh, &vp)) != 0)
787: goto bad;
1.26 cube 788:
789: error = vn_stat(vp, &sb, l);
790: vput(vp);
791: if (error)
1.29 martin 792: goto bad;
1.26 cube 793: netbsd32_from___stat30(&sb, &sb32);
794: error = copyout(&sb32, NETBSD32PTR64(SCARG(uap, sb)), sizeof(sb));
1.29 martin 795: bad:
796: vfs_copyinfh_free(fh);
797: return error;
1.26 cube 798: }
799:
1.1 mrg 800: int
1.11 thorpej 801: netbsd32_preadv(l, v, retval)
802: struct lwp *l;
1.1 mrg 803: void *v;
804: register_t *retval;
805: {
806: struct netbsd32_preadv_args /* {
807: syscallarg(int) fd;
808: syscallarg(const netbsd32_iovecp_t) iovp;
809: syscallarg(int) iovcnt;
810: syscallarg(int) pad;
811: syscallarg(off_t) offset;
812: } */ *uap = v;
1.14 fvdl 813: struct proc *p = l->l_proc;
814: struct filedesc *fdp = p->p_fd;
1.1 mrg 815: struct file *fp;
816: struct vnode *vp;
817: off_t offset;
818: int error, fd = SCARG(uap, fd);
819:
1.6 thorpej 820: if ((fp = fd_getfile(fdp, fd)) == NULL)
821: return (EBADF);
822:
823: if ((fp->f_flag & FREAD) == 0)
1.1 mrg 824: return (EBADF);
825:
1.9 jdolecek 826: FILE_USE(fp);
827:
1.1 mrg 828: vp = (struct vnode *)fp->f_data;
1.9 jdolecek 829: if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
830: error = ESPIPE;
831: goto out;
832: }
1.1 mrg 833:
834: offset = SCARG(uap, offset);
835:
836: /*
837: * XXX This works because no file systems actually
838: * XXX take any action on the seek operation.
839: */
840: if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.9 jdolecek 841: goto out;
1.1 mrg 842:
1.23 christos 843: return (dofilereadv32(l, fd, fp,
1.10 scw 844: (struct netbsd32_iovec *)NETBSD32PTR64(SCARG(uap, iovp)),
845: SCARG(uap, iovcnt), &offset, 0, retval));
1.9 jdolecek 846:
847: out:
1.23 christos 848: FILE_UNUSE(fp, l);
1.9 jdolecek 849: return (error);
1.1 mrg 850: }
851:
852: int
1.11 thorpej 853: netbsd32_pwritev(l, v, retval)
854: struct lwp *l;
1.1 mrg 855: void *v;
856: register_t *retval;
857: {
858: struct netbsd32_pwritev_args /* {
859: syscallarg(int) fd;
860: syscallarg(const netbsd32_iovecp_t) iovp;
861: syscallarg(int) iovcnt;
862: syscallarg(int) pad;
863: syscallarg(off_t) offset;
864: } */ *uap = v;
1.14 fvdl 865: struct proc *p = l->l_proc;
866: struct filedesc *fdp = p->p_fd;
1.1 mrg 867: struct file *fp;
868: struct vnode *vp;
869: off_t offset;
870: int error, fd = SCARG(uap, fd);
871:
1.6 thorpej 872: if ((fp = fd_getfile(fdp, fd)) == NULL)
873: return (EBADF);
874:
875: if ((fp->f_flag & FWRITE) == 0)
1.1 mrg 876: return (EBADF);
877:
1.9 jdolecek 878: FILE_USE(fp);
879:
1.1 mrg 880: vp = (struct vnode *)fp->f_data;
1.9 jdolecek 881: if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
882: error = ESPIPE;
883: goto out;
884: }
1.1 mrg 885:
886: offset = SCARG(uap, offset);
887:
888: /*
889: * XXX This works because no file systems actually
890: * XXX take any action on the seek operation.
891: */
892: if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.9 jdolecek 893: goto out;
1.1 mrg 894:
1.23 christos 895: return (dofilewritev32(l, fd, fp,
1.10 scw 896: (struct netbsd32_iovec *)NETBSD32PTR64(SCARG(uap, iovp)),
897: SCARG(uap, iovcnt), &offset, 0, retval));
1.9 jdolecek 898:
899: out:
1.23 christos 900: FILE_UNUSE(fp, l);
1.9 jdolecek 901: return (error);
1.1 mrg 902: }
903:
904: /*
905: * Find pathname of process's current directory.
906: *
907: * Use vfs vnode-to-name reverse cache; if that fails, fall back
908: * to reading directory contents.
909: */
1.23 christos 910: /* XXX NH Why does this exist */
1.14 fvdl 911: int
912: getcwd_common __P((struct vnode *, struct vnode *,
1.23 christos 913: char **, char *, int, int, struct lwp *));
1.14 fvdl 914:
1.19 perry 915: int netbsd32___getcwd(l, v, retval)
1.11 thorpej 916: struct lwp *l;
1.1 mrg 917: void *v;
918: register_t *retval;
919: {
920: struct netbsd32___getcwd_args /* {
921: syscallarg(char *) bufp;
922: syscallarg(size_t) length;
923: } */ *uap = v;
1.11 thorpej 924: struct proc *p = l->l_proc;
1.1 mrg 925: int error;
926: char *path;
927: char *bp, *bend;
928: int len = (int)SCARG(uap, length);
929: int lenused;
930:
931: if (len > MAXPATHLEN*4)
932: len = MAXPATHLEN*4;
933: else if (len < 2)
934: return ERANGE;
935:
936: path = (char *)malloc(len, M_TEMP, M_WAITOK);
937: if (!path)
938: return ENOMEM;
939:
940: bp = &path[len];
941: bend = bp;
942: *(--bp) = '\0';
943:
944: /*
945: * 5th argument here is "max number of vnodes to traverse".
946: * Since each entry takes up at least 2 bytes in the output buffer,
947: * limit it to N/2 vnodes for an N byte buffer.
948: */
949: #define GETCWD_CHECK_ACCESS 0x0001
950: error = getcwd_common (p->p_cwdi->cwdi_cdir, NULL, &bp, path, len/2,
1.23 christos 951: GETCWD_CHECK_ACCESS, l);
1.1 mrg 952:
953: if (error)
954: goto out;
955: lenused = bend - bp;
956: *retval = lenused;
957: /* put the result into user buffer */
1.36 christos 958: error = copyout(bp, (void *)NETBSD32PTR64(SCARG(uap, bufp)), lenused);
1.1 mrg 959:
960: out:
961: free(path, M_TEMP);
962: return error;
963: }
CVSweb <webmaster@jp.NetBSD.org>