eb2fdf826a4aa795ad06f46ac112ca0111c419bb
[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.11 2006/09/05 00:55:44 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 <sys/mplock2.h>
67
68 #include <vfs/union/union.h>
69
70 /*
71  * MPALMOSTSAFE
72  */
73 int
74 sys_ocreat(struct ocreat_args *uap)
75 {
76         struct nlookupdata nd;
77         int error;
78
79         get_mplock();
80         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
81         if (error == 0) {
82                 error = kern_open(&nd, O_WRONLY | O_CREAT | O_TRUNC, 
83                                     uap->mode, &uap->sysmsg_iresult);
84         }
85         rel_mplock();
86         return (error);
87 }
88
89 /*
90  * MPALMOSTSAFE
91  */
92 int
93 sys_oftruncate(struct oftruncate_args *uap)
94 {
95         int error;
96
97         get_mplock();
98         error = kern_ftruncate(uap->fd, uap->length);
99         rel_mplock();
100
101         return (error);
102 }
103
104 /*
105  * MPSAFE
106  */
107 int
108 sys_olseek(struct olseek_args *uap)
109 {
110         int error;
111
112         error = kern_lseek(uap->fd, uap->offset, uap->whence,
113                            &uap->sysmsg_offset);
114
115         return (error);
116 }
117
118 /*
119  * MPALMOSTSAFE
120  */
121 int
122 sys_otruncate(struct otruncate_args *uap)
123 {
124         struct nlookupdata nd;
125         int error;
126
127         get_mplock();
128         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
129         if (error == 0)
130                 error = kern_truncate(&nd, uap->length);
131         nlookup_done(&nd);
132         rel_mplock();
133         return (error);
134 }
135
136 #define PADDED_SIZE(x)  \
137         ((sizeof(struct odirent) + (x) + 1 + 3) & ~3)
138 #define MAX_NAMELEN     255
139
140 struct odirent {
141         uint32_t        od_fileno;
142         uint16_t        od_reclen;
143         uint8_t         od_type;
144         uint8_t         od_namlen;
145         char            od_name[];
146 };
147
148 /*
149  * MPALMOSTSAFE
150  */
151 int
152 sys_ogetdirentries(struct ogetdirentries_args *uap)
153 {
154         int error, bytes_transfered;
155         char *buf, *outbuf;
156         size_t len;
157         struct dirent *ndp;
158         struct odirent *destdp;
159         long base;
160
161         if (uap->count > 16384)
162                 len = 16384;
163         else
164                 len = uap->count;
165
166         buf = kmalloc(len, M_TEMP, M_WAITOK);
167
168         get_mplock();
169         error = kern_getdirentries(uap->fd, buf, len,
170                                    &base, &bytes_transfered, UIO_SYSSPACE);
171         rel_mplock();
172
173         if (error) {
174                 kfree(buf, M_TEMP);
175                 return(error);
176         }
177
178         ndp = (struct dirent *)buf;
179         outbuf = uap->buf;
180         destdp = kmalloc(PADDED_SIZE(MAX_NAMELEN), M_TEMP, M_WAITOK);
181
182         for (; (char *)ndp < buf + bytes_transfered; ndp = _DIRENT_NEXT(ndp)) {
183                 if ((char *)_DIRENT_NEXT(ndp) > buf + bytes_transfered)
184                         break;
185                 if (ndp->d_namlen > MAX_NAMELEN)
186                         continue;
187                 destdp->od_fileno = ndp->d_ino;
188 #if BYTE_ORDER == LITTLE_ENDIAN
189                 destdp->od_type = ndp->d_namlen;
190                 destdp->od_namlen = ndp->d_type;
191 #else
192                 destdp->od_type = ndp->d_type;
193                 destdp->od_namlen = ndp->d_namlen;
194 #endif
195                 destdp->od_reclen = PADDED_SIZE(destdp->od_namlen);
196                 if (destdp->od_reclen > len)
197                         break; /* XXX can not happen */
198                 bcopy(ndp->d_name, destdp->od_name, destdp->od_namlen);
199                 bzero(destdp->od_name + destdp->od_namlen,
200                     PADDED_SIZE(destdp->od_namlen) - sizeof(*destdp) -
201                     destdp->od_namlen);
202                 error = copyout(destdp, outbuf,
203                     PADDED_SIZE(destdp->od_namlen));
204                 if (error)
205                         break;
206                 outbuf += PADDED_SIZE(destdp->od_namlen);
207                 len -= PADDED_SIZE(destdp->od_namlen);
208         }
209
210         kfree(destdp, M_TEMP);
211         kfree(buf, M_TEMP);
212         uap->sysmsg_iresult = (int)(outbuf - uap->buf);
213         return (0);
214 }