Sync usage with man page.
[netbsd-mini2440.git] / sys / compat / osf1 / osf1_file.c
blobf0f9db9879675f45bf545b60e2754f2332a236d7
1 /* $NetBSD: osf1_file.c,v 1.36 2009/05/29 09:32:41 njoly Exp $ */
3 /*
4 * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Christopher G. Demetriou
17 * for the NetBSD Project.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1994, 1995 Carnegie-Mellon University.
35 * All rights reserved.
37 * Author: Chris G. Demetriou
39 * Permission to use, copy, modify and distribute this software and
40 * its documentation is hereby granted, provided that both the copyright
41 * notice and this permission notice appear in all copies of the
42 * software, derivative works or modified versions, and any portions
43 * thereof, and that both notices appear in supporting documentation.
45 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
46 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
47 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
49 * Carnegie Mellon requests users of this software to return to
51 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
52 * School of Computer Science
53 * Carnegie Mellon University
54 * Pittsburgh PA 15213-3890
56 * any improvements or extensions that they make and grant Carnegie the
57 * rights to redistribute these changes.
60 #include <sys/cdefs.h>
61 __KERNEL_RCSID(0, "$NetBSD: osf1_file.c,v 1.36 2009/05/29 09:32:41 njoly Exp $");
63 #if defined(_KERNEL_OPT)
64 #include "opt_syscall_debug.h"
65 #endif
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/namei.h>
70 #include <sys/proc.h>
71 #include <sys/file.h>
72 #include <sys/stat.h>
73 #include <sys/filedesc.h>
74 #include <sys/kernel.h>
75 #include <sys/malloc.h>
76 #include <sys/mman.h>
77 #include <sys/mount.h>
78 #include <sys/signal.h>
79 #include <sys/signalvar.h>
80 #include <sys/reboot.h>
81 #include <sys/syscallargs.h>
82 #include <sys/exec.h>
83 #include <sys/vnode.h>
84 #include <sys/socketvar.h>
85 #include <sys/resource.h>
86 #include <sys/resourcevar.h>
87 #include <sys/wait.h>
88 #include <sys/vfs_syscalls.h>
89 #include <sys/dirent.h>
91 #include <compat/osf1/osf1.h>
92 #include <compat/osf1/osf1_syscallargs.h>
93 #include <compat/common/compat_util.h>
94 #include <compat/osf1/osf1_cvt.h>
95 #include <compat/osf1/osf1_dirent.h>
97 int
98 osf1_sys_access(struct lwp *l, const struct osf1_sys_access_args *uap, register_t *retval)
100 struct sys_access_args a;
101 unsigned long leftovers;
103 SCARG(&a, path) = SCARG(uap, path);
105 /* translate flags */
106 SCARG(&a, flags) = emul_flags_translate(osf1_access_flags_xtab,
107 SCARG(uap, flags), &leftovers);
108 if (leftovers != 0)
109 return (EINVAL);
111 return sys_access(l, &a, retval);
115 osf1_sys_execve(struct lwp *l, const struct osf1_sys_execve_args *uap, register_t *retval)
117 struct sys_execve_args ap;
119 SCARG(&ap, path) = SCARG(uap, path);
120 SCARG(&ap, argp) = SCARG(uap, argp);
121 SCARG(&ap, envp) = SCARG(uap, envp);
123 return sys_execve(l, &ap, retval);
127 osf1_sys_getdirentries(struct lwp *l, const struct osf1_sys_getdirentries_args *uap, register_t *retval)
129 /* {
130 syscallarg(int) fd;
131 syscallarg(char *) buf;
132 syscallarg(u_int) nbytes;
133 syscallarg(long *) basep;
134 } */
135 struct dirent *bdp;
136 struct vnode *vp;
137 char *inp, *buf; /* BSD-format */
138 int len, reclen; /* BSD-format */
139 char *outp; /* OSF1-format */
140 int resid, osf1_reclen; /* OSF1-format */
141 struct file *fp;
142 struct uio auio;
143 struct iovec aiov;
144 struct osf1_dirent idb;
145 off_t off, off1; /* true file offset */
146 int buflen, error, eofflag;
147 off_t *cookiebuf = NULL, *cookie;
148 int ncookies, fd;
150 fd = SCARG(uap, fd);
151 if ((error = fd_getvnode(fd, &fp)) != 0)
152 return (error);
153 if ((fp->f_flag & FREAD) == 0) {
154 error = EBADF;
155 goto out1;
158 vp = (struct vnode *)fp->f_data;
159 if (vp->v_type != VDIR) {
160 error = EINVAL;
161 goto out1;
164 buflen = min(MAXBSIZE, SCARG(uap, nbytes));
165 buf = malloc(buflen, M_TEMP, M_WAITOK);
166 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
167 off = off1 = fp->f_offset;
168 again:
169 aiov.iov_base = buf;
170 aiov.iov_len = buflen;
171 auio.uio_iov = &aiov;
172 auio.uio_iovcnt = 1;
173 auio.uio_rw = UIO_READ;
174 auio.uio_resid = buflen;
175 auio.uio_offset = off;
176 UIO_SETUP_SYSSPACE(&auio);
178 * First we read into the malloc'ed buffer, then
179 * we massage it into user space, one record at a time.
181 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
182 &ncookies);
183 if (error)
184 goto out;
186 inp = buf;
187 outp = (char *)SCARG(uap, buf);
188 resid = SCARG(uap, nbytes);
189 if ((len = buflen - auio.uio_resid) == 0)
190 goto eof;
192 for (cookie = cookiebuf; len > 0; len -= reclen) {
193 bdp = (struct dirent *)inp;
194 reclen = bdp->d_reclen;
195 if (reclen & 3)
196 panic("osf1_sys_getdirentries: bad reclen");
197 if (cookie)
198 off = *cookie++; /* each entry points to the next */
199 else
200 off += reclen;
201 if ((off >> 32) != 0) {
202 compat_offseterr(vp, "osf1_sys_getdirentries");
203 error = EINVAL;
204 goto out;
206 if (bdp->d_fileno == 0) {
207 inp += reclen; /* it is a hole; squish it out */
208 continue;
210 osf1_reclen = OSF1_RECLEN(&idb, bdp->d_namlen);
211 if (reclen > len || resid < osf1_reclen) {
212 /* entry too big for buffer, so just stop */
213 outp++;
214 break;
217 * Massage in place to make a OSF1-shaped dirent (otherwise
218 * we have to worry about touching user memory outside of
219 * the copyout() call).
221 idb.d_ino = (osf1_ino_t)bdp->d_fileno;
222 idb.d_reclen = (u_short)osf1_reclen;
223 idb.d_namlen = (u_short)bdp->d_namlen;
224 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
225 if ((error = copyout((void *)&idb, outp, osf1_reclen)))
226 goto out;
227 /* advance past this real entry */
228 inp += reclen;
229 /* advance output past OSF1-shaped entry */
230 outp += osf1_reclen;
231 resid -= osf1_reclen;
234 /* if we squished out the whole block, try again */
235 if (outp == (char *)SCARG(uap, buf))
236 goto again;
237 fp->f_offset = off; /* update the vnode offset */
239 eof:
240 *retval = SCARG(uap, nbytes) - resid;
241 out:
242 VOP_UNLOCK(vp, 0);
243 if (cookiebuf)
244 free(cookiebuf, M_TEMP);
245 free(buf, M_TEMP);
246 if (SCARG(uap, basep) != NULL)
247 error = copyout(&off1, SCARG(uap, basep), sizeof(long));
248 out1:
249 fd_putfile(fd);
250 return error;
254 * Get file status; this version does not follow links.
256 /* ARGSUSED */
258 osf1_sys_lstat(struct lwp *l, const struct osf1_sys_lstat_args *uap, register_t *retval)
260 struct stat sb;
261 struct osf1_stat osb;
262 int error;
264 error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb);
265 if (error)
266 return (error);
267 osf1_cvt_stat_from_native(&sb, &osb);
268 error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
269 return (error);
273 * Get file status; this version does not follow links.
275 /* ARGSUSED */
277 osf1_sys_lstat2(struct lwp *l, const struct osf1_sys_lstat2_args *uap, register_t *retval)
279 struct stat sb;
280 struct osf1_stat2 osb;
281 int error;
283 error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb);
284 if (error)
285 return (error);
286 osf1_cvt_stat2_from_native(&sb, &osb);
287 error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb));
288 return (error);
292 osf1_sys_mknod(struct lwp *l, const struct osf1_sys_mknod_args *uap, register_t *retval)
295 return do_sys_mknod(l, SCARG(uap, path), SCARG(uap, mode),
296 osf1_cvt_dev_to_native(SCARG(uap, dev)), retval, UIO_USERSPACE);
300 osf1_sys_open(struct lwp *l, const struct osf1_sys_open_args *uap, register_t *retval)
302 struct sys_open_args a;
303 const char *path;
304 unsigned long leftovers;
305 #ifdef SYSCALL_DEBUG
306 char pnbuf[1024];
308 if (scdebug &&
309 copyinstr(SCARG(uap, path), pnbuf, sizeof pnbuf, NULL) == 0)
310 printf("osf1_open: open: %s\n", pnbuf);
311 #endif
313 /* translate flags */
314 SCARG(&a, flags) = emul_flags_translate(osf1_open_flags_xtab,
315 SCARG(uap, flags), &leftovers);
316 if (leftovers != 0)
317 return (EINVAL);
319 /* copy mode, no translation necessary */
320 SCARG(&a, mode) = SCARG(uap, mode);
322 /* pick appropriate path */
323 path = SCARG(uap, path);
324 SCARG(&a, path) = path;
326 return sys_open(l, &a, retval);
330 osf1_sys_pathconf(struct lwp *l, const struct osf1_sys_pathconf_args *uap, register_t *retval)
332 struct sys_pathconf_args a;
333 int error;
335 SCARG(&a, path) = SCARG(uap, path);
337 error = osf1_cvt_pathconf_name_to_native(SCARG(uap, name),
338 &SCARG(&a, name));
340 if (error == 0)
341 error = sys_pathconf(l, &a, retval);
343 return (error);
347 * Get file status; this version follows links.
349 /* ARGSUSED */
351 osf1_sys_stat(struct lwp *l, const struct osf1_sys_stat_args *uap, register_t *retval)
353 struct stat sb;
354 struct osf1_stat osb;
355 int error;
357 error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb);
358 if (error)
359 return (error);
360 osf1_cvt_stat_from_native(&sb, &osb);
361 error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb));
362 return (error);
366 * Get file status; this version follows links.
368 /* ARGSUSED */
370 osf1_sys_stat2(struct lwp *l, const struct osf1_sys_stat2_args *uap, register_t *retval)
372 struct stat sb;
373 struct osf1_stat2 osb;
374 int error;
376 error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb);
377 if (error)
378 return (error);
379 osf1_cvt_stat2_from_native(&sb, &osb);
380 error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb));
381 return (error);
385 osf1_sys_truncate(struct lwp *l, const struct osf1_sys_truncate_args *uap, register_t *retval)
387 struct sys_truncate_args a;
389 SCARG(&a, path) = SCARG(uap, path);
390 SCARG(&a, PAD) = 0;
391 SCARG(&a, length) = SCARG(uap, length);
393 return sys_truncate(l, &a, retval);
397 osf1_sys_utimes(struct lwp *l, const struct osf1_sys_utimes_args *uap, register_t *retval)
399 struct osf1_timeval otv;
400 struct timeval tv[2], *tvp;
401 int error;
403 if (SCARG(uap, tptr) == NULL)
404 tvp = NULL;
405 else {
406 /* get the OSF/1 timeval argument */
407 error = copyin(SCARG(uap, tptr), &otv, sizeof otv);
408 if (error != 0)
409 return error;
411 /* fill in and copy out the NetBSD timeval */
412 tv[0].tv_sec = otv.tv_sec;
413 tv[0].tv_usec = otv.tv_usec;
414 /* Set access and modified to the same time */
415 tv[1].tv_sec = otv.tv_sec;
416 tv[1].tv_usec = otv.tv_usec;
417 tvp = tv;
420 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW,
421 tvp, UIO_SYSSPACE);