1 /* $NetBSD: vfs_syscalls_50.c,v 1.25 2020/01/21 02:37:16 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 * 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.25 2020/01/21 02:37:16 pgoyette 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 #include <compat/common/compat_util.h> 66 #include <compat/common/compat_mod.h> 67 #include <compat/sys/time.h> 68 #include <compat/sys/stat.h> 69 #include <compat/sys/dirent.h> 70 #include <compat/sys/mount.h> 71 72 static void cvtstat(struct stat30 *, const struct stat *); 73 74 static const struct syscall_package vfs_syscalls_50_syscalls[] = { 75 { SYS_compat_50___stat30, 0, (sy_call_t *)compat_50_sys___stat30 }, 76 { SYS_compat_50___fstat30, 0, (sy_call_t *)compat_50_sys___fstat30 }, 77 { SYS_compat_50___lstat30, 0, (sy_call_t *)compat_50_sys___lstat30 }, 78 { SYS_compat_50___fhstat40, 0, (sy_call_t *)compat_50_sys___fhstat40 }, 79 { SYS_compat_50_utimes, 0, (sy_call_t *)compat_50_sys_utimes }, 80 { SYS_compat_50_lfs_segwait, 0, 81 (sy_call_t *)compat_50_sys_lfs_segwait } , 82 { SYS_compat_50_futimes, 0, (sy_call_t *)compat_50_sys_futimes }, 83 { SYS_compat_50_lutimes, 0, (sy_call_t *)compat_50_sys_lutimes }, 84 { SYS_compat_50_mknod, 0, (sy_call_t *)compat_50_sys_mknod }, 85 { 0, 0, NULL } 86 }; 87 88 /* 89 * Convert from a new to an old stat structure. 90 */ 91 static void 92 cvtstat(struct stat30 *ost, const struct stat *st) 93 { 94 95 ost->st_dev = st->st_dev; 96 ost->st_ino = st->st_ino; 97 ost->st_mode = st->st_mode; 98 ost->st_nlink = st->st_nlink; 99 ost->st_uid = st->st_uid; 100 ost->st_gid = st->st_gid; 101 ost->st_rdev = st->st_rdev; 102 timespec_to_timespec50(&st->st_atimespec, &ost->st_atimespec); 103 timespec_to_timespec50(&st->st_mtimespec, &ost->st_mtimespec); 104 timespec_to_timespec50(&st->st_ctimespec, &ost->st_ctimespec); 105 timespec_to_timespec50(&st->st_birthtimespec, &ost->st_birthtimespec); 106 ost->st_size = st->st_size; 107 ost->st_blocks = st->st_blocks; 108 ost->st_blksize = st->st_blksize; 109 ost->st_flags = st->st_flags; 110 ost->st_gen = st->st_gen; 111 memset(ost->st_spare, 0, sizeof(ost->st_spare)); 112 } 113 114 /* 115 * Get file status; this version follows links. 116 */ 117 /* ARGSUSED */ 118 int 119 compat_50_sys___stat30(struct lwp *l, const struct compat_50_sys___stat30_args *uap, register_t *retval) 120 { 121 /* { 122 syscallarg(const char *) path; 123 syscallarg(struct stat30 *) ub; 124 } */ 125 struct stat sb; 126 struct stat30 osb; 127 int error; 128 129 error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb); 130 if (error) 131 return error; 132 cvtstat(&osb, &sb); 133 error = copyout(&osb, SCARG(uap, ub), sizeof (osb)); 134 return error; 135 } 136 137 138 /* 139 * Get file status; this version does not follow links. 140 */ 141 /* ARGSUSED */ 142 int 143 compat_50_sys___lstat30(struct lwp *l, const struct compat_50_sys___lstat30_args *uap, register_t *retval) 144 { 145 /* { 146 syscallarg(const char *) path; 147 syscallarg(struct stat30 *) ub; 148 } */ 149 struct stat sb; 150 struct stat30 osb; 151 int error; 152 153 error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb); 154 if (error) 155 return error; 156 cvtstat(&osb, &sb); 157 error = copyout(&osb, SCARG(uap, ub), sizeof (osb)); 158 return error; 159 } 160 161 /* 162 * Return status information about a file descriptor. 163 */ 164 /* ARGSUSED */ 165 int 166 compat_50_sys___fstat30(struct lwp *l, const struct compat_50_sys___fstat30_args *uap, register_t *retval) 167 { 168 /* { 169 syscallarg(int) fd; 170 syscallarg(struct stat30 *) sb; 171 } */ 172 struct stat sb; 173 struct stat30 osb; 174 int error; 175 176 error = do_sys_fstat(SCARG(uap, fd), &sb); 177 if (error) 178 return error; 179 cvtstat(&osb, &sb); 180 error = copyout(&osb, SCARG(uap, sb), sizeof (osb)); 181 return error; 182 } 183 184 /* ARGSUSED */ 185 int 186 compat_50_sys___fhstat40(struct lwp *l, const struct compat_50_sys___fhstat40_args *uap, register_t *retval) 187 { 188 /* { 189 syscallarg(const void *) fhp; 190 syscallarg(size_t) fh_size; 191 syscallarg(struct stat30 *) sb; 192 } */ 193 struct stat sb; 194 struct stat30 osb; 195 int error; 196 197 error = do_fhstat(l, SCARG(uap, fhp), SCARG(uap, fh_size), &sb); 198 if (error) 199 return error; 200 cvtstat(&osb, &sb); 201 error = copyout(&osb, SCARG(uap, sb), sizeof (osb)); 202 return error; 203 } 204 205 static int 206 compat_50_do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, 207 int flag, const struct timeval50 *tptr) 208 { 209 struct timeval tv[2], *tvp; 210 struct timeval50 tv50[2]; 211 if (tptr) { 212 int error = copyin(tptr, tv50, sizeof(tv50)); 213 if (error) 214 return error; 215 timeval50_to_timeval(&tv50[0], &tv[0]); 216 timeval50_to_timeval(&tv50[1], &tv[1]); 217 tvp = tv; 218 } else 219 tvp = NULL; 220 return do_sys_utimes(l, vp, path, flag, tvp, UIO_SYSSPACE); 221 } 222 223 /* 224 * Set the access and modification times given a path name; this 225 * version follows links. 226 */ 227 /* ARGSUSED */ 228 int 229 compat_50_sys_utimes(struct lwp *l, const struct compat_50_sys_utimes_args *uap, 230 register_t *retval) 231 { 232 /* { 233 syscallarg(const char *) path; 234 syscallarg(const struct timeval50 *) tptr; 235 } */ 236 237 return compat_50_do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW, 238 SCARG(uap, tptr)); 239 } 240 241 /* 242 * Set the access and modification times given a file descriptor. 243 */ 244 /* ARGSUSED */ 245 int 246 compat_50_sys_futimes(struct lwp *l, 247 const struct compat_50_sys_futimes_args *uap, register_t *retval) 248 { 249 /* { 250 syscallarg(int) fd; 251 syscallarg(const struct timeval50 *) tptr; 252 } */ 253 int error; 254 struct file *fp; 255 256 /* fd_getvnode() will use the descriptor for us */ 257 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 258 return error; 259 error = compat_50_do_sys_utimes(l, fp->f_vnode, NULL, 0, 260 SCARG(uap, tptr)); 261 fd_putfile(SCARG(uap, fd)); 262 return error; 263 } 264 265 /* 266 * Set the access and modification times given a path name; this 267 * version does not follow links. 268 */ 269 int 270 compat_50_sys_lutimes(struct lwp *l, 271 const struct compat_50_sys_lutimes_args *uap, register_t *retval) 272 { 273 /* { 274 syscallarg(const char *) path; 275 syscallarg(const struct timeval50 *) tptr; 276 } */ 277 278 return compat_50_do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW, 279 SCARG(uap, tptr)); 280 } 281 282 int 283 compat_50_sys_lfs_segwait(struct lwp *l, 284 const struct compat_50_sys_lfs_segwait_args *uap, register_t *retval) 285 { 286 /* { 287 syscallarg(fsid_t *) fsidp; 288 syscallarg(struct timeval50 *) tv; 289 } */ 290 #ifdef notyet 291 /* XXX need to check presence of LFS at run-time XXX */ 292 struct timeval atv; 293 struct timeval50 atv50; 294 fsid_t fsid; 295 int error; 296 297 /* XXX need we be su to segwait? */ 298 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS, 299 KAUTH_REQ_SYSTEM_LFS_SEGWAIT, NULL, NULL, NULL); 300 if (error) 301 return (error); 302 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) 303 return (error); 304 305 if (SCARG(uap, tv)) { 306 error = copyin(SCARG(uap, tv), &atv50, sizeof(atv50)); 307 if (error) 308 return (error); 309 timeval50_to_timeval(&atv50, &atv); 310 if (itimerfix(&atv)) 311 return (EINVAL); 312 } else /* NULL or invalid */ 313 atv.tv_sec = atv.tv_usec = 0; 314 return lfs_segwait(&fsid, &atv); 315 #else 316 return ENOSYS; 317 #endif 318 } 319 320 int 321 compat_50_sys_mknod(struct lwp *l, 322 const struct compat_50_sys_mknod_args *uap, register_t *retval) 323 { 324 /* { 325 syscallarg(const char *) path; 326 syscallarg(mode_t) mode; 327 syscallarg(uint32_t) dev; 328 } */ 329 return do_sys_mknod(l, SCARG(uap, path), SCARG(uap, mode), 330 SCARG(uap, dev), UIO_USERSPACE); 331 } 332 333 int 334 vfs_syscalls_50_init(void) 335 { 336 337 return syscall_establish(NULL, vfs_syscalls_50_syscalls); 338 } 339 340 int 341 vfs_syscalls_50_fini(void) 342 { 343 344 return syscall_disestablish(NULL, vfs_syscalls_50_syscalls); 345 } 346