1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * Portions of this source code were derived from Berkeley 4.3 BSD 31 * under license from the Regents of the University of California. 32 */ 33 34 #pragma ident "%Z%%M% %I% %E% SMI" 35 36 #include <sys/param.h> 37 #include <sys/isa_defs.h> 38 #include <sys/types.h> 39 #include <sys/sysmacros.h> 40 #include <sys/systm.h> 41 #include <sys/errno.h> 42 #include <sys/vnode.h> 43 #include <sys/vfs.h> 44 #include <sys/time.h> 45 #include <sys/debug.h> 46 #include <sys/model.h> 47 #include <sys/fcntl.h> 48 #include <sys/file.h> 49 #include <sys/pathname.h> 50 #include <c2/audit.h> 51 52 extern int namesetattr(char *, enum symfollow, vattr_t *, int); 53 extern int fdsetattr(int, vattr_t *); 54 55 static int 56 cfutimesat(int fd, char *fname, int nmflag, vattr_t *vap, int flags) 57 { 58 59 file_t *fp; 60 vnode_t *startvp, *vp; 61 int error; 62 char startchar; 63 64 if (fd == AT_FDCWD && fname == NULL) 65 return (set_errno(EFAULT)); 66 67 if (nmflag == 1 || (nmflag == 2 && fname != NULL)) { 68 if (copyin(fname, &startchar, sizeof (char))) 69 return (set_errno(EFAULT)); 70 } else 71 startchar = '\0'; 72 73 if (fd == AT_FDCWD) 74 startvp = NULL; 75 else { 76 77 /* 78 * is this absolute path? 79 */ 80 if (startchar != '/') { 81 if ((fp = getf(fd)) == NULL) { 82 return (set_errno(EBADF)); 83 } 84 startvp = fp->f_vnode; 85 VN_HOLD(startvp); 86 releasef(fd); 87 } else { 88 startvp = NULL; 89 } 90 } 91 92 if (audit_active) 93 audit_setfsat_path(1); 94 95 if ((nmflag == 1) || ((nmflag == 2) && (fname != NULL))) { 96 if (error = lookupnameat(fname, UIO_USERSPACE, FOLLOW, 97 NULLVPP, &vp, startvp)) { 98 if (startvp != NULL) 99 VN_RELE(startvp); 100 return (set_errno(error)); 101 } 102 } else { 103 vp = startvp; 104 VN_HOLD(vp); 105 } 106 107 if (startvp != NULL) { 108 VN_RELE(startvp); 109 } 110 111 if (vn_is_readonly(vp)) { 112 error = EROFS; 113 } else { 114 error = VOP_SETATTR(vp, vap, flags, CRED(), NULL); 115 } 116 117 VN_RELE(vp); 118 if (error != 0) 119 return (set_errno(error)); 120 else 121 return (0); 122 } 123 124 static int 125 get_utimesvattr(struct timeval *tvptr, struct vattr *vattr, int *flags) 126 { 127 struct timeval tv[2]; 128 129 *flags = 0; 130 131 if (tvptr != NULL) { 132 if (get_udatamodel() == DATAMODEL_NATIVE) { 133 if (copyin(tvptr, tv, sizeof (tv))) 134 return (EFAULT); 135 } else { 136 struct timeval32 tv32[2]; 137 138 if (copyin(tvptr, tv32, sizeof (tv32))) 139 return (EFAULT); 140 141 TIMEVAL32_TO_TIMEVAL(&tv[0], &tv32[0]); 142 TIMEVAL32_TO_TIMEVAL(&tv[1], &tv32[1]); 143 } 144 145 if (tv[0].tv_usec < 0 || tv[0].tv_usec >= 1000000 || 146 tv[1].tv_usec < 0 || tv[1].tv_usec >= 1000000) 147 return (EINVAL); 148 149 vattr->va_atime.tv_sec = tv[0].tv_sec; 150 vattr->va_atime.tv_nsec = tv[0].tv_usec * 1000; 151 vattr->va_mtime.tv_sec = tv[1].tv_sec; 152 vattr->va_mtime.tv_nsec = tv[1].tv_usec * 1000; 153 *flags |= ATTR_UTIME; 154 } else { 155 gethrestime(&vattr->va_atime); 156 vattr->va_mtime = vattr->va_atime; 157 } 158 vattr->va_mask = AT_ATIME | AT_MTIME; 159 160 return (0); 161 } 162 int 163 futimesat(int fd, char *fname, struct timeval *tvptr) 164 { 165 struct vattr vattr; 166 int flags = 0; 167 int error; 168 169 if ((error = get_utimesvattr(tvptr, &vattr, &flags)) != 0) 170 return (set_errno(error)); 171 172 return (cfutimesat(fd, fname, 2, &vattr, flags)); 173 } 174 /* 175 * Set access/modify times on named file. 176 */ 177 int 178 utime(char *fname, time_t *tptr) 179 { 180 time_t tv[2]; 181 struct vattr vattr; 182 int flags = 0; 183 184 if (tptr != NULL) { 185 if (get_udatamodel() == DATAMODEL_NATIVE) { 186 if (copyin(tptr, tv, sizeof (tv))) 187 return (set_errno(EFAULT)); 188 } else { 189 time32_t tv32[2]; 190 191 if (copyin(tptr, &tv32, sizeof (tv32))) 192 return (set_errno(EFAULT)); 193 194 tv[0] = (time_t)tv32[0]; 195 tv[1] = (time_t)tv32[1]; 196 } 197 198 vattr.va_atime.tv_sec = tv[0]; 199 vattr.va_atime.tv_nsec = 0; 200 vattr.va_mtime.tv_sec = tv[1]; 201 vattr.va_mtime.tv_nsec = 0; 202 flags |= ATTR_UTIME; 203 } else { 204 gethrestime(&vattr.va_atime); 205 vattr.va_mtime = vattr.va_atime; 206 } 207 208 vattr.va_mask = AT_ATIME|AT_MTIME; 209 return (cfutimesat(AT_FDCWD, fname, 1, &vattr, flags)); 210 } 211 212 /* 213 * SunOS4.1 Buyback: 214 * Set access/modify time on named file, with hi res timer 215 */ 216 int 217 utimes(char *fname, struct timeval *tvptr) 218 { 219 struct vattr vattr; 220 int flags = 0; 221 int error; 222 223 if ((error = get_utimesvattr(tvptr, &vattr, &flags)) != 0) 224 return (set_errno(error)); 225 226 return (cfutimesat(AT_FDCWD, fname, 1, &vattr, flags)); 227 } 228