1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
27 * Tv_t conversion support
30 #if defined(__STDPP__directive) && defined(__STDPP__hide)
31 __STDPP__directive pragma pp
:hide utime
33 #define utime ______utime
36 #ifndef _ATFILE_SOURCE
37 #define _ATFILE_SOURCE 1
46 #include "FEATURE/tvlib"
48 #if _hdr_utime && _lib_utime
52 #if defined(__STDPP__directive) && defined(__STDPP__hide)
53 __STDPP__directive pragma pp
:nohide utime
60 extern int utime(const char*, const struct utimbuf
*);
62 extern int utime(const char*, const time_t*);
66 #define NS(n) (((uint32_t)(n))<1000000000L?(n):0)
69 * touch path <atime,mtime,ctime>
70 * Tv_t==0 uses current time
71 * Tv_t==TV_TOUCH_RETAIN retains path value if it exists, current time otherwise
72 * otherwise it is exact time
73 * file created if it doesn't exist and (flags&TV_TOUCH_CREATE)
74 * symlink not followed if (flags&TV_TOUCH_PHYSICAL)
75 * cv most likely ignored on most implementations
77 * NOTE: when *at() calls are integrated TV_TOUCH_* should be advertized!
80 #define TV_TOUCH_CREATE 1
81 #define TV_TOUCH_PHYSICAL 2
83 #if !defined(UTIME_NOW) || !defined(UTIME_OMIT) || defined(__stub_utimensat)
88 tvtouch(const char* path
, register const Tv_t
* av
, register const Tv_t
* mv
, const Tv_t
* cv
, int flags
)
95 #if _lib_utimets || _lib_utimensat
96 struct timespec ts
[2];
113 ts
[0].tv_nsec
= UTIME_NOW
;
115 else if (av
== TV_TOUCH_RETAIN
)
118 ts
[0].tv_nsec
= UTIME_OMIT
;
122 ts
[0].tv_sec
= av
->tv_sec
;
123 ts
[0].tv_nsec
= NS(av
->tv_nsec
);
128 ts
[1].tv_nsec
= UTIME_NOW
;
130 else if (mv
== TV_TOUCH_RETAIN
)
133 ts
[1].tv_nsec
= UTIME_OMIT
;
137 ts
[1].tv_sec
= mv
->tv_sec
;
138 ts
[1].tv_nsec
= NS(mv
->tv_nsec
);
140 if (!cv
&& av
== TV_TOUCH_RETAIN
&& mv
== TV_TOUCH_RETAIN
&& !stat(path
, &st
) && !chmod(path
, st
.st_mode
& S_IPERM
))
142 if (!utimensat(AT_FDCWD
, path
, ts
[0].tv_nsec
== UTIME_NOW
&& ts
[1].tv_nsec
== UTIME_NOW
? (struct timespec
*)0 : ts
, (flags
& TV_TOUCH_PHYSICAL
) ? AT_SYMLINK_NOFOLLOW
: 0))
146 if (errno
!= ENOENT
|| !(flags
& TV_TOUCH_CREATE
))
148 umask(mode
= umask(0));
149 mode
= (~mode
) & (S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
|S_IROTH
|S_IWOTH
);
150 if ((fd
= open(path
, O_WRONLY
|O_CREAT
|O_TRUNC
, mode
)) < 0)
154 if ((ts
[0].tv_nsec
!= UTIME_NOW
|| ts
[1].tv_nsec
!= UTIME_NOW
) && utimensat(AT_FDCWD
, path
, ts
, (flags
& TV_TOUCH_PHYSICAL
) ? AT_SYMLINK_NOFOLLOW
: 0))
159 if ((av
== TV_TOUCH_RETAIN
|| mv
== TV_TOUCH_RETAIN
) && stat(path
, &st
))
162 if (av
== TV_TOUCH_RETAIN
)
164 if (mv
== TV_TOUCH_RETAIN
)
171 av
= (const Tv_t
*)&now
;
173 mv
= (const Tv_t
*)&now
;
176 if (av
== TV_TOUCH_RETAIN
)
178 ts
[0].tv_sec
= st
.st_atime
;
179 ts
[0].tv_nsec
= ST_ATIME_NSEC_GET(&st
);
183 ts
[0].tv_sec
= av
->tv_sec
;
184 ts
[0].tv_nsec
= NS(av
->tv_nsec
);
186 if (mv
== TV_TOUCH_RETAIN
)
188 ts
[1].tv_sec
= st
.st_mtime
;
189 ts
[1].tv_nsec
= ST_MTIME_NSEC_GET(&st
);
193 ts
[1].tv_sec
= mv
->tv_sec
;
194 ts
[1].tv_nsec
= NS(mv
->tv_nsec
);
196 if (!utimets(path
, ts
))
198 if (errno
!= ENOENT
&& av
== (const Tv_t
*)&now
&& mv
== (const Tv_t
*)&now
&& !utimets(path
, NiL
))
205 if (av
== TV_TOUCH_RETAIN
)
207 am
[0].tv_sec
= st
.st_atime
;
208 am
[0].tv_usec
= ST_ATIME_NSEC_GET(&st
) / 1000;
212 am
[0].tv_sec
= av
->tv_sec
;
213 am
[0].tv_usec
= NS(av
->tv_nsec
) / 1000;
215 if (mv
== TV_TOUCH_RETAIN
)
217 am
[1].tv_sec
= st
.st_mtime
;
218 am
[1].tv_usec
= ST_MTIME_NSEC_GET(&st
) / 1000;
222 am
[1].tv_sec
= mv
->tv_sec
;
223 am
[1].tv_usec
= NS(mv
->tv_nsec
) / 1000;
225 if (!utimes(path
, am
))
227 if (errno
!= ENOENT
&& av
== (const Tv_t
*)&now
&& mv
== (const Tv_t
*)&now
&& !utimes(path
, NiL
))
234 am
.actime
= (av
== TV_TOUCH_RETAIN
) ? st
.st_atime
: av
->tv_sec
;
235 am
.modtime
= (mv
== TV_TOUCH_RETAIN
) ? st
.st_mtime
: mv
->tv_sec
;
236 if (!utime(path
, &am
))
239 if (errno
!= ENOENT
&& av
== (const Tv_t
*)&now
&& mv
== (const Tv_t
*)&now
&& !utime(path
, NiL
))
247 if (!access(path
, F_OK
))
249 if (av
!= (const Tv_t
*)&now
|| mv
!= (const Tv_t
*)&now
)
254 if ((fd
= open(path
, O_RDWR
)) >= 0)
258 if (read(fd
, &c
, 1) == 1)
260 if (c
= (lseek(fd
, 0L, 0) == 0L && write(fd
, &c
, 1) == 1))
270 if (errno
!= ENOENT
|| !(flags
& TV_TOUCH_CREATE
))
272 umask(mode
= umask(0));
273 mode
= (~mode
) & (S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
|S_IROTH
|S_IWOTH
);
274 if ((fd
= open(path
, O_WRONLY
|O_CREAT
|O_TRUNC
, mode
)) < 0)
278 if (av
== (const Tv_t
*)&now
&& mv
== (const Tv_t
*)&now
)
281 return utimets(path
, am
);
284 return utimes(path
, am
);
287 return utime(path
, &am
);