xref: /titanic_50/usr/src/lib/libast/common/tm/tvtouch.c (revision 3eae19d9cf3390cf5b75e10c9c1945fd36ad856a)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #pragma prototyped
23 /*
24  * Glenn Fowler
25  * AT&T Research
26  *
27  * Tv_t conversion support
28  */
29 
30 #if defined(__STDPP__directive) && defined(__STDPP__hide)
31 __STDPP__directive pragma pp:hide utime
32 #else
33 #define utime		______utime
34 #endif
35 
36 #include <ast.h>
37 #include <ls.h>
38 #include <tv.h>
39 #include <times.h>
40 #include <error.h>
41 
42 #include "FEATURE/tvlib"
43 
44 #if _hdr_utime && _lib_utime
45 #include <utime.h>
46 #endif
47 
48 #if defined(__STDPP__directive) && defined(__STDPP__hide)
49 __STDPP__directive pragma pp:nohide utime
50 #else
51 #undef	utime
52 #endif
53 
54 #if _lib_utime
55 #if _hdr_utime
56 extern int	utime(const char*, const struct utimbuf*);
57 #else
58 extern int	utime(const char*, const time_t*);
59 #endif
60 #endif
61 
62 #define NS(n)		(((uint32_t)(n))<1000000000L?(n):0)
63 
64 /*
65  * touch path <atime,mtime,ctime>
66  * Tv_t==0 uses current time
67  * Tv_t==TV_TOUCH_RETAIN retains path value if it exists, current time otherwise
68  * otherwise it is exact time
69  * file created if it doesn't exist and (flags&1)
70  * cv most likely ignored on most implementations
71  */
72 
73 int
74 tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, const Tv_t* cv, int flags)
75 {
76 	struct stat	st;
77 	Tv_t		now;
78 	int		fd;
79 	int		mode;
80 	int		oerrno;
81 #if _lib_utimets
82 	struct timespec	am[2];
83 #else
84 #if _lib_utimes
85 	struct timeval	am[2];
86 #else
87 #if _hdr_utime
88 	struct utimbuf	am;
89 #else
90 	time_t		am[2];
91 #endif
92 #endif
93 #endif
94 
95 	oerrno = errno;
96 	if ((av == TV_TOUCH_RETAIN || mv == TV_TOUCH_RETAIN) && stat(path, &st))
97 	{
98 		errno = oerrno;
99 		if (av == TV_TOUCH_RETAIN)
100 			av = 0;
101 		if (mv == TV_TOUCH_RETAIN)
102 			mv = 0;
103 	}
104 	if (!av || !mv)
105 	{
106 		tvgettime(&now);
107 		if (!av)
108 			av = (const Tv_t*)&now;
109 		if (!mv)
110 			mv = (const Tv_t*)&now;
111 	}
112 #if _lib_utimets
113 	if (av == TV_TOUCH_RETAIN)
114 	{
115 		am[0].tv_sec = st.st_atime;
116 		am[0].tv_nsec = ST_ATIME_NSEC_GET(&st);
117 	}
118 	else
119 	{
120 		am[0].tv_sec = av->tv_sec;
121 		am[0].tv_nsec = NS(av->tv_nsec);
122 	}
123 	if (mv == TV_TOUCH_RETAIN)
124 	{
125 		am[1].tv_sec = st.st_mtime;
126 		am[1].tv_nsec = ST_MTIME_NSEC_GET(&st);
127 	}
128 	else
129 	{
130 		am[1].tv_sec = mv->tv_sec;
131 		am[1].tv_nsec = NS(mv->tv_nsec);
132 	}
133 	if (!utimets(path, am))
134 		return 0;
135 	if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimets(path, NiL))
136 	{
137 		errno = oerrno;
138 		return 0;
139 	}
140 #else
141 #if _lib_utimes
142 	if (av == TV_TOUCH_RETAIN)
143 	{
144 		am[0].tv_sec = st.st_atime;
145 		am[0].tv_usec = ST_ATIME_NSEC_GET(&st) / 1000;
146 	}
147 	else
148 	{
149 		am[0].tv_sec = av->tv_sec;
150 		am[0].tv_usec = NS(av->tv_nsec) / 1000;
151 	}
152 	if (mv == TV_TOUCH_RETAIN)
153 	{
154 		am[1].tv_sec = st.st_mtime;
155 		am[1].tv_usec = ST_MTIME_NSEC_GET(&st) / 1000;
156 	}
157 	else
158 	{
159 		am[1].tv_sec = mv->tv_sec;
160 		am[1].tv_usec = NS(mv->tv_nsec) / 1000;
161 	}
162 	if (!utimes(path, am))
163 		return 0;
164 	if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimes(path, NiL))
165 	{
166 		errno = oerrno;
167 		return 0;
168 	}
169 #else
170 #if _lib_utime
171 	am.actime = (av == TV_TOUCH_RETAIN) ? st.st_atime : av->tv_sec;
172 	am.modtime = (mv == TV_TOUCH_RETAIN) ? st.st_mtime : mv->tv_sec;
173 	if (!utime(path, &am))
174 		return 0;
175 #if _lib_utime_now
176 	if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utime(path, NiL))
177 	{
178 		errno = oerrno;
179 		return 0;
180 	}
181 #endif
182 #endif
183 #endif
184 	if (!access(path, F_OK))
185 	{
186 		if (av != (const Tv_t*)&now || mv != (const Tv_t*)&now)
187 		{
188 			errno = EINVAL;
189 			return -1;
190 		}
191 		if ((fd = open(path, O_RDWR)) >= 0)
192 		{
193 			char	c;
194 
195 			if (read(fd, &c, 1) == 1)
196 			{
197 				if (c = (lseek(fd, 0L, 0) == 0L && write(fd, &c, 1) == 1))
198 					errno = oerrno;
199 				close(fd);
200 				if (c)
201 					return 0;
202 			}
203 			close(fd);
204 		}
205 	}
206 #endif
207 	if (errno != ENOENT || !(flags & 1))
208 		return -1;
209 	umask(mode = umask(0));
210 	mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
211 	if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0)
212 		return -1;
213 	close(fd);
214 	errno = oerrno;
215 	if (av == (const Tv_t*)&now && mv == (const Tv_t*)&now)
216 		return 0;
217 #if _lib_utimets
218 	return utimets(path, am);
219 #else
220 #if _lib_utimes
221 	return utimes(path, am);
222 #else
223 #if _lib_utime
224 	return utime(path, &am);
225 #else
226 	errno = EINVAL;
227 	return -1;
228 #endif
229 #endif
230 #endif
231 
232 }
233