Tue Mar 17 00:01:54 2009 UTC ()
Add #include "opt_compat_netbsd.h" for COMPAT_09.


(dyoung)
diff -r1.49 -r1.50 src/sys/compat/common/vfs_syscalls_43.c

cvs diff -r1.49 -r1.50 src/sys/compat/common/vfs_syscalls_43.c (switch to unified diff)

--- src/sys/compat/common/vfs_syscalls_43.c 2009/01/26 13:00:04 1.49
+++ src/sys/compat/common/vfs_syscalls_43.c 2009/03/17 00:01:54 1.50
@@ -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
75static void cvtstat(struct stat *, struct stat43 *); 76static 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 */
80static void 81static void
81cvtstat(struct stat *st, struct stat43 *ost) 82cvtstat(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 */
108int 109int
109compat_43_sys_stat(struct lwp *l, const struct compat_43_sys_stat_args *uap, register_t *retval) 110compat_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 */
131int 132int
132compat_43_sys_lstat(struct lwp *l, const struct compat_43_sys_lstat_args *uap, register_t *retval) 133compat_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;
146again: 147again:
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 */
202int 203int
203compat_43_sys_fstat(struct lwp *l, const struct compat_43_sys_fstat_args *uap, register_t *retval) 204compat_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 */
228int 229int
229compat_43_sys_ftruncate(struct lwp *l, const struct compat_43_sys_ftruncate_args *uap, register_t *retval) 230compat_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 */
250int 251int
251compat_43_sys_truncate(struct lwp *l, const struct compat_43_sys_truncate_args *uap, register_t *retval) 252compat_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 */
272int 273int
273compat_43_sys_lseek(struct lwp *l, const struct compat_43_sys_lseek_args *uap, register_t *retval) 274compat_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 */
301int 302int
302compat_43_sys_creat(struct lwp *l, const struct compat_43_sys_creat_args *uap, register_t *retval) 303compat_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*/
321int 322int
322compat_43_sys_quota(struct lwp *l, const void *v, register_t *retval) 323compat_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 */
332int 333int
333compat_43_sys_getdirentries(struct lwp *l, const struct compat_43_sys_getdirentries_args *uap, register_t *retval) 334compat_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;
360unionread: 361unionread:
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)
453static struct sysctllog *compat_clog; 454static struct sysctllog *compat_clog;
454 455
455static int 456static int
456sysctl_vfs_generic_conf(SYSCTLFN_ARGS) 457sysctl_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 */
492void 493void
493compat_sysctl_init(void) 494compat_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
512void 513void
513compat_sysctl_fini(void) 514compat_sysctl_fini(void)
514{ 515{
515 516
516 sysctl_teardown(&compat_clog); 517 sysctl_teardown(&compat_clog);
517} 518}
518#endif 519#endif