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