Merge from vendor branch NTPD:
[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.7 2004/11/12 00:09:10 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/uio.h>
62 #include <sys/namei.h>
63 #include <sys/nlookup.h>
64 #include <sys/vnode.h>
65
66 #include <vfs/union/union.h>
67
68 int
69 ocreat(struct ocreat_args *uap)
70 {
71         struct nlookupdata nd;
72         int error;
73
74         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
75         if (error == 0) {
76                 error = kern_open(&nd, O_WRONLY | O_CREAT | O_TRUNC, 
77                                     uap->mode, &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 nlookupdata nd;
107         int error;
108
109         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
110         if (error == 0)
111                 error = kern_truncate(&nd, uap->length);
112         nlookup_done(&nd);
113         return (error);
114 }
115
116 int
117 ogetdirentries(struct ogetdirentries_args *uap)
118 {
119         struct thread *td = curthread;
120         struct proc *p = td->td_proc;
121         struct vnode *vp;
122         struct file *fp;
123         struct uio auio, kuio;
124         struct iovec aiov, kiov;
125         struct dirent *dp, *edp;
126         caddr_t dirbuf;
127         int error, eofflag, readcnt;
128         long loff;
129
130         /* XXX arbitrary sanity limit on `count'. */
131         if (uap->count > 64 * 1024)
132                 return (EINVAL);
133         if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0)
134                 return (error);
135         if ((fp->f_flag & FREAD) == 0)
136                 return (EBADF);
137         vp = (struct vnode *)fp->f_data;
138 unionread:
139         if (vp->v_type != VDIR)
140                 return (EINVAL);
141         aiov.iov_base = uap->buf;
142         aiov.iov_len = uap->count;
143         auio.uio_iov = &aiov;
144         auio.uio_iovcnt = 1;
145         auio.uio_rw = UIO_READ;
146         auio.uio_segflg = UIO_USERSPACE;
147         auio.uio_td = td;
148         auio.uio_resid = uap->count;
149         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
150         loff = auio.uio_offset = fp->f_offset;
151 #       if (BYTE_ORDER != LITTLE_ENDIAN)
152                 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
153                         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
154                             NULL, NULL);
155                         fp->f_offset = auio.uio_offset;
156                 } else
157 #       endif
158         {
159                 kuio = auio;
160                 kuio.uio_iov = &kiov;
161                 kuio.uio_segflg = UIO_SYSSPACE;
162                 kiov.iov_len = uap->count;
163                 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
164                 kiov.iov_base = dirbuf;
165                 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
166                             NULL, NULL);
167                 fp->f_offset = kuio.uio_offset;
168                 if (error == 0) {
169                         readcnt = uap->count - kuio.uio_resid;
170                         edp = (struct dirent *)&dirbuf[readcnt];
171                         for (dp = (struct dirent *)dirbuf; dp < edp; ) {
172 #                               if (BYTE_ORDER == LITTLE_ENDIAN)
173                                         /*
174                                          * The expected low byte of
175                                          * dp->d_namlen is our dp->d_type.
176                                          * The high MBZ byte of dp->d_namlen
177                                          * is our dp->d_namlen.
178                                          */
179                                         dp->d_type = dp->d_namlen;
180                                         dp->d_namlen = 0;
181 #                               else
182                                         /*
183                                          * The dp->d_type is the high byte
184                                          * of the expected dp->d_namlen,
185                                          * so must be zero'ed.
186                                          */
187                                         dp->d_type = 0;
188 #                               endif
189                                 if (dp->d_reclen > 0) {
190                                         dp = (struct dirent *)
191                                             ((char *)dp + dp->d_reclen);
192                                 } else {
193                                         error = EIO;
194                                         break;
195                                 }
196                         }
197                         if (dp >= edp)
198                                 error = uiomove(dirbuf, readcnt, &auio);
199                 }
200                 FREE(dirbuf, M_TEMP);
201         }
202         VOP_UNLOCK(vp, 0, td);
203         if (error)
204                 return (error);
205         if (uap->count == auio.uio_resid) {
206                 if (union_dircheckp) {
207                         error = union_dircheckp(td, &vp, fp);
208                         if (error == -1)
209                                 goto unionread;
210                         if (error)
211                                 return (error);
212                 }
213                 if ((vp->v_flag & VROOT) &&
214                     (vp->v_mount->mnt_flag & MNT_UNION)) {
215                         struct vnode *tvp = vp;
216                         vp = vp->v_mount->mnt_vnodecovered;
217                         vref(vp);
218                         fp->f_data = (caddr_t) vp;
219                         fp->f_offset = 0;
220                         vrele(tvp);
221                         goto unionread;
222                 }
223         }
224         error = copyout(&loff, uap->basep, sizeof(long));
225         uap->sysmsg_result = uap->count - auio.uio_resid;
226         return (error);
227 }