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