vfs_syscalls_50.c revision 1.22 1 /* $NetBSD: vfs_syscalls_50.c,v 1.22 2019/06/17 14:59:15 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_50.c,v 1.22 2019/06/17 14:59:15 christos Exp $");
40
41 #if defined(_KERNEL_OPT)
42 #include "opt_compat_netbsd.h"
43 #include "opt_quota.h"
44 #endif
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/namei.h>
49 #include <sys/filedesc.h>
50 #include <sys/kernel.h>
51 #include <sys/file.h>
52 #include <sys/stat.h>
53 #include <sys/socketvar.h>
54 #include <sys/vnode.h>
55 #include <sys/mount.h>
56 #include <sys/proc.h>
57 #include <sys/uio.h>
58 #include <sys/dirent.h>
59 #include <sys/kauth.h>
60 #include <sys/time.h>
61 #include <sys/syscall.h>
62 #include <sys/syscallvar.h>
63 #include <sys/syscallargs.h>
64 #include <sys/vfs_syscalls.h>
65 #ifndef LFS
66 #define LFS
67 #endif
68 #include <sys/syscallargs.h>
69
70 #include <ufs/lfs/lfs_extern.h>
71
72 #ifdef QUOTA
73 #include <sys/quota.h>
74 #include <sys/quotactl.h>
75 #include <ufs/ufs/quota1.h>
76 #endif
77
78 #include <compat/common/compat_util.h>
79 #include <compat/common/compat_mod.h>
80 #include <compat/sys/time.h>
81 #include <compat/sys/stat.h>
82 #include <compat/sys/dirent.h>
83 #include <compat/sys/mount.h>
84
85 static void cvtstat(struct stat30 *, const struct stat *);
86
87 static const struct syscall_package vfs_syscalls_50_syscalls[] = {
88 { SYS_compat_50___stat30, 0, (sy_call_t *)compat_50_sys___stat30 },
89 { SYS_compat_50___fstat30, 0, (sy_call_t *)compat_50_sys___fstat30 },
90 { SYS_compat_50___lstat30, 0, (sy_call_t *)compat_50_sys___lstat30 },
91 { SYS_compat_50___fhstat40, 0, (sy_call_t *)compat_50_sys___fhstat40 },
92 { SYS_compat_50_utimes, 0, (sy_call_t *)compat_50_sys_utimes },
93 { SYS_compat_50_lfs_segwait, 0,
94 (sy_call_t *)compat_50_sys_lfs_segwait } ,
95 { SYS_compat_50_futimes, 0, (sy_call_t *)compat_50_sys_futimes },
96 { SYS_compat_50_lutimes, 0, (sy_call_t *)compat_50_sys_lutimes },
97 { SYS_compat_50_mknod, 0, (sy_call_t *)compat_50_sys_mknod },
98 #ifdef QUOTA
99 { SYS_compat_50_quotactl, 0, (sy_call_t *)compat_50_sys_quotactl },
100 #endif
101 { 0, 0, NULL }
102 };
103
104 /*
105 * Convert from a new to an old stat structure.
106 */
107 static void
108 cvtstat(struct stat30 *ost, const struct stat *st)
109 {
110
111 ost->st_dev = st->st_dev;
112 ost->st_ino = st->st_ino;
113 ost->st_mode = st->st_mode;
114 ost->st_nlink = st->st_nlink;
115 ost->st_uid = st->st_uid;
116 ost->st_gid = st->st_gid;
117 ost->st_rdev = st->st_rdev;
118 timespec_to_timespec50(&st->st_atimespec, &ost->st_atimespec);
119 timespec_to_timespec50(&st->st_mtimespec, &ost->st_mtimespec);
120 timespec_to_timespec50(&st->st_ctimespec, &ost->st_ctimespec);
121 timespec_to_timespec50(&st->st_birthtimespec, &ost->st_birthtimespec);
122 ost->st_size = st->st_size;
123 ost->st_blocks = st->st_blocks;
124 ost->st_blksize = st->st_blksize;
125 ost->st_flags = st->st_flags;
126 ost->st_gen = st->st_gen;
127 memset(ost->st_spare, 0, sizeof(ost->st_spare));
128 }
129
130 /*
131 * Get file status; this version follows links.
132 */
133 /* ARGSUSED */
134 int
135 compat_50_sys___stat30(struct lwp *l, const struct compat_50_sys___stat30_args *uap, register_t *retval)
136 {
137 /* {
138 syscallarg(const char *) path;
139 syscallarg(struct stat30 *) ub;
140 } */
141 struct stat sb;
142 struct stat30 osb;
143 int error;
144
145 error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb);
146 if (error)
147 return error;
148 cvtstat(&osb, &sb);
149 error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
150 return error;
151 }
152
153
154 /*
155 * Get file status; this version does not follow links.
156 */
157 /* ARGSUSED */
158 int
159 compat_50_sys___lstat30(struct lwp *l, const struct compat_50_sys___lstat30_args *uap, register_t *retval)
160 {
161 /* {
162 syscallarg(const char *) path;
163 syscallarg(struct stat30 *) ub;
164 } */
165 struct stat sb;
166 struct stat30 osb;
167 int error;
168
169 error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb);
170 if (error)
171 return error;
172 cvtstat(&osb, &sb);
173 error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
174 return error;
175 }
176
177 /*
178 * Return status information about a file descriptor.
179 */
180 /* ARGSUSED */
181 int
182 compat_50_sys___fstat30(struct lwp *l, const struct compat_50_sys___fstat30_args *uap, register_t *retval)
183 {
184 /* {
185 syscallarg(int) fd;
186 syscallarg(struct stat30 *) sb;
187 } */
188 struct stat sb;
189 struct stat30 osb;
190 int error;
191
192 error = do_sys_fstat(SCARG(uap, fd), &sb);
193 if (error)
194 return error;
195 cvtstat(&osb, &sb);
196 error = copyout(&osb, SCARG(uap, sb), sizeof (osb));
197 return error;
198 }
199
200 /* ARGSUSED */
201 int
202 compat_50_sys___fhstat40(struct lwp *l, const struct compat_50_sys___fhstat40_args *uap, register_t *retval)
203 {
204 /* {
205 syscallarg(const void *) fhp;
206 syscallarg(size_t) fh_size;
207 syscallarg(struct stat30 *) sb;
208 } */
209 struct stat sb;
210 struct stat30 osb;
211 int error;
212
213 error = do_fhstat(l, SCARG(uap, fhp), SCARG(uap, fh_size), &sb);
214 if (error)
215 return error;
216 cvtstat(&osb, &sb);
217 error = copyout(&osb, SCARG(uap, sb), sizeof (osb));
218 return error;
219 }
220
221 static int
222 compat_50_do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path,
223 int flag, const struct timeval50 *tptr)
224 {
225 struct timeval tv[2], *tvp;
226 struct timeval50 tv50[2];
227 if (tptr) {
228 int error = copyin(tptr, tv50, sizeof(tv50));
229 if (error)
230 return error;
231 timeval50_to_timeval(&tv50[0], &tv[0]);
232 timeval50_to_timeval(&tv50[1], &tv[1]);
233 tvp = tv;
234 } else
235 tvp = NULL;
236 return do_sys_utimes(l, vp, path, flag, tvp, UIO_SYSSPACE);
237 }
238
239 /*
240 * Set the access and modification times given a path name; this
241 * version follows links.
242 */
243 /* ARGSUSED */
244 int
245 compat_50_sys_utimes(struct lwp *l, const struct compat_50_sys_utimes_args *uap,
246 register_t *retval)
247 {
248 /* {
249 syscallarg(const char *) path;
250 syscallarg(const struct timeval50 *) tptr;
251 } */
252
253 return compat_50_do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW,
254 SCARG(uap, tptr));
255 }
256
257 /*
258 * Set the access and modification times given a file descriptor.
259 */
260 /* ARGSUSED */
261 int
262 compat_50_sys_futimes(struct lwp *l,
263 const struct compat_50_sys_futimes_args *uap, register_t *retval)
264 {
265 /* {
266 syscallarg(int) fd;
267 syscallarg(const struct timeval50 *) tptr;
268 } */
269 int error;
270 struct file *fp;
271
272 /* fd_getvnode() will use the descriptor for us */
273 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
274 return error;
275 error = compat_50_do_sys_utimes(l, fp->f_vnode, NULL, 0,
276 SCARG(uap, tptr));
277 fd_putfile(SCARG(uap, fd));
278 return error;
279 }
280
281 /*
282 * Set the access and modification times given a path name; this
283 * version does not follow links.
284 */
285 int
286 compat_50_sys_lutimes(struct lwp *l,
287 const struct compat_50_sys_lutimes_args *uap, register_t *retval)
288 {
289 /* {
290 syscallarg(const char *) path;
291 syscallarg(const struct timeval50 *) tptr;
292 } */
293
294 return compat_50_do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW,
295 SCARG(uap, tptr));
296 }
297
298 int
299 compat_50_sys_lfs_segwait(struct lwp *l,
300 const struct compat_50_sys_lfs_segwait_args *uap, register_t *retval)
301 {
302 /* {
303 syscallarg(fsid_t *) fsidp;
304 syscallarg(struct timeval50 *) tv;
305 } */
306 #ifdef notyet
307 /* XXX need to check presence of LFS at run-time XXX */
308 struct timeval atv;
309 struct timeval50 atv50;
310 fsid_t fsid;
311 int error;
312
313 /* XXX need we be su to segwait? */
314 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS,
315 KAUTH_REQ_SYSTEM_LFS_SEGWAIT, NULL, NULL, NULL);
316 if (error)
317 return (error);
318 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
319 return (error);
320
321 if (SCARG(uap, tv)) {
322 error = copyin(SCARG(uap, tv), &atv50, sizeof(atv50));
323 if (error)
324 return (error);
325 timeval50_to_timeval(&atv50, &atv);
326 if (itimerfix(&atv))
327 return (EINVAL);
328 } else /* NULL or invalid */
329 atv.tv_sec = atv.tv_usec = 0;
330 return lfs_segwait(&fsid, &atv);
331 #else
332 return ENOSYS;
333 #endif
334 }
335
336 int
337 compat_50_sys_mknod(struct lwp *l,
338 const struct compat_50_sys_mknod_args *uap, register_t *retval)
339 {
340 /* {
341 syscallarg(const char *) path;
342 syscallarg(mode_t) mode;
343 syscallarg(uint32_t) dev;
344 } */
345 return do_sys_mknod(l, SCARG(uap, path), SCARG(uap, mode),
346 SCARG(uap, dev), retval, UIO_USERSPACE);
347 }
348
349 #ifdef QUOTA
350 /* ARGSUSED */
351 int
352 compat_50_sys_quotactl(struct lwp *l, const struct compat_50_sys_quotactl_args *uap, register_t *retval)
353 {
354 /* {
355 syscallarg(const char *) path;
356 syscallarg(int) cmd;
357 syscallarg(int) uid;
358 syscallarg(void *) arg;
359 } */
360 struct vnode *vp;
361 struct mount *mp;
362 int q1cmd;
363 int idtype;
364 char *qfile;
365 struct dqblk dqblk;
366 struct quotakey key;
367 struct quotaval blocks, files;
368 struct quotastat qstat;
369 int error;
370
371 error = namei_simple_user(SCARG(uap, path),
372 NSM_FOLLOW_TRYEMULROOT, &vp);
373 if (error != 0)
374 return (error);
375
376 mp = vp->v_mount;
377 q1cmd = SCARG(uap, cmd);
378 idtype = quota_idtype_from_ufs(q1cmd & SUBCMDMASK);
379
380 switch ((q1cmd & ~SUBCMDMASK) >> SUBCMDSHIFT) {
381 case Q_QUOTAON:
382 qfile = PNBUF_GET();
383 error = copyinstr(SCARG(uap, arg), qfile, PATH_MAX, NULL);
384 if (error != 0) {
385 PNBUF_PUT(qfile);
386 break;
387 }
388
389 error = vfs_quotactl_quotaon(mp, idtype, qfile);
390
391 PNBUF_PUT(qfile);
392 break;
393
394 case Q_QUOTAOFF:
395 error = vfs_quotactl_quotaoff(mp, idtype);
396 break;
397
398 case Q_GETQUOTA:
399 key.qk_idtype = idtype;
400 key.qk_id = SCARG(uap, uid);
401
402 key.qk_objtype = QUOTA_OBJTYPE_BLOCKS;
403 error = vfs_quotactl_get(mp, &key, &blocks);
404 if (error) {
405 break;
406 }
407
408 key.qk_objtype = QUOTA_OBJTYPE_FILES;
409 error = vfs_quotactl_get(mp, &key, &files);
410 if (error) {
411 break;
412 }
413
414 quotavals_to_dqblk(&blocks, &files, &dqblk);
415 error = copyout(&dqblk, SCARG(uap, arg), sizeof(dqblk));
416 break;
417
418 case Q_SETQUOTA:
419 error = copyin(SCARG(uap, arg), &dqblk, sizeof(dqblk));
420 if (error) {
421 break;
422 }
423 dqblk_to_quotavals(&dqblk, &blocks, &files);
424
425 key.qk_idtype = idtype;
426 key.qk_id = SCARG(uap, uid);
427
428 key.qk_objtype = QUOTA_OBJTYPE_BLOCKS;
429 error = vfs_quotactl_put(mp, &key, &blocks);
430 if (error) {
431 break;
432 }
433
434 key.qk_objtype = QUOTA_OBJTYPE_FILES;
435 error = vfs_quotactl_put(mp, &key, &files);
436 break;
437
438 case Q_SYNC:
439 /*
440 * not supported but used only to see if quota is supported,
441 * emulate with stat
442 *
443 * XXX should probably be supported
444 */
445 (void)idtype; /* not used */
446
447 error = vfs_quotactl_stat(mp, &qstat);
448 break;
449
450 case Q_SETUSE:
451 default:
452 error = EOPNOTSUPP;
453 break;
454 }
455
456 vrele(vp);
457 return error;
458 }
459 #endif
460
461 int
462 vfs_syscalls_50_init(void)
463 {
464
465 return syscall_establish(NULL, vfs_syscalls_50_syscalls);
466 }
467
468 int
469 vfs_syscalls_50_fini(void)
470 {
471
472 return syscall_disestablish(NULL, vfs_syscalls_50_syscalls);
473 }
474