1 /* $NetBSD: vfs_syscalls_43.c,v 1.50 2009/03/17 00:01:54 dyoung Exp $ */
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.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_43.c,v 1.50 2009/03/17 00:01:54 dyoung Exp $");
42 #if defined(_KERNEL_OPT)
43 #include "opt_compat_netbsd.h"
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/filedesc.h>
50 #include <sys/kernel.h>
53 #include <sys/vnode.h>
54 #include <sys/namei.h>
55 #include <sys/dirent.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
59 #include <sys/malloc.h>
60 #include <sys/ioctl.h>
61 #include <sys/fcntl.h>
62 #include <sys/syslog.h>
63 #include <sys/unistd.h>
64 #include <sys/resourcevar.h>
65 #include <sys/sysctl.h>
67 #include <sys/mount.h>
68 #include <sys/syscallargs.h>
69 #include <sys/vfs_syscalls.h>
71 #include <compat/sys/stat.h>
72 #include <compat/sys/mount.h>
74 #include <compat/common/compat_util.h>
76 static void cvtstat(struct stat
*, struct stat43
*);
79 * Convert from an old to a new stat structure.
82 cvtstat(struct stat
*st
, struct stat43
*ost
)
85 ost
->st_dev
= st
->st_dev
;
86 ost
->st_ino
= st
->st_ino
;
87 ost
->st_mode
= st
->st_mode
& 0xffff;
88 ost
->st_nlink
= st
->st_nlink
;
89 ost
->st_uid
= st
->st_uid
;
90 ost
->st_gid
= st
->st_gid
;
91 ost
->st_rdev
= st
->st_rdev
;
92 if (st
->st_size
< (quad_t
)1 << 32)
93 ost
->st_size
= st
->st_size
;
96 ost
->st_atime
= st
->st_atime
;
97 ost
->st_mtime
= st
->st_mtime
;
98 ost
->st_ctime
= st
->st_ctime
;
99 ost
->st_blksize
= st
->st_blksize
;
100 ost
->st_blocks
= st
->st_blocks
;
101 ost
->st_flags
= st
->st_flags
;
102 ost
->st_gen
= st
->st_gen
;
106 * Get file status; this version follows links.
110 compat_43_sys_stat(struct lwp
*l
, const struct compat_43_sys_stat_args
*uap
, register_t
*retval
)
113 syscallarg(char *) path;
114 syscallarg(struct stat43 *) ub;
120 error
= do_sys_stat(SCARG(uap
, path
), FOLLOW
, &sb
);
124 error
= copyout((void *)&osb
, (void *)SCARG(uap
, ub
), sizeof (osb
));
129 * Get file status; this version does not follow links.
133 compat_43_sys_lstat(struct lwp
*l
, const struct compat_43_sys_lstat_args
*uap
, register_t
*retval
)
136 syscallarg(char *) path;
137 syscallarg(struct ostat *) ub;
139 struct vnode
*vp
, *dvp
;
146 ndflags
= NOFOLLOW
| LOCKLEAF
| LOCKPARENT
| TRYEMULROOT
;
148 NDINIT(&nd
, LOOKUP
, ndflags
, UIO_USERSPACE
, SCARG(uap
, path
));
149 if ((error
= namei(&nd
))) {
150 if (error
== EISDIR
&& (ndflags
& LOCKPARENT
) != 0) {
152 * Should only happen on '/'. Retry without LOCKPARENT;
153 * this is safe since the vnode won't be a VLNK.
155 ndflags
&= ~LOCKPARENT
;
161 * For symbolic links, always return the attributes of its
162 * containing directory, except for mode, size, and links.
166 if (vp
->v_type
!= VLNK
) {
167 if ((ndflags
& LOCKPARENT
) != 0) {
173 error
= vn_stat(vp
, &sb
);
178 error
= vn_stat(dvp
, &sb
);
184 error
= vn_stat(vp
, &sb1
);
188 sb
.st_mode
&= ~S_IFDIR
;
189 sb
.st_mode
|= S_IFLNK
;
190 sb
.st_nlink
= sb1
.st_nlink
;
191 sb
.st_size
= sb1
.st_size
;
192 sb
.st_blocks
= sb1
.st_blocks
;
195 error
= copyout((void *)&osb
, (void *)SCARG(uap
, ub
), sizeof (osb
));
200 * Return status information about a file descriptor.
204 compat_43_sys_fstat(struct lwp
*l
, const struct compat_43_sys_fstat_args
*uap
, register_t
*retval
)
208 syscallarg(struct stat43 *) sb;
214 error
= do_sys_fstat(SCARG(uap
, fd
), &ub
);
217 error
= copyout((void *)&oub
, (void *)SCARG(uap
, sb
),
226 * Truncate a file given a file descriptor.
230 compat_43_sys_ftruncate(struct lwp
*l
, const struct compat_43_sys_ftruncate_args
*uap
, register_t
*retval
)
234 syscallarg(long) length;
236 struct sys_ftruncate_args
/* {
239 syscallarg(off_t) length;
242 SCARG(&nuap
, fd
) = SCARG(uap
, fd
);
243 SCARG(&nuap
, length
) = SCARG(uap
, length
);
244 return (sys_ftruncate(l
, &nuap
, retval
));
248 * Truncate a file given its path name.
252 compat_43_sys_truncate(struct lwp
*l
, const struct compat_43_sys_truncate_args
*uap
, register_t
*retval
)
255 syscallarg(char *) path;
256 syscallarg(long) length;
258 struct sys_truncate_args
/* {
259 syscallarg(char *) path;
261 syscallarg(off_t) length;
264 SCARG(&nuap
, path
) = SCARG(uap
, path
);
265 SCARG(&nuap
, length
) = SCARG(uap
, length
);
266 return (sys_truncate(l
, &nuap
, retval
));
271 * Reposition read/write file offset.
274 compat_43_sys_lseek(struct lwp
*l
, const struct compat_43_sys_lseek_args
*uap
, register_t
*retval
)
278 syscallarg(long) offset;
279 syscallarg(int) whence;
281 struct sys_lseek_args
/* {
284 syscallarg(off_t) offset;
285 syscallarg(int) whence;
290 SCARG(&nuap
, fd
) = SCARG(uap
, fd
);
291 SCARG(&nuap
, offset
) = SCARG(uap
, offset
);
292 SCARG(&nuap
, whence
) = SCARG(uap
, whence
);
293 error
= sys_lseek(l
, &nuap
, (void *)&qret
);
294 *(long *)retval
= qret
;
303 compat_43_sys_creat(struct lwp
*l
, const struct compat_43_sys_creat_args
*uap
, register_t
*retval
)
306 syscallarg(char *) path;
307 syscallarg(int) mode;
309 struct sys_open_args
/* {
310 syscallarg(char *) path;
311 syscallarg(int) flags;
312 syscallarg(int) mode;
315 SCARG(&nuap
, path
) = SCARG(uap
, path
);
316 SCARG(&nuap
, mode
) = SCARG(uap
, mode
);
317 SCARG(&nuap
, flags
) = O_WRONLY
| O_CREAT
| O_TRUNC
;
318 return (sys_open(l
, &nuap
, retval
));
323 compat_43_sys_quota(struct lwp
*l
, const void *v
, register_t
*retval
)
331 * Read a block of directory entries in a file system independent format.
334 compat_43_sys_getdirentries(struct lwp
*l
, const struct compat_43_sys_getdirentries_args
*uap
, register_t
*retval
)
338 syscallarg(char *) buf;
339 syscallarg(u_int) count;
340 syscallarg(long *) basep;
344 struct uio auio
, kuio
;
345 struct iovec aiov
, kiov
;
346 struct dirent
*dp
, *edp
;
348 size_t count
= min(MAXBSIZE
, (size_t)SCARG(uap
, count
));
350 int error
, eofflag
, readcnt
;
353 /* fd_getvnode() will use the descriptor for us */
354 if ((error
= fd_getvnode(SCARG(uap
, fd
), &fp
)) != 0)
356 if ((fp
->f_flag
& FREAD
) == 0) {
360 vp
= (struct vnode
*)fp
->f_data
;
362 if (vp
->v_type
!= VDIR
) {
366 aiov
.iov_base
= SCARG(uap
, buf
);
367 aiov
.iov_len
= count
;
368 auio
.uio_iov
= &aiov
;
370 auio
.uio_rw
= UIO_READ
;
371 auio
.uio_resid
= count
;
372 KASSERT(l
== curlwp
);
373 auio
.uio_vmspace
= curproc
->p_vmspace
;
374 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
375 loff
= auio
.uio_offset
= fp
->f_offset
;
376 # if (BYTE_ORDER != LITTLE_ENDIAN)
377 if ((vp
->v_mount
->mnt_iflag
& IMNT_DTYPE
) == 0) {
378 error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
,
379 (off_t
**)0, (int *)0);
380 fp
->f_offset
= auio
.uio_offset
;
385 kuio
.uio_iov
= &kiov
;
386 kiov
.iov_len
= count
;
387 dirbuf
= malloc(count
, M_TEMP
, M_WAITOK
);
388 kiov
.iov_base
= dirbuf
;
389 UIO_SETUP_SYSSPACE(&kuio
);
390 error
= VOP_READDIR(vp
, &kuio
, fp
->f_cred
, &eofflag
,
391 (off_t
**)0, (int *)0);
392 fp
->f_offset
= kuio
.uio_offset
;
394 readcnt
= count
- kuio
.uio_resid
;
395 edp
= (struct dirent
*)&dirbuf
[readcnt
];
396 for (dp
= (struct dirent
*)dirbuf
; dp
< edp
; ) {
397 # if (BYTE_ORDER == LITTLE_ENDIAN)
399 * The expected low byte of
400 * dp->d_namlen is our dp->d_type.
401 * The high MBZ byte of dp->d_namlen
402 * is our dp->d_namlen.
404 dp
->d_type
= dp
->d_namlen
;
408 * The dp->d_type is the high byte
409 * of the expected dp->d_namlen,
410 * so must be zero'ed.
414 if (dp
->d_reclen
> 0) {
415 dp
= (struct dirent
*)
416 ((char *)dp
+ dp
->d_reclen
);
423 error
= uiomove(dirbuf
, readcnt
, &auio
);
425 free(dirbuf
, M_TEMP
);
431 if ((count
== auio
.uio_resid
) &&
432 (vp
->v_vflag
& VV_ROOT
) &&
433 (vp
->v_mount
->mnt_flag
& MNT_UNION
)) {
434 struct vnode
*tvp
= vp
;
435 vp
= vp
->v_mount
->mnt_vnodecovered
;
437 fp
->f_data
= (void *) vp
;
442 error
= copyout((void *)&loff
, (void *)SCARG(uap
, basep
),
444 *retval
= count
- auio
.uio_resid
;
446 fd_putfile(SCARG(uap
, fd
));
451 * sysctl helper routine for vfs.generic.conf lookups.
453 #if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_44)
454 static struct sysctllog
*compat_clog
;
457 sysctl_vfs_generic_conf(SYSCTLFN_ARGS
)
460 extern const char * const mountcompatnames
[];
461 extern int nmountcompatnames
;
462 struct sysctlnode node
;
469 if (vfsnum
>= nmountcompatnames
||
470 mountcompatnames
[vfsnum
] == NULL
)
472 vfsp
= vfs_getopsbyname(mountcompatnames
[vfsnum
]);
476 vfc
.vfc_vfsops
= vfsp
;
477 strncpy(vfc
.vfc_name
, vfsp
->vfs_name
, sizeof(vfc
.vfc_name
));
478 vfc
.vfc_typenum
= vfsnum
;
479 vfc
.vfc_refcount
= vfsp
->vfs_refcount
;
481 vfc
.vfc_mountroot
= vfsp
->vfs_mountroot
;
486 node
.sysctl_data
= &vfc
;
487 return (sysctl_lookup(SYSCTLFN_CALL(&node
)));
491 * Top level filesystem related information gathering.
494 compat_sysctl_init(void)
496 extern int nmountcompatnames
;
498 sysctl_createv(&compat_clog
, 0, NULL
, NULL
,
499 CTLFLAG_PERMANENT
|CTLFLAG_IMMEDIATE
,
500 CTLTYPE_INT
, "maxtypenum",
501 SYSCTL_DESCR("Highest valid filesystem type number"),
502 NULL
, nmountcompatnames
, NULL
, 0,
503 CTL_VFS
, VFS_GENERIC
, VFS_MAXTYPENUM
, CTL_EOL
);
504 sysctl_createv(&compat_clog
, 0, NULL
, NULL
,
506 CTLTYPE_STRUCT
, "conf",
507 SYSCTL_DESCR("Filesystem configuration information"),
508 sysctl_vfs_generic_conf
, 0, NULL
,
509 sizeof(struct vfsconf
),
510 CTL_VFS
, VFS_GENERIC
, VFS_CONF
, CTL_EOL
);
514 compat_sysctl_fini(void)
517 sysctl_teardown(&compat_clog
);