1 /* $OpenBSD: vfs_syscalls_43.c,v 1.27 2005/05/26 01:15:12 pedro Exp $ */
2 /* $NetBSD: vfs_syscalls_43.c,v 1.4 1996/03/14 19:31:52 christos Exp $ */
3
4 /*
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 * (c) UNIX System Laboratories, Inc.
8 * All or some portions of this file are derived from material licensed
9 * to the University of California by American Telephone and Telegraph
10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11 * the permission of UNIX System Laboratories, Inc.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/filedesc.h>
43 #include <sys/kernel.h>
44 #include <sys/proc.h>
45 #include <sys/file.h>
46 #include <sys/vnode.h>
47 #include <sys/namei.h>
48 #include <sys/dirent.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/stat.h>
52 #include <sys/ioctl.h>
53 #include <sys/fcntl.h>
54 #include <sys/malloc.h>
55 #include <sys/syslog.h>
56 #include <sys/unistd.h>
57 #include <sys/resourcevar.h>
58
59 #include <sys/mount.h>
60 #include <sys/syscallargs.h>
61
62 #include <uvm/uvm_extern.h>
63
64 #include <sys/pipe.h>
65
66 static void cvtstat(struct stat *, struct stat43 *);
67
68 /*
69 * Convert from a new to an old stat structure.
70 */
71 static void
72 cvtstat(st, ost)
73 struct stat *st;
74 struct stat43 *ost;
75 {
76
77 ost->st_dev = st->st_dev;
78 ost->st_ino = st->st_ino;
79 ost->st_mode = st->st_mode;
80 ost->st_nlink = st->st_nlink;
81 ost->st_uid = st->st_uid;
82 ost->st_gid = st->st_gid;
83 ost->st_rdev = st->st_rdev;
84 if (st->st_size < (quad_t)1 << 32)
85 ost->st_size = st->st_size;
86 else
87 ost->st_size = -2;
88 ost->st_atime = st->st_atime;
89 ost->st_mtime = st->st_mtime;
90 ost->st_ctime = st->st_ctime;
91 ost->st_blksize = st->st_blksize;
92 ost->st_blocks = st->st_blocks;
93 ost->st_flags = st->st_flags;
94 ost->st_gen = st->st_gen;
95 }
96
97 /*
98 * Get file status; this version follows links.
99 */
100 /* ARGSUSED */
101 int
102 compat_43_sys_stat(p, v, retval)
103 struct proc *p;
104 void *v;
105 register_t *retval;
106 {
107 register struct compat_43_sys_stat_args /* {
108 syscallarg(char *) path;
109 syscallarg(struct stat43 *) ub;
110 } */ *uap = v;
111 struct stat sb;
112 struct stat43 osb;
113 int error;
114 struct nameidata nd;
115
116 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
117 SCARG(uap, path), p);
118 if ((error = namei(&nd)) != 0)
119 return (error);
120 error = vn_stat(nd.ni_vp, &sb, p);
121 vput(nd.ni_vp);
122 if (error)
123 return (error);
124 /* Don't let non-root see generation numbers (for NFS security) */
125 if (suser(p, 0))
126 sb.st_gen = 0;
127 cvtstat(&sb, &osb);
128 error = copyout(&osb, SCARG(uap, ub), sizeof(osb));
129 return (error);
130 }
131
132
133 /*
134 * Get file status; this version does not follow links.
135 */
136 /* ARGSUSED */
137 int
138 compat_43_sys_lstat(p, v, retval)
139 struct proc *p;
140 void *v;
141 register_t *retval;
142 {
143 register struct compat_43_sys_lstat_args /* {
144 syscallarg(char *) path;
145 syscallarg(struct stat43 *) ub;
146 } */ *uap = v;
147 struct stat sb;
148 struct stat43 osb;
149 int error;
150 struct nameidata nd;
151
152 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
153 SCARG(uap, path), p);
154 if ((error = namei(&nd)) != 0)
155 return (error);
156 error = vn_stat(nd.ni_vp, &sb, p);
157 vput(nd.ni_vp);
158 if (error)
159 return (error);
160 /* Don't let non-root see generation numbers (for NFS security) */
161 if (suser(p, 0))
162 sb.st_gen = 0;
163 cvtstat(&sb, &osb);
164 error = copyout(&osb, SCARG(uap, ub), sizeof(osb));
165 return (error);
166 }
167
168 /*
169 * Return status information about a file descriptor.
170 */
171 /* ARGSUSED */
172 int
173 compat_43_sys_fstat(p, v, retval)
174 struct proc *p;
175 void *v;
176 register_t *retval;
177 {
178 struct compat_43_sys_fstat_args /* {
179 syscallarg(int) fd;
180 syscallarg(struct stat43 *) sb;
181 } */ *uap = v;
182 int fd = SCARG(uap, fd);
183 struct filedesc *fdp = p->p_fd;
184 struct file *fp;
185 struct stat ub;
186 struct stat43 oub;
187 int error;
188
189 if ((fp = fd_getfile(fdp, fd)) == NULL)
190 return (EBADF);
191 FREF(fp);
192 error = (*fp->f_ops->fo_stat)(fp, &ub, p);
193 FRELE(fp);
194 if (error == 0) {
195 /* Don't let non-root see generation numbers
196 (for NFS security) */
197 if (suser(p, 0))
198 ub.st_gen = 0;
199 cvtstat(&ub, &oub);
200 error = copyout(&oub, SCARG(uap, sb), sizeof(oub));
201 }
202 return (error);
203 }
204
205 /*
206 * Truncate a file given a file descriptor.
207 */
208 /* ARGSUSED */
209 int
210 compat_43_sys_ftruncate(p, v, retval)
211 struct proc *p;
212 void *v;
213 register_t *retval;
214 {
215 register struct compat_43_sys_ftruncate_args /* {
216 syscallarg(int) fd;
217 syscallarg(long) length;
218 } */ *uap = v;
219 struct sys_ftruncate_args /* {
220 syscallarg(int) fd;
221 syscallarg(int) pad;
222 syscallarg(off_t) length;
223 } */ nuap;
224
225 SCARG(&nuap, fd) = SCARG(uap, fd);
226 SCARG(&nuap, length) = SCARG(uap, length);
227 return (sys_ftruncate(p, &nuap, retval));
228 }
229
230 /*
231 * Truncate a file given its path name.
232 */
233 /* ARGSUSED */
234 int
235 compat_43_sys_truncate(p, v, retval)
236 struct proc *p;
237 void *v;
238 register_t *retval;
239 {
240 register struct compat_43_sys_truncate_args /* {
241 syscallarg(char *) path;
242 syscallarg(long) length;
243 } */ *uap = v;
244 struct sys_truncate_args /* {
245 syscallarg(char *) path;
246 syscallarg(int) pad;
247 syscallarg(off_t) length;
248 } */ nuap;
249
250 SCARG(&nuap, path) = SCARG(uap, path);
251 SCARG(&nuap, length) = SCARG(uap, length);
252 return (sys_truncate(p, &nuap, retval));
253 }
254
255
256 /*
257 * Reposition read/write file offset.
258 */
259 int
260 compat_43_sys_lseek(p, v, retval)
261 struct proc *p;
262 void *v;
263 register_t *retval;
264 {
265 register struct compat_43_sys_lseek_args /* {
266 syscallarg(int) fd;
267 syscallarg(long) offset;
268 syscallarg(int) whence;
269 } */ *uap = v;
270 struct sys_lseek_args /* {
271 syscallarg(int) fd;
272 syscallarg(int) pad;
273 syscallarg(off_t) offset;
274 syscallarg(int) whence;
275 } */ nuap;
276 off_t qret;
277 int error;
278
279 SCARG(&nuap, fd) = SCARG(uap, fd);
280 SCARG(&nuap, offset) = SCARG(uap, offset);
281 SCARG(&nuap, whence) = SCARG(uap, whence);
282 error = sys_lseek(p, &nuap, (register_t *)&qret);
283 *(long *)retval = qret;
284 return (error);
285 }
286
287
288 /*
289 * Create a file.
290 */
291 int
292 compat_43_sys_creat(p, v, retval)
293 struct proc *p;
294 void *v;
295 register_t *retval;
296 {
297 register struct compat_43_sys_creat_args /* {
298 syscallarg(char *) path;
299 syscallarg(mode_t) mode;
300 } */ *uap = v;
301 struct sys_open_args /* {
302 syscallarg(char *) path;
303 syscallarg(int) flags;
304 syscallarg(mode_t) mode;
305 } */ nuap;
306
307 SCARG(&nuap, path) = SCARG(uap, path);
308 SCARG(&nuap, mode) = SCARG(uap, mode);
309 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
310 return (sys_open(p, &nuap, retval));
311 }
312
313 /*ARGSUSED*/
314 int
315 compat_43_sys_quota(p, v, retval)
316 struct proc *p;
317 void *v;
318 register_t *retval;
319 {
320
321 return (ENOSYS);
322 }
323
324
325 /*
326 * Read a block of directory entries in a file system independent format.
327 */
328 int
329 compat_43_sys_getdirentries(p, v, retval)
330 struct proc *p;
331 void *v;
332 register_t *retval;
333 {
334 register struct compat_43_sys_getdirentries_args /* {
335 syscallarg(int) fd;
336 syscallarg(char *) buf;
337 syscallarg(int) count;
338 syscallarg(long *) basep;
339 } */ *uap = v;
340 struct vnode *vp;
341 struct file *fp;
342 struct uio auio, kuio;
343 struct iovec aiov, kiov;
344 struct dirent *dp, *edp;
345 caddr_t dirbuf;
346 int error, eofflag, readcnt;
347 long loff;
348
349 if (SCARG(uap, count) < 0)
350 return EINVAL;
351 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
352 return (error);
353 if ((fp->f_flag & FREAD) == 0) {
354 error = EBADF;
355 goto bad;
356 }
357 vp = (struct vnode *)fp->f_data;
358 if (vp->v_type != VDIR) {
359 error = EINVAL;
360 goto bad;
361 }
362 aiov.iov_base = SCARG(uap, buf);
363 aiov.iov_len = SCARG(uap, count);
364 auio.uio_iov = &aiov;
365 auio.uio_iovcnt = 1;
366 auio.uio_rw = UIO_READ;
367 auio.uio_segflg = UIO_USERSPACE;
368 auio.uio_procp = p;
369 auio.uio_resid = SCARG(uap, count);
370
371 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
372 loff = auio.uio_offset = fp->f_offset;
373 # if (BYTE_ORDER != LITTLE_ENDIAN)
374 if (vp->v_mount->mnt_maxsymlinklen <= 0) {
375 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
376 (int *)0, (u_long **)0);
377 fp->f_offset = auio.uio_offset;
378 } else
379 # endif
380 {
381 u_int nbytes = SCARG(uap, count);
382
383 nbytes = min(nbytes, MAXBSIZE);
384
385 kuio = auio;
386 kuio.uio_iov = &kiov;
387 kuio.uio_segflg = UIO_SYSSPACE;
388 kiov.iov_len = nbytes;
389 dirbuf = (caddr_t)malloc(nbytes, M_TEMP, M_WAITOK);
390 kiov.iov_base = dirbuf;
391
392 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
393 0, 0);
394 fp->f_offset = kuio.uio_offset;
395 if (error == 0) {
396 readcnt = nbytes - kuio.uio_resid;
397 edp = (struct dirent *)&dirbuf[readcnt];
398 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
399 # if (BYTE_ORDER == LITTLE_ENDIAN)
400 /*
401 * The expected low byte of
402 * dp->d_namlen is our dp->d_type.
403 * The high MBZ byte of dp->d_namlen
404 * is our dp->d_namlen.
405 */
406 dp->d_type = dp->d_namlen;
407 dp->d_namlen = 0;
408 # else
409 /*
410 * The dp->d_type is the high byte
411 * of the expected dp->d_namlen,
412 * so must be zero'ed.
413 */
414 dp->d_type = 0;
415 # endif
416 if (dp->d_reclen > 0) {
417 dp = (struct dirent *)
418 ((char *)dp + dp->d_reclen);
419 } else {
420 error = EIO;
421 break;
422 }
423 }
424 if (dp >= edp)
425 error = uiomove(dirbuf, readcnt, &auio);
426 }
427 FREE(dirbuf, M_TEMP);
428 }
429 VOP_UNLOCK(vp, 0, p);
430 if (error)
431 goto bad;
432 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
433 sizeof(long));
434 *retval = SCARG(uap, count) - auio.uio_resid;
435 bad:
436 FRELE(fp);
437 return (error);
438 }