1/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "defs.h"
31#include <fcntl.h>
32#include <signal.h>
33#include <sys/timex.h>
34
35static void
36print_timezone(struct tcb *const tcp, const kernel_ulong_t addr)
37{
38	struct timezone tz;
39
40	if (umove_or_printaddr(tcp, addr, &tz))
41		return;
42
43	tprintf("{tz_minuteswest=%d, tz_dsttime=%d}",
44		tz.tz_minuteswest, tz.tz_dsttime);
45}
46
47SYS_FUNC(gettimeofday)
48{
49	if (exiting(tcp)) {
50		print_timeval(tcp, tcp->u_arg[0]);
51		tprints(", ");
52		print_timezone(tcp, tcp->u_arg[1]);
53	}
54	return 0;
55}
56
57#ifdef ALPHA
58SYS_FUNC(osf_gettimeofday)
59{
60	if (exiting(tcp)) {
61		print_timeval32(tcp, tcp->u_arg[0]);
62		tprints(", ");
63		print_timezone(tcp, tcp->u_arg[1]);
64	}
65	return 0;
66}
67#endif
68
69SYS_FUNC(settimeofday)
70{
71	print_timeval(tcp, tcp->u_arg[0]);
72	tprints(", ");
73	print_timezone(tcp, tcp->u_arg[1]);
74
75	return RVAL_DECODED;
76}
77
78#ifdef ALPHA
79SYS_FUNC(osf_settimeofday)
80{
81	print_timeval32(tcp, tcp->u_arg[0]);
82	tprints(", ");
83	print_timezone(tcp, tcp->u_arg[1]);
84
85	return RVAL_DECODED;
86}
87#endif
88
89SYS_FUNC(nanosleep)
90{
91	if (entering(tcp)) {
92		print_timespec(tcp, tcp->u_arg[0]);
93		tprints(", ");
94	} else {
95
96		/*
97		 * Second (returned) timespec is only significant if syscall
98		 * was interrupted.  On success and in case of other errors we
99		 * print only its address, since kernel doesn't modify it,
100		 * and printing the value may show uninitialized data.
101		 */
102		if (is_erestart(tcp)) {
103			temporarily_clear_syserror(tcp);
104			print_timespec(tcp, tcp->u_arg[1]);
105			restore_cleared_syserror(tcp);
106		} else {
107			printaddr(tcp->u_arg[1]);
108		}
109	}
110	return 0;
111}
112
113#include "xlat/itimer_which.h"
114
115SYS_FUNC(getitimer)
116{
117	if (entering(tcp)) {
118		printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
119		tprints(", ");
120	} else {
121		print_itimerval(tcp, tcp->u_arg[1]);
122	}
123	return 0;
124}
125
126#ifdef ALPHA
127SYS_FUNC(osf_getitimer)
128{
129	if (entering(tcp)) {
130		printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
131		tprints(", ");
132	} else {
133		print_itimerval32(tcp, tcp->u_arg[1]);
134	}
135	return 0;
136}
137#endif
138
139SYS_FUNC(setitimer)
140{
141	if (entering(tcp)) {
142		printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
143		tprints(", ");
144		print_itimerval(tcp, tcp->u_arg[1]);
145		tprints(", ");
146	} else {
147		print_itimerval(tcp, tcp->u_arg[2]);
148	}
149	return 0;
150}
151
152#ifdef ALPHA
153SYS_FUNC(osf_setitimer)
154{
155	if (entering(tcp)) {
156		printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
157		tprints(", ");
158		print_itimerval32(tcp, tcp->u_arg[1]);
159		tprints(", ");
160	} else {
161		print_itimerval32(tcp, tcp->u_arg[2]);
162	}
163	return 0;
164}
165#endif
166
167#include "xlat/adjtimex_state.h"
168
169static int
170do_adjtimex(struct tcb *const tcp, const kernel_ulong_t addr)
171{
172	if (print_timex(tcp, addr))
173		return 0;
174	tcp->auxstr = xlookup(adjtimex_state, (kernel_ulong_t) tcp->u_rval);
175	if (tcp->auxstr)
176		return RVAL_STR;
177	return 0;
178}
179
180SYS_FUNC(adjtimex)
181{
182	if (exiting(tcp))
183		return do_adjtimex(tcp, tcp->u_arg[0]);
184	return 0;
185}
186
187#include "xlat/clockflags.h"
188#include "xlat/clocknames.h"
189
190static void
191printclockname(int clockid)
192{
193#ifdef CLOCKID_TO_FD
194# include "xlat/cpuclocknames.h"
195
196	if (clockid < 0) {
197		if ((clockid & CLOCKFD_MASK) == CLOCKFD)
198			tprintf("FD_TO_CLOCKID(%d)", CLOCKID_TO_FD(clockid));
199		else {
200			if(CPUCLOCK_PERTHREAD(clockid))
201				tprintf("MAKE_THREAD_CPUCLOCK(%d,", CPUCLOCK_PID(clockid));
202			else
203				tprintf("MAKE_PROCESS_CPUCLOCK(%d,", CPUCLOCK_PID(clockid));
204			printxval(cpuclocknames, clockid & CLOCKFD_MASK, "CPUCLOCK_???");
205			tprints(")");
206		}
207	}
208	else
209#endif
210		printxval(clocknames, clockid, "CLOCK_???");
211}
212
213SYS_FUNC(clock_settime)
214{
215	printclockname(tcp->u_arg[0]);
216	tprints(", ");
217	print_timespec(tcp, tcp->u_arg[1]);
218
219	return RVAL_DECODED;
220}
221
222SYS_FUNC(clock_gettime)
223{
224	if (entering(tcp)) {
225		printclockname(tcp->u_arg[0]);
226		tprints(", ");
227	} else {
228		print_timespec(tcp, tcp->u_arg[1]);
229	}
230	return 0;
231}
232
233SYS_FUNC(clock_nanosleep)
234{
235	if (entering(tcp)) {
236		printclockname(tcp->u_arg[0]);
237		tprints(", ");
238		printflags(clockflags, tcp->u_arg[1], "TIMER_???");
239		tprints(", ");
240		print_timespec(tcp, tcp->u_arg[2]);
241		tprints(", ");
242	} else {
243		/*
244		 * Second (returned) timespec is only significant
245		 * if syscall was interrupted and flags is not TIMER_ABSTIME.
246		 */
247		if (!tcp->u_arg[1] && is_erestart(tcp)) {
248			temporarily_clear_syserror(tcp);
249			print_timespec(tcp, tcp->u_arg[3]);
250			restore_cleared_syserror(tcp);
251		} else {
252			printaddr(tcp->u_arg[3]);
253		}
254	}
255	return 0;
256}
257
258SYS_FUNC(clock_adjtime)
259{
260	if (exiting(tcp))
261		return do_adjtimex(tcp, tcp->u_arg[1]);
262	printclockname(tcp->u_arg[0]);
263	tprints(", ");
264	return 0;
265}
266
267SYS_FUNC(timer_create)
268{
269	if (entering(tcp)) {
270		printclockname(tcp->u_arg[0]);
271		tprints(", ");
272		print_sigevent(tcp, tcp->u_arg[1]);
273		tprints(", ");
274	} else {
275		printnum_int(tcp, tcp->u_arg[2], "%d");
276	}
277	return 0;
278}
279
280SYS_FUNC(timer_settime)
281{
282	if (entering(tcp)) {
283		tprintf("%d, ", (int) tcp->u_arg[0]);
284		printflags(clockflags, tcp->u_arg[1], "TIMER_???");
285		tprints(", ");
286		print_itimerspec(tcp, tcp->u_arg[2]);
287		tprints(", ");
288	} else {
289		print_itimerspec(tcp, tcp->u_arg[3]);
290	}
291	return 0;
292}
293
294SYS_FUNC(timer_gettime)
295{
296	if (entering(tcp)) {
297		tprintf("%d, ", (int) tcp->u_arg[0]);
298	} else {
299		print_itimerspec(tcp, tcp->u_arg[1]);
300	}
301	return 0;
302}
303
304#include "xlat/timerfdflags.h"
305
306SYS_FUNC(timerfd_create)
307{
308	printclockname(tcp->u_arg[0]);
309	tprints(", ");
310	printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
311
312	return RVAL_DECODED | RVAL_FD;
313}
314
315SYS_FUNC(timerfd_settime)
316{
317	if (entering(tcp)) {
318		printfd(tcp, tcp->u_arg[0]);
319		tprints(", ");
320		printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
321		tprints(", ");
322		print_itimerspec(tcp, tcp->u_arg[2]);
323		tprints(", ");
324	} else {
325		print_itimerspec(tcp, tcp->u_arg[3]);
326	}
327	return 0;
328}
329
330SYS_FUNC(timerfd_gettime)
331{
332	if (entering(tcp)) {
333		printfd(tcp, tcp->u_arg[0]);
334		tprints(", ");
335	} else {
336		print_itimerspec(tcp, tcp->u_arg[1]);
337	}
338	return 0;
339}
340