1 /* $NetBSD: vfs_syscalls_50.c,v 1.6 2010/07/13 15:38:15 pooka 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.6 2010/07/13 15:38:15 pooka 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 memset(ost->st_spare, 0, sizeof(ost->st_spare)); 97 } 98 99 /* 100 * Get file status; this version follows links. 101 */ 102 /* ARGSUSED */ 103 int 104 compat_50_sys___stat30(struct lwp *l, const struct compat_50_sys___stat30_args *uap, register_t *retval) 105 { 106 /* { 107 syscallarg(const char *) path; 108 syscallarg(struct stat30 *) ub; 109 } */ 110 struct stat sb; 111 struct stat30 osb; 112 int error; 113 114 error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb); 115 if (error) 116 return error; 117 cvtstat(&osb, &sb); 118 error = copyout(&osb, SCARG(uap, ub), sizeof (osb)); 119 return error; 120 } 121 122 123 /* 124 * Get file status; this version does not follow links. 125 */ 126 /* ARGSUSED */ 127 int 128 compat_50_sys___lstat30(struct lwp *l, const struct compat_50_sys___lstat30_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), NOFOLLOW, &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 * Return status information about a file descriptor. 148 */ 149 /* ARGSUSED */ 150 int 151 compat_50_sys___fstat30(struct lwp *l, const struct compat_50_sys___fstat30_args *uap, register_t *retval) 152 { 153 /* { 154 syscallarg(int) fd; 155 syscallarg(struct stat30 *) sb; 156 } */ 157 struct stat sb; 158 struct stat30 osb; 159 int error; 160 161 error = do_sys_fstat(SCARG(uap, fd), &sb); 162 if (error) 163 return error; 164 cvtstat(&osb, &sb); 165 error = copyout(&osb, SCARG(uap, sb), sizeof (osb)); 166 return error; 167 } 168 169 /* ARGSUSED */ 170 int 171 compat_50_sys___fhstat40(struct lwp *l, const struct compat_50_sys___fhstat40_args *uap, register_t *retval) 172 { 173 /* { 174 syscallarg(const void *) fhp; 175 syscallarg(size_t) fh_size; 176 syscallarg(struct stat30 *) sb; 177 } */ 178 struct stat sb; 179 struct stat30 osb; 180 int error; 181 182 error = do_fhstat(l, SCARG(uap, fhp), SCARG(uap, fh_size), &sb); 183 if (error) 184 return error; 185 cvtstat(&osb, &sb); 186 error = copyout(&osb, SCARG(uap, sb), sizeof (osb)); 187 return error; 188 } 189 190 static int 191 compat_50_do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, 192 int flag, const struct timeval50 *tptr) 193 { 194 struct timeval tv[2], *tvp; 195 struct timeval50 tv50[2]; 196 if (tptr) { 197 int error = copyin(tptr, tv50, sizeof(tv50)); 198 if (error) 199 return error; 200 timeval50_to_timeval(&tv50[0], &tv[0]); 201 timeval50_to_timeval(&tv50[1], &tv[1]); 202 tvp = tv; 203 } else 204 tvp = NULL; 205 return do_sys_utimes(l, vp, path, flag, tvp, UIO_SYSSPACE); 206 } 207 208 /* 209 * Set the access and modification times given a path name; this 210 * version follows links. 211 */ 212 /* ARGSUSED */ 213 int 214 compat_50_sys_utimes(struct lwp *l, const struct compat_50_sys_utimes_args *uap, 215 register_t *retval) 216 { 217 /* { 218 syscallarg(const char *) path; 219 syscallarg(const struct timeval50 *) tptr; 220 } */ 221 222 return compat_50_do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW, 223 SCARG(uap, tptr)); 224 } 225 226 /* 227 * Set the access and modification times given a file descriptor. 228 */ 229 /* ARGSUSED */ 230 int 231 compat_50_sys_futimes(struct lwp *l, 232 const struct compat_50_sys_futimes_args *uap, register_t *retval) 233 { 234 /* { 235 syscallarg(int) fd; 236 syscallarg(const struct timeval50 *) tptr; 237 } */ 238 int error; 239 struct file *fp; 240 241 /* fd_getvnode() will use the descriptor for us */ 242 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 243 return error; 244 error = compat_50_do_sys_utimes(l, fp->f_data, NULL, 0, 245 SCARG(uap, tptr)); 246 fd_putfile(SCARG(uap, fd)); 247 return error; 248 } 249 250 /* 251 * Set the access and modification times given a path name; this 252 * version does not follow links. 253 */ 254 int 255 compat_50_sys_lutimes(struct lwp *l, 256 const struct compat_50_sys_lutimes_args *uap, register_t *retval) 257 { 258 /* { 259 syscallarg(const char *) path; 260 syscallarg(const struct timeval50 *) tptr; 261 } */ 262 263 return compat_50_do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW, 264 SCARG(uap, tptr)); 265 } 266 267 int 268 compat_50_sys_lfs_segwait(struct lwp *l, 269 const struct compat_50_sys_lfs_segwait_args *uap, register_t *retval) 270 { 271 /* { 272 syscallarg(fsid_t *) fsidp; 273 syscallarg(struct timeval50 *) tv; 274 } */ 275 #ifdef notyet 276 struct timeval atv; 277 struct timeval50 atv50; 278 fsid_t fsid; 279 int error; 280 281 /* XXX need we be su to segwait? */ 282 if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, 283 NULL)) != 0) 284 return (error); 285 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) 286 return (error); 287 288 if (SCARG(uap, tv)) { 289 error = copyin(SCARG(uap, tv), &atv50, sizeof(atv50)); 290 if (error) 291 return (error); 292 timeval50_to_timeval(&atv50, &atv); 293 if (itimerfix(&atv)) 294 return (EINVAL); 295 } else /* NULL or invalid */ 296 atv.tv_sec = atv.tv_usec = 0; 297 return lfs_segwait(&fsid, &atv); 298 #else 299 return ENOSYS; 300 #endif 301 } 302 303 int 304 compat_50_sys_mknod(struct lwp *l, 305 const struct compat_50_sys_mknod_args *uap, register_t *retval) 306 { 307 /* { 308 syscallarg(const char *) path; 309 syscallarg(mode_t) mode; 310 syscallarg(uint32_t) dev; 311 } */ 312 return do_sys_mknod(l, SCARG(uap, path), SCARG(uap, mode), 313 SCARG(uap, dev), retval, UIO_USERSPACE); 314 } 315