Annotation of src/sys/compat/common/vfs_syscalls_30.c, Revision 1.7.2.2
1.7.2.2 ! yamt 1: /* $NetBSD: vfs_syscalls_30.c,v 1.7.2.1 2006/05/24 10:57:27 yamt Exp $ */
1.1 christos 2:
3: /*-
4: * Copyright (c) 2005 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Christos Zoulas.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38: #include <sys/cdefs.h>
1.7.2.2 ! yamt 39: __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_30.c,v 1.7.2.1 2006/05/24 10:57:27 yamt Exp $");
1.1 christos 40:
41: #include <sys/param.h>
42: #include <sys/systm.h>
43: #include <sys/namei.h>
44: #include <sys/filedesc.h>
45: #include <sys/kernel.h>
46: #include <sys/file.h>
47: #include <sys/stat.h>
48: #include <sys/socketvar.h>
49: #include <sys/vnode.h>
50: #include <sys/mount.h>
51: #include <sys/proc.h>
52: #include <sys/uio.h>
53: #include <sys/dirent.h>
54: #include <sys/malloc.h>
1.7.2.1 yamt 55: #include <sys/kauth.h>
1.1 christos 56:
57: #include <sys/sa.h>
58: #include <sys/syscallargs.h>
59:
60: #include <compat/common/compat_util.h>
1.5 christos 61: #include <compat/sys/stat.h>
62: #include <compat/sys/dirent.h>
1.7.2.2 ! yamt 63: #include <compat/sys/mount.h>
1.1 christos 64:
65: static void cvtstat(struct stat13 *, const struct stat *);
66:
67: /*
68: * Convert from a new to an old stat structure.
69: */
70: static void
71: cvtstat(struct stat13 *ost, const struct stat *st)
72: {
73:
74: ost->st_dev = st->st_dev;
75: ost->st_ino = (uint32_t)st->st_ino;
76: ost->st_mode = st->st_mode;
77: ost->st_nlink = st->st_nlink;
78: ost->st_uid = st->st_uid;
79: ost->st_gid = st->st_gid;
80: ost->st_rdev = st->st_rdev;
81: ost->st_atimespec = st->st_atimespec;
82: ost->st_mtimespec = st->st_mtimespec;
83: ost->st_ctimespec = st->st_ctimespec;
84: ost->st_birthtimespec = st->st_birthtimespec;
85: ost->st_size = st->st_size;
86: ost->st_blocks = st->st_blocks;
87: ost->st_blksize = st->st_blksize;
88: ost->st_flags = st->st_flags;
89: ost->st_gen = st->st_gen;
90: }
91:
92: /*
93: * Get file status; this version follows links.
94: */
95: /* ARGSUSED */
96: int
97: compat_30_sys___stat13(struct lwp *l, void *v, register_t *retval)
98: {
99: struct compat_30_sys___stat13_args /* {
100: syscallarg(const char *) path;
101: syscallarg(struct stat13 *) ub;
102: } */ *uap = v;
103: struct stat sb;
104: struct stat13 osb;
105: int error;
106: struct nameidata nd;
107:
108: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1.6 christos 109: SCARG(uap, path), l);
1.1 christos 110: if ((error = namei(&nd)) != 0)
111: return error;
1.6 christos 112: error = vn_stat(nd.ni_vp, &sb, l);
1.1 christos 113: vput(nd.ni_vp);
114: if (error)
115: return error;
116: cvtstat(&osb, &sb);
117: error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
118: return error;
119: }
120:
121:
122: /*
123: * Get file status; this version does not follow links.
124: */
125: /* ARGSUSED */
126: int
127: compat_30_sys___lstat13(struct lwp *l, void *v, register_t *retval)
128: {
129: struct compat_30_sys___lstat13_args /* {
130: syscallarg(const char *) path;
131: syscallarg(struct stat13 *) ub;
132: } */ *uap = v;
133: struct stat sb;
134: struct stat13 osb;
135: int error;
136: struct nameidata nd;
137:
138: NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1.6 christos 139: SCARG(uap, path), l);
1.1 christos 140: if ((error = namei(&nd)) != 0)
141: return error;
1.6 christos 142: error = vn_stat(nd.ni_vp, &sb, l);
1.1 christos 143: vput(nd.ni_vp);
144: if (error)
145: return error;
146: cvtstat(&osb, &sb);
147: error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
148: return error;
149: }
150:
1.7.2.1 yamt 151: /* ARGSUSED */
152: int
153: compat_30_sys_fhstat(struct lwp *l, void *v, register_t *retval)
154: {
155: struct compat_30_sys_fhstat_args /* {
1.7.2.2 ! yamt 156: syscallarg(const struct compat_30_fhandle *) fhp;
1.7.2.1 yamt 157: syscallarg(struct stat13 *) sb;
158: } */ *uap = v;
159: struct stat sb;
160: struct stat13 osb;
161: int error;
1.7.2.2 ! yamt 162: struct compat_30_fhandle fh;
1.7.2.1 yamt 163: struct mount *mp;
164: struct vnode *vp;
165:
166: /*
167: * Must be super user
168: */
1.7.2.2 ! yamt 169: if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
! 170: &l->l_acflag)))
1.7.2.1 yamt 171: return (error);
172:
1.7.2.2 ! yamt 173: if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fh))) != 0)
1.7.2.1 yamt 174: return (error);
175:
176: if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
177: return (ESTALE);
178: if (mp->mnt_op->vfs_fhtovp == NULL)
179: return EOPNOTSUPP;
1.7.2.2 ! yamt 180: if ((error = VFS_FHTOVP(mp, (struct fid*)&fh.fh_fid, &vp)))
1.7.2.1 yamt 181: return (error);
182: error = vn_stat(vp, &sb, l);
183: vput(vp);
184: if (error)
185: return (error);
186: cvtstat(&osb, &sb);
187: error = copyout(&osb, SCARG(uap, sb), sizeof(sb));
188: return (error);
189: }
190:
1.1 christos 191: /*
192: * Return status information about a file descriptor.
193: */
194: /* ARGSUSED */
195: int
196: compat_30_sys___fstat13(struct lwp *l, void *v, register_t *retval)
197: {
198: struct compat_30_sys___fstat13_args /* {
199: syscallarg(int) fd;
200: syscallarg(struct stat13 *) sb;
201: } */ *uap = v;
202: struct proc *p = l->l_proc;
203: int fd = SCARG(uap, fd);
204: struct filedesc *fdp = p->p_fd;
205: struct file *fp;
206: struct stat sb;
207: struct stat13 osb;
208: int error;
209:
210: if ((fp = fd_getfile(fdp, fd)) == NULL)
211: return EBADF;
212:
213: FILE_USE(fp);
1.6 christos 214: error = (*fp->f_ops->fo_stat)(fp, &sb, l);
215: FILE_UNUSE(fp, l);
1.1 christos 216:
217: if (error)
218: return error;
219: cvtstat(&osb, &sb);
220: error = copyout(&osb, SCARG(uap, sb), sizeof (osb));
221: return error;
222: }
223:
224: /*
225: * Read a block of directory entries in a file system independent format.
226: */
227: int
228: compat_30_sys_getdents(struct lwp *l, void *v, register_t *retval)
229: {
230: struct compat_30_sys_getdents_args /* {
231: syscallarg(int) fd;
232: syscallarg(char *) buf;
233: syscallarg(size_t) count;
234: } */ *uap = v;
235: struct proc *p = l->l_proc;
236: struct dirent *bdp;
237: struct vnode *vp;
238: caddr_t inp, tbuf; /* BSD-format */
239: int len, reclen; /* BSD-format */
1.4 yamt 240: caddr_t outp; /* NetBSD-3.0-format */
1.1 christos 241: int resid;
242: struct file *fp;
243: struct uio auio;
244: struct iovec aiov;
245: struct dirent12 idb;
246: off_t off; /* true file offset */
247: int buflen, error, eofflag;
248: off_t *cookiebuf = NULL, *cookie;
249: int ncookies;
250:
251: /* getvnode() will use the descriptor for us */
252: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
253: return error;
254:
255: if ((fp->f_flag & FREAD) == 0) {
256: error = EBADF;
257: goto out1;
258: }
259:
260: vp = (struct vnode *)fp->f_data;
261: if (vp->v_type != VDIR) {
262: error = EINVAL;
263: goto out1;
264: }
265:
266: buflen = min(MAXBSIZE, SCARG(uap, count));
267: tbuf = malloc(buflen, M_TEMP, M_WAITOK);
268: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
269: off = fp->f_offset;
270: again:
271: aiov.iov_base = tbuf;
272: aiov.iov_len = buflen;
273: auio.uio_iov = &aiov;
274: auio.uio_iovcnt = 1;
275: auio.uio_rw = UIO_READ;
276: auio.uio_resid = buflen;
277: auio.uio_offset = off;
1.7 yamt 278: UIO_SETUP_SYSSPACE(&auio);
1.1 christos 279: /*
280: * First we read into the malloc'ed buffer, then
281: * we massage it into user space, one record at a time.
282: */
283: error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
284: &ncookies);
285: if (error)
286: goto out;
287:
288: inp = tbuf;
289: outp = SCARG(uap, buf);
290: resid = SCARG(uap, count);
291: if ((len = buflen - auio.uio_resid) == 0)
292: goto eof;
293:
294: for (cookie = cookiebuf; len > 0; len -= reclen) {
295: bdp = (struct dirent *)inp;
296: reclen = bdp->d_reclen;
1.2 christos 297: if (reclen & _DIRENT_ALIGN(bdp))
1.1 christos 298: panic("netbsd30_getdents: bad reclen %d", reclen);
299: if (cookie)
300: off = *cookie++; /* each entry points to the next */
301: else
302: off += reclen;
303: if ((off >> 32) != 0) {
1.4 yamt 304: compat_offseterr(vp, "netbsd30_getdents");
1.1 christos 305: error = EINVAL;
306: goto out;
307: }
308: if (bdp->d_namlen >= sizeof(idb.d_name))
309: idb.d_namlen = sizeof(idb.d_name) - 1;
310: else
311: idb.d_namlen = bdp->d_namlen;
312: idb.d_reclen = _DIRENT_SIZE(&idb);
313: if (reclen > len || resid < idb.d_reclen) {
314: /* entry too big for buffer, so just stop */
315: outp++;
316: break;
317: }
318: /*
1.4 yamt 319: * Massage in place to make a NetBSD-3.0-shaped dirent
1.1 christos 320: * (otherwise we have to worry about touching user memory
321: * outside of the copyout() call).
322: */
323: idb.d_fileno = (u_int32_t)bdp->d_fileno;
324: idb.d_type = bdp->d_type;
325: (void)memcpy(idb.d_name, bdp->d_name, idb.d_namlen);
1.3 yamt 326: memset(idb.d_name + idb.d_namlen, 0,
327: idb.d_reclen - _DIRENT_NAMEOFF(&idb) - idb.d_namlen);
1.1 christos 328: if ((error = copyout(&idb, outp, idb.d_reclen)) != 0)
329: goto out;
330: /* advance past this real entry */
331: inp += reclen;
1.4 yamt 332: /* advance output past NetBSD-3.0-shaped entry */
1.1 christos 333: outp += idb.d_reclen;
334: resid -= idb.d_reclen;
335: }
336:
337: /* if we squished out the whole block, try again */
338: if (outp == SCARG(uap, buf))
339: goto again;
340: fp->f_offset = off; /* update the vnode offset */
341:
342: eof:
343: *retval = SCARG(uap, count) - resid;
344: out:
345: VOP_UNLOCK(vp, 0);
346: if (cookiebuf)
347: free(cookiebuf, M_TEMP);
348: free(tbuf, M_TEMP);
349: out1:
1.6 christos 350: FILE_UNUSE(fp, l);
1.1 christos 351: return error;
352: }
1.7.2.2 ! yamt 353:
! 354: /*
! 355: * Get file handle system call
! 356: */
! 357: int
! 358: compat_30_sys_getfh(struct lwp *l, void *v, register_t *retval)
! 359: {
! 360: struct compat_30_sys_getfh_args /* {
! 361: syscallarg(char *) fname;
! 362: syscallarg(struct compat_30_fhandle *) fhp;
! 363: } */ *uap = v;
! 364: struct vnode *vp;
! 365: struct compat_30_fhandle fh;
! 366: int error;
! 367: struct nameidata nd;
! 368: size_t sz;
! 369:
! 370: /*
! 371: * Must be super user
! 372: */
! 373: error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
! 374: &l->l_acflag);
! 375: if (error)
! 376: return (error);
! 377: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
! 378: SCARG(uap, fname), l);
! 379: error = namei(&nd);
! 380: if (error)
! 381: return (error);
! 382: vp = nd.ni_vp;
! 383: sz = sizeof(struct compat_30_fhandle);
! 384: error = vfs_composefh(vp, (void *)&fh, &sz);
! 385: vput(vp);
! 386: if (sz != FHANDLE_SIZE_COMPAT) {
! 387: error = EINVAL;
! 388: }
! 389: if (error)
! 390: return (error);
! 391: error = copyout(&fh, SCARG(uap, fhp), sizeof(struct compat_30_fhandle));
! 392: return (error);
! 393: }
! 394:
! 395: /*
! 396: * Open a file given a file handle.
! 397: *
! 398: * Check permissions, allocate an open file structure,
! 399: * and call the device open routine if any.
! 400: */
! 401: int
! 402: compat_30_sys_fhopen(struct lwp *l, void *v, register_t *retval)
! 403: {
! 404: struct compat_30_sys_fhopen_args /* {
! 405: syscallarg(const fhandle_t *) fhp;
! 406: syscallarg(int) flags;
! 407: } */ *uap = v;
! 408:
! 409: return dofhopen(l, SCARG(uap, fhp), FHANDLE_SIZE_COMPAT,
! 410: SCARG(uap, flags), retval);
! 411: }
! 412:
! 413: /* ARGSUSED */
! 414: int
! 415: compat_30_sys___fhstat30(struct lwp *l, void *v, register_t *retval)
! 416: {
! 417: struct compat_30_sys___fhstat30_args /* {
! 418: syscallarg(const fhandle_t *) fhp;
! 419: syscallarg(struct stat *) sb;
! 420: } */ *uap = v;
! 421:
! 422: return dofhstat(l, SCARG(uap, fhp), FHANDLE_SIZE_COMPAT,
! 423: SCARG(uap, sb), retval);
! 424: }
! 425:
! 426: /* ARGSUSED */
! 427: int
! 428: compat_30_sys_fhstatvfs1(struct lwp *l, void *v, register_t *retval)
! 429: {
! 430: struct compat_30_sys_fhstatvfs1_args /* {
! 431: syscallarg(const fhandle_t *) fhp;
! 432: syscallarg(struct statvfs *) buf;
! 433: syscallarg(int) flags;
! 434: } */ *uap = v;
! 435:
! 436: return dofhstatvfs(l, SCARG(uap, fhp), FHANDLE_SIZE_COMPAT,
! 437: SCARG(uap, buf), SCARG(uap, flags), retval);
! 438: }
CVSweb <webmaster@jp.NetBSD.org>