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