1 /* $NetBSD: vfs_syscalls_50.c,v 1.4 2009/01/26 13:00:04 njoly 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.4 2009/01/26 13:00:04 njoly Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/namei.h> 44 #include <sys/filedesc.h> 45 #include <sys/kernel.h> 46 #include <sys/file.h> 47 #include <sys/stat.h> 48 #include <sys/socketvar.h> 49 #include <sys/vnode.h> 50 #include <sys/mount.h> 51 #include <sys/proc.h> 52 #include <sys/uio.h> 53 #include <sys/dirent.h> 54 #include <sys/malloc.h> 55 #include <sys/kauth.h> 56 #include <sys/time.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/sys/time.h> 67 #include <compat/sys/stat.h> 68 #include <compat/sys/dirent.h> 69 #include <compat/sys/mount.h> 70 71 static void cvtstat(struct stat30 *, const struct stat *); 72 73 /* 74 * Convert from a new to an old stat structure. 75 */ 76 static void 77 cvtstat(struct stat30 *ost, const struct stat *st) 78 { 79 80 ost->st_dev = st->st_dev; 81 ost->st_ino = st->st_ino; 82 ost->st_mode = st->st_mode; 83 ost->st_nlink = st->st_nlink; 84 ost->st_uid = st->st_uid; 85 ost->st_gid = st->st_gid; 86 ost->st_rdev = st->st_rdev; 87 timespec_to_timespec50(&st->st_atimespec, &ost->st_atimespec); 88 timespec_to_timespec50(&st->st_mtimespec, &ost->st_mtimespec); 89 timespec_to_timespec50(&st->st_ctimespec, &ost->st_ctimespec); 90 timespec_to_timespec50(&st->st_birthtimespec, &ost->st_birthtimespec); 91 ost->st_size = st->st_size; 92 ost->st_blocks = st->st_blocks; 93 ost->st_blksize = st->st_blksize; 94 ost->st_flags = st->st_flags; 95 ost->st_gen = st->st_gen; 96 } 97 98 /* 99 * Get file status; this version follows links. 100 */ 101 /* ARGSUSED */ 102 int 103 compat_50_sys___stat30(struct lwp *l, const struct compat_50_sys___stat30_args *uap, register_t *retval) 104 { 105 /* { 106 syscallarg(const char *) path; 107 syscallarg(struct stat30 *) ub; 108 } */ 109 struct stat sb; 110 struct stat30 osb; 111 int error; 112 113 error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb); 114 if (error) 115 return error; 116 cvtstat(&osb, &sb); 117 error = copyout(&osb, SCARG(uap, ub), sizeof (osb)); 118 return error; 119 } 120 121 122 /* 123 * Get file status; this version does not follow links. 124 */ 125 /* ARGSUSED */ 126 int 127 compat_50_sys___lstat30(struct lwp *l, const struct compat_50_sys___lstat30_args *uap, register_t *retval) 128 { 129 /* { 130 syscallarg(const char *) path; 131 syscallarg(struct stat30 *) ub; 132 } */ 133 struct stat sb; 134 struct stat30 osb; 135 int error; 136 137 error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb); 138 if (error) 139 return error; 140 cvtstat(&osb, &sb); 141 error = copyout(&osb, SCARG(uap, ub), sizeof (osb)); 142 return error; 143 } 144 145 /* 146 * Return status information about a file descriptor. 147 */ 148 /* ARGSUSED */ 149 int 150 compat_50_sys___fstat30(struct lwp *l, const struct compat_50_sys___fstat30_args *uap, register_t *retval) 151 { 152 /* { 153 syscallarg(int) fd; 154 syscallarg(struct stat30 *) sb; 155 } */ 156 struct stat sb; 157 struct stat30 osb; 158 int error; 159 160 error = do_sys_fstat(SCARG(uap, fd), &sb); 161 if (error) 162 return error; 163 cvtstat(&osb, &sb); 164 error = copyout(&osb, SCARG(uap, sb), sizeof (osb)); 165 return error; 166 } 167 168 /* ARGSUSED */ 169 int 170 compat_50_sys___fhstat40(struct lwp *l, const struct compat_50_sys___fhstat40_args *uap, register_t *retval) 171 { 172 /* { 173 syscallarg(const void *) fhp; 174 syscallarg(size_t) fh_size; 175 syscallarg(struct stat30 *) sb; 176 } */ 177 struct stat sb; 178 struct stat30 osb; 179 int error; 180 181 error = do_fhstat(l, SCARG(uap, fhp), SCARG(uap, fh_size), &sb); 182 if (error) 183 return error; 184 cvtstat(&osb, &sb); 185 error = copyout(&osb, SCARG(uap, sb), sizeof (osb)); 186 return error; 187 } 188 189 static int 190 compat_50_do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, 191 int flag, const struct timeval50 *tptr) 192 { 193 struct timeval tv[2], *tvp; 194 struct timeval50 tv50[2]; 195 if (tptr) { 196 int error = copyin(tptr, tv50, sizeof(tv50)); 197 if (error) 198 return error; 199 timeval50_to_timeval(&tv50[0], &tv[0]); 200 timeval50_to_timeval(&tv50[1], &tv[1]); 201 tvp = tv; 202 } else 203 tvp = NULL; 204 return do_sys_utimes(l, vp, path, flag, tvp, UIO_SYSSPACE); 205 } 206 207 /* 208 * Set the access and modification times given a path name; this 209 * version follows links. 210 */ 211 /* ARGSUSED */ 212 int 213 compat_50_sys_utimes(struct lwp *l, const struct compat_50_sys_utimes_args *uap, 214 register_t *retval) 215 { 216 /* { 217 syscallarg(const char *) path; 218 syscallarg(const struct timeval50 *) tptr; 219 } */ 220 221 return compat_50_do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW, 222 SCARG(uap, tptr)); 223 } 224 225 /* 226 * Set the access and modification times given a file descriptor. 227 */ 228 /* ARGSUSED */ 229 int 230 compat_50_sys_futimes(struct lwp *l, 231 const struct compat_50_sys_futimes_args *uap, register_t *retval) 232 { 233 /* { 234 syscallarg(int) fd; 235 syscallarg(const struct timeval50 *) tptr; 236 } */ 237 int error; 238 struct file *fp; 239 240 /* fd_getvnode() will use the descriptor for us */ 241 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 242 return error; 243 error = compat_50_do_sys_utimes(l, fp->f_data, NULL, 0, 244 SCARG(uap, tptr)); 245 fd_putfile(SCARG(uap, fd)); 246 return error; 247 } 248 249 /* 250 * Set the access and modification times given a path name; this 251 * version does not follow links. 252 */ 253 int 254 compat_50_sys_lutimes(struct lwp *l, 255 const struct compat_50_sys_lutimes_args *uap, register_t *retval) 256 { 257 /* { 258 syscallarg(const char *) path; 259 syscallarg(const struct timeval50 *) tptr; 260 } */ 261 262 return compat_50_do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW, 263 SCARG(uap, tptr)); 264 } 265 266 int 267 compat_50_sys_lfs_segwait(struct lwp *l, 268 const struct compat_50_sys_lfs_segwait_args *uap, register_t *retval) 269 { 270 /* { 271 syscallarg(fsid_t *) fsidp; 272 syscallarg(struct timeval50 *) tv; 273 } */ 274 #ifdef notyet 275 struct timeval atv; 276 struct timeval50 atv50; 277 fsid_t fsid; 278 int error; 279 280 /* XXX need we be su to segwait? */ 281 if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, 282 NULL)) != 0) 283 return (error); 284 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) 285 return (error); 286 287 if (SCARG(uap, tv)) { 288 error = copyin(SCARG(uap, tv), &atv50, sizeof(atv50)); 289 if (error) 290 return (error); 291 timeval50_to_timeval(&atv50, &atv); 292 if (itimerfix(&atv)) 293 return (EINVAL); 294 } else /* NULL or invalid */ 295 atv.tv_sec = atv.tv_usec = 0; 296 return lfs_segwait(&fsid, &atv); 297 #else 298 return ENOSYS; 299 #endif 300 } 301 302 int 303 compat_50_sys_mknod(struct lwp *l, 304 const struct compat_50_sys_mknod_args *uap, register_t *retval) 305 { 306 /* { 307 syscallarg(const char *) path; 308 syscallarg(mode_t) mode; 309 syscallarg(uint32_t) dev; 310 } */ 311 return do_sys_mknod(l, SCARG(uap, path), SCARG(uap, mode), 312 SCARG(uap, dev), retval); 313 } 314