| @@ -1,518 +1,519 @@ | | | @@ -1,518 +1,519 @@ |
1 | /* $NetBSD: vfs_syscalls_43.c,v 1.49 2009/01/26 13:00:04 njoly Exp $ */ | | 1 | /* $NetBSD: vfs_syscalls_43.c,v 1.50 2009/03/17 00:01:54 dyoung Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1989, 1993 | | 4 | * Copyright (c) 1989, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * (c) UNIX System Laboratories, Inc. | | 6 | * (c) UNIX System Laboratories, Inc. |
7 | * All or some portions of this file are derived from material licensed | | 7 | * All or some portions of this file are derived from material licensed |
8 | * to the University of California by American Telephone and Telegraph | | 8 | * to the University of California by American Telephone and Telegraph |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | | 9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with |
10 | * the permission of UNIX System Laboratories, Inc. | | 10 | * the permission of UNIX System Laboratories, Inc. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright | | 15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions and the following disclaimer. | | 16 | * notice, this list of conditions and the following disclaimer. |
17 | * 2. Redistributions in binary form must reproduce the above copyright | | 17 | * 2. Redistributions in binary form must reproduce the above copyright |
18 | * notice, this list of conditions and the following disclaimer in the | | 18 | * notice, this list of conditions and the following disclaimer in the |
19 | * documentation and/or other materials provided with the distribution. | | 19 | * documentation and/or other materials provided with the distribution. |
20 | * 3. Neither the name of the University nor the names of its contributors | | 20 | * 3. Neither the name of the University nor the names of its contributors |
21 | * may be used to endorse or promote products derived from this software | | 21 | * may be used to endorse or promote products derived from this software |
22 | * without specific prior written permission. | | 22 | * without specific prior written permission. |
23 | * | | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 | * SUCH DAMAGE. | | 34 | * SUCH DAMAGE. |
35 | * | | 35 | * |
36 | * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94 | | 36 | * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94 |
37 | */ | | 37 | */ |
38 | | | 38 | |
39 | #include <sys/cdefs.h> | | 39 | #include <sys/cdefs.h> |
40 | __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_43.c,v 1.49 2009/01/26 13:00:04 njoly Exp $"); | | 40 | __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_43.c,v 1.50 2009/03/17 00:01:54 dyoung Exp $"); |
41 | | | 41 | |
42 | #if defined(_KERNEL_OPT) | | 42 | #if defined(_KERNEL_OPT) |
| | | 43 | #include "opt_compat_netbsd.h" |
43 | #include "fs_union.h" | | 44 | #include "fs_union.h" |
44 | #endif | | 45 | #endif |
45 | | | 46 | |
46 | #include <sys/param.h> | | 47 | #include <sys/param.h> |
47 | #include <sys/systm.h> | | 48 | #include <sys/systm.h> |
48 | #include <sys/filedesc.h> | | 49 | #include <sys/filedesc.h> |
49 | #include <sys/kernel.h> | | 50 | #include <sys/kernel.h> |
50 | #include <sys/proc.h> | | 51 | #include <sys/proc.h> |
51 | #include <sys/file.h> | | 52 | #include <sys/file.h> |
52 | #include <sys/vnode.h> | | 53 | #include <sys/vnode.h> |
53 | #include <sys/namei.h> | | 54 | #include <sys/namei.h> |
54 | #include <sys/dirent.h> | | 55 | #include <sys/dirent.h> |
55 | #include <sys/socket.h> | | 56 | #include <sys/socket.h> |
56 | #include <sys/socketvar.h> | | 57 | #include <sys/socketvar.h> |
57 | #include <sys/stat.h> | | 58 | #include <sys/stat.h> |
58 | #include <sys/malloc.h> | | 59 | #include <sys/malloc.h> |
59 | #include <sys/ioctl.h> | | 60 | #include <sys/ioctl.h> |
60 | #include <sys/fcntl.h> | | 61 | #include <sys/fcntl.h> |
61 | #include <sys/syslog.h> | | 62 | #include <sys/syslog.h> |
62 | #include <sys/unistd.h> | | 63 | #include <sys/unistd.h> |
63 | #include <sys/resourcevar.h> | | 64 | #include <sys/resourcevar.h> |
64 | #include <sys/sysctl.h> | | 65 | #include <sys/sysctl.h> |
65 | | | 66 | |
66 | #include <sys/mount.h> | | 67 | #include <sys/mount.h> |
67 | #include <sys/syscallargs.h> | | 68 | #include <sys/syscallargs.h> |
68 | #include <sys/vfs_syscalls.h> | | 69 | #include <sys/vfs_syscalls.h> |
69 | | | 70 | |
70 | #include <compat/sys/stat.h> | | 71 | #include <compat/sys/stat.h> |
71 | #include <compat/sys/mount.h> | | 72 | #include <compat/sys/mount.h> |
72 | | | 73 | |
73 | #include <compat/common/compat_util.h> | | 74 | #include <compat/common/compat_util.h> |
74 | | | 75 | |
75 | static void cvtstat(struct stat *, struct stat43 *); | | 76 | static void cvtstat(struct stat *, struct stat43 *); |
76 | | | 77 | |
77 | /* | | 78 | /* |
78 | * Convert from an old to a new stat structure. | | 79 | * Convert from an old to a new stat structure. |
79 | */ | | 80 | */ |
80 | static void | | 81 | static void |
81 | cvtstat(struct stat *st, struct stat43 *ost) | | 82 | cvtstat(struct stat *st, struct stat43 *ost) |
82 | { | | 83 | { |
83 | | | 84 | |
84 | ost->st_dev = st->st_dev; | | 85 | ost->st_dev = st->st_dev; |
85 | ost->st_ino = st->st_ino; | | 86 | ost->st_ino = st->st_ino; |
86 | ost->st_mode = st->st_mode & 0xffff; | | 87 | ost->st_mode = st->st_mode & 0xffff; |
87 | ost->st_nlink = st->st_nlink; | | 88 | ost->st_nlink = st->st_nlink; |
88 | ost->st_uid = st->st_uid; | | 89 | ost->st_uid = st->st_uid; |
89 | ost->st_gid = st->st_gid; | | 90 | ost->st_gid = st->st_gid; |
90 | ost->st_rdev = st->st_rdev; | | 91 | ost->st_rdev = st->st_rdev; |
91 | if (st->st_size < (quad_t)1 << 32) | | 92 | if (st->st_size < (quad_t)1 << 32) |
92 | ost->st_size = st->st_size; | | 93 | ost->st_size = st->st_size; |
93 | else | | 94 | else |
94 | ost->st_size = -2; | | 95 | ost->st_size = -2; |
95 | ost->st_atime = st->st_atime; | | 96 | ost->st_atime = st->st_atime; |
96 | ost->st_mtime = st->st_mtime; | | 97 | ost->st_mtime = st->st_mtime; |
97 | ost->st_ctime = st->st_ctime; | | 98 | ost->st_ctime = st->st_ctime; |
98 | ost->st_blksize = st->st_blksize; | | 99 | ost->st_blksize = st->st_blksize; |
99 | ost->st_blocks = st->st_blocks; | | 100 | ost->st_blocks = st->st_blocks; |
100 | ost->st_flags = st->st_flags; | | 101 | ost->st_flags = st->st_flags; |
101 | ost->st_gen = st->st_gen; | | 102 | ost->st_gen = st->st_gen; |
102 | } | | 103 | } |
103 | | | 104 | |
104 | /* | | 105 | /* |
105 | * Get file status; this version follows links. | | 106 | * Get file status; this version follows links. |
106 | */ | | 107 | */ |
107 | /* ARGSUSED */ | | 108 | /* ARGSUSED */ |
108 | int | | 109 | int |
109 | compat_43_sys_stat(struct lwp *l, const struct compat_43_sys_stat_args *uap, register_t *retval) | | 110 | compat_43_sys_stat(struct lwp *l, const struct compat_43_sys_stat_args *uap, register_t *retval) |
110 | { | | 111 | { |
111 | /* { | | 112 | /* { |
112 | syscallarg(char *) path; | | 113 | syscallarg(char *) path; |
113 | syscallarg(struct stat43 *) ub; | | 114 | syscallarg(struct stat43 *) ub; |
114 | } */ | | 115 | } */ |
115 | struct stat sb; | | 116 | struct stat sb; |
116 | struct stat43 osb; | | 117 | struct stat43 osb; |
117 | int error; | | 118 | int error; |
118 | | | 119 | |
119 | error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb); | | 120 | error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb); |
120 | if (error) | | 121 | if (error) |
121 | return (error); | | 122 | return (error); |
122 | cvtstat(&sb, &osb); | | 123 | cvtstat(&sb, &osb); |
123 | error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb)); | | 124 | error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb)); |
124 | return (error); | | 125 | return (error); |
125 | } | | 126 | } |
126 | | | 127 | |
127 | /* | | 128 | /* |
128 | * Get file status; this version does not follow links. | | 129 | * Get file status; this version does not follow links. |
129 | */ | | 130 | */ |
130 | /* ARGSUSED */ | | 131 | /* ARGSUSED */ |
131 | int | | 132 | int |
132 | compat_43_sys_lstat(struct lwp *l, const struct compat_43_sys_lstat_args *uap, register_t *retval) | | 133 | compat_43_sys_lstat(struct lwp *l, const struct compat_43_sys_lstat_args *uap, register_t *retval) |
133 | { | | 134 | { |
134 | /* { | | 135 | /* { |
135 | syscallarg(char *) path; | | 136 | syscallarg(char *) path; |
136 | syscallarg(struct ostat *) ub; | | 137 | syscallarg(struct ostat *) ub; |
137 | } */ | | 138 | } */ |
138 | struct vnode *vp, *dvp; | | 139 | struct vnode *vp, *dvp; |
139 | struct stat sb, sb1; | | 140 | struct stat sb, sb1; |
140 | struct stat43 osb; | | 141 | struct stat43 osb; |
141 | int error; | | 142 | int error; |
142 | struct nameidata nd; | | 143 | struct nameidata nd; |
143 | int ndflags; | | 144 | int ndflags; |
144 | | | 145 | |
145 | ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT | TRYEMULROOT; | | 146 | ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT | TRYEMULROOT; |
146 | again: | | 147 | again: |
147 | NDINIT(&nd, LOOKUP, ndflags, UIO_USERSPACE, SCARG(uap, path)); | | 148 | NDINIT(&nd, LOOKUP, ndflags, UIO_USERSPACE, SCARG(uap, path)); |
148 | if ((error = namei(&nd))) { | | 149 | if ((error = namei(&nd))) { |
149 | if (error == EISDIR && (ndflags & LOCKPARENT) != 0) { | | 150 | if (error == EISDIR && (ndflags & LOCKPARENT) != 0) { |
150 | /* | | 151 | /* |
151 | * Should only happen on '/'. Retry without LOCKPARENT; | | 152 | * Should only happen on '/'. Retry without LOCKPARENT; |
152 | * this is safe since the vnode won't be a VLNK. | | 153 | * this is safe since the vnode won't be a VLNK. |
153 | */ | | 154 | */ |
154 | ndflags &= ~LOCKPARENT; | | 155 | ndflags &= ~LOCKPARENT; |
155 | goto again; | | 156 | goto again; |
156 | } | | 157 | } |
157 | return (error); | | 158 | return (error); |
158 | } | | 159 | } |
159 | /* | | 160 | /* |
160 | * For symbolic links, always return the attributes of its | | 161 | * For symbolic links, always return the attributes of its |
161 | * containing directory, except for mode, size, and links. | | 162 | * containing directory, except for mode, size, and links. |
162 | */ | | 163 | */ |
163 | vp = nd.ni_vp; | | 164 | vp = nd.ni_vp; |
164 | dvp = nd.ni_dvp; | | 165 | dvp = nd.ni_dvp; |
165 | if (vp->v_type != VLNK) { | | 166 | if (vp->v_type != VLNK) { |
166 | if ((ndflags & LOCKPARENT) != 0) { | | 167 | if ((ndflags & LOCKPARENT) != 0) { |
167 | if (dvp == vp) | | 168 | if (dvp == vp) |
168 | vrele(dvp); | | 169 | vrele(dvp); |
169 | else | | 170 | else |
170 | vput(dvp); | | 171 | vput(dvp); |
171 | } | | 172 | } |
172 | error = vn_stat(vp, &sb); | | 173 | error = vn_stat(vp, &sb); |
173 | vput(vp); | | 174 | vput(vp); |
174 | if (error) | | 175 | if (error) |
175 | return (error); | | 176 | return (error); |
176 | } else { | | 177 | } else { |
177 | error = vn_stat(dvp, &sb); | | 178 | error = vn_stat(dvp, &sb); |
178 | vput(dvp); | | 179 | vput(dvp); |
179 | if (error) { | | 180 | if (error) { |
180 | vput(vp); | | 181 | vput(vp); |
181 | return (error); | | 182 | return (error); |
182 | } | | 183 | } |
183 | error = vn_stat(vp, &sb1); | | 184 | error = vn_stat(vp, &sb1); |
184 | vput(vp); | | 185 | vput(vp); |
185 | if (error) | | 186 | if (error) |
186 | return (error); | | 187 | return (error); |
187 | sb.st_mode &= ~S_IFDIR; | | 188 | sb.st_mode &= ~S_IFDIR; |
188 | sb.st_mode |= S_IFLNK; | | 189 | sb.st_mode |= S_IFLNK; |
189 | sb.st_nlink = sb1.st_nlink; | | 190 | sb.st_nlink = sb1.st_nlink; |
190 | sb.st_size = sb1.st_size; | | 191 | sb.st_size = sb1.st_size; |
191 | sb.st_blocks = sb1.st_blocks; | | 192 | sb.st_blocks = sb1.st_blocks; |
192 | } | | 193 | } |
193 | cvtstat(&sb, &osb); | | 194 | cvtstat(&sb, &osb); |
194 | error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb)); | | 195 | error = copyout((void *)&osb, (void *)SCARG(uap, ub), sizeof (osb)); |
195 | return (error); | | 196 | return (error); |
196 | } | | 197 | } |
197 | | | 198 | |
198 | /* | | 199 | /* |
199 | * Return status information about a file descriptor. | | 200 | * Return status information about a file descriptor. |
200 | */ | | 201 | */ |
201 | /* ARGSUSED */ | | 202 | /* ARGSUSED */ |
202 | int | | 203 | int |
203 | compat_43_sys_fstat(struct lwp *l, const struct compat_43_sys_fstat_args *uap, register_t *retval) | | 204 | compat_43_sys_fstat(struct lwp *l, const struct compat_43_sys_fstat_args *uap, register_t *retval) |
204 | { | | 205 | { |
205 | /* { | | 206 | /* { |
206 | syscallarg(int) fd; | | 207 | syscallarg(int) fd; |
207 | syscallarg(struct stat43 *) sb; | | 208 | syscallarg(struct stat43 *) sb; |
208 | } */ | | 209 | } */ |
209 | struct stat ub; | | 210 | struct stat ub; |
210 | struct stat43 oub; | | 211 | struct stat43 oub; |
211 | int error; | | 212 | int error; |
212 | | | 213 | |
213 | error = do_sys_fstat(SCARG(uap, fd), &ub); | | 214 | error = do_sys_fstat(SCARG(uap, fd), &ub); |
214 | if (error == 0) { | | 215 | if (error == 0) { |
215 | cvtstat(&ub, &oub); | | 216 | cvtstat(&ub, &oub); |
216 | error = copyout((void *)&oub, (void *)SCARG(uap, sb), | | 217 | error = copyout((void *)&oub, (void *)SCARG(uap, sb), |
217 | sizeof (oub)); | | 218 | sizeof (oub)); |
218 | } | | 219 | } |
219 | | | 220 | |
220 | return (error); | | 221 | return (error); |
221 | } | | 222 | } |
222 | | | 223 | |
223 | | | 224 | |
224 | /* | | 225 | /* |
225 | * Truncate a file given a file descriptor. | | 226 | * Truncate a file given a file descriptor. |
226 | */ | | 227 | */ |
227 | /* ARGSUSED */ | | 228 | /* ARGSUSED */ |
228 | int | | 229 | int |
229 | compat_43_sys_ftruncate(struct lwp *l, const struct compat_43_sys_ftruncate_args *uap, register_t *retval) | | 230 | compat_43_sys_ftruncate(struct lwp *l, const struct compat_43_sys_ftruncate_args *uap, register_t *retval) |
230 | { | | 231 | { |
231 | /* { | | 232 | /* { |
232 | syscallarg(int) fd; | | 233 | syscallarg(int) fd; |
233 | syscallarg(long) length; | | 234 | syscallarg(long) length; |
234 | } */ | | 235 | } */ |
235 | struct sys_ftruncate_args /* { | | 236 | struct sys_ftruncate_args /* { |
236 | syscallarg(int) fd; | | 237 | syscallarg(int) fd; |
237 | syscallarg(int) pad; | | 238 | syscallarg(int) pad; |
238 | syscallarg(off_t) length; | | 239 | syscallarg(off_t) length; |
239 | } */ nuap; | | 240 | } */ nuap; |
240 | | | 241 | |
241 | SCARG(&nuap, fd) = SCARG(uap, fd); | | 242 | SCARG(&nuap, fd) = SCARG(uap, fd); |
242 | SCARG(&nuap, length) = SCARG(uap, length); | | 243 | SCARG(&nuap, length) = SCARG(uap, length); |
243 | return (sys_ftruncate(l, &nuap, retval)); | | 244 | return (sys_ftruncate(l, &nuap, retval)); |
244 | } | | 245 | } |
245 | | | 246 | |
246 | /* | | 247 | /* |
247 | * Truncate a file given its path name. | | 248 | * Truncate a file given its path name. |
248 | */ | | 249 | */ |
249 | /* ARGSUSED */ | | 250 | /* ARGSUSED */ |
250 | int | | 251 | int |
251 | compat_43_sys_truncate(struct lwp *l, const struct compat_43_sys_truncate_args *uap, register_t *retval) | | 252 | compat_43_sys_truncate(struct lwp *l, const struct compat_43_sys_truncate_args *uap, register_t *retval) |
252 | { | | 253 | { |
253 | /* { | | 254 | /* { |
254 | syscallarg(char *) path; | | 255 | syscallarg(char *) path; |
255 | syscallarg(long) length; | | 256 | syscallarg(long) length; |
256 | } */ | | 257 | } */ |
257 | struct sys_truncate_args /* { | | 258 | struct sys_truncate_args /* { |
258 | syscallarg(char *) path; | | 259 | syscallarg(char *) path; |
259 | syscallarg(int) pad; | | 260 | syscallarg(int) pad; |
260 | syscallarg(off_t) length; | | 261 | syscallarg(off_t) length; |
261 | } */ nuap; | | 262 | } */ nuap; |
262 | | | 263 | |
263 | SCARG(&nuap, path) = SCARG(uap, path); | | 264 | SCARG(&nuap, path) = SCARG(uap, path); |
264 | SCARG(&nuap, length) = SCARG(uap, length); | | 265 | SCARG(&nuap, length) = SCARG(uap, length); |
265 | return (sys_truncate(l, &nuap, retval)); | | 266 | return (sys_truncate(l, &nuap, retval)); |
266 | } | | 267 | } |
267 | | | 268 | |
268 | | | 269 | |
269 | /* | | 270 | /* |
270 | * Reposition read/write file offset. | | 271 | * Reposition read/write file offset. |
271 | */ | | 272 | */ |
272 | int | | 273 | int |
273 | compat_43_sys_lseek(struct lwp *l, const struct compat_43_sys_lseek_args *uap, register_t *retval) | | 274 | compat_43_sys_lseek(struct lwp *l, const struct compat_43_sys_lseek_args *uap, register_t *retval) |
274 | { | | 275 | { |
275 | /* { | | 276 | /* { |
276 | syscallarg(int) fd; | | 277 | syscallarg(int) fd; |
277 | syscallarg(long) offset; | | 278 | syscallarg(long) offset; |
278 | syscallarg(int) whence; | | 279 | syscallarg(int) whence; |
279 | } */ | | 280 | } */ |
280 | struct sys_lseek_args /* { | | 281 | struct sys_lseek_args /* { |
281 | syscallarg(int) fd; | | 282 | syscallarg(int) fd; |
282 | syscallarg(int) pad; | | 283 | syscallarg(int) pad; |
283 | syscallarg(off_t) offset; | | 284 | syscallarg(off_t) offset; |
284 | syscallarg(int) whence; | | 285 | syscallarg(int) whence; |
285 | } */ nuap; | | 286 | } */ nuap; |
286 | off_t qret; | | 287 | off_t qret; |
287 | int error; | | 288 | int error; |
288 | | | 289 | |
289 | SCARG(&nuap, fd) = SCARG(uap, fd); | | 290 | SCARG(&nuap, fd) = SCARG(uap, fd); |
290 | SCARG(&nuap, offset) = SCARG(uap, offset); | | 291 | SCARG(&nuap, offset) = SCARG(uap, offset); |
291 | SCARG(&nuap, whence) = SCARG(uap, whence); | | 292 | SCARG(&nuap, whence) = SCARG(uap, whence); |
292 | error = sys_lseek(l, &nuap, (void *)&qret); | | 293 | error = sys_lseek(l, &nuap, (void *)&qret); |
293 | *(long *)retval = qret; | | 294 | *(long *)retval = qret; |
294 | return (error); | | 295 | return (error); |
295 | } | | 296 | } |
296 | | | 297 | |
297 | | | 298 | |
298 | /* | | 299 | /* |
299 | * Create a file. | | 300 | * Create a file. |
300 | */ | | 301 | */ |
301 | int | | 302 | int |
302 | compat_43_sys_creat(struct lwp *l, const struct compat_43_sys_creat_args *uap, register_t *retval) | | 303 | compat_43_sys_creat(struct lwp *l, const struct compat_43_sys_creat_args *uap, register_t *retval) |
303 | { | | 304 | { |
304 | /* { | | 305 | /* { |
305 | syscallarg(char *) path; | | 306 | syscallarg(char *) path; |
306 | syscallarg(int) mode; | | 307 | syscallarg(int) mode; |
307 | } */ | | 308 | } */ |
308 | struct sys_open_args /* { | | 309 | struct sys_open_args /* { |
309 | syscallarg(char *) path; | | 310 | syscallarg(char *) path; |
310 | syscallarg(int) flags; | | 311 | syscallarg(int) flags; |
311 | syscallarg(int) mode; | | 312 | syscallarg(int) mode; |
312 | } */ nuap; | | 313 | } */ nuap; |
313 | | | 314 | |
314 | SCARG(&nuap, path) = SCARG(uap, path); | | 315 | SCARG(&nuap, path) = SCARG(uap, path); |
315 | SCARG(&nuap, mode) = SCARG(uap, mode); | | 316 | SCARG(&nuap, mode) = SCARG(uap, mode); |
316 | SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; | | 317 | SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; |
317 | return (sys_open(l, &nuap, retval)); | | 318 | return (sys_open(l, &nuap, retval)); |
318 | } | | 319 | } |
319 | | | 320 | |
320 | /*ARGSUSED*/ | | 321 | /*ARGSUSED*/ |
321 | int | | 322 | int |
322 | compat_43_sys_quota(struct lwp *l, const void *v, register_t *retval) | | 323 | compat_43_sys_quota(struct lwp *l, const void *v, register_t *retval) |
323 | { | | 324 | { |
324 | | | 325 | |
325 | return (ENOSYS); | | 326 | return (ENOSYS); |
326 | } | | 327 | } |
327 | | | 328 | |
328 | | | 329 | |
329 | /* | | 330 | /* |
330 | * Read a block of directory entries in a file system independent format. | | 331 | * Read a block of directory entries in a file system independent format. |
331 | */ | | 332 | */ |
332 | int | | 333 | int |
333 | compat_43_sys_getdirentries(struct lwp *l, const struct compat_43_sys_getdirentries_args *uap, register_t *retval) | | 334 | compat_43_sys_getdirentries(struct lwp *l, const struct compat_43_sys_getdirentries_args *uap, register_t *retval) |
334 | { | | 335 | { |
335 | /* { | | 336 | /* { |
336 | syscallarg(int) fd; | | 337 | syscallarg(int) fd; |
337 | syscallarg(char *) buf; | | 338 | syscallarg(char *) buf; |
338 | syscallarg(u_int) count; | | 339 | syscallarg(u_int) count; |
339 | syscallarg(long *) basep; | | 340 | syscallarg(long *) basep; |
340 | } */ | | 341 | } */ |
341 | struct vnode *vp; | | 342 | struct vnode *vp; |
342 | struct file *fp; | | 343 | struct file *fp; |
343 | struct uio auio, kuio; | | 344 | struct uio auio, kuio; |
344 | struct iovec aiov, kiov; | | 345 | struct iovec aiov, kiov; |
345 | struct dirent *dp, *edp; | | 346 | struct dirent *dp, *edp; |
346 | char *dirbuf; | | 347 | char *dirbuf; |
347 | size_t count = min(MAXBSIZE, (size_t)SCARG(uap, count)); | | 348 | size_t count = min(MAXBSIZE, (size_t)SCARG(uap, count)); |
348 | | | 349 | |
349 | int error, eofflag, readcnt; | | 350 | int error, eofflag, readcnt; |
350 | long loff; | | 351 | long loff; |
351 | | | 352 | |
352 | /* fd_getvnode() will use the descriptor for us */ | | 353 | /* fd_getvnode() will use the descriptor for us */ |
353 | if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) | | 354 | if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) |
354 | return (error); | | 355 | return (error); |
355 | if ((fp->f_flag & FREAD) == 0) { | | 356 | if ((fp->f_flag & FREAD) == 0) { |
356 | error = EBADF; | | 357 | error = EBADF; |
357 | goto out; | | 358 | goto out; |
358 | } | | 359 | } |
359 | vp = (struct vnode *)fp->f_data; | | 360 | vp = (struct vnode *)fp->f_data; |
360 | unionread: | | 361 | unionread: |
361 | if (vp->v_type != VDIR) { | | 362 | if (vp->v_type != VDIR) { |
362 | error = EINVAL; | | 363 | error = EINVAL; |
363 | goto out; | | 364 | goto out; |
364 | } | | 365 | } |
365 | aiov.iov_base = SCARG(uap, buf); | | 366 | aiov.iov_base = SCARG(uap, buf); |
366 | aiov.iov_len = count; | | 367 | aiov.iov_len = count; |
367 | auio.uio_iov = &aiov; | | 368 | auio.uio_iov = &aiov; |
368 | auio.uio_iovcnt = 1; | | 369 | auio.uio_iovcnt = 1; |
369 | auio.uio_rw = UIO_READ; | | 370 | auio.uio_rw = UIO_READ; |
370 | auio.uio_resid = count; | | 371 | auio.uio_resid = count; |
371 | KASSERT(l == curlwp); | | 372 | KASSERT(l == curlwp); |
372 | auio.uio_vmspace = curproc->p_vmspace; | | 373 | auio.uio_vmspace = curproc->p_vmspace; |
373 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | | 374 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
374 | loff = auio.uio_offset = fp->f_offset; | | 375 | loff = auio.uio_offset = fp->f_offset; |
375 | # if (BYTE_ORDER != LITTLE_ENDIAN) | | 376 | # if (BYTE_ORDER != LITTLE_ENDIAN) |
376 | if ((vp->v_mount->mnt_iflag & IMNT_DTYPE) == 0) { | | 377 | if ((vp->v_mount->mnt_iflag & IMNT_DTYPE) == 0) { |
377 | error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, | | 378 | error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, |
378 | (off_t **)0, (int *)0); | | 379 | (off_t **)0, (int *)0); |
379 | fp->f_offset = auio.uio_offset; | | 380 | fp->f_offset = auio.uio_offset; |
380 | } else | | 381 | } else |
381 | # endif | | 382 | # endif |
382 | { | | 383 | { |
383 | kuio = auio; | | 384 | kuio = auio; |
384 | kuio.uio_iov = &kiov; | | 385 | kuio.uio_iov = &kiov; |
385 | kiov.iov_len = count; | | 386 | kiov.iov_len = count; |
386 | dirbuf = malloc(count, M_TEMP, M_WAITOK); | | 387 | dirbuf = malloc(count, M_TEMP, M_WAITOK); |
387 | kiov.iov_base = dirbuf; | | 388 | kiov.iov_base = dirbuf; |
388 | UIO_SETUP_SYSSPACE(&kuio); | | 389 | UIO_SETUP_SYSSPACE(&kuio); |
389 | error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, | | 390 | error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, |
390 | (off_t **)0, (int *)0); | | 391 | (off_t **)0, (int *)0); |
391 | fp->f_offset = kuio.uio_offset; | | 392 | fp->f_offset = kuio.uio_offset; |
392 | if (error == 0) { | | 393 | if (error == 0) { |
393 | readcnt = count - kuio.uio_resid; | | 394 | readcnt = count - kuio.uio_resid; |
394 | edp = (struct dirent *)&dirbuf[readcnt]; | | 395 | edp = (struct dirent *)&dirbuf[readcnt]; |
395 | for (dp = (struct dirent *)dirbuf; dp < edp; ) { | | 396 | for (dp = (struct dirent *)dirbuf; dp < edp; ) { |
396 | # if (BYTE_ORDER == LITTLE_ENDIAN) | | 397 | # if (BYTE_ORDER == LITTLE_ENDIAN) |
397 | /* | | 398 | /* |
398 | * The expected low byte of | | 399 | * The expected low byte of |
399 | * dp->d_namlen is our dp->d_type. | | 400 | * dp->d_namlen is our dp->d_type. |
400 | * The high MBZ byte of dp->d_namlen | | 401 | * The high MBZ byte of dp->d_namlen |
401 | * is our dp->d_namlen. | | 402 | * is our dp->d_namlen. |
402 | */ | | 403 | */ |
403 | dp->d_type = dp->d_namlen; | | 404 | dp->d_type = dp->d_namlen; |
404 | dp->d_namlen = 0; | | 405 | dp->d_namlen = 0; |
405 | # else | | 406 | # else |
406 | /* | | 407 | /* |
407 | * The dp->d_type is the high byte | | 408 | * The dp->d_type is the high byte |
408 | * of the expected dp->d_namlen, | | 409 | * of the expected dp->d_namlen, |
409 | * so must be zero'ed. | | 410 | * so must be zero'ed. |
410 | */ | | 411 | */ |
411 | dp->d_type = 0; | | 412 | dp->d_type = 0; |
412 | # endif | | 413 | # endif |
413 | if (dp->d_reclen > 0) { | | 414 | if (dp->d_reclen > 0) { |
414 | dp = (struct dirent *) | | 415 | dp = (struct dirent *) |
415 | ((char *)dp + dp->d_reclen); | | 416 | ((char *)dp + dp->d_reclen); |
416 | } else { | | 417 | } else { |
417 | error = EIO; | | 418 | error = EIO; |
418 | break; | | 419 | break; |
419 | } | | 420 | } |
420 | } | | 421 | } |
421 | if (dp >= edp) | | 422 | if (dp >= edp) |
422 | error = uiomove(dirbuf, readcnt, &auio); | | 423 | error = uiomove(dirbuf, readcnt, &auio); |
423 | } | | 424 | } |
424 | free(dirbuf, M_TEMP); | | 425 | free(dirbuf, M_TEMP); |
425 | } | | 426 | } |
426 | VOP_UNLOCK(vp, 0); | | 427 | VOP_UNLOCK(vp, 0); |
427 | if (error) | | 428 | if (error) |
428 | goto out; | | 429 | goto out; |
429 | | | 430 | |
430 | if ((count == auio.uio_resid) && | | 431 | if ((count == auio.uio_resid) && |
431 | (vp->v_vflag & VV_ROOT) && | | 432 | (vp->v_vflag & VV_ROOT) && |
432 | (vp->v_mount->mnt_flag & MNT_UNION)) { | | 433 | (vp->v_mount->mnt_flag & MNT_UNION)) { |
433 | struct vnode *tvp = vp; | | 434 | struct vnode *tvp = vp; |
434 | vp = vp->v_mount->mnt_vnodecovered; | | 435 | vp = vp->v_mount->mnt_vnodecovered; |
435 | VREF(vp); | | 436 | VREF(vp); |
436 | fp->f_data = (void *) vp; | | 437 | fp->f_data = (void *) vp; |
437 | fp->f_offset = 0; | | 438 | fp->f_offset = 0; |
438 | vrele(tvp); | | 439 | vrele(tvp); |
439 | goto unionread; | | 440 | goto unionread; |
440 | } | | 441 | } |
441 | error = copyout((void *)&loff, (void *)SCARG(uap, basep), | | 442 | error = copyout((void *)&loff, (void *)SCARG(uap, basep), |
442 | sizeof(long)); | | 443 | sizeof(long)); |
443 | *retval = count - auio.uio_resid; | | 444 | *retval = count - auio.uio_resid; |
444 | out: | | 445 | out: |
445 | fd_putfile(SCARG(uap, fd)); | | 446 | fd_putfile(SCARG(uap, fd)); |
446 | return (error); | | 447 | return (error); |
447 | } | | 448 | } |
448 | | | 449 | |
449 | /* | | 450 | /* |
450 | * sysctl helper routine for vfs.generic.conf lookups. | | 451 | * sysctl helper routine for vfs.generic.conf lookups. |
451 | */ | | 452 | */ |
452 | #if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_44) | | 453 | #if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_44) |
453 | static struct sysctllog *compat_clog; | | 454 | static struct sysctllog *compat_clog; |
454 | | | 455 | |
455 | static int | | 456 | static int |
456 | sysctl_vfs_generic_conf(SYSCTLFN_ARGS) | | 457 | sysctl_vfs_generic_conf(SYSCTLFN_ARGS) |
457 | { | | 458 | { |
458 | struct vfsconf vfc; | | 459 | struct vfsconf vfc; |
459 | extern const char * const mountcompatnames[]; | | 460 | extern const char * const mountcompatnames[]; |
460 | extern int nmountcompatnames; | | 461 | extern int nmountcompatnames; |
461 | struct sysctlnode node; | | 462 | struct sysctlnode node; |
462 | struct vfsops *vfsp; | | 463 | struct vfsops *vfsp; |
463 | u_int vfsnum; | | 464 | u_int vfsnum; |
464 | | | 465 | |
465 | if (namelen != 1) | | 466 | if (namelen != 1) |
466 | return (ENOTDIR); | | 467 | return (ENOTDIR); |
467 | vfsnum = name[0]; | | 468 | vfsnum = name[0]; |
468 | if (vfsnum >= nmountcompatnames || | | 469 | if (vfsnum >= nmountcompatnames || |
469 | mountcompatnames[vfsnum] == NULL) | | 470 | mountcompatnames[vfsnum] == NULL) |
470 | return (EOPNOTSUPP); | | 471 | return (EOPNOTSUPP); |
471 | vfsp = vfs_getopsbyname(mountcompatnames[vfsnum]); | | 472 | vfsp = vfs_getopsbyname(mountcompatnames[vfsnum]); |
472 | if (vfsp == NULL) | | 473 | if (vfsp == NULL) |
473 | return (EOPNOTSUPP); | | 474 | return (EOPNOTSUPP); |
474 | | | 475 | |
475 | vfc.vfc_vfsops = vfsp; | | 476 | vfc.vfc_vfsops = vfsp; |
476 | strncpy(vfc.vfc_name, vfsp->vfs_name, sizeof(vfc.vfc_name)); | | 477 | strncpy(vfc.vfc_name, vfsp->vfs_name, sizeof(vfc.vfc_name)); |
477 | vfc.vfc_typenum = vfsnum; | | 478 | vfc.vfc_typenum = vfsnum; |
478 | vfc.vfc_refcount = vfsp->vfs_refcount; | | 479 | vfc.vfc_refcount = vfsp->vfs_refcount; |
479 | vfc.vfc_flags = 0; | | 480 | vfc.vfc_flags = 0; |
480 | vfc.vfc_mountroot = vfsp->vfs_mountroot; | | 481 | vfc.vfc_mountroot = vfsp->vfs_mountroot; |
481 | vfc.vfc_next = NULL; | | 482 | vfc.vfc_next = NULL; |
482 | vfs_delref(vfsp); | | 483 | vfs_delref(vfsp); |
483 | | | 484 | |
484 | node = *rnode; | | 485 | node = *rnode; |
485 | node.sysctl_data = &vfc; | | 486 | node.sysctl_data = &vfc; |
486 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); | | 487 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); |
487 | } | | 488 | } |
488 | | | 489 | |
489 | /* | | 490 | /* |
490 | * Top level filesystem related information gathering. | | 491 | * Top level filesystem related information gathering. |
491 | */ | | 492 | */ |
492 | void | | 493 | void |
493 | compat_sysctl_init(void) | | 494 | compat_sysctl_init(void) |
494 | { | | 495 | { |
495 | extern int nmountcompatnames; | | 496 | extern int nmountcompatnames; |
496 | | | 497 | |
497 | sysctl_createv(&compat_clog, 0, NULL, NULL, | | 498 | sysctl_createv(&compat_clog, 0, NULL, NULL, |
498 | CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, | | 499 | CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, |
499 | CTLTYPE_INT, "maxtypenum", | | 500 | CTLTYPE_INT, "maxtypenum", |
500 | SYSCTL_DESCR("Highest valid filesystem type number"), | | 501 | SYSCTL_DESCR("Highest valid filesystem type number"), |
501 | NULL, nmountcompatnames, NULL, 0, | | 502 | NULL, nmountcompatnames, NULL, 0, |
502 | CTL_VFS, VFS_GENERIC, VFS_MAXTYPENUM, CTL_EOL); | | 503 | CTL_VFS, VFS_GENERIC, VFS_MAXTYPENUM, CTL_EOL); |
503 | sysctl_createv(&compat_clog, 0, NULL, NULL, | | 504 | sysctl_createv(&compat_clog, 0, NULL, NULL, |
504 | CTLFLAG_PERMANENT, | | 505 | CTLFLAG_PERMANENT, |
505 | CTLTYPE_STRUCT, "conf", | | 506 | CTLTYPE_STRUCT, "conf", |
506 | SYSCTL_DESCR("Filesystem configuration information"), | | 507 | SYSCTL_DESCR("Filesystem configuration information"), |
507 | sysctl_vfs_generic_conf, 0, NULL, | | 508 | sysctl_vfs_generic_conf, 0, NULL, |
508 | sizeof(struct vfsconf), | | 509 | sizeof(struct vfsconf), |
509 | CTL_VFS, VFS_GENERIC, VFS_CONF, CTL_EOL); | | 510 | CTL_VFS, VFS_GENERIC, VFS_CONF, CTL_EOL); |
510 | } | | 511 | } |
511 | | | 512 | |
512 | void | | 513 | void |
513 | compat_sysctl_fini(void) | | 514 | compat_sysctl_fini(void) |
514 | { | | 515 | { |
515 | | | 516 | |
516 | sysctl_teardown(&compat_clog); | | 517 | sysctl_teardown(&compat_clog); |
517 | } | | 518 | } |
518 | #endif | | 519 | #endif |