Annotation of src/sys/compat/netbsd32/netbsd32_fs.c, Revision 1.51
1.51 ! ad 1: /* $NetBSD: netbsd32_fs.c,v 1.50 2008/01/05 19:14:08 dsl 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.51 ! ad 32: __KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.50 2008/01/05 19:14:08 dsl Exp $");
1.1 mrg 33:
34: #include <sys/param.h>
35: #include <sys/systm.h>
36: #include <sys/malloc.h>
37: #include <sys/mount.h>
38: #include <sys/socket.h>
39: #include <sys/socketvar.h>
40: #include <sys/stat.h>
41: #include <sys/time.h>
42: #include <sys/ktrace.h>
43: #include <sys/resourcevar.h>
44: #include <sys/vnode.h>
45: #include <sys/file.h>
46: #include <sys/filedesc.h>
47: #include <sys/namei.h>
1.18 cube 48: #include <sys/statvfs.h>
1.1 mrg 49: #include <sys/syscallargs.h>
50: #include <sys/proc.h>
1.22 christos 51: #include <sys/dirent.h>
1.27 elad 52: #include <sys/kauth.h>
1.37 dsl 53: #include <sys/vfs_syscalls.h>
1.1 mrg 54:
55: #include <compat/netbsd32/netbsd32.h>
56: #include <compat/netbsd32/netbsd32_syscallargs.h>
57: #include <compat/netbsd32/netbsd32_conv.h>
1.28 martin 58: #include <compat/sys/mount.h>
1.1 mrg 59:
60:
1.51 ! ad 61: static int dofilereadv32(int, struct file *, struct netbsd32_iovec *,
1.47 dsl 62: int, off_t *, int, register_t *);
1.51 ! ad 63: static int dofilewritev32(int, struct file *, struct netbsd32_iovec *,
1.47 dsl 64: int, off_t *, int, register_t *);
1.1 mrg 65:
1.45 dsl 66: struct iovec *
67: netbsd32_get_iov(struct netbsd32_iovec *iov32, int iovlen, struct iovec *aiov,
68: int aiov_len)
69: {
70: #define N_IOV32 8
71: struct netbsd32_iovec aiov32[N_IOV32];
72: struct iovec *iov = aiov;
73: struct iovec *iovp;
74: int i, n, j;
75: int error;
76:
77: if (iovlen < 0 || iovlen > IOV_MAX)
78: return NULL;
79:
80: if (iovlen > aiov_len)
81: iov = malloc(iovlen * sizeof (*iov), M_TEMP, M_WAITOK);
82:
83: iovp = iov;
84: for (i = 0; i < iovlen; iov32 += N_IOV32, i += N_IOV32) {
85: n = iovlen - i;
86: if (n > N_IOV32)
87: n = N_IOV32;
88: error = copyin(iov32, aiov32, n * sizeof (*iov32));
89: if (error != 0) {
90: if (iov != aiov)
91: free(iov, M_TEMP);
92: return NULL;
93: }
94: for (j = 0; j < n; iovp++, j++) {
95: iovp->iov_base = NETBSD32PTR64(aiov32[j].iov_base);
96: iovp->iov_len = aiov32[j].iov_len;
97: }
98: }
99: return iov;
100: #undef N_IOV32
101: }
102:
1.1 mrg 103: int
1.49 dsl 104: netbsd32_readv(struct lwp *l, const struct netbsd32_readv_args *uap, register_t *retval)
1.1 mrg 105: {
1.49 dsl 106: /* {
1.1 mrg 107: syscallarg(int) fd;
108: syscallarg(const netbsd32_iovecp_t) iovp;
109: syscallarg(int) iovcnt;
1.49 dsl 110: } */
1.1 mrg 111: int fd = SCARG(uap, fd);
1.51 ! ad 112: file_t *fp;
1.1 mrg 113:
1.51 ! ad 114: if ((fp = fd_getfile(fd)) == NULL)
1.6 thorpej 115: return (EBADF);
116:
1.50 dsl 117: if ((fp->f_flag & FREAD) == 0) {
1.51 ! ad 118: fd_putfile(fd);
1.1 mrg 119: return (EBADF);
1.50 dsl 120: }
1.1 mrg 121:
1.51 ! ad 122: return (dofilereadv32(fd, fp,
1.39 dsl 123: (struct netbsd32_iovec *)SCARG_P32(uap, iovp),
1.10 scw 124: SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval));
1.1 mrg 125: }
126:
127: /* Damn thing copies in the iovec! */
128: int
1.51 ! ad 129: dofilereadv32(int fd, struct file *fp, struct netbsd32_iovec *iovp, int iovcnt, off_t *offset, int flags, register_t *retval)
1.1 mrg 130: {
131: struct uio auio;
132: struct iovec *iov;
133: struct iovec *needfree;
134: struct iovec aiov[UIO_SMALLIOV];
135: long i, cnt, error = 0;
136: u_int iovlen;
137: struct iovec *ktriov = NULL;
138:
139: /* note: can't use iovlen until iovcnt is validated */
140: iovlen = iovcnt * sizeof(struct iovec);
141: if ((u_int)iovcnt > UIO_SMALLIOV) {
1.9 jdolecek 142: if ((u_int)iovcnt > IOV_MAX) {
143: error = EINVAL;
144: goto out;
145: }
146: iov = malloc(iovlen, M_IOV, M_WAITOK);
1.1 mrg 147: needfree = iov;
148: } else if ((u_int)iovcnt > 0) {
149: iov = aiov;
150: needfree = NULL;
1.9 jdolecek 151: } else {
152: error = EINVAL;
153: goto out;
154: }
1.1 mrg 155:
156: auio.uio_iov = iov;
157: auio.uio_iovcnt = iovcnt;
158: auio.uio_rw = UIO_READ;
1.51 ! ad 159: auio.uio_vmspace = curproc->p_vmspace;
1.1 mrg 160: error = netbsd32_to_iovecin(iovp, iov, iovcnt);
161: if (error)
162: goto done;
163: auio.uio_resid = 0;
164: for (i = 0; i < iovcnt; i++) {
165: auio.uio_resid += iov->iov_len;
166: /*
167: * Reads return ssize_t because -1 is returned on error.
168: * Therefore we must restrict the length to SSIZE_MAX to
169: * avoid garbage return values.
170: */
171: if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
172: error = EINVAL;
173: goto done;
174: }
175: iov++;
176: }
1.46 ad 177:
1.1 mrg 178: /*
179: * if tracing, save a copy of iovec
180: */
1.46 ad 181: if (ktrpoint(KTR_GENIO)) {
1.9 jdolecek 182: ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
1.36 christos 183: memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
1.1 mrg 184: }
1.46 ad 185:
1.1 mrg 186: cnt = auio.uio_resid;
187: error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred, flags);
188: if (error)
189: if (auio.uio_resid != cnt && (error == ERESTART ||
190: error == EINTR || error == EWOULDBLOCK))
191: error = 0;
192: cnt -= auio.uio_resid;
1.46 ad 193:
194: if (ktriov != NULL) {
195: ktrgeniov(fd, UIO_READ, ktriov, cnt, error);
1.9 jdolecek 196: free(ktriov, M_TEMP);
1.1 mrg 197: }
1.46 ad 198:
1.1 mrg 199: *retval = cnt;
200: done:
201: if (needfree)
1.9 jdolecek 202: free(needfree, M_IOV);
203: out:
1.51 ! ad 204: fd_putfile(fd);
1.1 mrg 205: return (error);
206: }
207:
208: int
1.49 dsl 209: netbsd32_writev(struct lwp *l, const struct netbsd32_writev_args *uap, register_t *retval)
1.1 mrg 210: {
1.49 dsl 211: /* {
1.1 mrg 212: syscallarg(int) fd;
213: syscallarg(const netbsd32_iovecp_t) iovp;
214: syscallarg(int) iovcnt;
1.49 dsl 215: } */
1.1 mrg 216: int fd = SCARG(uap, fd);
1.51 ! ad 217: file_t *fp;
1.1 mrg 218:
1.51 ! ad 219: if ((fp = fd_getfile(fd)) == NULL)
1.6 thorpej 220: return (EBADF);
221:
1.50 dsl 222: if ((fp->f_flag & FWRITE) == 0) {
1.51 ! ad 223: fd_putfile(fd);
1.1 mrg 224: return (EBADF);
1.50 dsl 225: }
1.1 mrg 226:
1.51 ! ad 227: return (dofilewritev32(fd, fp,
1.39 dsl 228: (struct netbsd32_iovec *)SCARG_P32(uap, iovp),
1.10 scw 229: SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval));
1.1 mrg 230: }
231:
232: int
1.51 ! ad 233: dofilewritev32(int fd, struct file *fp, struct netbsd32_iovec *iovp, int iovcnt, off_t *offset, int flags, register_t *retval)
1.1 mrg 234: {
235: struct uio auio;
236: struct iovec *iov;
237: struct iovec *needfree;
238: struct iovec aiov[UIO_SMALLIOV];
239: long i, cnt, error = 0;
240: u_int iovlen;
241: struct iovec *ktriov = NULL;
242:
243: /* note: can't use iovlen until iovcnt is validated */
244: iovlen = iovcnt * sizeof(struct iovec);
245: if ((u_int)iovcnt > UIO_SMALLIOV) {
1.9 jdolecek 246: if ((u_int)iovcnt > IOV_MAX) {
247: error = EINVAL;
248: goto out;
249: }
250: iov = malloc(iovlen, M_IOV, M_WAITOK);
1.1 mrg 251: needfree = iov;
252: } else if ((u_int)iovcnt > 0) {
253: iov = aiov;
254: needfree = NULL;
1.9 jdolecek 255: } else {
256: error = EINVAL;
257: goto out;
258: }
1.1 mrg 259:
260: auio.uio_iov = iov;
261: auio.uio_iovcnt = iovcnt;
262: auio.uio_rw = UIO_WRITE;
1.51 ! ad 263: auio.uio_vmspace = curproc->p_vmspace;
1.1 mrg 264: error = netbsd32_to_iovecin(iovp, iov, iovcnt);
265: if (error)
266: goto done;
267: auio.uio_resid = 0;
268: for (i = 0; i < iovcnt; i++) {
269: auio.uio_resid += iov->iov_len;
270: /*
271: * Writes return ssize_t because -1 is returned on error.
272: * Therefore we must restrict the length to SSIZE_MAX to
273: * avoid garbage return values.
274: */
275: if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
276: error = EINVAL;
277: goto done;
278: }
279: iov++;
280: }
1.46 ad 281:
1.1 mrg 282: /*
283: * if tracing, save a copy of iovec
284: */
1.46 ad 285: if (ktrpoint(KTR_GENIO)) {
1.9 jdolecek 286: ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
1.36 christos 287: memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
1.1 mrg 288: }
1.46 ad 289:
1.1 mrg 290: cnt = auio.uio_resid;
291: error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred, flags);
292: if (error) {
293: if (auio.uio_resid != cnt && (error == ERESTART ||
294: error == EINTR || error == EWOULDBLOCK))
295: error = 0;
1.44 ad 296: if (error == EPIPE) {
297: mutex_enter(&proclist_mutex);
1.51 ! ad 298: psignal(curproc, SIGPIPE);
1.44 ad 299: mutex_exit(&proclist_mutex);
300: }
1.1 mrg 301: }
302: cnt -= auio.uio_resid;
1.46 ad 303: if (ktriov != NULL) {
304: ktrgenio(fd, UIO_WRITE, ktriov, cnt, error);
1.9 jdolecek 305: free(ktriov, M_TEMP);
1.1 mrg 306: }
307: *retval = cnt;
308: done:
309: if (needfree)
1.9 jdolecek 310: free(needfree, M_IOV);
311: out:
1.51 ! ad 312: fd_putfile(fd);
1.1 mrg 313: return (error);
314: }
315:
1.43 dsl 316: /*
317: * Common routine to set access and modification times given a vnode.
318: */
319: static int
320: get_utimes32(const netbsd32_timevalp_t *tptr, struct timeval *tv,
321: struct timeval **tvp)
322: {
323: int error;
324: struct netbsd32_timeval tv32[2];
325:
326: if (tptr == NULL) {
327: *tvp = NULL;
328: return 0;
329: }
330:
331: error = copyin(tptr, tv32, sizeof(tv32));
332: if (error)
333: return error;
334: netbsd32_to_timeval(&tv32[0], &tv[0]);
335: netbsd32_to_timeval(&tv32[1], &tv[1]);
336:
337: *tvp = tv;
338: return 0;
339: }
340:
1.1 mrg 341: int
1.49 dsl 342: netbsd32_utimes(struct lwp *l, const struct netbsd32_utimes_args *uap, register_t *retval)
1.1 mrg 343: {
1.49 dsl 344: /* {
1.1 mrg 345: syscallarg(const netbsd32_charp) path;
346: syscallarg(const netbsd32_timevalp_t) tptr;
1.49 dsl 347: } */
1.1 mrg 348: int error;
1.43 dsl 349: struct timeval tv[2], *tvp;
1.1 mrg 350:
1.43 dsl 351: error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
352: if (error != 0)
353: return error;
1.1 mrg 354:
1.43 dsl 355: return do_sys_utimes(l, NULL, SCARG_P32(uap, path), FOLLOW,
356: tvp, UIO_SYSSPACE);
1.1 mrg 357: }
358:
1.42 dsl 359: static int
360: netbds32_copyout_statvfs(const void *kp, void *up, size_t len)
361: {
362: struct netbsd32_statvfs *sbuf_32;
363: int error;
364:
365: sbuf_32 = malloc(sizeof *sbuf_32, M_TEMP, M_WAITOK);
366: netbsd32_from_statvfs(kp, sbuf_32);
367: error = copyout(sbuf_32, up, sizeof(*sbuf_32));
368: free(sbuf_32, M_TEMP);
369:
370: return error;
371: }
372:
1.1 mrg 373: int
1.49 dsl 374: netbsd32_statvfs1(struct lwp *l, const struct netbsd32_statvfs1_args *uap, register_t *retval)
1.1 mrg 375: {
1.49 dsl 376: /* {
1.1 mrg 377: syscallarg(const netbsd32_charp) path;
1.18 cube 378: syscallarg(netbsd32_statvfsp_t) buf;
379: syscallarg(int) flags;
1.49 dsl 380: } */
1.42 dsl 381: struct statvfs *sb;
1.1 mrg 382: int error;
383:
1.42 dsl 384: sb = STATVFSBUF_GET();
385: error = do_sys_pstatvfs(l, SCARG_P32(uap, path), SCARG(uap, flags), sb);
386: if (error == 0)
387: error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
388: STATVFSBUF_PUT(sb);
389: return error;
1.1 mrg 390: }
391:
392: int
1.49 dsl 393: netbsd32_fstatvfs1(struct lwp *l, const struct netbsd32_fstatvfs1_args *uap, register_t *retval)
1.1 mrg 394: {
1.49 dsl 395: /* {
1.1 mrg 396: syscallarg(int) fd;
1.18 cube 397: syscallarg(netbsd32_statvfsp_t) buf;
398: syscallarg(int) flags;
1.49 dsl 399: } */
1.42 dsl 400: struct statvfs *sb;
1.1 mrg 401: int error;
402:
1.42 dsl 403: sb = STATVFSBUF_GET();
404: error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb);
405: if (error == 0)
406: error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
407: STATVFSBUF_PUT(sb);
1.18 cube 408: return error;
409: }
410:
411: int
1.49 dsl 412: netbsd32_getvfsstat(struct lwp *l, const struct netbsd32_getvfsstat_args *uap, register_t *retval)
1.18 cube 413: {
1.49 dsl 414: /* {
1.18 cube 415: syscallarg(netbsd32_statvfsp_t) buf;
416: syscallarg(netbsd32_size_t) bufsize;
417: syscallarg(int) flags;
1.49 dsl 418: } */
1.18 cube 419:
1.42 dsl 420: return do_sys_getvfsstat(l, SCARG_P32(uap, buf), SCARG(uap, bufsize),
421: SCARG(uap, flags), netbds32_copyout_statvfs,
422: sizeof (struct netbsd32_statvfs), retval);
1.18 cube 423: }
424:
425: int
1.49 dsl 426: netbsd32___fhstatvfs140(struct lwp *l, const struct netbsd32___fhstatvfs140_args *uap, register_t *retval)
1.18 cube 427: {
1.49 dsl 428: /* {
1.32 martin 429: syscallarg(const netbsd32_pointer_t) fhp;
430: syscallarg(netbsd32_size_t) fh_size;
1.18 cube 431: syscallarg(netbsd32_statvfsp_t) buf;
432: syscallarg(int) flags;
1.49 dsl 433: } */
1.42 dsl 434: struct statvfs *sb;
1.18 cube 435: int error;
436:
1.42 dsl 437: sb = STATVFSBUF_GET();
438: error = do_fhstatvfs(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), sb,
439: SCARG(uap, flags));
440:
441: if (error == 0)
442: error = netbds32_copyout_statvfs(sb, SCARG_P32(uap, buf), 0);
443: STATVFSBUF_PUT(sb);
1.18 cube 444:
1.42 dsl 445: return error;
1.1 mrg 446: }
447:
448: int
1.49 dsl 449: netbsd32_futimes(struct lwp *l, const struct netbsd32_futimes_args *uap, register_t *retval)
1.1 mrg 450: {
1.49 dsl 451: /* {
1.1 mrg 452: syscallarg(int) fd;
453: syscallarg(const netbsd32_timevalp_t) tptr;
1.49 dsl 454: } */
1.1 mrg 455: int error;
1.51 ! ad 456: file_t *fp;
1.43 dsl 457: struct timeval tv[2], *tvp;
458:
459: error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
460: if (error != 0)
461: return error;
1.1 mrg 462:
463: /* getvnode() will use the descriptor for us */
1.51 ! ad 464: if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
1.1 mrg 465: return (error);
466:
1.43 dsl 467: error = do_sys_utimes(l, fp->f_data, NULL, 0, tvp, UIO_SYSSPACE);
468:
1.51 ! ad 469: fd_putfile(SCARG(uap, fd));
1.1 mrg 470: return (error);
471: }
472:
473: int
1.49 dsl 474: netbsd32_sys___getdents30(struct lwp *l, const struct netbsd32_sys___getdents30_args *uap, register_t *retval)
1.1 mrg 475: {
1.49 dsl 476: /* {
1.1 mrg 477: syscallarg(int) fd;
478: syscallarg(netbsd32_charp) buf;
479: syscallarg(netbsd32_size_t) count;
1.49 dsl 480: } */
1.51 ! ad 481: file_t *fp;
1.1 mrg 482: int error, done;
483:
484: /* getvnode() will use the descriptor for us */
1.51 ! ad 485: if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
1.1 mrg 486: return (error);
487: if ((fp->f_flag & FREAD) == 0) {
488: error = EBADF;
489: goto out;
490: }
1.39 dsl 491: error = vn_readdir(fp, SCARG_P32(uap, buf),
1.23 christos 492: UIO_USERSPACE, SCARG(uap, count), &done, l, 0, 0);
1.1 mrg 493: *retval = done;
494: out:
1.51 ! ad 495: fd_putfile(SCARG(uap, fd));
1.1 mrg 496: return (error);
497: }
498:
499: int
1.49 dsl 500: netbsd32_lutimes(struct lwp *l, const struct netbsd32_lutimes_args *uap, register_t *retval)
1.1 mrg 501: {
1.49 dsl 502: /* {
1.1 mrg 503: syscallarg(const netbsd32_charp) path;
504: syscallarg(const netbsd32_timevalp_t) tptr;
1.49 dsl 505: } */
1.1 mrg 506: int error;
1.43 dsl 507: struct timeval tv[2], *tvp;
1.1 mrg 508:
1.43 dsl 509: error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
510: if (error != 0)
511: return error;
1.1 mrg 512:
1.43 dsl 513: return do_sys_utimes(l, NULL, SCARG_P32(uap, path), NOFOLLOW,
514: tvp, UIO_SYSSPACE);
1.1 mrg 515: }
516:
517: int
1.49 dsl 518: netbsd32_sys___stat30(struct lwp *l, const struct netbsd32_sys___stat30_args *uap, register_t *retval)
1.1 mrg 519: {
1.49 dsl 520: /* {
1.1 mrg 521: syscallarg(const netbsd32_charp) path;
522: syscallarg(netbsd32_statp_t) ub;
1.49 dsl 523: } */
1.1 mrg 524: struct netbsd32_stat sb32;
525: struct stat sb;
526: int error;
527: const char *path;
528:
1.39 dsl 529: path = SCARG_P32(uap, path);
1.1 mrg 530:
1.51 ! ad 531: error = do_sys_stat(path, FOLLOW, &sb);
1.41 dsl 532: if (error)
533: return (error);
1.22 christos 534: netbsd32_from___stat30(&sb, &sb32);
1.39 dsl 535: error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
1.1 mrg 536: return (error);
537: }
538:
539: int
1.49 dsl 540: netbsd32_sys___fstat30(struct lwp *l, const struct netbsd32_sys___fstat30_args *uap, register_t *retval)
1.1 mrg 541: {
1.49 dsl 542: /* {
1.1 mrg 543: syscallarg(int) fd;
544: syscallarg(netbsd32_statp_t) sb;
1.49 dsl 545: } */
1.1 mrg 546: int fd = SCARG(uap, fd);
1.51 ! ad 547: file_t *fp;
1.1 mrg 548: struct netbsd32_stat sb32;
549: struct stat ub;
550: int error = 0;
551:
1.51 ! ad 552: if ((fp = fd_getfile(fd)) == NULL)
1.1 mrg 553: return (EBADF);
1.51 ! ad 554: error = (*fp->f_ops->fo_stat)(fp, &ub);
! 555: fd_putfile(fd);
1.1 mrg 556: if (error == 0) {
1.22 christos 557: netbsd32_from___stat30(&ub, &sb32);
1.39 dsl 558: error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32));
1.1 mrg 559: }
560: return (error);
561: }
562:
563: int
1.49 dsl 564: netbsd32_sys___lstat30(struct lwp *l, const struct netbsd32_sys___lstat30_args *uap, register_t *retval)
1.1 mrg 565: {
1.49 dsl 566: /* {
1.1 mrg 567: syscallarg(const netbsd32_charp) path;
568: syscallarg(netbsd32_statp_t) ub;
1.49 dsl 569: } */
1.1 mrg 570: struct netbsd32_stat sb32;
571: struct stat sb;
572: int error;
573: const char *path;
574:
1.39 dsl 575: path = SCARG_P32(uap, path);
1.1 mrg 576:
1.51 ! ad 577: error = do_sys_stat(path, NOFOLLOW, &sb);
1.1 mrg 578: if (error)
579: return (error);
1.22 christos 580: netbsd32_from___stat30(&sb, &sb32);
1.39 dsl 581: error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
1.1 mrg 582: return (error);
583: }
584:
1.49 dsl 585: int
586: netbsd32___fhstat40(struct lwp *l, const struct netbsd32___fhstat40_args *uap, register_t *retval)
1.26 cube 587: {
1.49 dsl 588: /* {
1.32 martin 589: syscallarg(const netbsd32_pointer_t) fhp;
590: syscallarg(netbsd32_size_t) fh_size;
1.26 cube 591: syscallarg(netbsd32_statp_t) sb;
1.49 dsl 592: } */
1.26 cube 593: struct stat sb;
594: struct netbsd32_stat sb32;
595: int error;
596:
1.42 dsl 597: error = do_fhstat(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), &sb);
598: if (error != 0) {
599: netbsd32_from___stat30(&sb, &sb32);
600: error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb));
601: }
1.29 martin 602: return error;
1.26 cube 603: }
604:
1.1 mrg 605: int
1.49 dsl 606: netbsd32_preadv(struct lwp *l, const struct netbsd32_preadv_args *uap, register_t *retval)
1.1 mrg 607: {
1.49 dsl 608: /* {
1.1 mrg 609: syscallarg(int) fd;
610: syscallarg(const netbsd32_iovecp_t) iovp;
611: syscallarg(int) iovcnt;
612: syscallarg(int) pad;
613: syscallarg(off_t) offset;
1.49 dsl 614: } */
1.51 ! ad 615: file_t *fp;
1.1 mrg 616: struct vnode *vp;
617: off_t offset;
618: int error, fd = SCARG(uap, fd);
619:
1.51 ! ad 620: if ((fp = fd_getfile(fd)) == NULL)
1.6 thorpej 621: return (EBADF);
622:
1.50 dsl 623: if ((fp->f_flag & FREAD) == 0) {
1.51 ! ad 624: fd_putfile(fd);
1.1 mrg 625: return (EBADF);
1.50 dsl 626: }
1.1 mrg 627:
1.51 ! ad 628: vp = fp->f_data;
1.9 jdolecek 629: if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
630: error = ESPIPE;
631: goto out;
632: }
1.1 mrg 633:
634: offset = SCARG(uap, offset);
635:
636: /*
637: * XXX This works because no file systems actually
638: * XXX take any action on the seek operation.
639: */
640: if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.9 jdolecek 641: goto out;
1.1 mrg 642:
1.51 ! ad 643: return (dofilereadv32(fd, fp, SCARG_P32(uap, iovp),
1.10 scw 644: SCARG(uap, iovcnt), &offset, 0, retval));
1.9 jdolecek 645:
646: out:
1.51 ! ad 647: fd_putfile(fd);
1.9 jdolecek 648: return (error);
1.1 mrg 649: }
650:
651: int
1.49 dsl 652: netbsd32_pwritev(struct lwp *l, const struct netbsd32_pwritev_args *uap, register_t *retval)
1.1 mrg 653: {
1.49 dsl 654: /* {
1.1 mrg 655: syscallarg(int) fd;
656: syscallarg(const netbsd32_iovecp_t) iovp;
657: syscallarg(int) iovcnt;
658: syscallarg(int) pad;
659: syscallarg(off_t) offset;
1.49 dsl 660: } */
1.51 ! ad 661: file_t *fp;
1.1 mrg 662: struct vnode *vp;
663: off_t offset;
664: int error, fd = SCARG(uap, fd);
665:
1.51 ! ad 666: if ((fp = fd_getfile(fd)) == NULL)
1.6 thorpej 667: return (EBADF);
668:
1.50 dsl 669: if ((fp->f_flag & FWRITE) == 0) {
1.51 ! ad 670: fd_putfile(fd);
1.1 mrg 671: return (EBADF);
1.50 dsl 672: }
1.1 mrg 673:
1.51 ! ad 674: vp = fp->f_data;
1.9 jdolecek 675: if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
676: error = ESPIPE;
677: goto out;
678: }
1.1 mrg 679:
680: offset = SCARG(uap, offset);
681:
682: /*
683: * XXX This works because no file systems actually
684: * XXX take any action on the seek operation.
685: */
686: if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.9 jdolecek 687: goto out;
1.1 mrg 688:
1.51 ! ad 689: return (dofilewritev32(fd, fp, SCARG_P32(uap, iovp),
1.10 scw 690: SCARG(uap, iovcnt), &offset, 0, retval));
1.9 jdolecek 691:
692: out:
1.51 ! ad 693: fd_putfile(fd);
1.9 jdolecek 694: return (error);
1.1 mrg 695: }
696:
697: /*
698: * Find pathname of process's current directory.
699: *
700: * Use vfs vnode-to-name reverse cache; if that fails, fall back
701: * to reading directory contents.
702: */
1.23 christos 703: /* XXX NH Why does this exist */
1.14 fvdl 704: int
1.47 dsl 705: getcwd_common(struct vnode *, struct vnode *,
706: char **, char *, int, int, struct lwp *);
1.14 fvdl 707:
1.49 dsl 708: int
709: netbsd32___getcwd(struct lwp *l, const struct netbsd32___getcwd_args *uap, register_t *retval)
1.1 mrg 710: {
1.49 dsl 711: /* {
1.1 mrg 712: syscallarg(char *) bufp;
713: syscallarg(size_t) length;
1.49 dsl 714: } */
1.11 thorpej 715: struct proc *p = l->l_proc;
1.1 mrg 716: int error;
717: char *path;
718: char *bp, *bend;
719: int len = (int)SCARG(uap, length);
720: int lenused;
721:
722: if (len > MAXPATHLEN*4)
723: len = MAXPATHLEN*4;
724: else if (len < 2)
725: return ERANGE;
726:
727: path = (char *)malloc(len, M_TEMP, M_WAITOK);
728: if (!path)
729: return ENOMEM;
730:
731: bp = &path[len];
732: bend = bp;
733: *(--bp) = '\0';
734:
735: /*
736: * 5th argument here is "max number of vnodes to traverse".
737: * Since each entry takes up at least 2 bytes in the output buffer,
738: * limit it to N/2 vnodes for an N byte buffer.
739: */
740: #define GETCWD_CHECK_ACCESS 0x0001
741: error = getcwd_common (p->p_cwdi->cwdi_cdir, NULL, &bp, path, len/2,
1.23 christos 742: GETCWD_CHECK_ACCESS, l);
1.1 mrg 743:
744: if (error)
745: goto out;
746: lenused = bend - bp;
747: *retval = lenused;
748: /* put the result into user buffer */
1.39 dsl 749: error = copyout(bp, SCARG_P32(uap, bufp), lenused);
1.1 mrg 750:
751: out:
752: free(path, M_TEMP);
753: return error;
754: }
CVSweb <webmaster@jp.NetBSD.org>