1 /* $NetBSD: vfs_syscalls_30.c,v 1.29 2009/01/11 02:45:47 christos Exp $ */
4 * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_30.c,v 1.29 2009/01/11 02:45:47 christos Exp $");
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/namei.h>
37 #include <sys/filedesc.h>
38 #include <sys/kernel.h>
41 #include <sys/socketvar.h>
42 #include <sys/vnode.h>
43 #include <sys/mount.h>
46 #include <sys/dirent.h>
47 #include <sys/malloc.h>
48 #include <sys/kauth.h>
49 #include <sys/vfs_syscalls.h>
51 #include <sys/syscallargs.h>
53 #include <compat/common/compat_util.h>
54 #include <compat/sys/stat.h>
55 #include <compat/sys/dirent.h>
56 #include <compat/sys/mount.h>
58 static void cvtstat(struct stat13
*, const struct stat
*);
61 * Convert from a new to an old stat structure.
64 cvtstat(struct stat13
*ost
, const struct stat
*st
)
67 ost
->st_dev
= st
->st_dev
;
68 ost
->st_ino
= (uint32_t)st
->st_ino
;
69 ost
->st_mode
= st
->st_mode
;
70 ost
->st_nlink
= st
->st_nlink
;
71 ost
->st_uid
= st
->st_uid
;
72 ost
->st_gid
= st
->st_gid
;
73 ost
->st_rdev
= st
->st_rdev
;
74 timespec_to_timespec50(&st
->st_atimespec
, &ost
->st_atimespec
);
75 timespec_to_timespec50(&st
->st_mtimespec
, &ost
->st_mtimespec
);
76 timespec_to_timespec50(&st
->st_ctimespec
, &ost
->st_ctimespec
);
77 timespec_to_timespec50(&st
->st_birthtimespec
, &ost
->st_birthtimespec
);
78 ost
->st_size
= st
->st_size
;
79 ost
->st_blocks
= st
->st_blocks
;
80 ost
->st_blksize
= st
->st_blksize
;
81 ost
->st_flags
= st
->st_flags
;
82 ost
->st_gen
= st
->st_gen
;
86 * Get file status; this version follows links.
90 compat_30_sys___stat13(struct lwp
*l
, const struct compat_30_sys___stat13_args
*uap
, register_t
*retval
)
93 syscallarg(const char *) path;
94 syscallarg(struct stat13 *) ub;
100 error
= do_sys_stat(SCARG(uap
, path
), FOLLOW
, &sb
);
104 error
= copyout(&osb
, SCARG(uap
, ub
), sizeof (osb
));
110 * Get file status; this version does not follow links.
114 compat_30_sys___lstat13(struct lwp
*l
, const struct compat_30_sys___lstat13_args
*uap
, register_t
*retval
)
117 syscallarg(const char *) path;
118 syscallarg(struct stat13 *) ub;
124 error
= do_sys_stat(SCARG(uap
, path
), NOFOLLOW
, &sb
);
128 error
= copyout(&osb
, SCARG(uap
, ub
), sizeof (osb
));
134 compat_30_sys_fhstat(struct lwp
*l
, const struct compat_30_sys_fhstat_args
*uap
, register_t
*retval
)
137 syscallarg(const struct compat_30_fhandle *) fhp;
138 syscallarg(struct stat13 *) sb;
143 struct compat_30_fhandle fh
;
150 if ((error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FILEHANDLE
,
151 0, NULL
, NULL
, NULL
)))
154 if ((error
= copyin(SCARG(uap
, fhp
), &fh
, sizeof(fh
))) != 0)
157 if ((mp
= vfs_getvfs(&fh
.fh_fsid
)) == NULL
)
159 if (mp
->mnt_op
->vfs_fhtovp
== NULL
)
161 if ((error
= VFS_FHTOVP(mp
, (struct fid
*)&fh
.fh_fid
, &vp
)))
163 error
= vn_stat(vp
, &sb
);
168 error
= copyout(&osb
, SCARG(uap
, sb
), sizeof(sb
));
173 * Return status information about a file descriptor.
177 compat_30_sys___fstat13(struct lwp
*l
, const struct compat_30_sys___fstat13_args
*uap
, register_t
*retval
)
181 syscallarg(struct stat13 *) sb;
187 error
= do_sys_fstat(SCARG(uap
, fd
), &sb
);
191 error
= copyout(&osb
, SCARG(uap
, sb
), sizeof (osb
));
196 * Read a block of directory entries in a file system independent format.
199 compat_30_sys_getdents(struct lwp
*l
, const struct compat_30_sys_getdents_args
*uap
, register_t
*retval
)
203 syscallarg(char *) buf;
204 syscallarg(size_t) count;
208 char *inp
, *tbuf
; /* BSD-format */
209 int len
, reclen
; /* BSD-format */
210 char *outp
; /* NetBSD-3.0-format */
216 off_t off
; /* true file offset */
217 int buflen
, error
, eofflag
;
218 off_t
*cookiebuf
= NULL
, *cookie
;
221 /* fd_getvnode() will use the descriptor for us */
222 if ((error
= fd_getvnode(SCARG(uap
, fd
), &fp
)) != 0)
225 if ((fp
->f_flag
& FREAD
) == 0) {
231 if (vp
->v_type
!= VDIR
) {
236 buflen
= min(MAXBSIZE
, SCARG(uap
, count
));
237 tbuf
= malloc(buflen
, M_TEMP
, M_WAITOK
);
238 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
241 aiov
.iov_base
= tbuf
;
242 aiov
.iov_len
= buflen
;
243 auio
.uio_iov
= &aiov
;
245 auio
.uio_rw
= UIO_READ
;
246 auio
.uio_resid
= buflen
;
247 auio
.uio_offset
= off
;
248 UIO_SETUP_SYSSPACE(&auio
);
250 * First we read into the malloc'ed buffer, then
251 * we massage it into user space, one record at a time.
253 error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
, &cookiebuf
,
259 outp
= SCARG(uap
, buf
);
260 resid
= SCARG(uap
, count
);
261 if ((len
= buflen
- auio
.uio_resid
) == 0)
264 for (cookie
= cookiebuf
; len
> 0; len
-= reclen
) {
265 bdp
= (struct dirent
*)inp
;
266 reclen
= bdp
->d_reclen
;
267 if (reclen
& _DIRENT_ALIGN(bdp
))
268 panic("netbsd30_getdents: bad reclen %d", reclen
);
270 off
= *cookie
++; /* each entry points to the next */
273 if ((off
>> 32) != 0) {
274 compat_offseterr(vp
, "netbsd30_getdents");
278 if (bdp
->d_namlen
>= sizeof(idb
.d_name
))
279 idb
.d_namlen
= sizeof(idb
.d_name
) - 1;
281 idb
.d_namlen
= bdp
->d_namlen
;
282 idb
.d_reclen
= _DIRENT_SIZE(&idb
);
283 if (reclen
> len
|| resid
< idb
.d_reclen
) {
284 /* entry too big for buffer, so just stop */
289 * Massage in place to make a NetBSD-3.0-shaped dirent
290 * (otherwise we have to worry about touching user memory
291 * outside of the copyout() call).
293 idb
.d_fileno
= (u_int32_t
)bdp
->d_fileno
;
294 idb
.d_type
= bdp
->d_type
;
295 (void)memcpy(idb
.d_name
, bdp
->d_name
, idb
.d_namlen
);
296 memset(idb
.d_name
+ idb
.d_namlen
, 0,
297 idb
.d_reclen
- _DIRENT_NAMEOFF(&idb
) - idb
.d_namlen
);
298 if ((error
= copyout(&idb
, outp
, idb
.d_reclen
)) != 0)
300 /* advance past this real entry */
302 /* advance output past NetBSD-3.0-shaped entry */
303 outp
+= idb
.d_reclen
;
304 resid
-= idb
.d_reclen
;
307 /* if we squished out the whole block, try again */
308 if (outp
== SCARG(uap
, buf
))
310 fp
->f_offset
= off
; /* update the vnode offset */
313 *retval
= SCARG(uap
, count
) - resid
;
317 free(cookiebuf
, M_TEMP
);
320 fd_putfile(SCARG(uap
, fd
));
325 * Get file handle system call
328 compat_30_sys_getfh(struct lwp
*l
, const struct compat_30_sys_getfh_args
*uap
, register_t
*retval
)
331 syscallarg(char *) fname;
332 syscallarg(struct compat_30_fhandle *) fhp;
335 struct compat_30_fhandle fh
;
343 error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FILEHANDLE
,
344 0, NULL
, NULL
, NULL
);
347 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| TRYEMULROOT
, UIO_USERSPACE
,
353 sz
= sizeof(struct compat_30_fhandle
);
354 error
= vfs_composefh(vp
, (void *)&fh
, &sz
);
356 if (sz
!= FHANDLE_SIZE_COMPAT
) {
361 error
= copyout(&fh
, SCARG(uap
, fhp
), sizeof(struct compat_30_fhandle
));
366 * Open a file given a file handle.
368 * Check permissions, allocate an open file structure,
369 * and call the device open routine if any.
372 compat_30_sys_fhopen(struct lwp
*l
, const struct compat_30_sys_fhopen_args
*uap
, register_t
*retval
)
375 syscallarg(const fhandle_t *) fhp;
376 syscallarg(int) flags;
379 return dofhopen(l
, SCARG(uap
, fhp
), FHANDLE_SIZE_COMPAT
,
380 SCARG(uap
, flags
), retval
);
385 compat_30_sys___fhstat30(struct lwp
*l
, const struct compat_30_sys___fhstat30_args
*uap_30
, register_t
*retval
)
388 syscallarg(const fhandle_t *) fhp;
389 syscallarg(struct stat30 *) sb;
395 error
= do_fhstat(l
, SCARG(uap_30
, fhp
), FHANDLE_SIZE_COMPAT
, &sb
);
399 error
= copyout(&osb
, SCARG(uap_30
, sb
), sizeof (osb
));
405 compat_30_sys_fhstatvfs1(struct lwp
*l
, const struct compat_30_sys_fhstatvfs1_args
*uap_30
, register_t
*retval
)
408 syscallarg(const fhandle_t *) fhp;
409 syscallarg(struct statvfs *) buf;
410 syscallarg(int) flags;
412 struct sys___fhstatvfs140_args uap
;
414 SCARG(&uap
, fhp
) = SCARG(uap_30
, fhp
);
415 SCARG(&uap
, fh_size
) = FHANDLE_SIZE_COMPAT
;
416 SCARG(&uap
, buf
) = SCARG(uap_30
, buf
);
417 SCARG(&uap
, flags
) = SCARG(uap_30
, flags
);
419 return sys___fhstatvfs140(l
, &uap
, retval
);