Wed Apr 22 18:18:26 2020 UTC ()
Pull up following revision(s) (requested by gdt in ticket #1534):

	sys/kern/vfs_syscalls.c: revision 1.544
	lib/libc/sys/fdatasync.2: revision 1.17

Relax fdatasync restriction that fd be writable

The restriction that a fd passed to fdatasync(2) must be writable was
added in 2003 in order to comply with POSIX.  Since then, POSIX has
removed that requirement, and POSIX-valid programs have been therefore
encountering errors on NetBSD.

Patch by Paul Ripke after discussion on netbsd-users.  Issue
discovered with pkgsrc/databases/mongodb3 as used by pkgsrc/net/unifi.


(martin)
diff -r1.16 -r1.16.56.1 src/lib/libc/sys/fdatasync.2
diff -r1.516 -r1.516.2.1 src/sys/kern/vfs_syscalls.c

cvs diff -r1.16 -r1.16.56.1 src/lib/libc/sys/fdatasync.2 (switch to unified diff)

--- src/lib/libc/sys/fdatasync.2 2008/04/30 13:10:51 1.16
+++ src/lib/libc/sys/fdatasync.2 2020/04/22 18:18:26 1.16.56.1
@@ -1,96 +1,96 @@ @@ -1,96 +1,96 @@
1.\" $NetBSD: fdatasync.2,v 1.16 2008/04/30 13:10:51 martin Exp $ 1.\" $NetBSD: fdatasync.2,v 1.16.56.1 2020/04/22 18:18:26 martin Exp $
2.\" 2.\"
3.\" Copyright (c) 1998 The NetBSD Foundation, Inc. 3.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
4.\" All rights reserved. 4.\" All rights reserved.
5.\" 5.\"
6.\" This code is derived from software contributed to The NetBSD Foundation 6.\" This code is derived from software contributed to The NetBSD Foundation
7.\" by Klaus Klein. 7.\" by Klaus Klein.
8.\" 8.\"
9.\" Redistribution and use in source and binary forms, with or without 9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions 10.\" modification, are permitted provided that the following conditions
11.\" are met: 11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright 12.\" 1. Redistributions of source code must retain the above copyright
13.\" notice, this list of conditions and the following disclaimer. 13.\" notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright 14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\" notice, this list of conditions and the following disclaimer in the 15.\" notice, this list of conditions and the following disclaimer in the
16.\" documentation and/or other materials provided with the distribution. 16.\" documentation and/or other materials provided with the distribution.
17.\" 17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28.\" POSSIBILITY OF SUCH DAMAGE. 28.\" POSSIBILITY OF SUCH DAMAGE.
29.\" 29.\"
30.Dd October 25, 2003 30.Dd October 25, 2003
31.Dt FDATASYNC 2 31.Dt FDATASYNC 2
32.Os 32.Os
33.Sh NAME 33.Sh NAME
34.Nm fdatasync 34.Nm fdatasync
35.Nd synchronize the data of a file 35.Nd synchronize the data of a file
36.Sh LIBRARY 36.Sh LIBRARY
37.Lb libc 37.Lb libc
38.Sh SYNOPSIS 38.Sh SYNOPSIS
39.In unistd.h 39.In unistd.h
40.Ft int 40.Ft int
41.Fn fdatasync "int fd" 41.Fn fdatasync "int fd"
42.Sh DESCRIPTION 42.Sh DESCRIPTION
43The 43The
44.Fn fdatasync 44.Fn fdatasync
45function forces all modified data associated with the file descriptor 45function forces all modified data associated with the file descriptor
46.Fa fd 46.Fa fd
47to be flushed to stable storage. 47to be flushed to stable storage.
48.Pp 48.Pp
49The functionality is as described for 49The functionality is as described for
50.Xr fsync 2 , 50.Xr fsync 2 ,
51with the exception that file status information need not be synchronized, 51with the exception that file status information need not be synchronized,
52which may result in a performance gain, compared to 52which may result in a performance gain, compared to
53.Xr fsync 2 . 53.Xr fsync 2 .
54This behaviour is commonly known as 54This behaviour is commonly known as
55.Bf -symbolic 55.Bf -symbolic
56synchronized I/O data integrity completion. 56synchronized I/O data integrity completion.
57.Ef 57.Ef
58.Sh RETURN VALUES 58.Sh RETURN VALUES
59A value of 0 is returned on success. 59A value of 0 is returned on success.
60Otherwise, a value \-1 is returned and 60Otherwise, a value \-1 is returned and
61.Va errno 61.Va errno
62is set to indicate the error. 62is set to indicate the error.
63.Sh ERRORS 63.Sh ERRORS
64The 64The
65.Fn fdatasync 65.Fn fdatasync
66function will fail if: 66function will fail if:
67.Bl -tag -width Er 67.Bl -tag -width Er
68.It Bq Er EBADF 68.It Bq Er EBADF
69The 69The
70.Fa fd 70.Fa fd
71argument is not a valid file descriptor open for writing. 71argument is not a valid file descriptor.
72.It Bq Er EINVAL 72.It Bq Er EINVAL
73This implementation does not support synchronized I/O for this file. 73This implementation does not support synchronized I/O for this file.
74.It Bq Er ENOSYS 74.It Bq Er ENOSYS
75The 75The
76.Fn fdatasync 76.Fn fdatasync
77function is not supported by this implementation. 77function is not supported by this implementation.
78.El 78.El
79.Pp 79.Pp
80In the event that any of the I/O operations to be performed fail, 80In the event that any of the I/O operations to be performed fail,
81.Fn fdatasync 81.Fn fdatasync
82returns the error conditions defined for 82returns the error conditions defined for
83.Xr read 2 83.Xr read 2
84and 84and
85.Xr write 2 , 85.Xr write 2 ,
86and outstanding I/O operations are not guaranteed to have been completed. 86and outstanding I/O operations are not guaranteed to have been completed.
87.Sh SEE ALSO 87.Sh SEE ALSO
88.Xr fsync 2 , 88.Xr fsync 2 ,
89.Xr open 2 , 89.Xr open 2 ,
90.Xr read 2 , 90.Xr read 2 ,
91.Xr write 2 91.Xr write 2
92.Sh STANDARDS 92.Sh STANDARDS
93The 93The
94.Fn fdatasync 94.Fn fdatasync
95function conforms to 95function conforms to
96.St -p1003.1b-93 . 96.St -p1003.1-2008 .

cvs diff -r1.516 -r1.516.2.1 src/sys/kern/vfs_syscalls.c (switch to unified diff)

--- src/sys/kern/vfs_syscalls.c 2017/06/01 02:45:13 1.516
+++ src/sys/kern/vfs_syscalls.c 2020/04/22 18:18:26 1.516.2.1
@@ -1,1072 +1,1072 @@ @@ -1,1072 +1,1072 @@
1/* $NetBSD: vfs_syscalls.c,v 1.516 2017/06/01 02:45:13 chs Exp $ */ 1/* $NetBSD: vfs_syscalls.c,v 1.516.2.1 2020/04/22 18:18:26 martin Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Copyright (c) 1989, 1993 33 * Copyright (c) 1989, 1993
34 * The Regents of the University of California. All rights reserved. 34 * The Regents of the University of California. All rights reserved.
35 * (c) UNIX System Laboratories, Inc. 35 * (c) UNIX System Laboratories, Inc.
36 * All or some portions of this file are derived from material licensed 36 * All or some portions of this file are derived from material licensed
37 * to the University of California by American Telephone and Telegraph 37 * to the University of California by American Telephone and Telegraph
38 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 38 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
39 * the permission of UNIX System Laboratories, Inc. 39 * the permission of UNIX System Laboratories, Inc.
40 * 40 *
41 * Redistribution and use in source and binary forms, with or without 41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions 42 * modification, are permitted provided that the following conditions
43 * are met: 43 * are met:
44 * 1. Redistributions of source code must retain the above copyright 44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer. 45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright 46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the 47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution. 48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors 49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software 50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission. 51 * without specific prior written permission.
52 * 52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE. 63 * SUCH DAMAGE.
64 * 64 *
65 * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95 65 * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95
66 */ 66 */
67 67
68/* 68/*
69 * Virtual File System System Calls 69 * Virtual File System System Calls
70 */ 70 */
71 71
72#include <sys/cdefs.h> 72#include <sys/cdefs.h>
73__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.516 2017/06/01 02:45:13 chs Exp $"); 73__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.516.2.1 2020/04/22 18:18:26 martin Exp $");
74 74
75#ifdef _KERNEL_OPT 75#ifdef _KERNEL_OPT
76#include "opt_fileassoc.h" 76#include "opt_fileassoc.h"
77#include "veriexec.h" 77#include "veriexec.h"
78#endif 78#endif
79 79
80#include <sys/param.h> 80#include <sys/param.h>
81#include <sys/systm.h> 81#include <sys/systm.h>
82#include <sys/namei.h> 82#include <sys/namei.h>
83#include <sys/filedesc.h> 83#include <sys/filedesc.h>
84#include <sys/kernel.h> 84#include <sys/kernel.h>
85#include <sys/file.h> 85#include <sys/file.h>
86#include <sys/fcntl.h> 86#include <sys/fcntl.h>
87#include <sys/stat.h> 87#include <sys/stat.h>
88#include <sys/vnode.h> 88#include <sys/vnode.h>
89#include <sys/mount.h> 89#include <sys/mount.h>
90#include <sys/fstrans.h> 90#include <sys/fstrans.h>
91#include <sys/proc.h> 91#include <sys/proc.h>
92#include <sys/uio.h> 92#include <sys/uio.h>
93#include <sys/kmem.h> 93#include <sys/kmem.h>
94#include <sys/dirent.h> 94#include <sys/dirent.h>
95#include <sys/sysctl.h> 95#include <sys/sysctl.h>
96#include <sys/syscallargs.h> 96#include <sys/syscallargs.h>
97#include <sys/vfs_syscalls.h> 97#include <sys/vfs_syscalls.h>
98#include <sys/quota.h> 98#include <sys/quota.h>
99#include <sys/quotactl.h> 99#include <sys/quotactl.h>
100#include <sys/ktrace.h> 100#include <sys/ktrace.h>
101#ifdef FILEASSOC 101#ifdef FILEASSOC
102#include <sys/fileassoc.h> 102#include <sys/fileassoc.h>
103#endif /* FILEASSOC */ 103#endif /* FILEASSOC */
104#include <sys/extattr.h> 104#include <sys/extattr.h>
105#include <sys/verified_exec.h> 105#include <sys/verified_exec.h>
106#include <sys/kauth.h> 106#include <sys/kauth.h>
107#include <sys/atomic.h> 107#include <sys/atomic.h>
108#include <sys/module.h> 108#include <sys/module.h>
109#include <sys/buf.h> 109#include <sys/buf.h>
110 110
111#include <miscfs/genfs/genfs.h> 111#include <miscfs/genfs/genfs.h>
112#include <miscfs/specfs/specdev.h> 112#include <miscfs/specfs/specdev.h>
113 113
114#include <nfs/rpcv2.h> 114#include <nfs/rpcv2.h>
115#include <nfs/nfsproto.h> 115#include <nfs/nfsproto.h>
116#include <nfs/nfs.h> 116#include <nfs/nfs.h>
117#include <nfs/nfs_var.h> 117#include <nfs/nfs_var.h>
118 118
119/* XXX this shouldn't be here */ 119/* XXX this shouldn't be here */
120#ifndef OFF_T_MAX 120#ifndef OFF_T_MAX
121#define OFF_T_MAX __type_max(off_t) 121#define OFF_T_MAX __type_max(off_t)
122#endif 122#endif
123 123
124static int change_flags(struct vnode *, u_long, struct lwp *); 124static int change_flags(struct vnode *, u_long, struct lwp *);
125static int change_mode(struct vnode *, int, struct lwp *); 125static int change_mode(struct vnode *, int, struct lwp *);
126static int change_owner(struct vnode *, uid_t, gid_t, struct lwp *, int); 126static int change_owner(struct vnode *, uid_t, gid_t, struct lwp *, int);
127static int do_sys_openat(lwp_t *, int, const char *, int, int, int *); 127static int do_sys_openat(lwp_t *, int, const char *, int, int, int *);
128static int do_sys_mkdirat(struct lwp *l, int, const char *, mode_t, 128static int do_sys_mkdirat(struct lwp *l, int, const char *, mode_t,
129 enum uio_seg); 129 enum uio_seg);
130static int do_sys_mkfifoat(struct lwp *, int, const char *, mode_t); 130static int do_sys_mkfifoat(struct lwp *, int, const char *, mode_t);
131static int do_sys_symlinkat(struct lwp *, const char *, int, const char *, 131static int do_sys_symlinkat(struct lwp *, const char *, int, const char *,
132 enum uio_seg); 132 enum uio_seg);
133static int do_sys_renameat(struct lwp *l, int, const char *, int, const char *, 133static int do_sys_renameat(struct lwp *l, int, const char *, int, const char *,
134 enum uio_seg, int); 134 enum uio_seg, int);
135static int do_sys_readlinkat(struct lwp *, int, const char *, char *, 135static int do_sys_readlinkat(struct lwp *, int, const char *, char *,
136 size_t, register_t *); 136 size_t, register_t *);
137static int do_sys_unlinkat(struct lwp *, int, const char *, int, enum uio_seg); 137static int do_sys_unlinkat(struct lwp *, int, const char *, int, enum uio_seg);
138 138
139static int fd_nameiat(struct lwp *, int, struct nameidata *); 139static int fd_nameiat(struct lwp *, int, struct nameidata *);
140static int fd_nameiat_simple_user(struct lwp *, int, const char *, 140static int fd_nameiat_simple_user(struct lwp *, int, const char *,
141 namei_simple_flags_t, struct vnode **); 141 namei_simple_flags_t, struct vnode **);
142 142
143 143
144/* 144/*
145 * This table is used to maintain compatibility with 4.3BSD 145 * This table is used to maintain compatibility with 4.3BSD
146 * and NetBSD 0.9 mount syscalls - and possibly other systems. 146 * and NetBSD 0.9 mount syscalls - and possibly other systems.
147 * Note, the order is important! 147 * Note, the order is important!
148 * 148 *
149 * Do not modify this table. It should only contain filesystems 149 * Do not modify this table. It should only contain filesystems
150 * supported by NetBSD 0.9 and 4.3BSD. 150 * supported by NetBSD 0.9 and 4.3BSD.
151 */ 151 */
152const char * const mountcompatnames[] = { 152const char * const mountcompatnames[] = {
153 NULL, /* 0 = MOUNT_NONE */ 153 NULL, /* 0 = MOUNT_NONE */
154 MOUNT_FFS, /* 1 = MOUNT_UFS */ 154 MOUNT_FFS, /* 1 = MOUNT_UFS */
155 MOUNT_NFS, /* 2 */ 155 MOUNT_NFS, /* 2 */
156 MOUNT_MFS, /* 3 */ 156 MOUNT_MFS, /* 3 */
157 MOUNT_MSDOS, /* 4 */ 157 MOUNT_MSDOS, /* 4 */
158 MOUNT_CD9660, /* 5 = MOUNT_ISOFS */ 158 MOUNT_CD9660, /* 5 = MOUNT_ISOFS */
159 MOUNT_FDESC, /* 6 */ 159 MOUNT_FDESC, /* 6 */
160 MOUNT_KERNFS, /* 7 */ 160 MOUNT_KERNFS, /* 7 */
161 NULL, /* 8 = MOUNT_DEVFS */ 161 NULL, /* 8 = MOUNT_DEVFS */
162 MOUNT_AFS, /* 9 */ 162 MOUNT_AFS, /* 9 */
163}; 163};
164 164
165const int nmountcompatnames = __arraycount(mountcompatnames); 165const int nmountcompatnames = __arraycount(mountcompatnames);
166 166
167static int  167static int
168fd_nameiat(struct lwp *l, int fdat, struct nameidata *ndp) 168fd_nameiat(struct lwp *l, int fdat, struct nameidata *ndp)
169{ 169{
170 file_t *dfp; 170 file_t *dfp;
171 int error; 171 int error;
172 172
173 if (fdat != AT_FDCWD) { 173 if (fdat != AT_FDCWD) {
174 if ((error = fd_getvnode(fdat, &dfp)) != 0) 174 if ((error = fd_getvnode(fdat, &dfp)) != 0)
175 goto out; 175 goto out;
176 176
177 NDAT(ndp, dfp->f_vnode); 177 NDAT(ndp, dfp->f_vnode);
178 } 178 }
179 179
180 error = namei(ndp); 180 error = namei(ndp);
181 181
182 if (fdat != AT_FDCWD) 182 if (fdat != AT_FDCWD)
183 fd_putfile(fdat); 183 fd_putfile(fdat);
184out: 184out:
185 return error;  185 return error;
186} 186}
187 187
188static int 188static int
189fd_nameiat_simple_user(struct lwp *l, int fdat, const char *path, 189fd_nameiat_simple_user(struct lwp *l, int fdat, const char *path,
190 namei_simple_flags_t sflags, struct vnode **vp_ret) 190 namei_simple_flags_t sflags, struct vnode **vp_ret)
191{ 191{
192 file_t *dfp; 192 file_t *dfp;
193 struct vnode *dvp; 193 struct vnode *dvp;
194 int error; 194 int error;
195 195
196 if (fdat != AT_FDCWD) { 196 if (fdat != AT_FDCWD) {
197 if ((error = fd_getvnode(fdat, &dfp)) != 0) 197 if ((error = fd_getvnode(fdat, &dfp)) != 0)
198 goto out; 198 goto out;
199 199
200 dvp = dfp->f_vnode; 200 dvp = dfp->f_vnode;
201 } else { 201 } else {
202 dvp = NULL; 202 dvp = NULL;
203 } 203 }
204 204
205 error = nameiat_simple_user(dvp, path, sflags, vp_ret); 205 error = nameiat_simple_user(dvp, path, sflags, vp_ret);
206 206
207 if (fdat != AT_FDCWD) 207 if (fdat != AT_FDCWD)
208 fd_putfile(fdat); 208 fd_putfile(fdat);
209out: 209out:
210 return error;  210 return error;
211} 211}
212 212
213static int 213static int
214open_setfp(struct lwp *l, file_t *fp, struct vnode *vp, int indx, int flags) 214open_setfp(struct lwp *l, file_t *fp, struct vnode *vp, int indx, int flags)
215{ 215{
216 int error; 216 int error;
217 217
218 fp->f_flag = flags & FMASK; 218 fp->f_flag = flags & FMASK;
219 fp->f_type = DTYPE_VNODE; 219 fp->f_type = DTYPE_VNODE;
220 fp->f_ops = &vnops; 220 fp->f_ops = &vnops;
221 fp->f_vnode = vp; 221 fp->f_vnode = vp;
222 222
223 if (flags & (O_EXLOCK | O_SHLOCK)) { 223 if (flags & (O_EXLOCK | O_SHLOCK)) {
224 struct flock lf; 224 struct flock lf;
225 int type; 225 int type;
226 226
227 lf.l_whence = SEEK_SET; 227 lf.l_whence = SEEK_SET;
228 lf.l_start = 0; 228 lf.l_start = 0;
229 lf.l_len = 0; 229 lf.l_len = 0;
230 if (flags & O_EXLOCK) 230 if (flags & O_EXLOCK)
231 lf.l_type = F_WRLCK; 231 lf.l_type = F_WRLCK;
232 else 232 else
233 lf.l_type = F_RDLCK; 233 lf.l_type = F_RDLCK;
234 type = F_FLOCK; 234 type = F_FLOCK;
235 if ((flags & FNONBLOCK) == 0) 235 if ((flags & FNONBLOCK) == 0)
236 type |= F_WAIT; 236 type |= F_WAIT;
237 VOP_UNLOCK(vp); 237 VOP_UNLOCK(vp);
238 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type); 238 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type);
239 if (error) { 239 if (error) {
240 (void) vn_close(vp, fp->f_flag, fp->f_cred); 240 (void) vn_close(vp, fp->f_flag, fp->f_cred);
241 fd_abort(l->l_proc, fp, indx); 241 fd_abort(l->l_proc, fp, indx);
242 return error; 242 return error;
243 } 243 }
244 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 244 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
245 atomic_or_uint(&fp->f_flag, FHASLOCK); 245 atomic_or_uint(&fp->f_flag, FHASLOCK);
246 } 246 }
247 if (flags & O_CLOEXEC) 247 if (flags & O_CLOEXEC)
248 fd_set_exclose(l, indx, true); 248 fd_set_exclose(l, indx, true);
249 return 0; 249 return 0;
250} 250}
251 251
252static int 252static int
253mount_update(struct lwp *l, struct vnode *vp, const char *path, int flags, 253mount_update(struct lwp *l, struct vnode *vp, const char *path, int flags,
254 void *data, size_t *data_len) 254 void *data, size_t *data_len)
255{ 255{
256 struct mount *mp; 256 struct mount *mp;
257 int error = 0, saved_flags; 257 int error = 0, saved_flags;
258 258
259 mp = vp->v_mount; 259 mp = vp->v_mount;
260 saved_flags = mp->mnt_flag; 260 saved_flags = mp->mnt_flag;
261 261
262 /* We can operate only on VV_ROOT nodes. */ 262 /* We can operate only on VV_ROOT nodes. */
263 if ((vp->v_vflag & VV_ROOT) == 0) { 263 if ((vp->v_vflag & VV_ROOT) == 0) {
264 error = EINVAL; 264 error = EINVAL;
265 goto out; 265 goto out;
266 } 266 }
267 267
268 /* 268 /*
269 * We only allow the filesystem to be reloaded if it 269 * We only allow the filesystem to be reloaded if it
270 * is currently mounted read-only. Additionally, we 270 * is currently mounted read-only. Additionally, we
271 * prevent read-write to read-only downgrades. 271 * prevent read-write to read-only downgrades.
272 */ 272 */
273 if ((flags & (MNT_RELOAD | MNT_RDONLY)) != 0 && 273 if ((flags & (MNT_RELOAD | MNT_RDONLY)) != 0 &&
274 (mp->mnt_flag & MNT_RDONLY) == 0 && 274 (mp->mnt_flag & MNT_RDONLY) == 0 &&
275 (mp->mnt_iflag & IMNT_CAN_RWTORO) == 0) { 275 (mp->mnt_iflag & IMNT_CAN_RWTORO) == 0) {
276 error = EOPNOTSUPP; /* Needs translation */ 276 error = EOPNOTSUPP; /* Needs translation */
277 goto out; 277 goto out;
278 } 278 }
279 279
280 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 280 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
281 KAUTH_REQ_SYSTEM_MOUNT_UPDATE, mp, KAUTH_ARG(flags), data); 281 KAUTH_REQ_SYSTEM_MOUNT_UPDATE, mp, KAUTH_ARG(flags), data);
282 if (error) 282 if (error)
283 goto out; 283 goto out;
284 284
285 error = vfs_suspend(mp, 0); 285 error = vfs_suspend(mp, 0);
286 if (error) 286 if (error)
287 goto out; 287 goto out;
288 288
289 mutex_enter(&mp->mnt_updating); 289 mutex_enter(&mp->mnt_updating);
290 290
291 mp->mnt_flag &= ~MNT_OP_FLAGS; 291 mp->mnt_flag &= ~MNT_OP_FLAGS;
292 mp->mnt_flag |= flags & MNT_OP_FLAGS; 292 mp->mnt_flag |= flags & MNT_OP_FLAGS;
293 293
294 /* 294 /*
295 * Set the mount level flags. 295 * Set the mount level flags.
296 */ 296 */
297 if ((flags & MNT_RDONLY) != (mp->mnt_flag & MNT_RDONLY)) { 297 if ((flags & MNT_RDONLY) != (mp->mnt_flag & MNT_RDONLY)) {
298 if ((flags & MNT_RDONLY)) 298 if ((flags & MNT_RDONLY))
299 mp->mnt_iflag |= IMNT_WANTRDONLY; 299 mp->mnt_iflag |= IMNT_WANTRDONLY;
300 else 300 else
301 mp->mnt_iflag |= IMNT_WANTRDWR; 301 mp->mnt_iflag |= IMNT_WANTRDWR;
302 } 302 }
303 mp->mnt_flag &= ~MNT_BASIC_FLAGS; 303 mp->mnt_flag &= ~MNT_BASIC_FLAGS;
304 mp->mnt_flag |= flags & MNT_BASIC_FLAGS; 304 mp->mnt_flag |= flags & MNT_BASIC_FLAGS;
305 if ((mp->mnt_iflag & IMNT_WANTRDONLY)) 305 if ((mp->mnt_iflag & IMNT_WANTRDONLY))
306 mp->mnt_flag &= ~MNT_RDONLY; 306 mp->mnt_flag &= ~MNT_RDONLY;
307 307
308 error = VFS_MOUNT(mp, path, data, data_len); 308 error = VFS_MOUNT(mp, path, data, data_len);
309 309
310 if (error && data != NULL) { 310 if (error && data != NULL) {
311 int error2; 311 int error2;
312 312
313 /* 313 /*
314 * Update failed; let's try and see if it was an 314 * Update failed; let's try and see if it was an
315 * export request. For compat with 3.0 and earlier. 315 * export request. For compat with 3.0 and earlier.
316 */ 316 */
317 error2 = vfs_hooks_reexport(mp, path, data); 317 error2 = vfs_hooks_reexport(mp, path, data);
318 318
319 /* 319 /*
320 * Only update error code if the export request was 320 * Only update error code if the export request was
321 * understood but some problem occurred while 321 * understood but some problem occurred while
322 * processing it. 322 * processing it.
323 */ 323 */
324 if (error2 != EJUSTRETURN) 324 if (error2 != EJUSTRETURN)
325 error = error2; 325 error = error2;
326 } 326 }
327 327
328 if (error == 0 && (mp->mnt_iflag & IMNT_WANTRDONLY)) 328 if (error == 0 && (mp->mnt_iflag & IMNT_WANTRDONLY))
329 mp->mnt_flag |= MNT_RDONLY; 329 mp->mnt_flag |= MNT_RDONLY;
330 if (error) 330 if (error)
331 mp->mnt_flag = saved_flags; 331 mp->mnt_flag = saved_flags;
332 mp->mnt_flag &= ~MNT_OP_FLAGS; 332 mp->mnt_flag &= ~MNT_OP_FLAGS;
333 mp->mnt_iflag &= ~(IMNT_WANTRDONLY | IMNT_WANTRDWR); 333 mp->mnt_iflag &= ~(IMNT_WANTRDONLY | IMNT_WANTRDWR);
334 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) { 334 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) {
335 if ((mp->mnt_iflag & IMNT_ONWORKLIST) == 0) 335 if ((mp->mnt_iflag & IMNT_ONWORKLIST) == 0)
336 vfs_syncer_add_to_worklist(mp); 336 vfs_syncer_add_to_worklist(mp);
337 } else { 337 } else {
338 if ((mp->mnt_iflag & IMNT_ONWORKLIST) != 0) 338 if ((mp->mnt_iflag & IMNT_ONWORKLIST) != 0)
339 vfs_syncer_remove_from_worklist(mp); 339 vfs_syncer_remove_from_worklist(mp);
340 } 340 }
341 mutex_exit(&mp->mnt_updating); 341 mutex_exit(&mp->mnt_updating);
342 vfs_resume(mp); 342 vfs_resume(mp);
343 343
344 if ((error == 0) && !(saved_flags & MNT_EXTATTR) &&  344 if ((error == 0) && !(saved_flags & MNT_EXTATTR) &&
345 (flags & MNT_EXTATTR)) { 345 (flags & MNT_EXTATTR)) {
346 if (VFS_EXTATTRCTL(mp, EXTATTR_CMD_START,  346 if (VFS_EXTATTRCTL(mp, EXTATTR_CMD_START,
347 NULL, 0, NULL) != 0) { 347 NULL, 0, NULL) != 0) {
348 printf("%s: failed to start extattr, error = %d", 348 printf("%s: failed to start extattr, error = %d",
349 mp->mnt_stat.f_mntonname, error); 349 mp->mnt_stat.f_mntonname, error);
350 mp->mnt_flag &= ~MNT_EXTATTR; 350 mp->mnt_flag &= ~MNT_EXTATTR;
351 } 351 }
352 } 352 }
353 353
354 if ((error == 0) && (saved_flags & MNT_EXTATTR) &&  354 if ((error == 0) && (saved_flags & MNT_EXTATTR) &&
355 !(flags & MNT_EXTATTR)) { 355 !(flags & MNT_EXTATTR)) {
356 if (VFS_EXTATTRCTL(mp, EXTATTR_CMD_STOP,  356 if (VFS_EXTATTRCTL(mp, EXTATTR_CMD_STOP,
357 NULL, 0, NULL) != 0) { 357 NULL, 0, NULL) != 0) {
358 printf("%s: failed to stop extattr, error = %d", 358 printf("%s: failed to stop extattr, error = %d",
359 mp->mnt_stat.f_mntonname, error); 359 mp->mnt_stat.f_mntonname, error);
360 mp->mnt_flag |= MNT_RDONLY; 360 mp->mnt_flag |= MNT_RDONLY;
361 } 361 }
362 } 362 }
363 out: 363 out:
364 return (error); 364 return (error);
365} 365}
366 366
367static int 367static int
368mount_get_vfsops(const char *fstype, enum uio_seg type_seg, 368mount_get_vfsops(const char *fstype, enum uio_seg type_seg,
369 struct vfsops **vfsops) 369 struct vfsops **vfsops)
370{ 370{
371 char fstypename[sizeof(((struct statvfs *)NULL)->f_fstypename)]; 371 char fstypename[sizeof(((struct statvfs *)NULL)->f_fstypename)];
372 int error; 372 int error;
373 373
374 if (type_seg == UIO_USERSPACE) { 374 if (type_seg == UIO_USERSPACE) {
375 /* Copy file-system type from userspace. */ 375 /* Copy file-system type from userspace. */
376 error = copyinstr(fstype, fstypename, sizeof(fstypename), NULL); 376 error = copyinstr(fstype, fstypename, sizeof(fstypename), NULL);
377 } else { 377 } else {
378 error = copystr(fstype, fstypename, sizeof(fstypename), NULL); 378 error = copystr(fstype, fstypename, sizeof(fstypename), NULL);
379 KASSERT(error == 0); 379 KASSERT(error == 0);
380 } 380 }
381 381
382 if (error) { 382 if (error) {
383 /* 383 /*
384 * Historically, filesystem types were identified by numbers. 384 * Historically, filesystem types were identified by numbers.
385 * If we get an integer for the filesystem type instead of a 385 * If we get an integer for the filesystem type instead of a
386 * string, we check to see if it matches one of the historic 386 * string, we check to see if it matches one of the historic
387 * filesystem types. 387 * filesystem types.
388 */ 388 */
389 u_long fsindex = (u_long)fstype; 389 u_long fsindex = (u_long)fstype;
390 if (fsindex >= nmountcompatnames || 390 if (fsindex >= nmountcompatnames ||
391 mountcompatnames[fsindex] == NULL) 391 mountcompatnames[fsindex] == NULL)
392 return ENODEV; 392 return ENODEV;
393 strlcpy(fstypename, mountcompatnames[fsindex], 393 strlcpy(fstypename, mountcompatnames[fsindex],
394 sizeof(fstypename)); 394 sizeof(fstypename));
395 } 395 }
396 396
397 /* Accept `ufs' as an alias for `ffs', for compatibility. */ 397 /* Accept `ufs' as an alias for `ffs', for compatibility. */
398 if (strcmp(fstypename, "ufs") == 0) 398 if (strcmp(fstypename, "ufs") == 0)
399 fstypename[0] = 'f'; 399 fstypename[0] = 'f';
400 400
401 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL) 401 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL)
402 return 0; 402 return 0;
403 403
404 /* If we can autoload a vfs module, try again */ 404 /* If we can autoload a vfs module, try again */
405 (void)module_autoload(fstypename, MODULE_CLASS_VFS); 405 (void)module_autoload(fstypename, MODULE_CLASS_VFS);
406 406
407 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL) 407 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL)
408 return 0; 408 return 0;
409 409
410 return ENODEV; 410 return ENODEV;
411} 411}
412 412
413static int 413static int
414mount_getargs(struct lwp *l, struct vnode *vp, const char *path, int flags, 414mount_getargs(struct lwp *l, struct vnode *vp, const char *path, int flags,
415 void *data, size_t *data_len) 415 void *data, size_t *data_len)
416{ 416{
417 struct mount *mp; 417 struct mount *mp;
418 int error; 418 int error;
419 419
420 /* If MNT_GETARGS is specified, it should be the only flag. */ 420 /* If MNT_GETARGS is specified, it should be the only flag. */
421 if (flags & ~MNT_GETARGS) 421 if (flags & ~MNT_GETARGS)
422 return EINVAL; 422 return EINVAL;
423 423
424 mp = vp->v_mount; 424 mp = vp->v_mount;
425 425
426 /* XXX: probably some notion of "can see" here if we want isolation. */  426 /* XXX: probably some notion of "can see" here if we want isolation. */
427 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 427 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
428 KAUTH_REQ_SYSTEM_MOUNT_GET, mp, data, NULL); 428 KAUTH_REQ_SYSTEM_MOUNT_GET, mp, data, NULL);
429 if (error) 429 if (error)
430 return error; 430 return error;
431 431
432 if ((vp->v_vflag & VV_ROOT) == 0) 432 if ((vp->v_vflag & VV_ROOT) == 0)
433 return EINVAL; 433 return EINVAL;
434 434
435 if (vfs_busy(mp)) 435 if (vfs_busy(mp))
436 return EPERM; 436 return EPERM;
437 437
438 mutex_enter(&mp->mnt_updating); 438 mutex_enter(&mp->mnt_updating);
439 mp->mnt_flag &= ~MNT_OP_FLAGS; 439 mp->mnt_flag &= ~MNT_OP_FLAGS;
440 mp->mnt_flag |= MNT_GETARGS; 440 mp->mnt_flag |= MNT_GETARGS;
441 error = VFS_MOUNT(mp, path, data, data_len); 441 error = VFS_MOUNT(mp, path, data, data_len);
442 mp->mnt_flag &= ~MNT_OP_FLAGS; 442 mp->mnt_flag &= ~MNT_OP_FLAGS;
443 mutex_exit(&mp->mnt_updating); 443 mutex_exit(&mp->mnt_updating);
444 444
445 vfs_unbusy(mp); 445 vfs_unbusy(mp);
446 return (error); 446 return (error);
447} 447}
448 448
449int 449int
450sys___mount50(struct lwp *l, const struct sys___mount50_args *uap, register_t *retval) 450sys___mount50(struct lwp *l, const struct sys___mount50_args *uap, register_t *retval)
451{ 451{
452 /* { 452 /* {
453 syscallarg(const char *) type; 453 syscallarg(const char *) type;
454 syscallarg(const char *) path; 454 syscallarg(const char *) path;
455 syscallarg(int) flags; 455 syscallarg(int) flags;
456 syscallarg(void *) data; 456 syscallarg(void *) data;
457 syscallarg(size_t) data_len; 457 syscallarg(size_t) data_len;
458 } */ 458 } */
459 459
460 return do_sys_mount(l, SCARG(uap, type), UIO_USERSPACE, SCARG(uap, path), 460 return do_sys_mount(l, SCARG(uap, type), UIO_USERSPACE, SCARG(uap, path),
461 SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE, 461 SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE,
462 SCARG(uap, data_len), retval); 462 SCARG(uap, data_len), retval);
463} 463}
464 464
465int 465int
466do_sys_mount(struct lwp *l, const char *type, enum uio_seg type_seg, 466do_sys_mount(struct lwp *l, const char *type, enum uio_seg type_seg,
467 const char *path, int flags, void *data, enum uio_seg data_seg, 467 const char *path, int flags, void *data, enum uio_seg data_seg,
468 size_t data_len, register_t *retval) 468 size_t data_len, register_t *retval)
469{ 469{
470 struct vfsops *vfsops = NULL; /* XXX gcc4.8 */ 470 struct vfsops *vfsops = NULL; /* XXX gcc4.8 */
471 struct vnode *vp; 471 struct vnode *vp;
472 void *data_buf = data; 472 void *data_buf = data;
473 bool vfsopsrele = false; 473 bool vfsopsrele = false;
474 size_t alloc_sz = 0; 474 size_t alloc_sz = 0;
475 int error; 475 int error;
476 476
477 /* 477 /*
478 * Get vnode to be covered 478 * Get vnode to be covered
479 */ 479 */
480 error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp); 480 error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp);
481 if (error != 0) { 481 if (error != 0) {
482 vp = NULL; 482 vp = NULL;
483 goto done; 483 goto done;
484 } 484 }
485 485
486 if (flags & (MNT_GETARGS | MNT_UPDATE)) { 486 if (flags & (MNT_GETARGS | MNT_UPDATE)) {
487 vfsops = vp->v_mount->mnt_op; 487 vfsops = vp->v_mount->mnt_op;
488 } else { 488 } else {
489 /* 'type' is userspace */ 489 /* 'type' is userspace */
490 error = mount_get_vfsops(type, type_seg, &vfsops); 490 error = mount_get_vfsops(type, type_seg, &vfsops);
491 if (error != 0) 491 if (error != 0)
492 goto done; 492 goto done;
493 vfsopsrele = true; 493 vfsopsrele = true;
494 } 494 }
495 495
496 /* 496 /*
497 * We allow data to be NULL, even for userspace. Some fs's don't need 497 * We allow data to be NULL, even for userspace. Some fs's don't need
498 * it. The others will handle NULL. 498 * it. The others will handle NULL.
499 */ 499 */
500 if (data != NULL && data_seg == UIO_USERSPACE) { 500 if (data != NULL && data_seg == UIO_USERSPACE) {
501 if (data_len == 0) { 501 if (data_len == 0) {
502 /* No length supplied, use default for filesystem */ 502 /* No length supplied, use default for filesystem */
503 data_len = vfsops->vfs_min_mount_data; 503 data_len = vfsops->vfs_min_mount_data;
504 504
505 /* 505 /*
506 * Hopefully a longer buffer won't make copyin() fail. 506 * Hopefully a longer buffer won't make copyin() fail.
507 * For compatibility with 3.0 and earlier. 507 * For compatibility with 3.0 and earlier.
508 */ 508 */
509 if (flags & MNT_UPDATE 509 if (flags & MNT_UPDATE
510 && data_len < sizeof (struct mnt_export_args30)) 510 && data_len < sizeof (struct mnt_export_args30))
511 data_len = sizeof (struct mnt_export_args30); 511 data_len = sizeof (struct mnt_export_args30);
512 } 512 }
513 if ((data_len == 0) || (data_len > VFS_MAX_MOUNT_DATA)) { 513 if ((data_len == 0) || (data_len > VFS_MAX_MOUNT_DATA)) {
514 error = EINVAL; 514 error = EINVAL;
515 goto done; 515 goto done;
516 } 516 }
517 alloc_sz = data_len; 517 alloc_sz = data_len;
518 data_buf = kmem_alloc(alloc_sz, KM_SLEEP); 518 data_buf = kmem_alloc(alloc_sz, KM_SLEEP);
519 519
520 /* NFS needs the buffer even for mnt_getargs .... */ 520 /* NFS needs the buffer even for mnt_getargs .... */
521 error = copyin(data, data_buf, data_len); 521 error = copyin(data, data_buf, data_len);
522 if (error != 0) 522 if (error != 0)
523 goto done; 523 goto done;
524 } 524 }
525 525
526 if (flags & MNT_GETARGS) { 526 if (flags & MNT_GETARGS) {
527 if (data_len == 0) { 527 if (data_len == 0) {
528 error = EINVAL; 528 error = EINVAL;
529 goto done; 529 goto done;
530 } 530 }
531 error = mount_getargs(l, vp, path, flags, data_buf, &data_len); 531 error = mount_getargs(l, vp, path, flags, data_buf, &data_len);
532 if (error != 0) 532 if (error != 0)
533 goto done; 533 goto done;
534 if (data_seg == UIO_USERSPACE) 534 if (data_seg == UIO_USERSPACE)
535 error = copyout(data_buf, data, data_len); 535 error = copyout(data_buf, data, data_len);
536 *retval = data_len; 536 *retval = data_len;
537 } else if (flags & MNT_UPDATE) { 537 } else if (flags & MNT_UPDATE) {
538 error = mount_update(l, vp, path, flags, data_buf, &data_len); 538 error = mount_update(l, vp, path, flags, data_buf, &data_len);
539 } else { 539 } else {
540 /* Locking is handled internally in mount_domount(). */ 540 /* Locking is handled internally in mount_domount(). */
541 KASSERT(vfsopsrele == true); 541 KASSERT(vfsopsrele == true);
542 error = mount_domount(l, &vp, vfsops, path, flags, data_buf, 542 error = mount_domount(l, &vp, vfsops, path, flags, data_buf,
543 &data_len); 543 &data_len);
544 vfsopsrele = false; 544 vfsopsrele = false;
545 } 545 }
546 546
547 done: 547 done:
548 if (vfsopsrele) 548 if (vfsopsrele)
549 vfs_delref(vfsops); 549 vfs_delref(vfsops);
550 if (vp != NULL) { 550 if (vp != NULL) {
551 vrele(vp); 551 vrele(vp);
552 } 552 }
553 if (data_buf != data) 553 if (data_buf != data)
554 kmem_free(data_buf, alloc_sz); 554 kmem_free(data_buf, alloc_sz);
555 return (error); 555 return (error);
556} 556}
557 557
558/* 558/*
559 * Unmount a file system. 559 * Unmount a file system.
560 * 560 *
561 * Note: unmount takes a path to the vnode mounted on as argument, 561 * Note: unmount takes a path to the vnode mounted on as argument,
562 * not special file (as before). 562 * not special file (as before).
563 */ 563 */
564/* ARGSUSED */ 564/* ARGSUSED */
565int 565int
566sys_unmount(struct lwp *l, const struct sys_unmount_args *uap, register_t *retval) 566sys_unmount(struct lwp *l, const struct sys_unmount_args *uap, register_t *retval)
567{ 567{
568 /* { 568 /* {
569 syscallarg(const char *) path; 569 syscallarg(const char *) path;
570 syscallarg(int) flags; 570 syscallarg(int) flags;
571 } */ 571 } */
572 struct vnode *vp; 572 struct vnode *vp;
573 struct mount *mp; 573 struct mount *mp;
574 int error; 574 int error;
575 struct pathbuf *pb; 575 struct pathbuf *pb;
576 struct nameidata nd; 576 struct nameidata nd;
577 577
578 error = pathbuf_copyin(SCARG(uap, path), &pb); 578 error = pathbuf_copyin(SCARG(uap, path), &pb);
579 if (error) { 579 if (error) {
580 return error; 580 return error;
581 } 581 }
582 582
583 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | TRYEMULROOT, pb); 583 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | TRYEMULROOT, pb);
584 if ((error = namei(&nd)) != 0) { 584 if ((error = namei(&nd)) != 0) {
585 pathbuf_destroy(pb); 585 pathbuf_destroy(pb);
586 return error; 586 return error;
587 } 587 }
588 vp = nd.ni_vp; 588 vp = nd.ni_vp;
589 pathbuf_destroy(pb); 589 pathbuf_destroy(pb);
590 590
591 mp = vp->v_mount; 591 mp = vp->v_mount;
592 vfs_ref(mp); 592 vfs_ref(mp);
593 VOP_UNLOCK(vp); 593 VOP_UNLOCK(vp);
594 594
595 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 595 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
596 KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, mp, NULL, NULL); 596 KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, mp, NULL, NULL);
597 if (error) { 597 if (error) {
598 vrele(vp); 598 vrele(vp);
599 vfs_rele(mp); 599 vfs_rele(mp);
600 return (error); 600 return (error);
601 } 601 }
602 602
603 /* 603 /*
604 * Don't allow unmounting the root file system. 604 * Don't allow unmounting the root file system.
605 */ 605 */
606 if (mp->mnt_flag & MNT_ROOTFS) { 606 if (mp->mnt_flag & MNT_ROOTFS) {
607 vrele(vp); 607 vrele(vp);
608 vfs_rele(mp); 608 vfs_rele(mp);
609 return (EINVAL); 609 return (EINVAL);
610 } 610 }
611 611
612 /* 612 /*
613 * Must be the root of the filesystem 613 * Must be the root of the filesystem
614 */ 614 */
615 if ((vp->v_vflag & VV_ROOT) == 0) { 615 if ((vp->v_vflag & VV_ROOT) == 0) {
616 vrele(vp); 616 vrele(vp);
617 vfs_rele(mp); 617 vfs_rele(mp);
618 return (EINVAL); 618 return (EINVAL);
619 } 619 }
620 620
621 vrele(vp); 621 vrele(vp);
622 error = dounmount(mp, SCARG(uap, flags), l); 622 error = dounmount(mp, SCARG(uap, flags), l);
623 vfs_rele(mp); 623 vfs_rele(mp);
624 return error; 624 return error;
625} 625}
626 626
627/* 627/*
628 * Sync each mounted filesystem. 628 * Sync each mounted filesystem.
629 */ 629 */
630#ifdef DEBUG 630#ifdef DEBUG
631int syncprt = 0; 631int syncprt = 0;
632struct ctldebug debug0 = { "syncprt", &syncprt }; 632struct ctldebug debug0 = { "syncprt", &syncprt };
633#endif 633#endif
634 634
635void 635void
636do_sys_sync(struct lwp *l) 636do_sys_sync(struct lwp *l)
637{ 637{
638 mount_iterator_t *iter; 638 mount_iterator_t *iter;
639 struct mount *mp; 639 struct mount *mp;
640 int asyncflag; 640 int asyncflag;
641 641
642 mountlist_iterator_init(&iter); 642 mountlist_iterator_init(&iter);
643 while ((mp = mountlist_iterator_next(iter)) != NULL) { 643 while ((mp = mountlist_iterator_next(iter)) != NULL) {
644 mutex_enter(&mp->mnt_updating); 644 mutex_enter(&mp->mnt_updating);
645 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 645 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
646 asyncflag = mp->mnt_flag & MNT_ASYNC; 646 asyncflag = mp->mnt_flag & MNT_ASYNC;
647 mp->mnt_flag &= ~MNT_ASYNC; 647 mp->mnt_flag &= ~MNT_ASYNC;
648 VFS_SYNC(mp, MNT_NOWAIT, l->l_cred); 648 VFS_SYNC(mp, MNT_NOWAIT, l->l_cred);
649 if (asyncflag) 649 if (asyncflag)
650 mp->mnt_flag |= MNT_ASYNC; 650 mp->mnt_flag |= MNT_ASYNC;
651 } 651 }
652 mutex_exit(&mp->mnt_updating); 652 mutex_exit(&mp->mnt_updating);
653 } 653 }
654 mountlist_iterator_destroy(iter); 654 mountlist_iterator_destroy(iter);
655#ifdef DEBUG 655#ifdef DEBUG
656 if (syncprt) 656 if (syncprt)
657 vfs_bufstats(); 657 vfs_bufstats();
658#endif /* DEBUG */ 658#endif /* DEBUG */
659} 659}
660 660
661/* ARGSUSED */ 661/* ARGSUSED */
662int 662int
663sys_sync(struct lwp *l, const void *v, register_t *retval) 663sys_sync(struct lwp *l, const void *v, register_t *retval)
664{ 664{
665 do_sys_sync(l); 665 do_sys_sync(l);
666 return (0); 666 return (0);
667} 667}
668 668
669 669
670/* 670/*
671 * Access or change filesystem quotas. 671 * Access or change filesystem quotas.
672 * 672 *
673 * (this is really 14 different calls bundled into one) 673 * (this is really 14 different calls bundled into one)
674 */ 674 */
675 675
676static int 676static int
677do_sys_quotactl_stat(struct mount *mp, struct quotastat *info_u) 677do_sys_quotactl_stat(struct mount *mp, struct quotastat *info_u)
678{ 678{
679 struct quotastat info_k; 679 struct quotastat info_k;
680 int error; 680 int error;
681 681
682 /* ensure any padding bytes are cleared */ 682 /* ensure any padding bytes are cleared */
683 memset(&info_k, 0, sizeof(info_k)); 683 memset(&info_k, 0, sizeof(info_k));
684 684
685 error = vfs_quotactl_stat(mp, &info_k); 685 error = vfs_quotactl_stat(mp, &info_k);
686 if (error) { 686 if (error) {
687 return error; 687 return error;
688 } 688 }
689 689
690 return copyout(&info_k, info_u, sizeof(info_k)); 690 return copyout(&info_k, info_u, sizeof(info_k));
691} 691}
692 692
693static int 693static int
694do_sys_quotactl_idtypestat(struct mount *mp, int idtype, 694do_sys_quotactl_idtypestat(struct mount *mp, int idtype,
695 struct quotaidtypestat *info_u) 695 struct quotaidtypestat *info_u)
696{ 696{
697 struct quotaidtypestat info_k; 697 struct quotaidtypestat info_k;
698 int error; 698 int error;
699 699
700 /* ensure any padding bytes are cleared */ 700 /* ensure any padding bytes are cleared */
701 memset(&info_k, 0, sizeof(info_k)); 701 memset(&info_k, 0, sizeof(info_k));
702 702
703 error = vfs_quotactl_idtypestat(mp, idtype, &info_k); 703 error = vfs_quotactl_idtypestat(mp, idtype, &info_k);
704 if (error) { 704 if (error) {
705 return error; 705 return error;
706 } 706 }
707 707
708 return copyout(&info_k, info_u, sizeof(info_k)); 708 return copyout(&info_k, info_u, sizeof(info_k));
709} 709}
710 710
711static int 711static int
712do_sys_quotactl_objtypestat(struct mount *mp, int objtype, 712do_sys_quotactl_objtypestat(struct mount *mp, int objtype,
713 struct quotaobjtypestat *info_u) 713 struct quotaobjtypestat *info_u)
714{ 714{
715 struct quotaobjtypestat info_k; 715 struct quotaobjtypestat info_k;
716 int error; 716 int error;
717 717
718 /* ensure any padding bytes are cleared */ 718 /* ensure any padding bytes are cleared */
719 memset(&info_k, 0, sizeof(info_k)); 719 memset(&info_k, 0, sizeof(info_k));
720 720
721 error = vfs_quotactl_objtypestat(mp, objtype, &info_k); 721 error = vfs_quotactl_objtypestat(mp, objtype, &info_k);
722 if (error) { 722 if (error) {
723 return error; 723 return error;
724 } 724 }
725 725
726 return copyout(&info_k, info_u, sizeof(info_k)); 726 return copyout(&info_k, info_u, sizeof(info_k));
727} 727}
728 728
729static int 729static int
730do_sys_quotactl_get(struct mount *mp, const struct quotakey *key_u, 730do_sys_quotactl_get(struct mount *mp, const struct quotakey *key_u,
731 struct quotaval *val_u) 731 struct quotaval *val_u)
732{ 732{
733 struct quotakey key_k; 733 struct quotakey key_k;
734 struct quotaval val_k; 734 struct quotaval val_k;
735 int error; 735 int error;
736 736
737 /* ensure any padding bytes are cleared */ 737 /* ensure any padding bytes are cleared */
738 memset(&val_k, 0, sizeof(val_k)); 738 memset(&val_k, 0, sizeof(val_k));
739 739
740 error = copyin(key_u, &key_k, sizeof(key_k)); 740 error = copyin(key_u, &key_k, sizeof(key_k));
741 if (error) { 741 if (error) {
742 return error; 742 return error;
743 } 743 }
744 744
745 error = vfs_quotactl_get(mp, &key_k, &val_k); 745 error = vfs_quotactl_get(mp, &key_k, &val_k);
746 if (error) { 746 if (error) {
747 return error; 747 return error;
748 } 748 }
749 749
750 return copyout(&val_k, val_u, sizeof(val_k)); 750 return copyout(&val_k, val_u, sizeof(val_k));
751} 751}
752 752
753static int 753static int
754do_sys_quotactl_put(struct mount *mp, const struct quotakey *key_u, 754do_sys_quotactl_put(struct mount *mp, const struct quotakey *key_u,
755 const struct quotaval *val_u) 755 const struct quotaval *val_u)
756{ 756{
757 struct quotakey key_k; 757 struct quotakey key_k;
758 struct quotaval val_k; 758 struct quotaval val_k;
759 int error; 759 int error;
760 760
761 error = copyin(key_u, &key_k, sizeof(key_k)); 761 error = copyin(key_u, &key_k, sizeof(key_k));
762 if (error) { 762 if (error) {
763 return error; 763 return error;
764 } 764 }
765 765
766 error = copyin(val_u, &val_k, sizeof(val_k)); 766 error = copyin(val_u, &val_k, sizeof(val_k));
767 if (error) { 767 if (error) {
768 return error; 768 return error;
769 } 769 }
770 770
771 return vfs_quotactl_put(mp, &key_k, &val_k); 771 return vfs_quotactl_put(mp, &key_k, &val_k);
772} 772}
773 773
774static int 774static int
775do_sys_quotactl_del(struct mount *mp, const struct quotakey *key_u) 775do_sys_quotactl_del(struct mount *mp, const struct quotakey *key_u)
776{ 776{
777 struct quotakey key_k; 777 struct quotakey key_k;
778 int error; 778 int error;
779 779
780 error = copyin(key_u, &key_k, sizeof(key_k)); 780 error = copyin(key_u, &key_k, sizeof(key_k));
781 if (error) { 781 if (error) {
782 return error; 782 return error;
783 } 783 }
784 784
785 return vfs_quotactl_del(mp, &key_k); 785 return vfs_quotactl_del(mp, &key_k);
786} 786}
787 787
788static int 788static int
789do_sys_quotactl_cursoropen(struct mount *mp, struct quotakcursor *cursor_u) 789do_sys_quotactl_cursoropen(struct mount *mp, struct quotakcursor *cursor_u)
790{ 790{
791 struct quotakcursor cursor_k; 791 struct quotakcursor cursor_k;
792 int error; 792 int error;
793 793
794 /* ensure any padding bytes are cleared */ 794 /* ensure any padding bytes are cleared */
795 memset(&cursor_k, 0, sizeof(cursor_k)); 795 memset(&cursor_k, 0, sizeof(cursor_k));
796 796
797 error = vfs_quotactl_cursoropen(mp, &cursor_k); 797 error = vfs_quotactl_cursoropen(mp, &cursor_k);
798 if (error) { 798 if (error) {
799 return error; 799 return error;
800 } 800 }
801 801
802 return copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 802 return copyout(&cursor_k, cursor_u, sizeof(cursor_k));
803} 803}
804 804
805static int 805static int
806do_sys_quotactl_cursorclose(struct mount *mp, struct quotakcursor *cursor_u) 806do_sys_quotactl_cursorclose(struct mount *mp, struct quotakcursor *cursor_u)
807{ 807{
808 struct quotakcursor cursor_k; 808 struct quotakcursor cursor_k;
809 int error; 809 int error;
810 810
811 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 811 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
812 if (error) { 812 if (error) {
813 return error; 813 return error;
814 } 814 }
815 815
816 return vfs_quotactl_cursorclose(mp, &cursor_k); 816 return vfs_quotactl_cursorclose(mp, &cursor_k);
817} 817}
818 818
819static int 819static int
820do_sys_quotactl_cursorskipidtype(struct mount *mp, 820do_sys_quotactl_cursorskipidtype(struct mount *mp,
821 struct quotakcursor *cursor_u, int idtype) 821 struct quotakcursor *cursor_u, int idtype)
822{ 822{
823 struct quotakcursor cursor_k; 823 struct quotakcursor cursor_k;
824 int error; 824 int error;
825 825
826 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 826 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
827 if (error) { 827 if (error) {
828 return error; 828 return error;
829 } 829 }
830 830
831 error = vfs_quotactl_cursorskipidtype(mp, &cursor_k, idtype); 831 error = vfs_quotactl_cursorskipidtype(mp, &cursor_k, idtype);
832 if (error) { 832 if (error) {
833 return error; 833 return error;
834 } 834 }
835 835
836 return copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 836 return copyout(&cursor_k, cursor_u, sizeof(cursor_k));
837} 837}
838 838
839static int 839static int
840do_sys_quotactl_cursorget(struct mount *mp, struct quotakcursor *cursor_u, 840do_sys_quotactl_cursorget(struct mount *mp, struct quotakcursor *cursor_u,
841 struct quotakey *keys_u, struct quotaval *vals_u, unsigned maxnum, 841 struct quotakey *keys_u, struct quotaval *vals_u, unsigned maxnum,
842 unsigned *ret_u) 842 unsigned *ret_u)
843{ 843{
844#define CGET_STACK_MAX 8 844#define CGET_STACK_MAX 8
845 struct quotakcursor cursor_k; 845 struct quotakcursor cursor_k;
846 struct quotakey stackkeys[CGET_STACK_MAX]; 846 struct quotakey stackkeys[CGET_STACK_MAX];
847 struct quotaval stackvals[CGET_STACK_MAX]; 847 struct quotaval stackvals[CGET_STACK_MAX];
848 struct quotakey *keys_k; 848 struct quotakey *keys_k;
849 struct quotaval *vals_k; 849 struct quotaval *vals_k;
850 unsigned ret_k; 850 unsigned ret_k;
851 int error; 851 int error;
852 852
853 if (maxnum > 128) { 853 if (maxnum > 128) {
854 maxnum = 128; 854 maxnum = 128;
855 } 855 }
856 856
857 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 857 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
858 if (error) { 858 if (error) {
859 return error; 859 return error;
860 } 860 }
861 861
862 if (maxnum <= CGET_STACK_MAX) { 862 if (maxnum <= CGET_STACK_MAX) {
863 keys_k = stackkeys; 863 keys_k = stackkeys;
864 vals_k = stackvals; 864 vals_k = stackvals;
865 /* ensure any padding bytes are cleared */ 865 /* ensure any padding bytes are cleared */
866 memset(keys_k, 0, maxnum * sizeof(keys_k[0])); 866 memset(keys_k, 0, maxnum * sizeof(keys_k[0]));
867 memset(vals_k, 0, maxnum * sizeof(vals_k[0])); 867 memset(vals_k, 0, maxnum * sizeof(vals_k[0]));
868 } else { 868 } else {
869 keys_k = kmem_zalloc(maxnum * sizeof(keys_k[0]), KM_SLEEP); 869 keys_k = kmem_zalloc(maxnum * sizeof(keys_k[0]), KM_SLEEP);
870 vals_k = kmem_zalloc(maxnum * sizeof(vals_k[0]), KM_SLEEP); 870 vals_k = kmem_zalloc(maxnum * sizeof(vals_k[0]), KM_SLEEP);
871 } 871 }
872 872
873 error = vfs_quotactl_cursorget(mp, &cursor_k, keys_k, vals_k, maxnum, 873 error = vfs_quotactl_cursorget(mp, &cursor_k, keys_k, vals_k, maxnum,
874 &ret_k); 874 &ret_k);
875 if (error) { 875 if (error) {
876 goto fail; 876 goto fail;
877 } 877 }
878 878
879 error = copyout(keys_k, keys_u, ret_k * sizeof(keys_k[0])); 879 error = copyout(keys_k, keys_u, ret_k * sizeof(keys_k[0]));
880 if (error) { 880 if (error) {
881 goto fail; 881 goto fail;
882 } 882 }
883 883
884 error = copyout(vals_k, vals_u, ret_k * sizeof(vals_k[0])); 884 error = copyout(vals_k, vals_u, ret_k * sizeof(vals_k[0]));
885 if (error) { 885 if (error) {
886 goto fail; 886 goto fail;
887 } 887 }
888 888
889 error = copyout(&ret_k, ret_u, sizeof(ret_k)); 889 error = copyout(&ret_k, ret_u, sizeof(ret_k));
890 if (error) { 890 if (error) {
891 goto fail; 891 goto fail;
892 } 892 }
893 893
894 /* do last to maximize the chance of being able to recover a failure */ 894 /* do last to maximize the chance of being able to recover a failure */
895 error = copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 895 error = copyout(&cursor_k, cursor_u, sizeof(cursor_k));
896 896
897fail: 897fail:
898 if (keys_k != stackkeys) { 898 if (keys_k != stackkeys) {
899 kmem_free(keys_k, maxnum * sizeof(keys_k[0])); 899 kmem_free(keys_k, maxnum * sizeof(keys_k[0]));
900 } 900 }
901 if (vals_k != stackvals) { 901 if (vals_k != stackvals) {
902 kmem_free(vals_k, maxnum * sizeof(vals_k[0])); 902 kmem_free(vals_k, maxnum * sizeof(vals_k[0]));
903 } 903 }
904 return error; 904 return error;
905} 905}
906 906
907static int 907static int
908do_sys_quotactl_cursoratend(struct mount *mp, struct quotakcursor *cursor_u, 908do_sys_quotactl_cursoratend(struct mount *mp, struct quotakcursor *cursor_u,
909 int *ret_u) 909 int *ret_u)
910{ 910{
911 struct quotakcursor cursor_k; 911 struct quotakcursor cursor_k;
912 int ret_k; 912 int ret_k;
913 int error; 913 int error;
914 914
915 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 915 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
916 if (error) { 916 if (error) {
917 return error; 917 return error;
918 } 918 }
919 919
920 error = vfs_quotactl_cursoratend(mp, &cursor_k, &ret_k); 920 error = vfs_quotactl_cursoratend(mp, &cursor_k, &ret_k);
921 if (error) { 921 if (error) {
922 return error; 922 return error;
923 } 923 }
924 924
925 error = copyout(&ret_k, ret_u, sizeof(ret_k)); 925 error = copyout(&ret_k, ret_u, sizeof(ret_k));
926 if (error) { 926 if (error) {
927 return error; 927 return error;
928 } 928 }
929 929
930 return copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 930 return copyout(&cursor_k, cursor_u, sizeof(cursor_k));
931} 931}
932 932
933static int 933static int
934do_sys_quotactl_cursorrewind(struct mount *mp, struct quotakcursor *cursor_u) 934do_sys_quotactl_cursorrewind(struct mount *mp, struct quotakcursor *cursor_u)
935{ 935{
936 struct quotakcursor cursor_k; 936 struct quotakcursor cursor_k;
937 int error; 937 int error;
938 938
939 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 939 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k));
940 if (error) { 940 if (error) {
941 return error; 941 return error;
942 } 942 }
943 943
944 error = vfs_quotactl_cursorrewind(mp, &cursor_k); 944 error = vfs_quotactl_cursorrewind(mp, &cursor_k);
945 if (error) { 945 if (error) {
946 return error; 946 return error;
947 } 947 }
948 948
949 return copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 949 return copyout(&cursor_k, cursor_u, sizeof(cursor_k));
950} 950}
951 951
952static int 952static int
953do_sys_quotactl_quotaon(struct mount *mp, int idtype, const char *path_u) 953do_sys_quotactl_quotaon(struct mount *mp, int idtype, const char *path_u)
954{ 954{
955 char *path_k; 955 char *path_k;
956 int error; 956 int error;
957 957
958 /* XXX this should probably be a struct pathbuf */ 958 /* XXX this should probably be a struct pathbuf */
959 path_k = PNBUF_GET(); 959 path_k = PNBUF_GET();
960 error = copyin(path_u, path_k, PATH_MAX); 960 error = copyin(path_u, path_k, PATH_MAX);
961 if (error) { 961 if (error) {
962 PNBUF_PUT(path_k); 962 PNBUF_PUT(path_k);
963 return error; 963 return error;
964 } 964 }
965 965
966 error = vfs_quotactl_quotaon(mp, idtype, path_k); 966 error = vfs_quotactl_quotaon(mp, idtype, path_k);
967 967
968 PNBUF_PUT(path_k); 968 PNBUF_PUT(path_k);
969 return error; 969 return error;
970} 970}
971 971
972static int 972static int
973do_sys_quotactl_quotaoff(struct mount *mp, int idtype) 973do_sys_quotactl_quotaoff(struct mount *mp, int idtype)
974{ 974{
975 return vfs_quotactl_quotaoff(mp, idtype); 975 return vfs_quotactl_quotaoff(mp, idtype);
976} 976}
977 977
978int 978int
979do_sys_quotactl(const char *path_u, const struct quotactl_args *args) 979do_sys_quotactl(const char *path_u, const struct quotactl_args *args)
980{ 980{
981 struct mount *mp; 981 struct mount *mp;
982 struct vnode *vp; 982 struct vnode *vp;
983 int error; 983 int error;
984 984
985 error = namei_simple_user(path_u, NSM_FOLLOW_TRYEMULROOT, &vp); 985 error = namei_simple_user(path_u, NSM_FOLLOW_TRYEMULROOT, &vp);
986 if (error != 0) 986 if (error != 0)
987 return (error); 987 return (error);
988 mp = vp->v_mount; 988 mp = vp->v_mount;
989 989
990 switch (args->qc_op) { 990 switch (args->qc_op) {
991 case QUOTACTL_STAT: 991 case QUOTACTL_STAT:
992 error = do_sys_quotactl_stat(mp, args->u.stat.qc_info); 992 error = do_sys_quotactl_stat(mp, args->u.stat.qc_info);
993 break; 993 break;
994 case QUOTACTL_IDTYPESTAT: 994 case QUOTACTL_IDTYPESTAT:
995 error = do_sys_quotactl_idtypestat(mp, 995 error = do_sys_quotactl_idtypestat(mp,
996 args->u.idtypestat.qc_idtype, 996 args->u.idtypestat.qc_idtype,
997 args->u.idtypestat.qc_info); 997 args->u.idtypestat.qc_info);
998 break; 998 break;
999 case QUOTACTL_OBJTYPESTAT: 999 case QUOTACTL_OBJTYPESTAT:
1000 error = do_sys_quotactl_objtypestat(mp, 1000 error = do_sys_quotactl_objtypestat(mp,
1001 args->u.objtypestat.qc_objtype, 1001 args->u.objtypestat.qc_objtype,
1002 args->u.objtypestat.qc_info); 1002 args->u.objtypestat.qc_info);
1003 break; 1003 break;
1004 case QUOTACTL_GET: 1004 case QUOTACTL_GET:
1005 error = do_sys_quotactl_get(mp, 1005 error = do_sys_quotactl_get(mp,
1006 args->u.get.qc_key, 1006 args->u.get.qc_key,
1007 args->u.get.qc_val); 1007 args->u.get.qc_val);
1008 break; 1008 break;
1009 case QUOTACTL_PUT: 1009 case QUOTACTL_PUT:
1010 error = do_sys_quotactl_put(mp, 1010 error = do_sys_quotactl_put(mp,
1011 args->u.put.qc_key, 1011 args->u.put.qc_key,
1012 args->u.put.qc_val); 1012 args->u.put.qc_val);
1013 break; 1013 break;
1014 case QUOTACTL_DEL: 1014 case QUOTACTL_DEL:
1015 error = do_sys_quotactl_del(mp, args->u.del.qc_key); 1015 error = do_sys_quotactl_del(mp, args->u.del.qc_key);
1016 break; 1016 break;
1017 case QUOTACTL_CURSOROPEN: 1017 case QUOTACTL_CURSOROPEN:
1018 error = do_sys_quotactl_cursoropen(mp, 1018 error = do_sys_quotactl_cursoropen(mp,
1019 args->u.cursoropen.qc_cursor); 1019 args->u.cursoropen.qc_cursor);
1020 break; 1020 break;
1021 case QUOTACTL_CURSORCLOSE: 1021 case QUOTACTL_CURSORCLOSE:
1022 error = do_sys_quotactl_cursorclose(mp, 1022 error = do_sys_quotactl_cursorclose(mp,
1023 args->u.cursorclose.qc_cursor); 1023 args->u.cursorclose.qc_cursor);
1024 break; 1024 break;
1025 case QUOTACTL_CURSORSKIPIDTYPE: 1025 case QUOTACTL_CURSORSKIPIDTYPE:
1026 error = do_sys_quotactl_cursorskipidtype(mp, 1026 error = do_sys_quotactl_cursorskipidtype(mp,
1027 args->u.cursorskipidtype.qc_cursor, 1027 args->u.cursorskipidtype.qc_cursor,
1028 args->u.cursorskipidtype.qc_idtype); 1028 args->u.cursorskipidtype.qc_idtype);
1029 break; 1029 break;
1030 case QUOTACTL_CURSORGET: 1030 case QUOTACTL_CURSORGET:
1031 error = do_sys_quotactl_cursorget(mp, 1031 error = do_sys_quotactl_cursorget(mp,
1032 args->u.cursorget.qc_cursor, 1032 args->u.cursorget.qc_cursor,
1033 args->u.cursorget.qc_keys, 1033 args->u.cursorget.qc_keys,
1034 args->u.cursorget.qc_vals, 1034 args->u.cursorget.qc_vals,
1035 args->u.cursorget.qc_maxnum, 1035 args->u.cursorget.qc_maxnum,
1036 args->u.cursorget.qc_ret); 1036 args->u.cursorget.qc_ret);
1037 break; 1037 break;
1038 case QUOTACTL_CURSORATEND: 1038 case QUOTACTL_CURSORATEND:
1039 error = do_sys_quotactl_cursoratend(mp, 1039 error = do_sys_quotactl_cursoratend(mp,
1040 args->u.cursoratend.qc_cursor, 1040 args->u.cursoratend.qc_cursor,
1041 args->u.cursoratend.qc_ret); 1041 args->u.cursoratend.qc_ret);
1042 break; 1042 break;
1043 case QUOTACTL_CURSORREWIND: 1043 case QUOTACTL_CURSORREWIND:
1044 error = do_sys_quotactl_cursorrewind(mp, 1044 error = do_sys_quotactl_cursorrewind(mp,
1045 args->u.cursorrewind.qc_cursor); 1045 args->u.cursorrewind.qc_cursor);
1046 break; 1046 break;
1047 case QUOTACTL_QUOTAON: 1047 case QUOTACTL_QUOTAON:
1048 error = do_sys_quotactl_quotaon(mp, 1048 error = do_sys_quotactl_quotaon(mp,
1049 args->u.quotaon.qc_idtype, 1049 args->u.quotaon.qc_idtype,
1050 args->u.quotaon.qc_quotafile); 1050 args->u.quotaon.qc_quotafile);
1051 break; 1051 break;
1052 case QUOTACTL_QUOTAOFF: 1052 case QUOTACTL_QUOTAOFF:
1053 error = do_sys_quotactl_quotaoff(mp, 1053 error = do_sys_quotactl_quotaoff(mp,
1054 args->u.quotaoff.qc_idtype); 1054 args->u.quotaoff.qc_idtype);
1055 break; 1055 break;
1056 default: 1056 default:
1057 error = EINVAL; 1057 error = EINVAL;
1058 break; 1058 break;
1059 } 1059 }
1060 1060
1061 vrele(vp); 1061 vrele(vp);
1062 return error; 1062 return error;
1063} 1063}
1064 1064
1065/* ARGSUSED */ 1065/* ARGSUSED */
1066int 1066int
1067sys___quotactl(struct lwp *l, const struct sys___quotactl_args *uap, 1067sys___quotactl(struct lwp *l, const struct sys___quotactl_args *uap,
1068 register_t *retval) 1068 register_t *retval)
1069{ 1069{
1070 /* { 1070 /* {
1071 syscallarg(const char *) path; 1071 syscallarg(const char *) path;
1072 syscallarg(struct quotactl_args *) args; 1072 syscallarg(struct quotactl_args *) args;
@@ -3008,1789 +3008,1784 @@ sys_faccessat(struct lwp *l, const struc @@ -3008,1789 +3008,1784 @@ sys_faccessat(struct lwp *l, const struc
3008 SCARG(uap, amode), SCARG(uap, flag)); 3008 SCARG(uap, amode), SCARG(uap, flag));
3009} 3009}
3010 3010
3011/* 3011/*
3012 * Common code for all sys_stat functions, including compat versions. 3012 * Common code for all sys_stat functions, including compat versions.
3013 */ 3013 */
3014int 3014int
3015do_sys_stat(const char *userpath, unsigned int nd_flag, 3015do_sys_stat(const char *userpath, unsigned int nd_flag,
3016 struct stat *sb) 3016 struct stat *sb)
3017{ 3017{
3018 return do_sys_statat(NULL, AT_FDCWD, userpath, nd_flag, sb); 3018 return do_sys_statat(NULL, AT_FDCWD, userpath, nd_flag, sb);
3019} 3019}
3020 3020
3021int 3021int
3022do_sys_statat(struct lwp *l, int fdat, const char *userpath, 3022do_sys_statat(struct lwp *l, int fdat, const char *userpath,
3023 unsigned int nd_flag, struct stat *sb)  3023 unsigned int nd_flag, struct stat *sb)
3024{ 3024{
3025 int error; 3025 int error;
3026 struct pathbuf *pb; 3026 struct pathbuf *pb;
3027 struct nameidata nd; 3027 struct nameidata nd;
3028 3028
3029 KASSERT(l != NULL || fdat == AT_FDCWD); 3029 KASSERT(l != NULL || fdat == AT_FDCWD);
3030 3030
3031 error = pathbuf_copyin(userpath, &pb); 3031 error = pathbuf_copyin(userpath, &pb);
3032 if (error) { 3032 if (error) {
3033 return error; 3033 return error;
3034 } 3034 }
3035 3035
3036 NDINIT(&nd, LOOKUP, nd_flag | LOCKLEAF | TRYEMULROOT, pb); 3036 NDINIT(&nd, LOOKUP, nd_flag | LOCKLEAF | TRYEMULROOT, pb);
3037 3037
3038 error = fd_nameiat(l, fdat, &nd); 3038 error = fd_nameiat(l, fdat, &nd);
3039 if (error != 0) { 3039 if (error != 0) {
3040 pathbuf_destroy(pb); 3040 pathbuf_destroy(pb);
3041 return error; 3041 return error;
3042 } 3042 }
3043 error = vn_stat(nd.ni_vp, sb); 3043 error = vn_stat(nd.ni_vp, sb);
3044 vput(nd.ni_vp); 3044 vput(nd.ni_vp);
3045 pathbuf_destroy(pb); 3045 pathbuf_destroy(pb);
3046 return error; 3046 return error;
3047} 3047}
3048 3048
3049/* 3049/*
3050 * Get file status; this version follows links. 3050 * Get file status; this version follows links.
3051 */ 3051 */
3052/* ARGSUSED */ 3052/* ARGSUSED */
3053int 3053int
3054sys___stat50(struct lwp *l, const struct sys___stat50_args *uap, register_t *retval) 3054sys___stat50(struct lwp *l, const struct sys___stat50_args *uap, register_t *retval)
3055{ 3055{
3056 /* { 3056 /* {
3057 syscallarg(const char *) path; 3057 syscallarg(const char *) path;
3058 syscallarg(struct stat *) ub; 3058 syscallarg(struct stat *) ub;
3059 } */ 3059 } */
3060 struct stat sb; 3060 struct stat sb;
3061 int error; 3061 int error;
3062 3062
3063 error = do_sys_statat(l, AT_FDCWD, SCARG(uap, path), FOLLOW, &sb); 3063 error = do_sys_statat(l, AT_FDCWD, SCARG(uap, path), FOLLOW, &sb);
3064 if (error) 3064 if (error)
3065 return error; 3065 return error;
3066 return copyout(&sb, SCARG(uap, ub), sizeof(sb)); 3066 return copyout(&sb, SCARG(uap, ub), sizeof(sb));
3067} 3067}
3068 3068
3069/* 3069/*
3070 * Get file status; this version does not follow links. 3070 * Get file status; this version does not follow links.
3071 */ 3071 */
3072/* ARGSUSED */ 3072/* ARGSUSED */
3073int 3073int
3074sys___lstat50(struct lwp *l, const struct sys___lstat50_args *uap, register_t *retval) 3074sys___lstat50(struct lwp *l, const struct sys___lstat50_args *uap, register_t *retval)
3075{ 3075{
3076 /* { 3076 /* {
3077 syscallarg(const char *) path; 3077 syscallarg(const char *) path;
3078 syscallarg(struct stat *) ub; 3078 syscallarg(struct stat *) ub;
3079 } */ 3079 } */
3080 struct stat sb; 3080 struct stat sb;
3081 int error; 3081 int error;
3082 3082
3083 error = do_sys_statat(l, AT_FDCWD, SCARG(uap, path), NOFOLLOW, &sb); 3083 error = do_sys_statat(l, AT_FDCWD, SCARG(uap, path), NOFOLLOW, &sb);
3084 if (error) 3084 if (error)
3085 return error; 3085 return error;
3086 return copyout(&sb, SCARG(uap, ub), sizeof(sb)); 3086 return copyout(&sb, SCARG(uap, ub), sizeof(sb));
3087} 3087}
3088 3088
3089int 3089int
3090sys_fstatat(struct lwp *l, const struct sys_fstatat_args *uap, 3090sys_fstatat(struct lwp *l, const struct sys_fstatat_args *uap,
3091 register_t *retval) 3091 register_t *retval)
3092{ 3092{
3093 /* { 3093 /* {
3094 syscallarg(int) fd; 3094 syscallarg(int) fd;
3095 syscallarg(const char *) path; 3095 syscallarg(const char *) path;
3096 syscallarg(struct stat *) buf; 3096 syscallarg(struct stat *) buf;
3097 syscallarg(int) flag; 3097 syscallarg(int) flag;
3098 } */ 3098 } */
3099 unsigned int nd_flag; 3099 unsigned int nd_flag;
3100 struct stat sb; 3100 struct stat sb;
3101 int error; 3101 int error;
3102 3102
3103 if (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) 3103 if (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW)
3104 nd_flag = NOFOLLOW; 3104 nd_flag = NOFOLLOW;
3105 else 3105 else
3106 nd_flag = FOLLOW; 3106 nd_flag = FOLLOW;
3107 3107
3108 error = do_sys_statat(l, SCARG(uap, fd), SCARG(uap, path), nd_flag,  3108 error = do_sys_statat(l, SCARG(uap, fd), SCARG(uap, path), nd_flag,
3109 &sb); 3109 &sb);
3110 if (error) 3110 if (error)
3111 return error; 3111 return error;
3112 return copyout(&sb, SCARG(uap, buf), sizeof(sb)); 3112 return copyout(&sb, SCARG(uap, buf), sizeof(sb));
3113} 3113}
3114 3114
3115/* 3115/*
3116 * Get configurable pathname variables. 3116 * Get configurable pathname variables.
3117 */ 3117 */
3118/* ARGSUSED */ 3118/* ARGSUSED */
3119int 3119int
3120sys_pathconf(struct lwp *l, const struct sys_pathconf_args *uap, register_t *retval) 3120sys_pathconf(struct lwp *l, const struct sys_pathconf_args *uap, register_t *retval)
3121{ 3121{
3122 /* { 3122 /* {
3123 syscallarg(const char *) path; 3123 syscallarg(const char *) path;
3124 syscallarg(int) name; 3124 syscallarg(int) name;
3125 } */ 3125 } */
3126 int error; 3126 int error;
3127 struct pathbuf *pb; 3127 struct pathbuf *pb;
3128 struct nameidata nd; 3128 struct nameidata nd;
3129 3129
3130 error = pathbuf_copyin(SCARG(uap, path), &pb); 3130 error = pathbuf_copyin(SCARG(uap, path), &pb);
3131 if (error) { 3131 if (error) {
3132 return error; 3132 return error;
3133 } 3133 }
3134 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); 3134 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
3135 if ((error = namei(&nd)) != 0) { 3135 if ((error = namei(&nd)) != 0) {
3136 pathbuf_destroy(pb); 3136 pathbuf_destroy(pb);
3137 return (error); 3137 return (error);
3138 } 3138 }
3139 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); 3139 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
3140 vput(nd.ni_vp); 3140 vput(nd.ni_vp);
3141 pathbuf_destroy(pb); 3141 pathbuf_destroy(pb);
3142 return (error); 3142 return (error);
3143} 3143}
3144 3144
3145/* 3145/*
3146 * Return target name of a symbolic link. 3146 * Return target name of a symbolic link.
3147 */ 3147 */
3148/* ARGSUSED */ 3148/* ARGSUSED */
3149int 3149int
3150sys_readlink(struct lwp *l, const struct sys_readlink_args *uap, 3150sys_readlink(struct lwp *l, const struct sys_readlink_args *uap,
3151 register_t *retval) 3151 register_t *retval)
3152{ 3152{
3153 /* { 3153 /* {
3154 syscallarg(const char *) path; 3154 syscallarg(const char *) path;
3155 syscallarg(char *) buf; 3155 syscallarg(char *) buf;
3156 syscallarg(size_t) count; 3156 syscallarg(size_t) count;
3157 } */ 3157 } */
3158 return do_sys_readlinkat(l, AT_FDCWD, SCARG(uap, path), 3158 return do_sys_readlinkat(l, AT_FDCWD, SCARG(uap, path),
3159 SCARG(uap, buf), SCARG(uap, count), retval); 3159 SCARG(uap, buf), SCARG(uap, count), retval);
3160} 3160}
3161 3161
3162static int 3162static int
3163do_sys_readlinkat(struct lwp *l, int fdat, const char *path, char *buf, 3163do_sys_readlinkat(struct lwp *l, int fdat, const char *path, char *buf,
3164 size_t count, register_t *retval) 3164 size_t count, register_t *retval)
3165{ 3165{
3166 struct vnode *vp; 3166 struct vnode *vp;
3167 struct iovec aiov; 3167 struct iovec aiov;
3168 struct uio auio; 3168 struct uio auio;
3169 int error; 3169 int error;
3170 struct pathbuf *pb; 3170 struct pathbuf *pb;
3171 struct nameidata nd; 3171 struct nameidata nd;
3172 3172
3173 error = pathbuf_copyin(path, &pb); 3173 error = pathbuf_copyin(path, &pb);
3174 if (error) { 3174 if (error) {
3175 return error; 3175 return error;
3176 } 3176 }
3177 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | TRYEMULROOT, pb); 3177 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | TRYEMULROOT, pb);
3178 if ((error = fd_nameiat(l, fdat, &nd)) != 0) { 3178 if ((error = fd_nameiat(l, fdat, &nd)) != 0) {
3179 pathbuf_destroy(pb); 3179 pathbuf_destroy(pb);
3180 return error; 3180 return error;
3181 } 3181 }
3182 vp = nd.ni_vp; 3182 vp = nd.ni_vp;
3183 pathbuf_destroy(pb); 3183 pathbuf_destroy(pb);
3184 if (vp->v_type != VLNK) 3184 if (vp->v_type != VLNK)
3185 error = EINVAL; 3185 error = EINVAL;
3186 else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) || 3186 else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) ||
3187 (error = VOP_ACCESS(vp, VREAD, l->l_cred)) == 0) { 3187 (error = VOP_ACCESS(vp, VREAD, l->l_cred)) == 0) {
3188 aiov.iov_base = buf; 3188 aiov.iov_base = buf;
3189 aiov.iov_len = count; 3189 aiov.iov_len = count;
3190 auio.uio_iov = &aiov; 3190 auio.uio_iov = &aiov;
3191 auio.uio_iovcnt = 1; 3191 auio.uio_iovcnt = 1;
3192 auio.uio_offset = 0; 3192 auio.uio_offset = 0;
3193 auio.uio_rw = UIO_READ; 3193 auio.uio_rw = UIO_READ;
3194 KASSERT(l == curlwp); 3194 KASSERT(l == curlwp);
3195 auio.uio_vmspace = l->l_proc->p_vmspace; 3195 auio.uio_vmspace = l->l_proc->p_vmspace;
3196 auio.uio_resid = count; 3196 auio.uio_resid = count;
3197 if ((error = VOP_READLINK(vp, &auio, l->l_cred)) == 0) 3197 if ((error = VOP_READLINK(vp, &auio, l->l_cred)) == 0)
3198 *retval = count - auio.uio_resid; 3198 *retval = count - auio.uio_resid;
3199 } 3199 }
3200 vput(vp); 3200 vput(vp);
3201 return (error); 3201 return (error);
3202} 3202}
3203 3203
3204int 3204int
3205sys_readlinkat(struct lwp *l, const struct sys_readlinkat_args *uap, 3205sys_readlinkat(struct lwp *l, const struct sys_readlinkat_args *uap,
3206 register_t *retval) 3206 register_t *retval)
3207{ 3207{
3208 /* { 3208 /* {
3209 syscallarg(int) fd; 3209 syscallarg(int) fd;
3210 syscallarg(const char *) path; 3210 syscallarg(const char *) path;
3211 syscallarg(char *) buf; 3211 syscallarg(char *) buf;
3212 syscallarg(size_t) bufsize; 3212 syscallarg(size_t) bufsize;
3213 } */ 3213 } */
3214 3214
3215 return do_sys_readlinkat(l, SCARG(uap, fd), SCARG(uap, path), 3215 return do_sys_readlinkat(l, SCARG(uap, fd), SCARG(uap, path),
3216 SCARG(uap, buf), SCARG(uap, bufsize), retval); 3216 SCARG(uap, buf), SCARG(uap, bufsize), retval);
3217} 3217}
3218 3218
3219/* 3219/*
3220 * Change flags of a file given a path name. 3220 * Change flags of a file given a path name.
3221 */ 3221 */
3222/* ARGSUSED */ 3222/* ARGSUSED */
3223int 3223int
3224sys_chflags(struct lwp *l, const struct sys_chflags_args *uap, register_t *retval) 3224sys_chflags(struct lwp *l, const struct sys_chflags_args *uap, register_t *retval)
3225{ 3225{
3226 /* { 3226 /* {
3227 syscallarg(const char *) path; 3227 syscallarg(const char *) path;
3228 syscallarg(u_long) flags; 3228 syscallarg(u_long) flags;
3229 } */ 3229 } */
3230 struct vnode *vp; 3230 struct vnode *vp;
3231 int error; 3231 int error;
3232 3232
3233 error = namei_simple_user(SCARG(uap, path), 3233 error = namei_simple_user(SCARG(uap, path),
3234 NSM_FOLLOW_TRYEMULROOT, &vp); 3234 NSM_FOLLOW_TRYEMULROOT, &vp);
3235 if (error != 0) 3235 if (error != 0)
3236 return (error); 3236 return (error);
3237 error = change_flags(vp, SCARG(uap, flags), l); 3237 error = change_flags(vp, SCARG(uap, flags), l);
3238 vput(vp); 3238 vput(vp);
3239 return (error); 3239 return (error);
3240} 3240}
3241 3241
3242/* 3242/*
3243 * Change flags of a file given a file descriptor. 3243 * Change flags of a file given a file descriptor.
3244 */ 3244 */
3245/* ARGSUSED */ 3245/* ARGSUSED */
3246int 3246int
3247sys_fchflags(struct lwp *l, const struct sys_fchflags_args *uap, register_t *retval) 3247sys_fchflags(struct lwp *l, const struct sys_fchflags_args *uap, register_t *retval)
3248{ 3248{
3249 /* { 3249 /* {
3250 syscallarg(int) fd; 3250 syscallarg(int) fd;
3251 syscallarg(u_long) flags; 3251 syscallarg(u_long) flags;
3252 } */ 3252 } */
3253 struct vnode *vp; 3253 struct vnode *vp;
3254 file_t *fp; 3254 file_t *fp;
3255 int error; 3255 int error;
3256 3256
3257 /* fd_getvnode() will use the descriptor for us */ 3257 /* fd_getvnode() will use the descriptor for us */
3258 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3258 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3259 return (error); 3259 return (error);
3260 vp = fp->f_vnode; 3260 vp = fp->f_vnode;
3261 error = change_flags(vp, SCARG(uap, flags), l); 3261 error = change_flags(vp, SCARG(uap, flags), l);
3262 VOP_UNLOCK(vp); 3262 VOP_UNLOCK(vp);
3263 fd_putfile(SCARG(uap, fd)); 3263 fd_putfile(SCARG(uap, fd));
3264 return (error); 3264 return (error);
3265} 3265}
3266 3266
3267/* 3267/*
3268 * Change flags of a file given a path name; this version does 3268 * Change flags of a file given a path name; this version does
3269 * not follow links. 3269 * not follow links.
3270 */ 3270 */
3271int 3271int
3272sys_lchflags(struct lwp *l, const struct sys_lchflags_args *uap, register_t *retval) 3272sys_lchflags(struct lwp *l, const struct sys_lchflags_args *uap, register_t *retval)
3273{ 3273{
3274 /* { 3274 /* {
3275 syscallarg(const char *) path; 3275 syscallarg(const char *) path;
3276 syscallarg(u_long) flags; 3276 syscallarg(u_long) flags;
3277 } */ 3277 } */
3278 struct vnode *vp; 3278 struct vnode *vp;
3279 int error; 3279 int error;
3280 3280
3281 error = namei_simple_user(SCARG(uap, path), 3281 error = namei_simple_user(SCARG(uap, path),
3282 NSM_NOFOLLOW_TRYEMULROOT, &vp); 3282 NSM_NOFOLLOW_TRYEMULROOT, &vp);
3283 if (error != 0) 3283 if (error != 0)
3284 return (error); 3284 return (error);
3285 error = change_flags(vp, SCARG(uap, flags), l); 3285 error = change_flags(vp, SCARG(uap, flags), l);
3286 vput(vp); 3286 vput(vp);
3287 return (error); 3287 return (error);
3288} 3288}
3289 3289
3290/* 3290/*
3291 * Common routine to change flags of a file. 3291 * Common routine to change flags of a file.
3292 */ 3292 */
3293int 3293int
3294change_flags(struct vnode *vp, u_long flags, struct lwp *l) 3294change_flags(struct vnode *vp, u_long flags, struct lwp *l)
3295{ 3295{
3296 struct vattr vattr; 3296 struct vattr vattr;
3297 int error; 3297 int error;
3298 3298
3299 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3299 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3300 3300
3301 vattr_null(&vattr); 3301 vattr_null(&vattr);
3302 vattr.va_flags = flags; 3302 vattr.va_flags = flags;
3303 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3303 error = VOP_SETATTR(vp, &vattr, l->l_cred);
3304 3304
3305 return (error); 3305 return (error);
3306} 3306}
3307 3307
3308/* 3308/*
3309 * Change mode of a file given path name; this version follows links. 3309 * Change mode of a file given path name; this version follows links.
3310 */ 3310 */
3311/* ARGSUSED */ 3311/* ARGSUSED */
3312int 3312int
3313sys_chmod(struct lwp *l, const struct sys_chmod_args *uap, register_t *retval) 3313sys_chmod(struct lwp *l, const struct sys_chmod_args *uap, register_t *retval)
3314{ 3314{
3315 /* { 3315 /* {
3316 syscallarg(const char *) path; 3316 syscallarg(const char *) path;
3317 syscallarg(int) mode; 3317 syscallarg(int) mode;
3318 } */ 3318 } */
3319 return do_sys_chmodat(l, AT_FDCWD, SCARG(uap, path), 3319 return do_sys_chmodat(l, AT_FDCWD, SCARG(uap, path),
3320 SCARG(uap, mode), 0); 3320 SCARG(uap, mode), 0);
3321} 3321}
3322 3322
3323int 3323int
3324do_sys_chmodat(struct lwp *l, int fdat, const char *path, int mode, int flags) 3324do_sys_chmodat(struct lwp *l, int fdat, const char *path, int mode, int flags)
3325{ 3325{
3326 int error; 3326 int error;
3327 struct vnode *vp; 3327 struct vnode *vp;
3328 namei_simple_flags_t ns_flag; 3328 namei_simple_flags_t ns_flag;
3329 3329
3330 if (flags & AT_SYMLINK_NOFOLLOW) 3330 if (flags & AT_SYMLINK_NOFOLLOW)
3331 ns_flag = NSM_NOFOLLOW_TRYEMULROOT; 3331 ns_flag = NSM_NOFOLLOW_TRYEMULROOT;
3332 else 3332 else
3333 ns_flag = NSM_FOLLOW_TRYEMULROOT; 3333 ns_flag = NSM_FOLLOW_TRYEMULROOT;
3334 3334
3335 error = fd_nameiat_simple_user(l, fdat, path, ns_flag, &vp); 3335 error = fd_nameiat_simple_user(l, fdat, path, ns_flag, &vp);
3336 if (error != 0) 3336 if (error != 0)
3337 return error; 3337 return error;
3338 3338
3339 error = change_mode(vp, mode, l); 3339 error = change_mode(vp, mode, l);
3340 3340
3341 vrele(vp); 3341 vrele(vp);
3342 3342
3343 return (error); 3343 return (error);
3344} 3344}
3345 3345
3346/* 3346/*
3347 * Change mode of a file given a file descriptor. 3347 * Change mode of a file given a file descriptor.
3348 */ 3348 */
3349/* ARGSUSED */ 3349/* ARGSUSED */
3350int 3350int
3351sys_fchmod(struct lwp *l, const struct sys_fchmod_args *uap, register_t *retval) 3351sys_fchmod(struct lwp *l, const struct sys_fchmod_args *uap, register_t *retval)
3352{ 3352{
3353 /* { 3353 /* {
3354 syscallarg(int) fd; 3354 syscallarg(int) fd;
3355 syscallarg(int) mode; 3355 syscallarg(int) mode;
3356 } */ 3356 } */
3357 file_t *fp; 3357 file_t *fp;
3358 int error; 3358 int error;
3359 3359
3360 /* fd_getvnode() will use the descriptor for us */ 3360 /* fd_getvnode() will use the descriptor for us */
3361 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3361 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3362 return (error); 3362 return (error);
3363 error = change_mode(fp->f_vnode, SCARG(uap, mode), l); 3363 error = change_mode(fp->f_vnode, SCARG(uap, mode), l);
3364 fd_putfile(SCARG(uap, fd)); 3364 fd_putfile(SCARG(uap, fd));
3365 return (error); 3365 return (error);
3366} 3366}
3367 3367
3368int 3368int
3369sys_fchmodat(struct lwp *l, const struct sys_fchmodat_args *uap, 3369sys_fchmodat(struct lwp *l, const struct sys_fchmodat_args *uap,
3370 register_t *retval) 3370 register_t *retval)
3371{ 3371{
3372 /* { 3372 /* {
3373 syscallarg(int) fd; 3373 syscallarg(int) fd;
3374 syscallarg(const char *) path; 3374 syscallarg(const char *) path;
3375 syscallarg(int) mode; 3375 syscallarg(int) mode;
3376 syscallarg(int) flag; 3376 syscallarg(int) flag;
3377 } */ 3377 } */
3378 3378
3379 return do_sys_chmodat(l, SCARG(uap, fd), SCARG(uap, path), 3379 return do_sys_chmodat(l, SCARG(uap, fd), SCARG(uap, path),
3380 SCARG(uap, mode), SCARG(uap, flag)); 3380 SCARG(uap, mode), SCARG(uap, flag));
3381} 3381}
3382 3382
3383/* 3383/*
3384 * Change mode of a file given path name; this version does not follow links. 3384 * Change mode of a file given path name; this version does not follow links.
3385 */ 3385 */
3386/* ARGSUSED */ 3386/* ARGSUSED */
3387int 3387int
3388sys_lchmod(struct lwp *l, const struct sys_lchmod_args *uap, register_t *retval) 3388sys_lchmod(struct lwp *l, const struct sys_lchmod_args *uap, register_t *retval)
3389{ 3389{
3390 /* { 3390 /* {
3391 syscallarg(const char *) path; 3391 syscallarg(const char *) path;
3392 syscallarg(int) mode; 3392 syscallarg(int) mode;
3393 } */ 3393 } */
3394 int error; 3394 int error;
3395 struct vnode *vp; 3395 struct vnode *vp;
3396 3396
3397 error = namei_simple_user(SCARG(uap, path), 3397 error = namei_simple_user(SCARG(uap, path),
3398 NSM_NOFOLLOW_TRYEMULROOT, &vp); 3398 NSM_NOFOLLOW_TRYEMULROOT, &vp);
3399 if (error != 0) 3399 if (error != 0)
3400 return (error); 3400 return (error);
3401 3401
3402 error = change_mode(vp, SCARG(uap, mode), l); 3402 error = change_mode(vp, SCARG(uap, mode), l);
3403 3403
3404 vrele(vp); 3404 vrele(vp);
3405 return (error); 3405 return (error);
3406} 3406}
3407 3407
3408/* 3408/*
3409 * Common routine to set mode given a vnode. 3409 * Common routine to set mode given a vnode.
3410 */ 3410 */
3411static int 3411static int
3412change_mode(struct vnode *vp, int mode, struct lwp *l) 3412change_mode(struct vnode *vp, int mode, struct lwp *l)
3413{ 3413{
3414 struct vattr vattr; 3414 struct vattr vattr;
3415 int error; 3415 int error;
3416 3416
3417 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3417 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3418 vattr_null(&vattr); 3418 vattr_null(&vattr);
3419 vattr.va_mode = mode & ALLPERMS; 3419 vattr.va_mode = mode & ALLPERMS;
3420 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3420 error = VOP_SETATTR(vp, &vattr, l->l_cred);
3421 VOP_UNLOCK(vp); 3421 VOP_UNLOCK(vp);
3422 return (error); 3422 return (error);
3423} 3423}
3424 3424
3425/* 3425/*
3426 * Set ownership given a path name; this version follows links. 3426 * Set ownership given a path name; this version follows links.
3427 */ 3427 */
3428/* ARGSUSED */ 3428/* ARGSUSED */
3429int 3429int
3430sys_chown(struct lwp *l, const struct sys_chown_args *uap, register_t *retval) 3430sys_chown(struct lwp *l, const struct sys_chown_args *uap, register_t *retval)
3431{ 3431{
3432 /* { 3432 /* {
3433 syscallarg(const char *) path; 3433 syscallarg(const char *) path;
3434 syscallarg(uid_t) uid; 3434 syscallarg(uid_t) uid;
3435 syscallarg(gid_t) gid; 3435 syscallarg(gid_t) gid;
3436 } */ 3436 } */
3437 return do_sys_chownat(l, AT_FDCWD, SCARG(uap, path), SCARG(uap,uid), 3437 return do_sys_chownat(l, AT_FDCWD, SCARG(uap, path), SCARG(uap,uid),
3438 SCARG(uap, gid), 0); 3438 SCARG(uap, gid), 0);
3439} 3439}
3440 3440
3441int 3441int
3442do_sys_chownat(struct lwp *l, int fdat, const char *path, uid_t uid, 3442do_sys_chownat(struct lwp *l, int fdat, const char *path, uid_t uid,
3443 gid_t gid, int flags) 3443 gid_t gid, int flags)
3444{ 3444{
3445 int error; 3445 int error;
3446 struct vnode *vp; 3446 struct vnode *vp;
3447 namei_simple_flags_t ns_flag; 3447 namei_simple_flags_t ns_flag;
3448 3448
3449 if (flags & AT_SYMLINK_NOFOLLOW) 3449 if (flags & AT_SYMLINK_NOFOLLOW)
3450 ns_flag = NSM_NOFOLLOW_TRYEMULROOT; 3450 ns_flag = NSM_NOFOLLOW_TRYEMULROOT;
3451 else 3451 else
3452 ns_flag = NSM_FOLLOW_TRYEMULROOT; 3452 ns_flag = NSM_FOLLOW_TRYEMULROOT;
3453 3453
3454 error = fd_nameiat_simple_user(l, fdat, path, ns_flag, &vp); 3454 error = fd_nameiat_simple_user(l, fdat, path, ns_flag, &vp);
3455 if (error != 0) 3455 if (error != 0)
3456 return error; 3456 return error;
3457 3457
3458 error = change_owner(vp, uid, gid, l, 0); 3458 error = change_owner(vp, uid, gid, l, 0);
3459 3459
3460 vrele(vp); 3460 vrele(vp);
3461 3461
3462 return (error); 3462 return (error);
3463} 3463}
3464 3464
3465/* 3465/*
3466 * Set ownership given a path name; this version follows links. 3466 * Set ownership given a path name; this version follows links.
3467 * Provides POSIX semantics. 3467 * Provides POSIX semantics.
3468 */ 3468 */
3469/* ARGSUSED */ 3469/* ARGSUSED */
3470int 3470int
3471sys___posix_chown(struct lwp *l, const struct sys___posix_chown_args *uap, register_t *retval) 3471sys___posix_chown(struct lwp *l, const struct sys___posix_chown_args *uap, register_t *retval)
3472{ 3472{
3473 /* { 3473 /* {
3474 syscallarg(const char *) path; 3474 syscallarg(const char *) path;
3475 syscallarg(uid_t) uid; 3475 syscallarg(uid_t) uid;
3476 syscallarg(gid_t) gid; 3476 syscallarg(gid_t) gid;
3477 } */ 3477 } */
3478 int error; 3478 int error;
3479 struct vnode *vp; 3479 struct vnode *vp;
3480 3480
3481 error = namei_simple_user(SCARG(uap, path), 3481 error = namei_simple_user(SCARG(uap, path),
3482 NSM_FOLLOW_TRYEMULROOT, &vp); 3482 NSM_FOLLOW_TRYEMULROOT, &vp);
3483 if (error != 0) 3483 if (error != 0)
3484 return (error); 3484 return (error);
3485 3485
3486 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1); 3486 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1);
3487 3487
3488 vrele(vp); 3488 vrele(vp);
3489 return (error); 3489 return (error);
3490} 3490}
3491 3491
3492/* 3492/*
3493 * Set ownership given a file descriptor. 3493 * Set ownership given a file descriptor.
3494 */ 3494 */
3495/* ARGSUSED */ 3495/* ARGSUSED */
3496int 3496int
3497sys_fchown(struct lwp *l, const struct sys_fchown_args *uap, register_t *retval) 3497sys_fchown(struct lwp *l, const struct sys_fchown_args *uap, register_t *retval)
3498{ 3498{
3499 /* { 3499 /* {
3500 syscallarg(int) fd; 3500 syscallarg(int) fd;
3501 syscallarg(uid_t) uid; 3501 syscallarg(uid_t) uid;
3502 syscallarg(gid_t) gid; 3502 syscallarg(gid_t) gid;
3503 } */ 3503 } */
3504 int error; 3504 int error;
3505 file_t *fp; 3505 file_t *fp;
3506 3506
3507 /* fd_getvnode() will use the descriptor for us */ 3507 /* fd_getvnode() will use the descriptor for us */
3508 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3508 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3509 return (error); 3509 return (error);
3510 error = change_owner(fp->f_vnode, SCARG(uap, uid), SCARG(uap, gid), 3510 error = change_owner(fp->f_vnode, SCARG(uap, uid), SCARG(uap, gid),
3511 l, 0); 3511 l, 0);
3512 fd_putfile(SCARG(uap, fd)); 3512 fd_putfile(SCARG(uap, fd));
3513 return (error); 3513 return (error);
3514} 3514}
3515 3515
3516int 3516int
3517sys_fchownat(struct lwp *l, const struct sys_fchownat_args *uap, 3517sys_fchownat(struct lwp *l, const struct sys_fchownat_args *uap,
3518 register_t *retval) 3518 register_t *retval)
3519{ 3519{
3520 /* { 3520 /* {
3521 syscallarg(int) fd; 3521 syscallarg(int) fd;
3522 syscallarg(const char *) path; 3522 syscallarg(const char *) path;
3523 syscallarg(uid_t) owner; 3523 syscallarg(uid_t) owner;
3524 syscallarg(gid_t) group; 3524 syscallarg(gid_t) group;
3525 syscallarg(int) flag; 3525 syscallarg(int) flag;
3526 } */ 3526 } */
3527 3527
3528 return do_sys_chownat(l, SCARG(uap, fd), SCARG(uap, path), 3528 return do_sys_chownat(l, SCARG(uap, fd), SCARG(uap, path),
3529 SCARG(uap, owner), SCARG(uap, group), 3529 SCARG(uap, owner), SCARG(uap, group),
3530 SCARG(uap, flag)); 3530 SCARG(uap, flag));
3531} 3531}
3532 3532
3533/* 3533/*
3534 * Set ownership given a file descriptor, providing POSIX/XPG semantics. 3534 * Set ownership given a file descriptor, providing POSIX/XPG semantics.
3535 */ 3535 */
3536/* ARGSUSED */ 3536/* ARGSUSED */
3537int 3537int
3538sys___posix_fchown(struct lwp *l, const struct sys___posix_fchown_args *uap, register_t *retval) 3538sys___posix_fchown(struct lwp *l, const struct sys___posix_fchown_args *uap, register_t *retval)
3539{ 3539{
3540 /* { 3540 /* {
3541 syscallarg(int) fd; 3541 syscallarg(int) fd;
3542 syscallarg(uid_t) uid; 3542 syscallarg(uid_t) uid;
3543 syscallarg(gid_t) gid; 3543 syscallarg(gid_t) gid;
3544 } */ 3544 } */
3545 int error; 3545 int error;
3546 file_t *fp; 3546 file_t *fp;
3547 3547
3548 /* fd_getvnode() will use the descriptor for us */ 3548 /* fd_getvnode() will use the descriptor for us */
3549 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3549 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3550 return (error); 3550 return (error);
3551 error = change_owner(fp->f_vnode, SCARG(uap, uid), SCARG(uap, gid), 3551 error = change_owner(fp->f_vnode, SCARG(uap, uid), SCARG(uap, gid),
3552 l, 1); 3552 l, 1);
3553 fd_putfile(SCARG(uap, fd)); 3553 fd_putfile(SCARG(uap, fd));
3554 return (error); 3554 return (error);
3555} 3555}
3556 3556
3557/* 3557/*
3558 * Set ownership given a path name; this version does not follow links. 3558 * Set ownership given a path name; this version does not follow links.
3559 */ 3559 */
3560/* ARGSUSED */ 3560/* ARGSUSED */
3561int 3561int
3562sys_lchown(struct lwp *l, const struct sys_lchown_args *uap, register_t *retval) 3562sys_lchown(struct lwp *l, const struct sys_lchown_args *uap, register_t *retval)
3563{ 3563{
3564 /* { 3564 /* {
3565 syscallarg(const char *) path; 3565 syscallarg(const char *) path;
3566 syscallarg(uid_t) uid; 3566 syscallarg(uid_t) uid;
3567 syscallarg(gid_t) gid; 3567 syscallarg(gid_t) gid;
3568 } */ 3568 } */
3569 int error; 3569 int error;
3570 struct vnode *vp; 3570 struct vnode *vp;
3571 3571
3572 error = namei_simple_user(SCARG(uap, path), 3572 error = namei_simple_user(SCARG(uap, path),
3573 NSM_NOFOLLOW_TRYEMULROOT, &vp); 3573 NSM_NOFOLLOW_TRYEMULROOT, &vp);
3574 if (error != 0) 3574 if (error != 0)
3575 return (error); 3575 return (error);
3576 3576
3577 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0); 3577 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0);
3578 3578
3579 vrele(vp); 3579 vrele(vp);
3580 return (error); 3580 return (error);
3581} 3581}
3582 3582
3583/* 3583/*
3584 * Set ownership given a path name; this version does not follow links. 3584 * Set ownership given a path name; this version does not follow links.
3585 * Provides POSIX/XPG semantics. 3585 * Provides POSIX/XPG semantics.
3586 */ 3586 */
3587/* ARGSUSED */ 3587/* ARGSUSED */
3588int 3588int
3589sys___posix_lchown(struct lwp *l, const struct sys___posix_lchown_args *uap, register_t *retval) 3589sys___posix_lchown(struct lwp *l, const struct sys___posix_lchown_args *uap, register_t *retval)
3590{ 3590{
3591 /* { 3591 /* {
3592 syscallarg(const char *) path; 3592 syscallarg(const char *) path;
3593 syscallarg(uid_t) uid; 3593 syscallarg(uid_t) uid;
3594 syscallarg(gid_t) gid; 3594 syscallarg(gid_t) gid;
3595 } */ 3595 } */
3596 int error; 3596 int error;
3597 struct vnode *vp; 3597 struct vnode *vp;
3598 3598
3599 error = namei_simple_user(SCARG(uap, path), 3599 error = namei_simple_user(SCARG(uap, path),
3600 NSM_NOFOLLOW_TRYEMULROOT, &vp); 3600 NSM_NOFOLLOW_TRYEMULROOT, &vp);
3601 if (error != 0) 3601 if (error != 0)
3602 return (error); 3602 return (error);
3603 3603
3604 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1); 3604 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1);
3605 3605
3606 vrele(vp); 3606 vrele(vp);
3607 return (error); 3607 return (error);
3608} 3608}
3609 3609
3610/* 3610/*
3611 * Common routine to set ownership given a vnode. 3611 * Common routine to set ownership given a vnode.
3612 */ 3612 */
3613static int 3613static int
3614change_owner(struct vnode *vp, uid_t uid, gid_t gid, struct lwp *l, 3614change_owner(struct vnode *vp, uid_t uid, gid_t gid, struct lwp *l,
3615 int posix_semantics) 3615 int posix_semantics)
3616{ 3616{
3617 struct vattr vattr; 3617 struct vattr vattr;
3618 mode_t newmode; 3618 mode_t newmode;
3619 int error; 3619 int error;
3620 3620
3621 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3621 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3622 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0) 3622 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0)
3623 goto out; 3623 goto out;
3624 3624
3625#define CHANGED(x) ((int)(x) != -1) 3625#define CHANGED(x) ((int)(x) != -1)
3626 newmode = vattr.va_mode; 3626 newmode = vattr.va_mode;
3627 if (posix_semantics) { 3627 if (posix_semantics) {
3628 /* 3628 /*
3629 * POSIX/XPG semantics: if the caller is not the super-user, 3629 * POSIX/XPG semantics: if the caller is not the super-user,
3630 * clear set-user-id and set-group-id bits. Both POSIX and 3630 * clear set-user-id and set-group-id bits. Both POSIX and
3631 * the XPG consider the behaviour for calls by the super-user 3631 * the XPG consider the behaviour for calls by the super-user
3632 * implementation-defined; we leave the set-user-id and set- 3632 * implementation-defined; we leave the set-user-id and set-
3633 * group-id settings intact in that case. 3633 * group-id settings intact in that case.
3634 */ 3634 */
3635 if (vattr.va_mode & S_ISUID) { 3635 if (vattr.va_mode & S_ISUID) {
3636 if (kauth_authorize_vnode(l->l_cred, 3636 if (kauth_authorize_vnode(l->l_cred,
3637 KAUTH_VNODE_RETAIN_SUID, vp, NULL, EPERM) != 0) 3637 KAUTH_VNODE_RETAIN_SUID, vp, NULL, EPERM) != 0)
3638 newmode &= ~S_ISUID; 3638 newmode &= ~S_ISUID;
3639 } 3639 }
3640 if (vattr.va_mode & S_ISGID) { 3640 if (vattr.va_mode & S_ISGID) {
3641 if (kauth_authorize_vnode(l->l_cred, 3641 if (kauth_authorize_vnode(l->l_cred,
3642 KAUTH_VNODE_RETAIN_SGID, vp, NULL, EPERM) != 0) 3642 KAUTH_VNODE_RETAIN_SGID, vp, NULL, EPERM) != 0)
3643 newmode &= ~S_ISGID; 3643 newmode &= ~S_ISGID;
3644 } 3644 }
3645 } else { 3645 } else {
3646 /* 3646 /*
3647 * NetBSD semantics: when changing owner and/or group, 3647 * NetBSD semantics: when changing owner and/or group,
3648 * clear the respective bit(s). 3648 * clear the respective bit(s).
3649 */ 3649 */
3650 if (CHANGED(uid)) 3650 if (CHANGED(uid))
3651 newmode &= ~S_ISUID; 3651 newmode &= ~S_ISUID;
3652 if (CHANGED(gid)) 3652 if (CHANGED(gid))
3653 newmode &= ~S_ISGID; 3653 newmode &= ~S_ISGID;
3654 } 3654 }
3655 /* Update va_mode iff altered. */ 3655 /* Update va_mode iff altered. */
3656 if (vattr.va_mode == newmode) 3656 if (vattr.va_mode == newmode)
3657 newmode = VNOVAL; 3657 newmode = VNOVAL;
3658 3658
3659 vattr_null(&vattr); 3659 vattr_null(&vattr);
3660 vattr.va_uid = CHANGED(uid) ? uid : (uid_t)VNOVAL; 3660 vattr.va_uid = CHANGED(uid) ? uid : (uid_t)VNOVAL;
3661 vattr.va_gid = CHANGED(gid) ? gid : (gid_t)VNOVAL; 3661 vattr.va_gid = CHANGED(gid) ? gid : (gid_t)VNOVAL;
3662 vattr.va_mode = newmode; 3662 vattr.va_mode = newmode;
3663 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3663 error = VOP_SETATTR(vp, &vattr, l->l_cred);
3664#undef CHANGED 3664#undef CHANGED
3665 3665
3666out: 3666out:
3667 VOP_UNLOCK(vp); 3667 VOP_UNLOCK(vp);
3668 return (error); 3668 return (error);
3669} 3669}
3670 3670
3671/* 3671/*
3672 * Set the access and modification times given a path name; this 3672 * Set the access and modification times given a path name; this
3673 * version follows links. 3673 * version follows links.
3674 */ 3674 */
3675/* ARGSUSED */ 3675/* ARGSUSED */
3676int 3676int
3677sys___utimes50(struct lwp *l, const struct sys___utimes50_args *uap, 3677sys___utimes50(struct lwp *l, const struct sys___utimes50_args *uap,
3678 register_t *retval) 3678 register_t *retval)
3679{ 3679{
3680 /* { 3680 /* {
3681 syscallarg(const char *) path; 3681 syscallarg(const char *) path;
3682 syscallarg(const struct timeval *) tptr; 3682 syscallarg(const struct timeval *) tptr;
3683 } */ 3683 } */
3684 3684
3685 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW, 3685 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW,
3686 SCARG(uap, tptr), UIO_USERSPACE); 3686 SCARG(uap, tptr), UIO_USERSPACE);
3687} 3687}
3688 3688
3689/* 3689/*
3690 * Set the access and modification times given a file descriptor. 3690 * Set the access and modification times given a file descriptor.
3691 */ 3691 */
3692/* ARGSUSED */ 3692/* ARGSUSED */
3693int 3693int
3694sys___futimes50(struct lwp *l, const struct sys___futimes50_args *uap, 3694sys___futimes50(struct lwp *l, const struct sys___futimes50_args *uap,
3695 register_t *retval) 3695 register_t *retval)
3696{ 3696{
3697 /* { 3697 /* {
3698 syscallarg(int) fd; 3698 syscallarg(int) fd;
3699 syscallarg(const struct timeval *) tptr; 3699 syscallarg(const struct timeval *) tptr;
3700 } */ 3700 } */
3701 int error; 3701 int error;
3702 file_t *fp; 3702 file_t *fp;
3703 3703
3704 /* fd_getvnode() will use the descriptor for us */ 3704 /* fd_getvnode() will use the descriptor for us */
3705 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3705 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3706 return (error); 3706 return (error);
3707 error = do_sys_utimes(l, fp->f_vnode, NULL, 0, SCARG(uap, tptr), 3707 error = do_sys_utimes(l, fp->f_vnode, NULL, 0, SCARG(uap, tptr),
3708 UIO_USERSPACE); 3708 UIO_USERSPACE);
3709 fd_putfile(SCARG(uap, fd)); 3709 fd_putfile(SCARG(uap, fd));
3710 return (error); 3710 return (error);
3711} 3711}
3712 3712
3713int 3713int
3714sys_futimens(struct lwp *l, const struct sys_futimens_args *uap, 3714sys_futimens(struct lwp *l, const struct sys_futimens_args *uap,
3715 register_t *retval) 3715 register_t *retval)
3716{ 3716{
3717 /* { 3717 /* {
3718 syscallarg(int) fd; 3718 syscallarg(int) fd;
3719 syscallarg(const struct timespec *) tptr; 3719 syscallarg(const struct timespec *) tptr;
3720 } */ 3720 } */
3721 int error; 3721 int error;
3722 file_t *fp; 3722 file_t *fp;
3723 3723
3724 /* fd_getvnode() will use the descriptor for us */ 3724 /* fd_getvnode() will use the descriptor for us */
3725 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3725 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3726 return (error); 3726 return (error);
3727 error = do_sys_utimensat(l, AT_FDCWD, fp->f_vnode, NULL, 0, 3727 error = do_sys_utimensat(l, AT_FDCWD, fp->f_vnode, NULL, 0,
3728 SCARG(uap, tptr), UIO_USERSPACE); 3728 SCARG(uap, tptr), UIO_USERSPACE);
3729 fd_putfile(SCARG(uap, fd)); 3729 fd_putfile(SCARG(uap, fd));
3730 return (error); 3730 return (error);
3731} 3731}
3732 3732
3733/* 3733/*
3734 * Set the access and modification times given a path name; this 3734 * Set the access and modification times given a path name; this
3735 * version does not follow links. 3735 * version does not follow links.
3736 */ 3736 */
3737int 3737int
3738sys___lutimes50(struct lwp *l, const struct sys___lutimes50_args *uap, 3738sys___lutimes50(struct lwp *l, const struct sys___lutimes50_args *uap,
3739 register_t *retval) 3739 register_t *retval)
3740{ 3740{
3741 /* { 3741 /* {
3742 syscallarg(const char *) path; 3742 syscallarg(const char *) path;
3743 syscallarg(const struct timeval *) tptr; 3743 syscallarg(const struct timeval *) tptr;
3744 } */ 3744 } */
3745 3745
3746 return do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW, 3746 return do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW,
3747 SCARG(uap, tptr), UIO_USERSPACE); 3747 SCARG(uap, tptr), UIO_USERSPACE);
3748} 3748}
3749 3749
3750int 3750int
3751sys_utimensat(struct lwp *l, const struct sys_utimensat_args *uap, 3751sys_utimensat(struct lwp *l, const struct sys_utimensat_args *uap,
3752 register_t *retval) 3752 register_t *retval)
3753{ 3753{
3754 /* { 3754 /* {
3755 syscallarg(int) fd; 3755 syscallarg(int) fd;
3756 syscallarg(const char *) path; 3756 syscallarg(const char *) path;
3757 syscallarg(const struct timespec *) tptr; 3757 syscallarg(const struct timespec *) tptr;
3758 syscallarg(int) flag; 3758 syscallarg(int) flag;
3759 } */ 3759 } */
3760 int follow; 3760 int follow;
3761 const struct timespec *tptr; 3761 const struct timespec *tptr;
3762 int error; 3762 int error;
3763 3763
3764 tptr = SCARG(uap, tptr); 3764 tptr = SCARG(uap, tptr);
3765 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 3765 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
3766 3766
3767 error = do_sys_utimensat(l, SCARG(uap, fd), NULL,  3767 error = do_sys_utimensat(l, SCARG(uap, fd), NULL,
3768 SCARG(uap, path), follow, tptr, UIO_USERSPACE); 3768 SCARG(uap, path), follow, tptr, UIO_USERSPACE);
3769 3769
3770 return error; 3770 return error;
3771} 3771}
3772 3772
3773/* 3773/*
3774 * Common routine to set access and modification times given a vnode. 3774 * Common routine to set access and modification times given a vnode.
3775 */ 3775 */
3776int 3776int
3777do_sys_utimens(struct lwp *l, struct vnode *vp, const char *path, int flag, 3777do_sys_utimens(struct lwp *l, struct vnode *vp, const char *path, int flag,
3778 const struct timespec *tptr, enum uio_seg seg) 3778 const struct timespec *tptr, enum uio_seg seg)
3779{ 3779{
3780 return do_sys_utimensat(l, AT_FDCWD, vp, path, flag, tptr, seg); 3780 return do_sys_utimensat(l, AT_FDCWD, vp, path, flag, tptr, seg);
3781} 3781}
3782 3782
3783int 3783int
3784do_sys_utimensat(struct lwp *l, int fdat, struct vnode *vp, 3784do_sys_utimensat(struct lwp *l, int fdat, struct vnode *vp,
3785 const char *path, int flag, const struct timespec *tptr, enum uio_seg seg) 3785 const char *path, int flag, const struct timespec *tptr, enum uio_seg seg)
3786{ 3786{
3787 struct vattr vattr; 3787 struct vattr vattr;
3788 int error, dorele = 0; 3788 int error, dorele = 0;
3789 namei_simple_flags_t sflags; 3789 namei_simple_flags_t sflags;
3790 bool vanull, setbirthtime; 3790 bool vanull, setbirthtime;
3791 struct timespec ts[2]; 3791 struct timespec ts[2];
3792 3792
3793 KASSERT(l != NULL || fdat == AT_FDCWD); 3793 KASSERT(l != NULL || fdat == AT_FDCWD);
3794 3794
3795 /*  3795 /*
3796 * I have checked all callers and they pass either FOLLOW, 3796 * I have checked all callers and they pass either FOLLOW,
3797 * NOFOLLOW, or 0 (when they don't pass a path), and NOFOLLOW 3797 * NOFOLLOW, or 0 (when they don't pass a path), and NOFOLLOW
3798 * is 0. More to the point, they don't pass anything else. 3798 * is 0. More to the point, they don't pass anything else.
3799 * Let's keep it that way at least until the namei interfaces 3799 * Let's keep it that way at least until the namei interfaces
3800 * are fully sanitized. 3800 * are fully sanitized.
3801 */ 3801 */
3802 KASSERT(flag == NOFOLLOW || flag == FOLLOW); 3802 KASSERT(flag == NOFOLLOW || flag == FOLLOW);
3803 sflags = (flag == FOLLOW) ?  3803 sflags = (flag == FOLLOW) ?
3804 NSM_FOLLOW_TRYEMULROOT : NSM_NOFOLLOW_TRYEMULROOT; 3804 NSM_FOLLOW_TRYEMULROOT : NSM_NOFOLLOW_TRYEMULROOT;
3805 3805
3806 if (tptr == NULL) { 3806 if (tptr == NULL) {
3807 vanull = true; 3807 vanull = true;
3808 nanotime(&ts[0]); 3808 nanotime(&ts[0]);
3809 ts[1] = ts[0]; 3809 ts[1] = ts[0];
3810 } else { 3810 } else {
3811 vanull = false; 3811 vanull = false;
3812 if (seg != UIO_SYSSPACE) { 3812 if (seg != UIO_SYSSPACE) {
3813 error = copyin(tptr, ts, sizeof (ts)); 3813 error = copyin(tptr, ts, sizeof (ts));
3814 if (error != 0) 3814 if (error != 0)
3815 return error; 3815 return error;
3816 } else { 3816 } else {
3817 ts[0] = tptr[0]; 3817 ts[0] = tptr[0];
3818 ts[1] = tptr[1]; 3818 ts[1] = tptr[1];
3819 } 3819 }
3820 } 3820 }
3821 3821
3822 if (ts[0].tv_nsec == UTIME_NOW) { 3822 if (ts[0].tv_nsec == UTIME_NOW) {
3823 nanotime(&ts[0]); 3823 nanotime(&ts[0]);
3824 if (ts[1].tv_nsec == UTIME_NOW) { 3824 if (ts[1].tv_nsec == UTIME_NOW) {
3825 vanull = true; 3825 vanull = true;
3826 ts[1] = ts[0]; 3826 ts[1] = ts[0];
3827 } 3827 }
3828 } else if (ts[1].tv_nsec == UTIME_NOW) 3828 } else if (ts[1].tv_nsec == UTIME_NOW)
3829 nanotime(&ts[1]); 3829 nanotime(&ts[1]);
3830 3830
3831 if (vp == NULL) { 3831 if (vp == NULL) {
3832 /* note: SEG describes TPTR, not PATH; PATH is always user */ 3832 /* note: SEG describes TPTR, not PATH; PATH is always user */
3833 error = fd_nameiat_simple_user(l, fdat, path, sflags, &vp); 3833 error = fd_nameiat_simple_user(l, fdat, path, sflags, &vp);
3834 if (error != 0) 3834 if (error != 0)
3835 return error; 3835 return error;
3836 dorele = 1; 3836 dorele = 1;
3837 } 3837 }
3838 3838
3839 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3839 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3840 setbirthtime = (VOP_GETATTR(vp, &vattr, l->l_cred) == 0 && 3840 setbirthtime = (VOP_GETATTR(vp, &vattr, l->l_cred) == 0 &&
3841 timespeccmp(&ts[1], &vattr.va_birthtime, <)); 3841 timespeccmp(&ts[1], &vattr.va_birthtime, <));
3842 vattr_null(&vattr); 3842 vattr_null(&vattr);
3843 3843
3844 if (ts[0].tv_nsec != UTIME_OMIT) 3844 if (ts[0].tv_nsec != UTIME_OMIT)
3845 vattr.va_atime = ts[0]; 3845 vattr.va_atime = ts[0];
3846 3846
3847 if (ts[1].tv_nsec != UTIME_OMIT) { 3847 if (ts[1].tv_nsec != UTIME_OMIT) {
3848 vattr.va_mtime = ts[1]; 3848 vattr.va_mtime = ts[1];
3849 if (setbirthtime) 3849 if (setbirthtime)
3850 vattr.va_birthtime = ts[1]; 3850 vattr.va_birthtime = ts[1];
3851 } 3851 }
3852 3852
3853 if (vanull) 3853 if (vanull)
3854 vattr.va_vaflags |= VA_UTIMES_NULL; 3854 vattr.va_vaflags |= VA_UTIMES_NULL;
3855 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3855 error = VOP_SETATTR(vp, &vattr, l->l_cred);
3856 VOP_UNLOCK(vp); 3856 VOP_UNLOCK(vp);
3857 3857
3858 if (dorele != 0) 3858 if (dorele != 0)
3859 vrele(vp); 3859 vrele(vp);
3860 3860
3861 return error; 3861 return error;
3862} 3862}
3863 3863
3864int 3864int
3865do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, int flag, 3865do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, int flag,
3866 const struct timeval *tptr, enum uio_seg seg) 3866 const struct timeval *tptr, enum uio_seg seg)
3867{ 3867{
3868 struct timespec ts[2]; 3868 struct timespec ts[2];
3869 struct timespec *tsptr = NULL; 3869 struct timespec *tsptr = NULL;
3870 int error; 3870 int error;
3871  3871
3872 if (tptr != NULL) { 3872 if (tptr != NULL) {
3873 struct timeval tv[2]; 3873 struct timeval tv[2];
3874 3874
3875 if (seg != UIO_SYSSPACE) { 3875 if (seg != UIO_SYSSPACE) {
3876 error = copyin(tptr, tv, sizeof (tv)); 3876 error = copyin(tptr, tv, sizeof (tv));
3877 if (error != 0) 3877 if (error != 0)
3878 return error; 3878 return error;
3879 tptr = tv; 3879 tptr = tv;
3880 } 3880 }
3881 3881
3882 if ((tv[0].tv_usec == UTIME_NOW) ||  3882 if ((tv[0].tv_usec == UTIME_NOW) ||
3883 (tv[0].tv_usec == UTIME_OMIT)) 3883 (tv[0].tv_usec == UTIME_OMIT))
3884 ts[0].tv_nsec = tv[0].tv_usec; 3884 ts[0].tv_nsec = tv[0].tv_usec;
3885 else 3885 else
3886 TIMEVAL_TO_TIMESPEC(&tptr[0], &ts[0]); 3886 TIMEVAL_TO_TIMESPEC(&tptr[0], &ts[0]);
3887 3887
3888 if ((tv[1].tv_usec == UTIME_NOW) ||  3888 if ((tv[1].tv_usec == UTIME_NOW) ||
3889 (tv[1].tv_usec == UTIME_OMIT)) 3889 (tv[1].tv_usec == UTIME_OMIT))
3890 ts[1].tv_nsec = tv[1].tv_usec; 3890 ts[1].tv_nsec = tv[1].tv_usec;
3891 else 3891 else
3892 TIMEVAL_TO_TIMESPEC(&tptr[1], &ts[1]); 3892 TIMEVAL_TO_TIMESPEC(&tptr[1], &ts[1]);
3893 3893
3894 tsptr = &ts[0];  3894 tsptr = &ts[0];
3895 } 3895 }
3896 3896
3897 return do_sys_utimens(l, vp, path, flag, tsptr, UIO_SYSSPACE); 3897 return do_sys_utimens(l, vp, path, flag, tsptr, UIO_SYSSPACE);
3898} 3898}
3899 3899
3900/* 3900/*
3901 * Truncate a file given its path name. 3901 * Truncate a file given its path name.
3902 */ 3902 */
3903/* ARGSUSED */ 3903/* ARGSUSED */
3904int 3904int
3905sys_truncate(struct lwp *l, const struct sys_truncate_args *uap, register_t *retval) 3905sys_truncate(struct lwp *l, const struct sys_truncate_args *uap, register_t *retval)
3906{ 3906{
3907 /* { 3907 /* {
3908 syscallarg(const char *) path; 3908 syscallarg(const char *) path;
3909 syscallarg(int) pad; 3909 syscallarg(int) pad;
3910 syscallarg(off_t) length; 3910 syscallarg(off_t) length;
3911 } */ 3911 } */
3912 struct vnode *vp; 3912 struct vnode *vp;
3913 struct vattr vattr; 3913 struct vattr vattr;
3914 int error; 3914 int error;
3915 3915
3916 if (SCARG(uap, length) < 0) 3916 if (SCARG(uap, length) < 0)
3917 return EINVAL; 3917 return EINVAL;
3918 3918
3919 error = namei_simple_user(SCARG(uap, path), 3919 error = namei_simple_user(SCARG(uap, path),
3920 NSM_FOLLOW_TRYEMULROOT, &vp); 3920 NSM_FOLLOW_TRYEMULROOT, &vp);
3921 if (error != 0) 3921 if (error != 0)
3922 return (error); 3922 return (error);
3923 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3923 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3924 if (vp->v_type == VDIR) 3924 if (vp->v_type == VDIR)
3925 error = EISDIR; 3925 error = EISDIR;
3926 else if ((error = vn_writechk(vp)) == 0 && 3926 else if ((error = vn_writechk(vp)) == 0 &&
3927 (error = VOP_ACCESS(vp, VWRITE, l->l_cred)) == 0) { 3927 (error = VOP_ACCESS(vp, VWRITE, l->l_cred)) == 0) {
3928 vattr_null(&vattr); 3928 vattr_null(&vattr);
3929 vattr.va_size = SCARG(uap, length); 3929 vattr.va_size = SCARG(uap, length);
3930 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3930 error = VOP_SETATTR(vp, &vattr, l->l_cred);
3931 } 3931 }
3932 vput(vp); 3932 vput(vp);
3933 return (error); 3933 return (error);
3934} 3934}
3935 3935
3936/* 3936/*
3937 * Truncate a file given a file descriptor. 3937 * Truncate a file given a file descriptor.
3938 */ 3938 */
3939/* ARGSUSED */ 3939/* ARGSUSED */
3940int 3940int
3941sys_ftruncate(struct lwp *l, const struct sys_ftruncate_args *uap, register_t *retval) 3941sys_ftruncate(struct lwp *l, const struct sys_ftruncate_args *uap, register_t *retval)
3942{ 3942{
3943 /* { 3943 /* {
3944 syscallarg(int) fd; 3944 syscallarg(int) fd;
3945 syscallarg(int) pad; 3945 syscallarg(int) pad;
3946 syscallarg(off_t) length; 3946 syscallarg(off_t) length;
3947 } */ 3947 } */
3948 struct vattr vattr; 3948 struct vattr vattr;
3949 struct vnode *vp; 3949 struct vnode *vp;
3950 file_t *fp; 3950 file_t *fp;
3951 int error; 3951 int error;
3952 3952
3953 if (SCARG(uap, length) < 0) 3953 if (SCARG(uap, length) < 0)
3954 return EINVAL; 3954 return EINVAL;
3955 3955
3956 /* fd_getvnode() will use the descriptor for us */ 3956 /* fd_getvnode() will use the descriptor for us */
3957 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3957 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3958 return (error); 3958 return (error);
3959 if ((fp->f_flag & FWRITE) == 0) { 3959 if ((fp->f_flag & FWRITE) == 0) {
3960 error = EINVAL; 3960 error = EINVAL;
3961 goto out; 3961 goto out;
3962 } 3962 }
3963 vp = fp->f_vnode; 3963 vp = fp->f_vnode;
3964 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3964 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3965 if (vp->v_type == VDIR) 3965 if (vp->v_type == VDIR)
3966 error = EISDIR; 3966 error = EISDIR;
3967 else if ((error = vn_writechk(vp)) == 0) { 3967 else if ((error = vn_writechk(vp)) == 0) {
3968 vattr_null(&vattr); 3968 vattr_null(&vattr);
3969 vattr.va_size = SCARG(uap, length); 3969 vattr.va_size = SCARG(uap, length);
3970 error = VOP_SETATTR(vp, &vattr, fp->f_cred); 3970 error = VOP_SETATTR(vp, &vattr, fp->f_cred);
3971 } 3971 }
3972 VOP_UNLOCK(vp); 3972 VOP_UNLOCK(vp);
3973 out: 3973 out:
3974 fd_putfile(SCARG(uap, fd)); 3974 fd_putfile(SCARG(uap, fd));
3975 return (error); 3975 return (error);
3976} 3976}
3977 3977
3978/* 3978/*
3979 * Sync an open file. 3979 * Sync an open file.
3980 */ 3980 */
3981/* ARGSUSED */ 3981/* ARGSUSED */
3982int 3982int
3983sys_fsync(struct lwp *l, const struct sys_fsync_args *uap, register_t *retval) 3983sys_fsync(struct lwp *l, const struct sys_fsync_args *uap, register_t *retval)
3984{ 3984{
3985 /* { 3985 /* {
3986 syscallarg(int) fd; 3986 syscallarg(int) fd;
3987 } */ 3987 } */
3988 struct vnode *vp; 3988 struct vnode *vp;
3989 file_t *fp; 3989 file_t *fp;
3990 int error; 3990 int error;
3991 3991
3992 /* fd_getvnode() will use the descriptor for us */ 3992 /* fd_getvnode() will use the descriptor for us */
3993 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3993 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3994 return (error); 3994 return (error);
3995 vp = fp->f_vnode; 3995 vp = fp->f_vnode;
3996 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3996 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3997 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0); 3997 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0);
3998 VOP_UNLOCK(vp); 3998 VOP_UNLOCK(vp);
3999 fd_putfile(SCARG(uap, fd)); 3999 fd_putfile(SCARG(uap, fd));
4000 return (error); 4000 return (error);
4001} 4001}
4002 4002
4003/* 4003/*
4004 * Sync a range of file data. API modeled after that found in AIX. 4004 * Sync a range of file data. API modeled after that found in AIX.
4005 * 4005 *
4006 * FDATASYNC indicates that we need only save enough metadata to be able 4006 * FDATASYNC indicates that we need only save enough metadata to be able
4007 * to re-read the written data. Note we duplicate AIX's requirement that 4007 * to re-read the written data.
4008 * the file be open for writing. 
4009 */ 4008 */
4010/* ARGSUSED */ 4009/* ARGSUSED */
4011int 4010int
4012sys_fsync_range(struct lwp *l, const struct sys_fsync_range_args *uap, register_t *retval) 4011sys_fsync_range(struct lwp *l, const struct sys_fsync_range_args *uap, register_t *retval)
4013{ 4012{
4014 /* { 4013 /* {
4015 syscallarg(int) fd; 4014 syscallarg(int) fd;
4016 syscallarg(int) flags; 4015 syscallarg(int) flags;
4017 syscallarg(off_t) start; 4016 syscallarg(off_t) start;
4018 syscallarg(off_t) length; 4017 syscallarg(off_t) length;
4019 } */ 4018 } */
4020 struct vnode *vp; 4019 struct vnode *vp;
4021 file_t *fp; 4020 file_t *fp;
4022 int flags, nflags; 4021 int flags, nflags;
4023 off_t s, e, len; 4022 off_t s, e, len;
4024 int error; 4023 int error;
4025 4024
4026 /* fd_getvnode() will use the descriptor for us */ 4025 /* fd_getvnode() will use the descriptor for us */
4027 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 4026 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
4028 return (error); 4027 return (error);
4029 4028
4030 if ((fp->f_flag & FWRITE) == 0) { 4029 if ((fp->f_flag & FWRITE) == 0) {
4031 error = EBADF; 4030 error = EBADF;
4032 goto out; 4031 goto out;
4033 } 4032 }
4034 4033
4035 flags = SCARG(uap, flags); 4034 flags = SCARG(uap, flags);
4036 if (((flags & (FDATASYNC | FFILESYNC)) == 0) || 4035 if (((flags & (FDATASYNC | FFILESYNC)) == 0) ||
4037 ((~flags & (FDATASYNC | FFILESYNC)) == 0)) { 4036 ((~flags & (FDATASYNC | FFILESYNC)) == 0)) {
4038 error = EINVAL; 4037 error = EINVAL;
4039 goto out; 4038 goto out;
4040 } 4039 }
4041 /* Now set up the flags for value(s) to pass to VOP_FSYNC() */ 4040 /* Now set up the flags for value(s) to pass to VOP_FSYNC() */
4042 if (flags & FDATASYNC) 4041 if (flags & FDATASYNC)
4043 nflags = FSYNC_DATAONLY | FSYNC_WAIT; 4042 nflags = FSYNC_DATAONLY | FSYNC_WAIT;
4044 else 4043 else
4045 nflags = FSYNC_WAIT; 4044 nflags = FSYNC_WAIT;
4046 if (flags & FDISKSYNC) 4045 if (flags & FDISKSYNC)
4047 nflags |= FSYNC_CACHE; 4046 nflags |= FSYNC_CACHE;
4048 4047
4049 len = SCARG(uap, length); 4048 len = SCARG(uap, length);
4050 /* If length == 0, we do the whole file, and s = e = 0 will do that */ 4049 /* If length == 0, we do the whole file, and s = e = 0 will do that */
4051 if (len) { 4050 if (len) {
4052 s = SCARG(uap, start); 4051 s = SCARG(uap, start);
4053 e = s + len; 4052 e = s + len;
4054 if (e < s) { 4053 if (e < s) {
4055 error = EINVAL; 4054 error = EINVAL;
4056 goto out; 4055 goto out;
4057 } 4056 }
4058 } else { 4057 } else {
4059 e = 0; 4058 e = 0;
4060 s = 0; 4059 s = 0;
4061 } 4060 }
4062 4061
4063 vp = fp->f_vnode; 4062 vp = fp->f_vnode;
4064 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 4063 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
4065 error = VOP_FSYNC(vp, fp->f_cred, nflags, s, e); 4064 error = VOP_FSYNC(vp, fp->f_cred, nflags, s, e);
4066 VOP_UNLOCK(vp); 4065 VOP_UNLOCK(vp);
4067out: 4066out:
4068 fd_putfile(SCARG(uap, fd)); 4067 fd_putfile(SCARG(uap, fd));
4069 return (error); 4068 return (error);
4070} 4069}
4071 4070
4072/* 4071/*
4073 * Sync the data of an open file. 4072 * Sync the data of an open file.
4074 */ 4073 */
4075/* ARGSUSED */ 4074/* ARGSUSED */
4076int 4075int
4077sys_fdatasync(struct lwp *l, const struct sys_fdatasync_args *uap, register_t *retval) 4076sys_fdatasync(struct lwp *l, const struct sys_fdatasync_args *uap, register_t *retval)
4078{ 4077{
4079 /* { 4078 /* {
4080 syscallarg(int) fd; 4079 syscallarg(int) fd;
4081 } */ 4080 } */
4082 struct vnode *vp; 4081 struct vnode *vp;
4083 file_t *fp; 4082 file_t *fp;
4084 int error; 4083 int error;
4085 4084
4086 /* fd_getvnode() will use the descriptor for us */ 4085 /* fd_getvnode() will use the descriptor for us */
4087 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 4086 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
4088 return (error); 4087 return (error);
4089 if ((fp->f_flag & FWRITE) == 0) { 
4090 fd_putfile(SCARG(uap, fd)); 
4091 return (EBADF); 
4092 } 
4093 vp = fp->f_vnode; 4088 vp = fp->f_vnode;
4094 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 4089 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
4095 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, 0, 0); 4090 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, 0, 0);
4096 VOP_UNLOCK(vp); 4091 VOP_UNLOCK(vp);
4097 fd_putfile(SCARG(uap, fd)); 4092 fd_putfile(SCARG(uap, fd));
4098 return (error); 4093 return (error);
4099} 4094}
4100 4095
4101/* 4096/*
4102 * Rename files, (standard) BSD semantics frontend. 4097 * Rename files, (standard) BSD semantics frontend.
4103 */ 4098 */
4104/* ARGSUSED */ 4099/* ARGSUSED */
4105int 4100int
4106sys_rename(struct lwp *l, const struct sys_rename_args *uap, register_t *retval) 4101sys_rename(struct lwp *l, const struct sys_rename_args *uap, register_t *retval)
4107{ 4102{
4108 /* { 4103 /* {
4109 syscallarg(const char *) from; 4104 syscallarg(const char *) from;
4110 syscallarg(const char *) to; 4105 syscallarg(const char *) to;
4111 } */ 4106 } */
4112 4107
4113 return (do_sys_renameat(l, AT_FDCWD, SCARG(uap, from), AT_FDCWD,  4108 return (do_sys_renameat(l, AT_FDCWD, SCARG(uap, from), AT_FDCWD,
4114 SCARG(uap, to), UIO_USERSPACE, 0)); 4109 SCARG(uap, to), UIO_USERSPACE, 0));
4115} 4110}
4116 4111
4117int 4112int
4118sys_renameat(struct lwp *l, const struct sys_renameat_args *uap,  4113sys_renameat(struct lwp *l, const struct sys_renameat_args *uap,
4119 register_t *retval) 4114 register_t *retval)
4120{ 4115{
4121 /* { 4116 /* {
4122 syscallarg(int) fromfd; 4117 syscallarg(int) fromfd;
4123 syscallarg(const char *) from; 4118 syscallarg(const char *) from;
4124 syscallarg(int) tofd; 4119 syscallarg(int) tofd;
4125 syscallarg(const char *) to; 4120 syscallarg(const char *) to;
4126 } */ 4121 } */
4127 4122
4128 return (do_sys_renameat(l, SCARG(uap, fromfd), SCARG(uap, from), 4123 return (do_sys_renameat(l, SCARG(uap, fromfd), SCARG(uap, from),
4129 SCARG(uap, tofd), SCARG(uap, to), UIO_USERSPACE, 0)); 4124 SCARG(uap, tofd), SCARG(uap, to), UIO_USERSPACE, 0));
4130} 4125}
4131 4126
4132/* 4127/*
4133 * Rename files, POSIX semantics frontend. 4128 * Rename files, POSIX semantics frontend.
4134 */ 4129 */
4135/* ARGSUSED */ 4130/* ARGSUSED */
4136int 4131int
4137sys___posix_rename(struct lwp *l, const struct sys___posix_rename_args *uap, register_t *retval) 4132sys___posix_rename(struct lwp *l, const struct sys___posix_rename_args *uap, register_t *retval)
4138{ 4133{
4139 /* { 4134 /* {
4140 syscallarg(const char *) from; 4135 syscallarg(const char *) from;
4141 syscallarg(const char *) to; 4136 syscallarg(const char *) to;
4142 } */ 4137 } */
4143 4138
4144 return (do_sys_renameat(l, AT_FDCWD, SCARG(uap, from), AT_FDCWD, 4139 return (do_sys_renameat(l, AT_FDCWD, SCARG(uap, from), AT_FDCWD,
4145 SCARG(uap, to), UIO_USERSPACE, 1)); 4140 SCARG(uap, to), UIO_USERSPACE, 1));
4146} 4141}
4147 4142
4148/* 4143/*
4149 * Rename files. Source and destination must either both be directories, 4144 * Rename files. Source and destination must either both be directories,
4150 * or both not be directories. If target is a directory, it must be empty. 4145 * or both not be directories. If target is a directory, it must be empty.
4151 * If `from' and `to' refer to the same object, the value of the `retain' 4146 * If `from' and `to' refer to the same object, the value of the `retain'
4152 * argument is used to determine whether `from' will be 4147 * argument is used to determine whether `from' will be
4153 * 4148 *
4154 * (retain == 0) deleted unless `from' and `to' refer to the same 4149 * (retain == 0) deleted unless `from' and `to' refer to the same
4155 * object in the file system's name space (BSD). 4150 * object in the file system's name space (BSD).
4156 * (retain == 1) always retained (POSIX). 4151 * (retain == 1) always retained (POSIX).
4157 * 4152 *
4158 * XXX Synchronize with nfsrv_rename in nfs_serv.c. 4153 * XXX Synchronize with nfsrv_rename in nfs_serv.c.
4159 */ 4154 */
4160int 4155int
4161do_sys_rename(const char *from, const char *to, enum uio_seg seg, int retain) 4156do_sys_rename(const char *from, const char *to, enum uio_seg seg, int retain)
4162{ 4157{
4163 return do_sys_renameat(NULL, AT_FDCWD, from, AT_FDCWD, to, seg, retain); 4158 return do_sys_renameat(NULL, AT_FDCWD, from, AT_FDCWD, to, seg, retain);
4164} 4159}
4165 4160
4166static int 4161static int
4167do_sys_renameat(struct lwp *l, int fromfd, const char *from, int tofd, 4162do_sys_renameat(struct lwp *l, int fromfd, const char *from, int tofd,
4168 const char *to, enum uio_seg seg, int retain) 4163 const char *to, enum uio_seg seg, int retain)
4169{ 4164{
4170 struct pathbuf *fpb, *tpb; 4165 struct pathbuf *fpb, *tpb;
4171 struct nameidata fnd, tnd; 4166 struct nameidata fnd, tnd;
4172 struct vnode *fdvp, *fvp; 4167 struct vnode *fdvp, *fvp;
4173 struct vnode *tdvp, *tvp; 4168 struct vnode *tdvp, *tvp;
4174 struct mount *mp, *tmp; 4169 struct mount *mp, *tmp;
4175 int error; 4170 int error;
4176 4171
4177 KASSERT(l != NULL || (fromfd == AT_FDCWD && tofd == AT_FDCWD)); 4172 KASSERT(l != NULL || (fromfd == AT_FDCWD && tofd == AT_FDCWD));
4178 4173
4179 error = pathbuf_maybe_copyin(from, seg, &fpb); 4174 error = pathbuf_maybe_copyin(from, seg, &fpb);
4180 if (error) 4175 if (error)
4181 goto out0; 4176 goto out0;
4182 KASSERT(fpb != NULL); 4177 KASSERT(fpb != NULL);
4183 4178
4184 error = pathbuf_maybe_copyin(to, seg, &tpb); 4179 error = pathbuf_maybe_copyin(to, seg, &tpb);
4185 if (error) 4180 if (error)
4186 goto out1; 4181 goto out1;
4187 KASSERT(tpb != NULL); 4182 KASSERT(tpb != NULL);
4188 4183
4189 /* 4184 /*
4190 * Lookup from. 4185 * Lookup from.
4191 * 4186 *
4192 * XXX LOCKPARENT is wrong because we don't actually want it 4187 * XXX LOCKPARENT is wrong because we don't actually want it
4193 * locked yet, but (a) namei is insane, and (b) VOP_RENAME is 4188 * locked yet, but (a) namei is insane, and (b) VOP_RENAME is
4194 * insane, so for the time being we need to leave it like this. 4189 * insane, so for the time being we need to leave it like this.
4195 */ 4190 */
4196 NDINIT(&fnd, DELETE, (LOCKPARENT | TRYEMULROOT), fpb); 4191 NDINIT(&fnd, DELETE, (LOCKPARENT | TRYEMULROOT), fpb);
4197 if ((error = fd_nameiat(l, fromfd, &fnd)) != 0) 4192 if ((error = fd_nameiat(l, fromfd, &fnd)) != 0)
4198 goto out2; 4193 goto out2;
4199 4194
4200 /* 4195 /*
4201 * Pull out the important results of the lookup, fdvp and fvp. 4196 * Pull out the important results of the lookup, fdvp and fvp.
4202 * Of course, fvp is bogus because we're about to unlock fdvp. 4197 * Of course, fvp is bogus because we're about to unlock fdvp.
4203 */ 4198 */
4204 fdvp = fnd.ni_dvp; 4199 fdvp = fnd.ni_dvp;
4205 fvp = fnd.ni_vp; 4200 fvp = fnd.ni_vp;
4206 KASSERT(fdvp != NULL); 4201 KASSERT(fdvp != NULL);
4207 KASSERT(fvp != NULL); 4202 KASSERT(fvp != NULL);
4208 KASSERT((fdvp == fvp) || (VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE)); 4203 KASSERT((fdvp == fvp) || (VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE));
4209 4204
4210 /* 4205 /*
4211 * Make sure neither fdvp nor fvp is locked. 4206 * Make sure neither fdvp nor fvp is locked.
4212 */ 4207 */
4213 if (fdvp != fvp) 4208 if (fdvp != fvp)
4214 VOP_UNLOCK(fdvp); 4209 VOP_UNLOCK(fdvp);
4215 /* XXX KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */ 4210 /* XXX KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
4216 /* XXX KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */ 4211 /* XXX KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */
4217 4212
4218 /* 4213 /*
4219 * Reject renaming `.' and `..'. Can't do this until after 4214 * Reject renaming `.' and `..'. Can't do this until after
4220 * namei because we need namei's parsing to find the final 4215 * namei because we need namei's parsing to find the final
4221 * component name. (namei should just leave us with the final 4216 * component name. (namei should just leave us with the final
4222 * component name and not look it up itself, but anyway...) 4217 * component name and not look it up itself, but anyway...)
4223 * 4218 *
4224 * This was here before because we used to relookup from 4219 * This was here before because we used to relookup from
4225 * instead of to and relookup requires the caller to check 4220 * instead of to and relookup requires the caller to check
4226 * this, but now file systems may depend on this check, so we 4221 * this, but now file systems may depend on this check, so we
4227 * must retain it until the file systems are all rototilled. 4222 * must retain it until the file systems are all rototilled.
4228 */ 4223 */
4229 if (((fnd.ni_cnd.cn_namelen == 1) && 4224 if (((fnd.ni_cnd.cn_namelen == 1) &&
4230 (fnd.ni_cnd.cn_nameptr[0] == '.')) || 4225 (fnd.ni_cnd.cn_nameptr[0] == '.')) ||
4231 ((fnd.ni_cnd.cn_namelen == 2) && 4226 ((fnd.ni_cnd.cn_namelen == 2) &&
4232 (fnd.ni_cnd.cn_nameptr[0] == '.') && 4227 (fnd.ni_cnd.cn_nameptr[0] == '.') &&
4233 (fnd.ni_cnd.cn_nameptr[1] == '.'))) { 4228 (fnd.ni_cnd.cn_nameptr[1] == '.'))) {
4234 error = EINVAL; /* XXX EISDIR? */ 4229 error = EINVAL; /* XXX EISDIR? */
4235 goto abort0; 4230 goto abort0;
4236 } 4231 }
4237 4232
4238 /* 4233 /*
4239 * Lookup to. 4234 * Lookup to.
4240 * 4235 *
4241 * XXX LOCKPARENT is wrong, but...insanity, &c. Also, using 4236 * XXX LOCKPARENT is wrong, but...insanity, &c. Also, using
4242 * fvp here to decide whether to add CREATEDIR is a load of 4237 * fvp here to decide whether to add CREATEDIR is a load of
4243 * bollocks because fvp might be the wrong node by now, since 4238 * bollocks because fvp might be the wrong node by now, since
4244 * fdvp is unlocked. 4239 * fdvp is unlocked.
4245 * 4240 *
4246 * XXX Why not pass CREATEDIR always? 4241 * XXX Why not pass CREATEDIR always?
4247 */ 4242 */
4248 NDINIT(&tnd, RENAME, 4243 NDINIT(&tnd, RENAME,
4249 (LOCKPARENT | NOCACHE | TRYEMULROOT | 4244 (LOCKPARENT | NOCACHE | TRYEMULROOT |
4250 ((fvp->v_type == VDIR)? CREATEDIR : 0)), 4245 ((fvp->v_type == VDIR)? CREATEDIR : 0)),
4251 tpb); 4246 tpb);
4252 if ((error = fd_nameiat(l, tofd, &tnd)) != 0) 4247 if ((error = fd_nameiat(l, tofd, &tnd)) != 0)
4253 goto abort0; 4248 goto abort0;
4254 4249
4255 /* 4250 /*
4256 * Pull out the important results of the lookup, tdvp and tvp. 4251 * Pull out the important results of the lookup, tdvp and tvp.
4257 * Of course, tvp is bogus because we're about to unlock tdvp. 4252 * Of course, tvp is bogus because we're about to unlock tdvp.
4258 */ 4253 */
4259 tdvp = tnd.ni_dvp; 4254 tdvp = tnd.ni_dvp;
4260 tvp = tnd.ni_vp; 4255 tvp = tnd.ni_vp;
4261 KASSERT(tdvp != NULL); 4256 KASSERT(tdvp != NULL);
4262 KASSERT((tdvp == tvp) || (VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE)); 4257 KASSERT((tdvp == tvp) || (VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE));
4263 4258
4264 /* 4259 /*
4265 * Make sure neither tdvp nor tvp is locked. 4260 * Make sure neither tdvp nor tvp is locked.
4266 */ 4261 */
4267 if (tdvp != tvp) 4262 if (tdvp != tvp)
4268 VOP_UNLOCK(tdvp); 4263 VOP_UNLOCK(tdvp);
4269 /* XXX KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */ 4264 /* XXX KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */
4270 /* XXX KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) != LK_EXCLUSIVE)); */ 4265 /* XXX KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) != LK_EXCLUSIVE)); */
4271 4266
4272 /* 4267 /*
4273 * Reject renaming onto `.' or `..'. relookup is unhappy with 4268 * Reject renaming onto `.' or `..'. relookup is unhappy with
4274 * these, which is why we must do this here. Once upon a time 4269 * these, which is why we must do this here. Once upon a time
4275 * we relooked up from instead of to, and consequently didn't 4270 * we relooked up from instead of to, and consequently didn't
4276 * need this check, but now that we relookup to instead of 4271 * need this check, but now that we relookup to instead of
4277 * from, we need this; and we shall need it forever forward 4272 * from, we need this; and we shall need it forever forward
4278 * until the VOP_RENAME protocol changes, because file systems 4273 * until the VOP_RENAME protocol changes, because file systems
4279 * will no doubt begin to depend on this check. 4274 * will no doubt begin to depend on this check.
4280 */ 4275 */
4281 if ((tnd.ni_cnd.cn_namelen == 1) && (tnd.ni_cnd.cn_nameptr[0] == '.')) { 4276 if ((tnd.ni_cnd.cn_namelen == 1) && (tnd.ni_cnd.cn_nameptr[0] == '.')) {
4282 error = EISDIR; 4277 error = EISDIR;
4283 goto abort1; 4278 goto abort1;
4284 } 4279 }
4285 if ((tnd.ni_cnd.cn_namelen == 2) && 4280 if ((tnd.ni_cnd.cn_namelen == 2) &&
4286 (tnd.ni_cnd.cn_nameptr[0] == '.') && 4281 (tnd.ni_cnd.cn_nameptr[0] == '.') &&
4287 (tnd.ni_cnd.cn_nameptr[1] == '.')) { 4282 (tnd.ni_cnd.cn_nameptr[1] == '.')) {
4288 error = EINVAL; 4283 error = EINVAL;
4289 goto abort1; 4284 goto abort1;
4290 } 4285 }
4291 4286
4292 /* 4287 /*
4293 * Get the mount point. If the file system has been unmounted, 4288 * Get the mount point. If the file system has been unmounted,
4294 * which it may be because we're not holding any vnode locks, 4289 * which it may be because we're not holding any vnode locks,
4295 * then v_mount will be NULL. We're not really supposed to 4290 * then v_mount will be NULL. We're not really supposed to
4296 * read v_mount without holding the vnode lock, but since we 4291 * read v_mount without holding the vnode lock, but since we
4297 * have fdvp referenced, if fdvp->v_mount changes then at worst 4292 * have fdvp referenced, if fdvp->v_mount changes then at worst
4298 * it will be set to NULL, not changed to another mount point. 4293 * it will be set to NULL, not changed to another mount point.
4299 * And, of course, since it is up to the file system to 4294 * And, of course, since it is up to the file system to
4300 * determine the real lock order, we can't lock both fdvp and 4295 * determine the real lock order, we can't lock both fdvp and
4301 * tdvp at the same time. 4296 * tdvp at the same time.
4302 */ 4297 */
4303 mp = fdvp->v_mount; 4298 mp = fdvp->v_mount;
4304 if (mp == NULL) { 4299 if (mp == NULL) {
4305 error = ENOENT; 4300 error = ENOENT;
4306 goto abort1; 4301 goto abort1;
4307 } 4302 }
4308 4303
4309 /* 4304 /*
4310 * Make sure the mount points match. Again, although we don't 4305 * Make sure the mount points match. Again, although we don't
4311 * hold any vnode locks, the v_mount fields may change -- but 4306 * hold any vnode locks, the v_mount fields may change -- but
4312 * at worst they will change to NULL, so this will never become 4307 * at worst they will change to NULL, so this will never become
4313 * a cross-device rename, because we hold vnode references. 4308 * a cross-device rename, because we hold vnode references.
4314 * 4309 *
4315 * XXX Because nothing is locked and the compiler may reorder 4310 * XXX Because nothing is locked and the compiler may reorder
4316 * things here, unmounting the file system at an inopportune 4311 * things here, unmounting the file system at an inopportune
4317 * moment may cause rename to fail with EXDEV when it really 4312 * moment may cause rename to fail with EXDEV when it really
4318 * should fail with ENOENT. 4313 * should fail with ENOENT.
4319 */ 4314 */
4320 tmp = tdvp->v_mount; 4315 tmp = tdvp->v_mount;
4321 if (tmp == NULL) { 4316 if (tmp == NULL) {
4322 error = ENOENT; 4317 error = ENOENT;
4323 goto abort1; 4318 goto abort1;
4324 } 4319 }
4325 4320
4326 if (mp != tmp) { 4321 if (mp != tmp) {
4327 error = EXDEV; 4322 error = EXDEV;
4328 goto abort1; 4323 goto abort1;
4329 } 4324 }
4330 4325
4331 /* 4326 /*
4332 * Take the vfs rename lock to avoid cross-directory screw cases. 4327 * Take the vfs rename lock to avoid cross-directory screw cases.
4333 * Nothing is locked currently, so taking this lock is safe. 4328 * Nothing is locked currently, so taking this lock is safe.
4334 */ 4329 */
4335 error = VFS_RENAMELOCK_ENTER(mp); 4330 error = VFS_RENAMELOCK_ENTER(mp);
4336 if (error) 4331 if (error)
4337 goto abort1; 4332 goto abort1;
4338 4333
4339 /* 4334 /*
4340 * Now fdvp, fvp, tdvp, and (if nonnull) tvp are referenced, 4335 * Now fdvp, fvp, tdvp, and (if nonnull) tvp are referenced,
4341 * and nothing is locked except for the vfs rename lock. 4336 * and nothing is locked except for the vfs rename lock.
4342 * 4337 *
4343 * The next step is a little rain dance to conform to the 4338 * The next step is a little rain dance to conform to the
4344 * insane lock protocol, even though it does nothing to ward 4339 * insane lock protocol, even though it does nothing to ward
4345 * off race conditions. 4340 * off race conditions.
4346 * 4341 *
4347 * We need tdvp and tvp to be locked. However, because we have 4342 * We need tdvp and tvp to be locked. However, because we have
4348 * unlocked tdvp in order to hold no locks while we take the 4343 * unlocked tdvp in order to hold no locks while we take the
4349 * vfs rename lock, tvp may be wrong here, and we can't safely 4344 * vfs rename lock, tvp may be wrong here, and we can't safely
4350 * lock it even if the sensible file systems will just unlock 4345 * lock it even if the sensible file systems will just unlock
4351 * it straight away. Consequently, we must lock tdvp and then 4346 * it straight away. Consequently, we must lock tdvp and then
4352 * relookup tvp to get it locked. 4347 * relookup tvp to get it locked.
4353 * 4348 *
4354 * Finally, because the VOP_RENAME protocol is brain-damaged 4349 * Finally, because the VOP_RENAME protocol is brain-damaged
4355 * and various file systems insanely depend on the semantics of 4350 * and various file systems insanely depend on the semantics of
4356 * this brain damage, the lookup of to must be the last lookup 4351 * this brain damage, the lookup of to must be the last lookup
4357 * before VOP_RENAME. 4352 * before VOP_RENAME.
4358 */ 4353 */
4359 vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY); 4354 vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY);
4360 error = relookup(tdvp, &tnd.ni_vp, &tnd.ni_cnd, 0); 4355 error = relookup(tdvp, &tnd.ni_vp, &tnd.ni_cnd, 0);
4361 if (error) 4356 if (error)
4362 goto abort2; 4357 goto abort2;
4363 4358
4364 /* 4359 /*
4365 * Drop the old tvp and pick up the new one -- which might be 4360 * Drop the old tvp and pick up the new one -- which might be
4366 * the same, but that doesn't matter to us. After this, tdvp 4361 * the same, but that doesn't matter to us. After this, tdvp
4367 * and tvp should both be locked. 4362 * and tvp should both be locked.
4368 */ 4363 */
4369 if (tvp != NULL) 4364 if (tvp != NULL)
4370 vrele(tvp); 4365 vrele(tvp);
4371 tvp = tnd.ni_vp; 4366 tvp = tnd.ni_vp;
4372 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 4367 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
4373 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 4368 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
4374 4369
4375 /* 4370 /*
4376 * The old do_sys_rename had various consistency checks here 4371 * The old do_sys_rename had various consistency checks here
4377 * involving fvp and tvp. fvp is bogus already here, and tvp 4372 * involving fvp and tvp. fvp is bogus already here, and tvp
4378 * will become bogus soon in any sensible file system, so the 4373 * will become bogus soon in any sensible file system, so the
4379 * only purpose in putting these checks here is to give lip 4374 * only purpose in putting these checks here is to give lip
4380 * service to these screw cases and to acknowledge that they 4375 * service to these screw cases and to acknowledge that they
4381 * exist, not actually to handle them, but here you go 4376 * exist, not actually to handle them, but here you go
4382 * anyway... 4377 * anyway...
4383 */ 4378 */
4384 4379
4385 /* 4380 /*
4386 * Acknowledge that directories and non-directories aren't 4381 * Acknowledge that directories and non-directories aren't
4387 * suposed to mix. 4382 * suposed to mix.
4388 */ 4383 */
4389 if (tvp != NULL) { 4384 if (tvp != NULL) {
4390 if ((fvp->v_type == VDIR) && (tvp->v_type != VDIR)) { 4385 if ((fvp->v_type == VDIR) && (tvp->v_type != VDIR)) {
4391 error = ENOTDIR; 4386 error = ENOTDIR;
4392 goto abort3; 4387 goto abort3;
4393 } else if ((fvp->v_type != VDIR) && (tvp->v_type == VDIR)) { 4388 } else if ((fvp->v_type != VDIR) && (tvp->v_type == VDIR)) {
4394 error = EISDIR; 4389 error = EISDIR;
4395 goto abort3; 4390 goto abort3;
4396 } 4391 }
4397 } 4392 }
4398 4393
4399 /* 4394 /*
4400 * Acknowledge some random screw case, among the dozens that 4395 * Acknowledge some random screw case, among the dozens that
4401 * might arise. 4396 * might arise.
4402 */ 4397 */
4403 if (fvp == tdvp) { 4398 if (fvp == tdvp) {
4404 error = EINVAL; 4399 error = EINVAL;
4405 goto abort3; 4400 goto abort3;
4406 } 4401 }
4407 4402
4408 /* 4403 /*
4409 * Acknowledge that POSIX has a wacky screw case. 4404 * Acknowledge that POSIX has a wacky screw case.
4410 * 4405 *
4411 * XXX Eventually the retain flag needs to be passed on to 4406 * XXX Eventually the retain flag needs to be passed on to
4412 * VOP_RENAME. 4407 * VOP_RENAME.
4413 */ 4408 */
4414 if (fvp == tvp) { 4409 if (fvp == tvp) {
4415 if (retain) { 4410 if (retain) {
4416 error = 0; 4411 error = 0;
4417 goto abort3; 4412 goto abort3;
4418 } else if ((fdvp == tdvp) && 4413 } else if ((fdvp == tdvp) &&
4419 (fnd.ni_cnd.cn_namelen == tnd.ni_cnd.cn_namelen) && 4414 (fnd.ni_cnd.cn_namelen == tnd.ni_cnd.cn_namelen) &&
4420 (0 == memcmp(fnd.ni_cnd.cn_nameptr, tnd.ni_cnd.cn_nameptr, 4415 (0 == memcmp(fnd.ni_cnd.cn_nameptr, tnd.ni_cnd.cn_nameptr,
4421 fnd.ni_cnd.cn_namelen))) { 4416 fnd.ni_cnd.cn_namelen))) {
4422 error = 0; 4417 error = 0;
4423 goto abort3; 4418 goto abort3;
4424 } 4419 }
4425 } 4420 }
4426 4421
4427 /* 4422 /*
4428 * Make sure veriexec can screw us up. (But a race can screw 4423 * Make sure veriexec can screw us up. (But a race can screw
4429 * up veriexec, of course -- remember, fvp and (soon) tvp are 4424 * up veriexec, of course -- remember, fvp and (soon) tvp are
4430 * bogus.) 4425 * bogus.)
4431 */ 4426 */
4432#if NVERIEXEC > 0 4427#if NVERIEXEC > 0
4433 { 4428 {
4434 char *f1, *f2; 4429 char *f1, *f2;
4435 size_t f1_len; 4430 size_t f1_len;
4436 size_t f2_len; 4431 size_t f2_len;
4437 4432
4438 f1_len = fnd.ni_cnd.cn_namelen + 1; 4433 f1_len = fnd.ni_cnd.cn_namelen + 1;
4439 f1 = kmem_alloc(f1_len, KM_SLEEP); 4434 f1 = kmem_alloc(f1_len, KM_SLEEP);
4440 strlcpy(f1, fnd.ni_cnd.cn_nameptr, f1_len); 4435 strlcpy(f1, fnd.ni_cnd.cn_nameptr, f1_len);
4441 4436
4442 f2_len = tnd.ni_cnd.cn_namelen + 1; 4437 f2_len = tnd.ni_cnd.cn_namelen + 1;
4443 f2 = kmem_alloc(f2_len, KM_SLEEP); 4438 f2 = kmem_alloc(f2_len, KM_SLEEP);
4444 strlcpy(f2, tnd.ni_cnd.cn_nameptr, f2_len); 4439 strlcpy(f2, tnd.ni_cnd.cn_nameptr, f2_len);
4445 4440
4446 error = veriexec_renamechk(curlwp, fvp, f1, tvp, f2); 4441 error = veriexec_renamechk(curlwp, fvp, f1, tvp, f2);
4447 4442
4448 kmem_free(f1, f1_len); 4443 kmem_free(f1, f1_len);
4449 kmem_free(f2, f2_len); 4444 kmem_free(f2, f2_len);
4450 4445
4451 if (error) 4446 if (error)
4452 goto abort3; 4447 goto abort3;
4453 } 4448 }
4454#endif /* NVERIEXEC > 0 */ 4449#endif /* NVERIEXEC > 0 */
4455 4450
4456 /* 4451 /*
4457 * All ready. Incant the rename vop. 4452 * All ready. Incant the rename vop.
4458 */ 4453 */
4459 /* XXX KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */ 4454 /* XXX KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
4460 /* XXX KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */ 4455 /* XXX KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */
4461 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE); 4456 KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
4462 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); 4457 KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
4463 error = VOP_RENAME(fdvp, fvp, &fnd.ni_cnd, tdvp, tvp, &tnd.ni_cnd); 4458 error = VOP_RENAME(fdvp, fvp, &fnd.ni_cnd, tdvp, tvp, &tnd.ni_cnd);
4464 4459
4465 /* 4460 /*
4466 * VOP_RENAME releases fdvp, fvp, tdvp, and tvp, and unlocks 4461 * VOP_RENAME releases fdvp, fvp, tdvp, and tvp, and unlocks
4467 * tdvp and tvp. But we can't assert any of that. 4462 * tdvp and tvp. But we can't assert any of that.
4468 */ 4463 */
4469 /* XXX KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */ 4464 /* XXX KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
4470 /* XXX KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */ 4465 /* XXX KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */
4471 /* XXX KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */ 4466 /* XXX KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */
4472 /* XXX KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) != LK_EXCLUSIVE)); */ 4467 /* XXX KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) != LK_EXCLUSIVE)); */
4473 4468
4474 /* 4469 /*
4475 * So all we have left to do is to drop the rename lock and 4470 * So all we have left to do is to drop the rename lock and
4476 * destroy the pathbufs. 4471 * destroy the pathbufs.
4477 */ 4472 */
4478 VFS_RENAMELOCK_EXIT(mp); 4473 VFS_RENAMELOCK_EXIT(mp);
4479 goto out2; 4474 goto out2;
4480 4475
4481abort3: if ((tvp != NULL) && (tvp != tdvp)) 4476abort3: if ((tvp != NULL) && (tvp != tdvp))
4482 VOP_UNLOCK(tvp); 4477 VOP_UNLOCK(tvp);
4483abort2: VOP_UNLOCK(tdvp); 4478abort2: VOP_UNLOCK(tdvp);
4484 VFS_RENAMELOCK_EXIT(mp); 4479 VFS_RENAMELOCK_EXIT(mp);
4485abort1: VOP_ABORTOP(tdvp, &tnd.ni_cnd); 4480abort1: VOP_ABORTOP(tdvp, &tnd.ni_cnd);
4486 vrele(tdvp); 4481 vrele(tdvp);
4487 if (tvp != NULL) 4482 if (tvp != NULL)
4488 vrele(tvp); 4483 vrele(tvp);
4489abort0: VOP_ABORTOP(fdvp, &fnd.ni_cnd); 4484abort0: VOP_ABORTOP(fdvp, &fnd.ni_cnd);
4490 vrele(fdvp); 4485 vrele(fdvp);
4491 vrele(fvp); 4486 vrele(fvp);
4492out2: pathbuf_destroy(tpb); 4487out2: pathbuf_destroy(tpb);
4493out1: pathbuf_destroy(fpb); 4488out1: pathbuf_destroy(fpb);
4494out0: return error; 4489out0: return error;
4495} 4490}
4496 4491
4497/* 4492/*
4498 * Make a directory file. 4493 * Make a directory file.
4499 */ 4494 */
4500/* ARGSUSED */ 4495/* ARGSUSED */
4501int 4496int
4502sys_mkdir(struct lwp *l, const struct sys_mkdir_args *uap, register_t *retval) 4497sys_mkdir(struct lwp *l, const struct sys_mkdir_args *uap, register_t *retval)
4503{ 4498{
4504 /* { 4499 /* {
4505 syscallarg(const char *) path; 4500 syscallarg(const char *) path;
4506 syscallarg(int) mode; 4501 syscallarg(int) mode;
4507 } */ 4502 } */
4508 4503
4509 return do_sys_mkdirat(l, AT_FDCWD, SCARG(uap, path), 4504 return do_sys_mkdirat(l, AT_FDCWD, SCARG(uap, path),
4510 SCARG(uap, mode), UIO_USERSPACE); 4505 SCARG(uap, mode), UIO_USERSPACE);
4511} 4506}
4512 4507
4513int 4508int
4514sys_mkdirat(struct lwp *l, const struct sys_mkdirat_args *uap, 4509sys_mkdirat(struct lwp *l, const struct sys_mkdirat_args *uap,
4515 register_t *retval) 4510 register_t *retval)
4516{ 4511{
4517 /* { 4512 /* {
4518 syscallarg(int) fd; 4513 syscallarg(int) fd;
4519 syscallarg(const char *) path; 4514 syscallarg(const char *) path;
4520 syscallarg(int) mode; 4515 syscallarg(int) mode;
4521 } */ 4516 } */
4522 4517
4523 return do_sys_mkdirat(l, SCARG(uap, fd), SCARG(uap, path), 4518 return do_sys_mkdirat(l, SCARG(uap, fd), SCARG(uap, path),
4524 SCARG(uap, mode), UIO_USERSPACE); 4519 SCARG(uap, mode), UIO_USERSPACE);
4525} 4520}
4526 4521
4527 4522
4528int 4523int
4529do_sys_mkdir(const char *path, mode_t mode, enum uio_seg seg) 4524do_sys_mkdir(const char *path, mode_t mode, enum uio_seg seg)
4530{ 4525{
4531 return do_sys_mkdirat(NULL, AT_FDCWD, path, mode, UIO_USERSPACE); 4526 return do_sys_mkdirat(NULL, AT_FDCWD, path, mode, UIO_USERSPACE);
4532} 4527}
4533 4528
4534static int 4529static int
4535do_sys_mkdirat(struct lwp *l, int fdat, const char *path, mode_t mode, 4530do_sys_mkdirat(struct lwp *l, int fdat, const char *path, mode_t mode,
4536 enum uio_seg seg) 4531 enum uio_seg seg)
4537{ 4532{
4538 struct proc *p = curlwp->l_proc; 4533 struct proc *p = curlwp->l_proc;
4539 struct vnode *vp; 4534 struct vnode *vp;
4540 struct vattr vattr; 4535 struct vattr vattr;
4541 int error; 4536 int error;
4542 struct pathbuf *pb; 4537 struct pathbuf *pb;
4543 struct nameidata nd; 4538 struct nameidata nd;
4544 4539
4545 KASSERT(l != NULL || fdat == AT_FDCWD); 4540 KASSERT(l != NULL || fdat == AT_FDCWD);
4546 4541
4547 /* XXX bollocks, should pass in a pathbuf */ 4542 /* XXX bollocks, should pass in a pathbuf */
4548 error = pathbuf_maybe_copyin(path, seg, &pb); 4543 error = pathbuf_maybe_copyin(path, seg, &pb);
4549 if (error) { 4544 if (error) {
4550 return error; 4545 return error;
4551 } 4546 }
4552 4547
4553 NDINIT(&nd, CREATE, LOCKPARENT | CREATEDIR | TRYEMULROOT, pb); 4548 NDINIT(&nd, CREATE, LOCKPARENT | CREATEDIR | TRYEMULROOT, pb);
4554 4549
4555 if ((error = fd_nameiat(l, fdat, &nd)) != 0) { 4550 if ((error = fd_nameiat(l, fdat, &nd)) != 0) {
4556 pathbuf_destroy(pb); 4551 pathbuf_destroy(pb);
4557 return (error); 4552 return (error);
4558 } 4553 }
4559 vp = nd.ni_vp; 4554 vp = nd.ni_vp;
4560 if (vp != NULL) { 4555 if (vp != NULL) {
4561 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 4556 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
4562 if (nd.ni_dvp == vp) 4557 if (nd.ni_dvp == vp)
4563 vrele(nd.ni_dvp); 4558 vrele(nd.ni_dvp);
4564 else 4559 else
4565 vput(nd.ni_dvp); 4560 vput(nd.ni_dvp);
4566 vrele(vp); 4561 vrele(vp);
4567 pathbuf_destroy(pb); 4562 pathbuf_destroy(pb);
4568 return (EEXIST); 4563 return (EEXIST);
4569 } 4564 }
4570 vattr_null(&vattr); 4565 vattr_null(&vattr);
4571 vattr.va_type = VDIR; 4566 vattr.va_type = VDIR;
4572 /* We will read cwdi->cwdi_cmask unlocked. */ 4567 /* We will read cwdi->cwdi_cmask unlocked. */
4573 vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask; 4568 vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask;
4574 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 4569 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
4575 if (!error) 4570 if (!error)
4576 vrele(nd.ni_vp); 4571 vrele(nd.ni_vp);
4577 vput(nd.ni_dvp); 4572 vput(nd.ni_dvp);
4578 pathbuf_destroy(pb); 4573 pathbuf_destroy(pb);
4579 return (error); 4574 return (error);
4580} 4575}
4581 4576
4582/* 4577/*
4583 * Remove a directory file. 4578 * Remove a directory file.
4584 */ 4579 */
4585/* ARGSUSED */ 4580/* ARGSUSED */
4586int 4581int
4587sys_rmdir(struct lwp *l, const struct sys_rmdir_args *uap, register_t *retval) 4582sys_rmdir(struct lwp *l, const struct sys_rmdir_args *uap, register_t *retval)
4588{ 4583{
4589 return do_sys_unlinkat(l, AT_FDCWD, SCARG(uap, path), 4584 return do_sys_unlinkat(l, AT_FDCWD, SCARG(uap, path),
4590 AT_REMOVEDIR, UIO_USERSPACE); 4585 AT_REMOVEDIR, UIO_USERSPACE);
4591} 4586}
4592 4587
4593/* 4588/*
4594 * Read a block of directory entries in a file system independent format. 4589 * Read a block of directory entries in a file system independent format.
4595 */ 4590 */
4596int 4591int
4597sys___getdents30(struct lwp *l, const struct sys___getdents30_args *uap, register_t *retval) 4592sys___getdents30(struct lwp *l, const struct sys___getdents30_args *uap, register_t *retval)
4598{ 4593{
4599 /* { 4594 /* {
4600 syscallarg(int) fd; 4595 syscallarg(int) fd;
4601 syscallarg(char *) buf; 4596 syscallarg(char *) buf;
4602 syscallarg(size_t) count; 4597 syscallarg(size_t) count;
4603 } */ 4598 } */
4604 file_t *fp; 4599 file_t *fp;
4605 int error, done; 4600 int error, done;
4606 4601
4607 /* fd_getvnode() will use the descriptor for us */ 4602 /* fd_getvnode() will use the descriptor for us */
4608 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 4603 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
4609 return (error); 4604 return (error);
4610 if ((fp->f_flag & FREAD) == 0) { 4605 if ((fp->f_flag & FREAD) == 0) {
4611 error = EBADF; 4606 error = EBADF;
4612 goto out; 4607 goto out;
4613 } 4608 }
4614 error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE, 4609 error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE,
4615 SCARG(uap, count), &done, l, 0, 0); 4610 SCARG(uap, count), &done, l, 0, 0);
4616 ktrgenio(SCARG(uap, fd), UIO_READ, SCARG(uap, buf), done, error); 4611 ktrgenio(SCARG(uap, fd), UIO_READ, SCARG(uap, buf), done, error);
4617 *retval = done; 4612 *retval = done;
4618 out: 4613 out:
4619 fd_putfile(SCARG(uap, fd)); 4614 fd_putfile(SCARG(uap, fd));
4620 return (error); 4615 return (error);
4621} 4616}
4622 4617
4623/* 4618/*
4624 * Set the mode mask for creation of filesystem nodes. 4619 * Set the mode mask for creation of filesystem nodes.
4625 */ 4620 */
4626int 4621int
4627sys_umask(struct lwp *l, const struct sys_umask_args *uap, register_t *retval) 4622sys_umask(struct lwp *l, const struct sys_umask_args *uap, register_t *retval)
4628{ 4623{
4629 /* { 4624 /* {
4630 syscallarg(mode_t) newmask; 4625 syscallarg(mode_t) newmask;
4631 } */ 4626 } */
4632 struct proc *p = l->l_proc; 4627 struct proc *p = l->l_proc;
4633 struct cwdinfo *cwdi; 4628 struct cwdinfo *cwdi;
4634 4629
4635 /* 4630 /*
4636 * cwdi->cwdi_cmask will be read unlocked elsewhere. What's 4631 * cwdi->cwdi_cmask will be read unlocked elsewhere. What's
4637 * important is that we serialize changes to the mask. The 4632 * important is that we serialize changes to the mask. The
4638 * rw_exit() will issue a write memory barrier on our behalf, 4633 * rw_exit() will issue a write memory barrier on our behalf,
4639 * and force the changes out to other CPUs (as it must use an 4634 * and force the changes out to other CPUs (as it must use an
4640 * atomic operation, draining the local CPU's store buffers). 4635 * atomic operation, draining the local CPU's store buffers).
4641 */ 4636 */
4642 cwdi = p->p_cwdi; 4637 cwdi = p->p_cwdi;
4643 rw_enter(&cwdi->cwdi_lock, RW_WRITER); 4638 rw_enter(&cwdi->cwdi_lock, RW_WRITER);
4644 *retval = cwdi->cwdi_cmask; 4639 *retval = cwdi->cwdi_cmask;
4645 cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS; 4640 cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS;
4646 rw_exit(&cwdi->cwdi_lock); 4641 rw_exit(&cwdi->cwdi_lock);
4647 4642
4648 return (0); 4643 return (0);
4649} 4644}
4650 4645
4651int 4646int
4652dorevoke(struct vnode *vp, kauth_cred_t cred) 4647dorevoke(struct vnode *vp, kauth_cred_t cred)
4653{ 4648{
4654 struct vattr vattr; 4649 struct vattr vattr;
4655 int error, fs_decision; 4650 int error, fs_decision;
4656 4651
4657 vn_lock(vp, LK_SHARED | LK_RETRY); 4652 vn_lock(vp, LK_SHARED | LK_RETRY);
4658 error = VOP_GETATTR(vp, &vattr, cred); 4653 error = VOP_GETATTR(vp, &vattr, cred);
4659 VOP_UNLOCK(vp); 4654 VOP_UNLOCK(vp);
4660 if (error != 0) 4655 if (error != 0)
4661 return error; 4656 return error;
4662 fs_decision = (kauth_cred_geteuid(cred) == vattr.va_uid) ? 0 : EPERM; 4657 fs_decision = (kauth_cred_geteuid(cred) == vattr.va_uid) ? 0 : EPERM;
4663 error = kauth_authorize_vnode(cred, KAUTH_VNODE_REVOKE, vp, NULL, 4658 error = kauth_authorize_vnode(cred, KAUTH_VNODE_REVOKE, vp, NULL,
4664 fs_decision); 4659 fs_decision);
4665 if (!error) 4660 if (!error)
4666 VOP_REVOKE(vp, REVOKEALL); 4661 VOP_REVOKE(vp, REVOKEALL);
4667 return (error); 4662 return (error);
4668} 4663}
4669 4664
4670/* 4665/*
4671 * Void all references to file by ripping underlying filesystem 4666 * Void all references to file by ripping underlying filesystem
4672 * away from vnode. 4667 * away from vnode.
4673 */ 4668 */
4674/* ARGSUSED */ 4669/* ARGSUSED */
4675int 4670int
4676sys_revoke(struct lwp *l, const struct sys_revoke_args *uap, register_t *retval) 4671sys_revoke(struct lwp *l, const struct sys_revoke_args *uap, register_t *retval)
4677{ 4672{
4678 /* { 4673 /* {
4679 syscallarg(const char *) path; 4674 syscallarg(const char *) path;
4680 } */ 4675 } */
4681 struct vnode *vp; 4676 struct vnode *vp;
4682 int error; 4677 int error;
4683 4678
4684 error = namei_simple_user(SCARG(uap, path), 4679 error = namei_simple_user(SCARG(uap, path),
4685 NSM_FOLLOW_TRYEMULROOT, &vp); 4680 NSM_FOLLOW_TRYEMULROOT, &vp);
4686 if (error != 0) 4681 if (error != 0)
4687 return (error); 4682 return (error);
4688 error = dorevoke(vp, l->l_cred); 4683 error = dorevoke(vp, l->l_cred);
4689 vrele(vp); 4684 vrele(vp);
4690 return (error); 4685 return (error);
4691} 4686}
4692 4687
4693/* 4688/*
4694 * Allocate backing store for a file, filling a hole without having to 4689 * Allocate backing store for a file, filling a hole without having to
4695 * explicitly write anything out. 4690 * explicitly write anything out.
4696 */ 4691 */
4697/* ARGSUSED */ 4692/* ARGSUSED */
4698int 4693int
4699sys_posix_fallocate(struct lwp *l, const struct sys_posix_fallocate_args *uap, 4694sys_posix_fallocate(struct lwp *l, const struct sys_posix_fallocate_args *uap,
4700 register_t *retval) 4695 register_t *retval)
4701{ 4696{
4702 /* { 4697 /* {
4703 syscallarg(int) fd; 4698 syscallarg(int) fd;
4704 syscallarg(off_t) pos; 4699 syscallarg(off_t) pos;
4705 syscallarg(off_t) len; 4700 syscallarg(off_t) len;
4706 } */ 4701 } */
4707 int fd; 4702 int fd;
4708 off_t pos, len; 4703 off_t pos, len;
4709 struct file *fp; 4704 struct file *fp;
4710 struct vnode *vp; 4705 struct vnode *vp;
4711 int error; 4706 int error;
4712 4707
4713 fd = SCARG(uap, fd); 4708 fd = SCARG(uap, fd);
4714 pos = SCARG(uap, pos); 4709 pos = SCARG(uap, pos);
4715 len = SCARG(uap, len); 4710 len = SCARG(uap, len);
4716  4711
4717 if (pos < 0 || len < 0 || len > OFF_T_MAX - pos) { 4712 if (pos < 0 || len < 0 || len > OFF_T_MAX - pos) {
4718 *retval = EINVAL; 4713 *retval = EINVAL;
4719 return 0; 4714 return 0;
4720 } 4715 }
4721  4716
4722 error = fd_getvnode(fd, &fp); 4717 error = fd_getvnode(fd, &fp);
4723 if (error) { 4718 if (error) {
4724 *retval = error; 4719 *retval = error;
4725 return 0; 4720 return 0;
4726 } 4721 }
4727 if ((fp->f_flag & FWRITE) == 0) { 4722 if ((fp->f_flag & FWRITE) == 0) {
4728 error = EBADF; 4723 error = EBADF;
4729 goto fail; 4724 goto fail;
4730 } 4725 }
4731 vp = fp->f_vnode; 4726 vp = fp->f_vnode;
4732 4727
4733 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 4728 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
4734 if (vp->v_type == VDIR) { 4729 if (vp->v_type == VDIR) {
4735 error = EISDIR; 4730 error = EISDIR;
4736 } else { 4731 } else {
4737 error = VOP_FALLOCATE(vp, pos, len); 4732 error = VOP_FALLOCATE(vp, pos, len);
4738 } 4733 }
4739 VOP_UNLOCK(vp); 4734 VOP_UNLOCK(vp);
4740 4735
4741fail: 4736fail:
4742 fd_putfile(fd); 4737 fd_putfile(fd);
4743 *retval = error; 4738 *retval = error;
4744 return 0; 4739 return 0;
4745} 4740}
4746 4741
4747/* 4742/*
4748 * Deallocate backing store for a file, creating a hole. Also used for 4743 * Deallocate backing store for a file, creating a hole. Also used for
4749 * invoking TRIM on disks. 4744 * invoking TRIM on disks.
4750 */ 4745 */
4751/* ARGSUSED */ 4746/* ARGSUSED */
4752int 4747int
4753sys_fdiscard(struct lwp *l, const struct sys_fdiscard_args *uap, 4748sys_fdiscard(struct lwp *l, const struct sys_fdiscard_args *uap,
4754 register_t *retval) 4749 register_t *retval)
4755{ 4750{
4756 /* { 4751 /* {
4757 syscallarg(int) fd; 4752 syscallarg(int) fd;
4758 syscallarg(off_t) pos; 4753 syscallarg(off_t) pos;
4759 syscallarg(off_t) len; 4754 syscallarg(off_t) len;
4760 } */ 4755 } */
4761 int fd; 4756 int fd;
4762 off_t pos, len; 4757 off_t pos, len;
4763 struct file *fp; 4758 struct file *fp;
4764 struct vnode *vp; 4759 struct vnode *vp;
4765 int error; 4760 int error;
4766 4761
4767 fd = SCARG(uap, fd); 4762 fd = SCARG(uap, fd);
4768 pos = SCARG(uap, pos); 4763 pos = SCARG(uap, pos);
4769 len = SCARG(uap, len); 4764 len = SCARG(uap, len);
4770 4765
4771 if (pos < 0 || len < 0 || len > OFF_T_MAX - pos) { 4766 if (pos < 0 || len < 0 || len > OFF_T_MAX - pos) {
4772 return EINVAL; 4767 return EINVAL;
4773 } 4768 }
4774  4769
4775 error = fd_getvnode(fd, &fp); 4770 error = fd_getvnode(fd, &fp);
4776 if (error) { 4771 if (error) {
4777 return error; 4772 return error;
4778 } 4773 }
4779 if ((fp->f_flag & FWRITE) == 0) { 4774 if ((fp->f_flag & FWRITE) == 0) {
4780 error = EBADF; 4775 error = EBADF;
4781 goto fail; 4776 goto fail;
4782 } 4777 }
4783 vp = fp->f_vnode; 4778 vp = fp->f_vnode;
4784 4779
4785 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 4780 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
4786 if (vp->v_type == VDIR) { 4781 if (vp->v_type == VDIR) {
4787 error = EISDIR; 4782 error = EISDIR;
4788 } else { 4783 } else {
4789 error = VOP_FDISCARD(vp, pos, len); 4784 error = VOP_FDISCARD(vp, pos, len);
4790 } 4785 }
4791 VOP_UNLOCK(vp); 4786 VOP_UNLOCK(vp);
4792 4787
4793fail: 4788fail:
4794 fd_putfile(fd); 4789 fd_putfile(fd);
4795 return error; 4790 return error;
4796} 4791}