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.
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.
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]
23 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
34 #include <sys/param.h>
35 #include <sys/isa_defs.h>
36 #include <sys/types.h>
38 #include <sys/sysmacros.h>
39 #include <sys/systm.h>
40 #include <sys/errno.h>
41 #include <sys/vnode.h>
44 #include <sys/debug.h>
45 #include <sys/model.h>
46 #include <sys/fcntl.h>
48 #include <sys/pathname.h>
52 cfutimesat(int fd
, char *fname
, int nmflag
, vattr_t
*vap
, int flags
, int follow
)
55 vnode_t
*startvp
, *vp
;
59 if (fd
== AT_FDCWD
&& fname
== NULL
)
60 return (set_errno(EFAULT
));
62 if (nmflag
== 1 || (nmflag
== 2 && fname
!= NULL
)) {
63 if (copyin(fname
, &startchar
, sizeof (char)))
64 return (set_errno(EFAULT
));
73 * is this absolute path?
75 if (startchar
!= '/') {
76 if ((fp
= getf(fd
)) == NULL
)
77 return (set_errno(EBADF
));
78 startvp
= fp
->f_vnode
;
86 if ((nmflag
== 1) || ((nmflag
== 2) && (fname
!= NULL
))) {
87 if (AU_AUDITING() && startvp
!= NULL
)
88 audit_setfsat_path(1);
89 if ((error
= lookupnameat(fname
, UIO_USERSPACE
,
90 follow
, NULLVPP
, &vp
, startvp
)) != 0) {
93 return (set_errno(error
));
100 if (startvp
!= NULL
) {
104 if (vn_is_readonly(vp
)) {
107 error
= fop_setattr(vp
, vap
, flags
, CRED(), NULL
);
112 return (set_errno(error
));
117 get_timespec_vattr(timespec_t
*tsptr
, struct vattr
*vattr
, int *flags
)
124 if (get_udatamodel() == DATAMODEL_NATIVE
) {
125 if (copyin(tsptr
, ts
, sizeof (ts
)))
128 timespec32_t ts32
[2];
130 if (copyin(tsptr
, ts32
, sizeof (ts32
)))
132 TIMESPEC32_TO_TIMESPEC(&ts
[0], &ts32
[0]);
133 TIMESPEC32_TO_TIMESPEC(&ts
[1], &ts32
[1]);
135 if (ts
[0].tv_nsec
== UTIME_NOW
|| ts
[1].tv_nsec
== UTIME_NOW
)
138 if (ts
[0].tv_nsec
== UTIME_OMIT
) {
142 if (ts
[0].tv_nsec
== UTIME_NOW
)
144 else if (ts
[0].tv_nsec
< 0 || ts
[0].tv_nsec
>= NANOSEC
)
147 if (ts
[1].tv_nsec
== UTIME_OMIT
) {
151 if (ts
[1].tv_nsec
== UTIME_NOW
)
153 else if (ts
[1].tv_nsec
< 0 || ts
[1].tv_nsec
>= NANOSEC
)
156 vattr
->va_atime
= ts
[0];
157 vattr
->va_mtime
= ts
[1];
158 vattr
->va_mask
= mask
;
162 vattr
->va_atime
= now
;
163 vattr
->va_mtime
= now
;
164 vattr
->va_mask
= AT_ATIME
| AT_MTIME
;
172 futimens(int fd
, timespec_t
*tsptr
)
178 if ((error
= get_timespec_vattr(tsptr
, &vattr
, &flags
)) != 0)
179 return (set_errno(error
));
181 return (cfutimesat(fd
, NULL
, 2, &vattr
, flags
, FOLLOW
));
185 utimensat(int fd
, char *fname
, timespec_t
*tsptr
, int flag
)
191 if ((error
= get_timespec_vattr(tsptr
, &vattr
, &flags
)) != 0)
192 return (set_errno(error
));
194 return (cfutimesat(fd
, fname
, 1, &vattr
, flags
,
195 (flag
& AT_SYMLINK_NOFOLLOW
)? NO_FOLLOW
: FOLLOW
));
200 uintptr_t arg1
, uintptr_t arg2
, uintptr_t arg3
, uintptr_t arg4
)
204 return (futimens((int)arg1
, (timespec_t
*)arg2
));
206 return (utimensat((int)arg1
, (char *)arg2
,
207 (timespec_t
*)arg3
, (int)arg4
));
209 return (set_errno(EINVAL
));