Per-CPU VFS Namecache Effectiveness Statistics:
[dragonfly.git] / sys / emulation / 43bsd / 43bsd_file.c
1 /*
2  * 43BSD_FILE.C         - 4.3BSD compatibility file syscalls
3  *
4  * Copyright (c) 1989, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  * (c) UNIX System Laboratories, Inc.
7  * All or some portions of this file are derived from material licensed
8  * to the University of California by American Telephone and Telegraph
9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10  * the permission of UNIX System Laboratories, Inc.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *      This product includes software developed by the University of
23  *      California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.4 2004/03/01 06:33:15 dillon Exp $
41  *      from: DragonFly kern/vfs_syscalls.c,v 1.20
42  *
43  * These syscalls used to live in kern/vfs_syscalls.c.  They are modified
44  * to use the new split syscalls.
45  */
46
47 #include "opt_compat.h"
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/sysproto.h>
52 #include <sys/conf.h>
53 #include <sys/dirent.h>
54 #include <sys/fcntl.h>
55 #include <sys/file.h>
56 #include <sys/filedesc.h>
57 #include <sys/kernel.h>
58 #include <sys/kern_syscall.h>
59 #include <sys/malloc.h>
60 #include <sys/mount.h>
61 #include <sys/namei.h>
62 #include <sys/uio.h>
63 #include <sys/vnode.h>
64
65 #include <vfs/union/union.h>
66
67 int
68 ocreat(struct ocreat_args *uap)
69 {
70         struct thread *td = curthread;
71         struct nameidata nd;
72         int error;
73
74         NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td);
75
76         error = kern_open(&nd, O_WRONLY | O_CREAT | O_TRUNC, uap->mode,
77             &uap->sysmsg_result);
78
79         return (error);
80 }
81
82 int
83 oftruncate(struct oftruncate_args *uap)
84 {
85         int error;
86
87         error = kern_ftruncate(uap->fd, uap->length);
88
89         return (error);
90 }
91
92 int
93 olseek(struct olseek_args *uap)
94 {
95         int error;
96
97         error = kern_lseek(uap->fd, uap->offset, uap->whence,
98             &uap->sysmsg_offset);
99
100         return (error);
101 }
102
103 int
104 otruncate(struct otruncate_args *uap)
105 {
106         struct thread *td = curthread;
107         struct nameidata nd;
108         int error;
109
110         NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td);
111
112         error = kern_truncate(&nd, uap->length);
113
114         return (error);
115 }
116
117 int
118 ogetdirentries(struct ogetdirentries_args *uap)
119 {
120         struct thread *td = curthread;
121         struct proc *p = td->td_proc;
122         struct vnode *vp;
123         struct file *fp;
124         struct uio auio, kuio;
125         struct iovec aiov, kiov;
126         struct dirent *dp, *edp;
127         caddr_t dirbuf;
128         int error, eofflag, readcnt;
129         long loff;
130
131         /* XXX arbitrary sanity limit on `count'. */
132         if (uap->count > 64 * 1024)
133                 return (EINVAL);
134         if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0)
135                 return (error);
136         if ((fp->f_flag & FREAD) == 0)
137                 return (EBADF);
138         vp = (struct vnode *)fp->f_data;
139 unionread:
140         if (vp->v_type != VDIR)
141                 return (EINVAL);
142         aiov.iov_base = uap->buf;
143         aiov.iov_len = uap->count;
144         auio.uio_iov = &aiov;
145         auio.uio_iovcnt = 1;
146         auio.uio_rw = UIO_READ;
147         auio.uio_segflg = UIO_USERSPACE;
148         auio.uio_td = td;
149         auio.uio_resid = uap->count;
150         vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
151         loff = auio.uio_offset = fp->f_offset;
152 #       if (BYTE_ORDER != LITTLE_ENDIAN)
153                 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
154                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
155                             NULL, NULL);
156                         fp->f_offset = auio.uio_offset;
157                 } else
158 #       endif
159         {
160                 kuio = auio;
161                 kuio.uio_iov = &kiov;
162                 kuio.uio_segflg = UIO_SYSSPACE;
163                 kiov.iov_len = uap->count;
164                 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
165                 kiov.iov_base = dirbuf;
166                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
167                             NULL, NULL);
168                 fp->f_offset = kuio.uio_offset;
169                 if (error == 0) {
170                         readcnt = uap->count - kuio.uio_resid;
171                         edp = (struct dirent *)&dirbuf[readcnt];
172                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
173 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
174                                         /*
175                                          * The expected low byte of
176                                          * dp->d_namlen is our dp->d_type.
177                                          * The high MBZ byte of dp->d_namlen
178                                          * is our dp->d_namlen.
179                                          */
180                                         dp->d_type = dp->d_namlen;
181                                         dp->d_namlen = 0;
182 #                               else
183                                         /*
184                                          * The dp->d_type is the high byte
185                                          * of the expected dp->d_namlen,
186                                          * so must be zero'ed.
187                                          */
188                                         dp->d_type = 0;
189 #                               endif
190                                 if (dp->d_reclen > 0) {
191                                         dp = (struct dirent *)
192                                             ((char *)dp + dp->d_reclen);
193                                 } else {
194                                         error = EIO;
195                                         break;
196                                 }
197                         }
198                         if (dp >= edp)
199                                 error = uiomove(dirbuf, readcnt, &auio);
200                 }
201                 FREE(dirbuf, M_TEMP);
202         }
203         VOP_UNLOCK(vp, NULL, 0, td);
204         if (error)
205                 return (error);
206         if (uap->count == auio.uio_resid) {
207                 if (union_dircheckp) {
208                         error = union_dircheckp(td, &vp, fp);
209                         if (error == -1)
210                                 goto unionread;
211                         if (error)
212                                 return (error);
213                 }
214                 if ((vp->v_flag & VROOT) &&
215                     (vp->v_mount->mnt_flag & MNT_UNION)) {
216                         struct vnode *tvp = vp;
217                         vp = vp->v_mount->mnt_vnodecovered;
218                         VREF(vp);
219                         fp->f_data = (caddr_t) vp;
220                         fp->f_offset = 0;
221                         vrele(tvp);
222                         goto unionread;
223                 }
224         }
225         error = copyout(&loff, uap->basep, sizeof(long));
226         uap->sysmsg_result = uap->count - auio.uio_resid;
227         return (error);
228 }