time.c revision d35bdcad13caac3e167735e1f0fc50355b2f9523
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 <linux/version.h>
32#include <sys/timex.h>
33#include <linux/ioctl.h>
34#include <linux/rtc.h>
35
36#ifndef UTIME_NOW
37#define UTIME_NOW ((1l << 30) - 1l)
38#endif
39#ifndef UTIME_OMIT
40#define UTIME_OMIT ((1l << 30) - 2l)
41#endif
42
43struct timeval32
44{
45	u_int32_t tv_sec, tv_usec;
46};
47
48static void
49tprint_timeval32(struct tcb *tcp, const struct timeval32 *tv)
50{
51	tprintf("{%u, %u}", tv->tv_sec, tv->tv_usec);
52}
53
54static void
55tprint_timeval(struct tcb *tcp, const struct timeval *tv)
56{
57	tprintf("{%lu, %lu}",
58		(unsigned long) tv->tv_sec, (unsigned long) tv->tv_usec);
59}
60
61void
62printtv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness, int special)
63{
64	char buf[TIMEVAL_TEXT_BUFSIZE];
65	sprinttv(buf, tcp, addr, bitness, special);
66	tprints(buf);
67}
68
69char *
70sprinttv(char *buf, struct tcb *tcp, long addr, enum bitness_t bitness, int special)
71{
72	int rc;
73
74	if (addr == 0)
75		return stpcpy(buf, "NULL");
76
77	if (!verbose(tcp))
78		return buf + sprintf(buf, "%#lx", addr);
79
80	if (bitness == BITNESS_32
81#if SUPPORTED_PERSONALITIES > 1
82	    || current_wordsize == 4
83#endif
84		)
85	{
86		struct timeval32 tv;
87
88		rc = umove(tcp, addr, &tv);
89		if (rc >= 0) {
90			if (special && tv.tv_sec == 0) {
91				if (tv.tv_usec == UTIME_NOW)
92					return stpcpy(buf, "UTIME_NOW");
93				if (tv.tv_usec == UTIME_OMIT)
94					return stpcpy(buf, "UTIME_OMIT");
95			}
96			return buf + sprintf(buf, "{%u, %u}",
97				tv.tv_sec, tv.tv_usec);
98		}
99	} else {
100		struct timeval tv;
101
102		rc = umove(tcp, addr, &tv);
103		if (rc >= 0) {
104			if (special && tv.tv_sec == 0) {
105				if (tv.tv_usec == UTIME_NOW)
106					return stpcpy(buf, "UTIME_NOW");
107				if (tv.tv_usec == UTIME_OMIT)
108					return stpcpy(buf, "UTIME_OMIT");
109			}
110			return buf + sprintf(buf, "{%lu, %lu}",
111				(unsigned long) tv.tv_sec,
112				(unsigned long) tv.tv_usec);
113		}
114	}
115
116	return stpcpy(buf, "{...}");
117}
118
119void
120print_timespec(struct tcb *tcp, long addr)
121{
122	char buf[TIMESPEC_TEXT_BUFSIZE];
123	sprint_timespec(buf, tcp, addr);
124	tprints(buf);
125}
126
127void
128sprint_timespec(char *buf, struct tcb *tcp, long addr)
129{
130	if (addr == 0)
131		strcpy(buf, "NULL");
132	else if (!verbose(tcp))
133		sprintf(buf, "%#lx", addr);
134	else {
135		int rc;
136
137#if SUPPORTED_PERSONALITIES > 1
138		if (current_wordsize == 4) {
139			struct timeval32 tv;
140
141			rc = umove(tcp, addr, &tv);
142			if (rc >= 0)
143				sprintf(buf, "{%u, %u}",
144					tv.tv_sec, tv.tv_usec);
145		} else
146#endif
147		{
148			struct timespec ts;
149
150			rc = umove(tcp, addr, &ts);
151			if (rc >= 0)
152				sprintf(buf, "{%lu, %lu}",
153					(unsigned long) ts.tv_sec,
154					(unsigned long) ts.tv_nsec);
155		}
156		if (rc < 0)
157			strcpy(buf, "{...}");
158	}
159}
160
161int
162sys_time(struct tcb *tcp)
163{
164	if (exiting(tcp)) {
165		printnum(tcp, tcp->u_arg[0], "%ld");
166	}
167	return 0;
168}
169
170int
171sys_stime(struct tcb *tcp)
172{
173	if (exiting(tcp)) {
174		printnum(tcp, tcp->u_arg[0], "%ld");
175	}
176	return 0;
177}
178
179int
180sys_gettimeofday(struct tcb *tcp)
181{
182	if (exiting(tcp)) {
183		if (syserror(tcp)) {
184			tprintf("%#lx, %#lx",
185				tcp->u_arg[0], tcp->u_arg[1]);
186			return 0;
187		}
188		printtv(tcp, tcp->u_arg[0]);
189		tprints(", ");
190		printtv(tcp, tcp->u_arg[1]);
191	}
192	return 0;
193}
194
195#ifdef ALPHA
196int
197sys_osf_gettimeofday(struct tcb *tcp)
198{
199	if (exiting(tcp)) {
200		if (syserror(tcp)) {
201			tprintf("%#lx, %#lx", tcp->u_arg[0], tcp->u_arg[1]);
202			return 0;
203		}
204		printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
205		tprints(", ");
206		printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
207	}
208	return 0;
209}
210#endif
211
212int
213sys_settimeofday(struct tcb *tcp)
214{
215	if (entering(tcp)) {
216		printtv(tcp, tcp->u_arg[0]);
217		tprints(", ");
218		printtv(tcp, tcp->u_arg[1]);
219	}
220	return 0;
221}
222
223#ifdef ALPHA
224int
225sys_osf_settimeofday(struct tcb *tcp)
226{
227	if (entering(tcp)) {
228		printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
229		tprints(", ");
230		printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
231	}
232	return 0;
233}
234#endif
235
236int
237sys_adjtime(struct tcb *tcp)
238{
239	if (entering(tcp)) {
240		printtv(tcp, tcp->u_arg[0]);
241		tprints(", ");
242	} else {
243		if (syserror(tcp))
244			tprintf("%#lx", tcp->u_arg[1]);
245		else
246			printtv(tcp, tcp->u_arg[1]);
247	}
248	return 0;
249}
250
251int
252sys_nanosleep(struct tcb *tcp)
253{
254	if (entering(tcp)) {
255		print_timespec(tcp, tcp->u_arg[0]);
256		tprints(", ");
257	} else {
258		/* Second (returned) timespec is only significant
259		 * if syscall was interrupted. On success, we print
260		 * only its address, since kernel doesn't modify it,
261		 * and printing the value may show uninitialized data.
262		 */
263		switch (tcp->u_error) {
264		default:
265			/* Not interrupted (slept entire interval) */
266			if (tcp->u_arg[1]) {
267				tprintf("%#lx", tcp->u_arg[1]);
268				break;
269			}
270			/* Fall through: print_timespec(NULL) prints "NULL" */
271		case ERESTARTSYS:
272		case ERESTARTNOINTR:
273		case ERESTARTNOHAND:
274		case ERESTART_RESTARTBLOCK:
275			/* Interrupted */
276			print_timespec(tcp, tcp->u_arg[1]);
277		}
278	}
279	return 0;
280}
281
282#include "xlat/itimer_which.h"
283
284static void
285printitv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness)
286{
287	if (addr == 0)
288		tprints("NULL");
289	else if (!verbose(tcp))
290		tprintf("%#lx", addr);
291	else {
292		int rc;
293
294		if (bitness == BITNESS_32
295#if SUPPORTED_PERSONALITIES > 1
296		    || current_wordsize == 4
297#endif
298			)
299		{
300			struct {
301				struct timeval32 it_interval, it_value;
302			} itv;
303
304			rc = umove(tcp, addr, &itv);
305			if (rc >= 0) {
306				tprints("{it_interval=");
307				tprint_timeval32(tcp, &itv.it_interval);
308				tprints(", it_value=");
309				tprint_timeval32(tcp, &itv.it_value);
310				tprints("}");
311			}
312		} else {
313			struct itimerval itv;
314
315			rc = umove(tcp, addr, &itv);
316			if (rc >= 0) {
317				tprints("{it_interval=");
318				tprint_timeval(tcp, &itv.it_interval);
319				tprints(", it_value=");
320				tprint_timeval(tcp, &itv.it_value);
321				tprints("}");
322			}
323		}
324		if (rc < 0)
325			tprints("{...}");
326	}
327}
328
329#define printitv(tcp, addr)	\
330	printitv_bitness((tcp), (addr), BITNESS_CURRENT)
331
332int
333sys_getitimer(struct tcb *tcp)
334{
335	if (entering(tcp)) {
336		printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
337		tprints(", ");
338	} else {
339		if (syserror(tcp))
340			tprintf("%#lx", tcp->u_arg[1]);
341		else
342			printitv(tcp, tcp->u_arg[1]);
343	}
344	return 0;
345}
346
347#ifdef ALPHA
348int
349sys_osf_getitimer(struct tcb *tcp)
350{
351	if (entering(tcp)) {
352		printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
353		tprints(", ");
354	} else {
355		if (syserror(tcp))
356			tprintf("%#lx", tcp->u_arg[1]);
357		else
358			printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
359	}
360	return 0;
361}
362#endif
363
364int
365sys_setitimer(struct tcb *tcp)
366{
367	if (entering(tcp)) {
368		printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
369		tprints(", ");
370		printitv(tcp, tcp->u_arg[1]);
371		tprints(", ");
372	} else {
373		if (syserror(tcp))
374			tprintf("%#lx", tcp->u_arg[2]);
375		else
376			printitv(tcp, tcp->u_arg[2]);
377	}
378	return 0;
379}
380
381#ifdef ALPHA
382int
383sys_osf_setitimer(struct tcb *tcp)
384{
385	if (entering(tcp)) {
386		printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
387		tprints(", ");
388		printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
389		tprints(", ");
390	} else {
391		if (syserror(tcp))
392			tprintf("%#lx", tcp->u_arg[2]);
393		else
394			printitv_bitness(tcp, tcp->u_arg[2], BITNESS_32);
395	}
396	return 0;
397}
398#endif
399
400#include "xlat/adjtimex_modes.h"
401#include "xlat/adjtimex_status.h"
402#include "xlat/adjtimex_state.h"
403
404#if SUPPORTED_PERSONALITIES > 1
405static int
406tprint_timex32(struct tcb *tcp, long addr)
407{
408	struct {
409		unsigned int modes;
410		int     offset;
411		int     freq;
412		int     maxerror;
413		int     esterror;
414		int     status;
415		int     constant;
416		int     precision;
417		int     tolerance;
418		struct timeval32 time;
419		int     tick;
420		int     ppsfreq;
421		int     jitter;
422		int     shift;
423		int     stabil;
424		int     jitcnt;
425		int     calcnt;
426		int     errcnt;
427		int     stbcnt;
428	} tx;
429
430	if (umove(tcp, addr, &tx) < 0)
431		return -1;
432
433	tprints("{modes=");
434	printflags(adjtimex_modes, tx.modes, "ADJ_???");
435	tprintf(", offset=%d, freq=%d, maxerror=%d, ",
436		tx.offset, tx.freq, tx.maxerror);
437	tprintf("esterror=%u, status=", tx.esterror);
438	printflags(adjtimex_status, tx.status, "STA_???");
439	tprintf(", constant=%d, precision=%u, ",
440		tx.constant, tx.precision);
441	tprintf("tolerance=%d, time=", tx.tolerance);
442	tprint_timeval32(tcp, &tx.time);
443	tprintf(", tick=%d, ppsfreq=%d, jitter=%d",
444		tx.tick, tx.ppsfreq, tx.jitter);
445	tprintf(", shift=%d, stabil=%d, jitcnt=%d",
446		tx.shift, tx.stabil, tx.jitcnt);
447	tprintf(", calcnt=%d, errcnt=%d, stbcnt=%d",
448		tx.calcnt, tx.errcnt, tx.stbcnt);
449	tprints("}");
450	return 0;
451}
452#endif /* SUPPORTED_PERSONALITIES > 1 */
453
454static int
455tprint_timex(struct tcb *tcp, long addr)
456{
457	struct timex tx;
458
459#if SUPPORTED_PERSONALITIES > 1
460	if (current_wordsize == 4)
461		return tprint_timex32(tcp, addr);
462#endif
463	if (umove(tcp, addr, &tx) < 0)
464		return -1;
465
466#if LINUX_VERSION_CODE < 66332
467	tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
468		tx.mode, tx.offset, tx.frequency);
469	tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
470		tx.maxerror, tx.esterror, tx.status);
471	tprintf("time_constant=%ld, precision=%lu, ",
472		tx.time_constant, tx.precision);
473	tprintf("tolerance=%ld, time=", tx.tolerance);
474	tprint_timeval(tcp, &tx.time);
475#else
476	tprints("{modes=");
477	printflags(adjtimex_modes, tx.modes, "ADJ_???");
478	tprintf(", offset=%ld, freq=%ld, maxerror=%ld, ",
479		(long) tx.offset, (long) tx.freq, (long) tx.maxerror);
480	tprintf("esterror=%lu, status=", (long) tx.esterror);
481	printflags(adjtimex_status, tx.status, "STA_???");
482	tprintf(", constant=%ld, precision=%lu, ",
483		(long) tx.constant, (long) tx.precision);
484	tprintf("tolerance=%ld, time=", (long) tx.tolerance);
485	tprint_timeval(tcp, &tx.time);
486	tprintf(", tick=%ld, ppsfreq=%ld, jitter=%ld",
487		(long) tx.tick, (long) tx.ppsfreq, (long) tx.jitter);
488	tprintf(", shift=%d, stabil=%ld, jitcnt=%ld",
489		tx.shift, (long) tx.stabil, (long) tx.jitcnt);
490	tprintf(", calcnt=%ld, errcnt=%ld, stbcnt=%ld",
491		(long) tx.calcnt, (long) tx.errcnt, (long) tx.stbcnt);
492#endif
493	tprints("}");
494	return 0;
495}
496
497static int
498do_adjtimex(struct tcb *tcp, long addr)
499{
500	if (addr == 0)
501		tprints("NULL");
502	else if (syserror(tcp) || !verbose(tcp))
503		tprintf("%#lx", addr);
504	else if (tprint_timex(tcp, addr) < 0)
505		tprints("{...}");
506	if (syserror(tcp))
507		return 0;
508	tcp->auxstr = xlookup(adjtimex_state, tcp->u_rval);
509	if (tcp->auxstr)
510		return RVAL_STR;
511	return 0;
512}
513
514int
515sys_adjtimex(struct tcb *tcp)
516{
517	if (exiting(tcp))
518		return do_adjtimex(tcp, tcp->u_arg[0]);
519	return 0;
520}
521
522#include "xlat/clockflags.h"
523#include "xlat/clocknames.h"
524
525static void
526printclockname(int clockid)
527{
528#ifdef CLOCKID_TO_FD
529# include "xlat/cpuclocknames.h"
530
531	if (clockid < 0) {
532		if ((clockid & CLOCKFD_MASK) == CLOCKFD)
533			tprintf("FD_TO_CLOCKID(%d)", CLOCKID_TO_FD(clockid));
534		else {
535			if(CPUCLOCK_PERTHREAD(clockid))
536				tprintf("MAKE_THREAD_CPUCLOCK(%d,", CPUCLOCK_PID(clockid));
537			else
538				tprintf("MAKE_PROCESS_CPUCLOCK(%d,", CPUCLOCK_PID(clockid));
539			printxval(cpuclocknames, clockid & CLOCKFD_MASK, "CPUCLOCK_???");
540			tprints(")");
541		}
542	}
543	else
544#endif
545		printxval(clocknames, clockid, "CLOCK_???");
546}
547
548int
549sys_clock_settime(struct tcb *tcp)
550{
551	if (entering(tcp)) {
552		printclockname(tcp->u_arg[0]);
553		tprints(", ");
554		printtv(tcp, tcp->u_arg[1]);
555	}
556	return 0;
557}
558
559int
560sys_clock_gettime(struct tcb *tcp)
561{
562	if (entering(tcp)) {
563		printclockname(tcp->u_arg[0]);
564		tprints(", ");
565	} else {
566		if (syserror(tcp))
567			tprintf("%#lx", tcp->u_arg[1]);
568		else
569			printtv(tcp, tcp->u_arg[1]);
570	}
571	return 0;
572}
573
574int
575sys_clock_nanosleep(struct tcb *tcp)
576{
577	if (entering(tcp)) {
578		printclockname(tcp->u_arg[0]);
579		tprints(", ");
580		printflags(clockflags, tcp->u_arg[1], "TIMER_???");
581		tprints(", ");
582		printtv(tcp, tcp->u_arg[2]);
583		tprints(", ");
584	} else {
585		if (syserror(tcp))
586			tprintf("%#lx", tcp->u_arg[3]);
587		else
588			printtv(tcp, tcp->u_arg[3]);
589	}
590	return 0;
591}
592
593int
594sys_clock_adjtime(struct tcb *tcp)
595{
596	if (exiting(tcp))
597		return do_adjtimex(tcp, tcp->u_arg[1]);
598	printclockname(tcp->u_arg[0]);
599	tprints(", ");
600	return 0;
601}
602
603#ifndef SIGEV_THREAD_ID
604# define SIGEV_THREAD_ID 4
605#endif
606#include "xlat/sigev_value.h"
607
608#if SUPPORTED_PERSONALITIES > 1
609static void
610printsigevent32(struct tcb *tcp, long arg)
611{
612	struct {
613		int     sigev_value;
614		int     sigev_signo;
615		int     sigev_notify;
616
617		union {
618			int     tid;
619			struct {
620				int     function, attribute;
621			} thread;
622		} un;
623	} sev;
624
625	if (umove(tcp, arg, &sev) < 0)
626		tprints("{...}");
627	else {
628		tprintf("{%#x, ", sev.sigev_value);
629		if (sev.sigev_notify == SIGEV_SIGNAL)
630			tprintf("%s, ", signame(sev.sigev_signo));
631		else
632			tprintf("%u, ", sev.sigev_signo);
633		printxval(sigev_value, sev.sigev_notify, "SIGEV_???");
634		tprints(", ");
635		if (sev.sigev_notify == SIGEV_THREAD_ID)
636			tprintf("{%d}", sev.un.tid);
637		else if (sev.sigev_notify == SIGEV_THREAD)
638			tprintf("{%#x, %#x}",
639				sev.un.thread.function,
640				sev.un.thread.attribute);
641		else
642			tprints("{...}");
643		tprints("}");
644	}
645}
646#endif
647
648void
649printsigevent(struct tcb *tcp, long arg)
650{
651	struct sigevent sev;
652
653#if SUPPORTED_PERSONALITIES > 1
654	if (current_wordsize == 4) {
655		printsigevent32(tcp, arg);
656		return;
657	}
658#endif
659	if (umove(tcp, arg, &sev) < 0)
660		tprints("{...}");
661	else {
662		tprintf("{%p, ", sev.sigev_value.sival_ptr);
663		if (sev.sigev_notify == SIGEV_SIGNAL)
664			tprintf("%s, ", signame(sev.sigev_signo));
665		else
666			tprintf("%u, ", sev.sigev_signo);
667		printxval(sigev_value, sev.sigev_notify, "SIGEV_???");
668		tprints(", ");
669		if (sev.sigev_notify == SIGEV_THREAD_ID)
670#if defined(HAVE_STRUCT_SIGEVENT__SIGEV_UN__PAD)
671			/* _pad[0] is the _tid field which might not be
672			   present in the userlevel definition of the
673			   struct.  */
674			tprintf("{%d}", sev._sigev_un._pad[0]);
675#elif defined(HAVE_STRUCT_SIGEVENT___PAD)
676			tprintf("{%d}", sev.__pad[0]);
677#else
678# warning unfamiliar struct sigevent => incomplete SIGEV_THREAD_ID decoding
679			tprints("{...}");
680#endif
681		else if (sev.sigev_notify == SIGEV_THREAD)
682			tprintf("{%p, %p}", sev.sigev_notify_function,
683				sev.sigev_notify_attributes);
684		else
685			tprints("{...}");
686		tprints("}");
687	}
688}
689
690int
691sys_timer_create(struct tcb *tcp)
692{
693	if (entering(tcp)) {
694		printclockname(tcp->u_arg[0]);
695		tprints(", ");
696		printsigevent(tcp, tcp->u_arg[1]);
697		tprints(", ");
698	} else {
699		int timer_id;
700
701		if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &timer_id) < 0)
702			tprintf("%#lx", tcp->u_arg[2]);
703		else
704			tprintf("{%d}", timer_id);
705	}
706	return 0;
707}
708
709int
710sys_timer_settime(struct tcb *tcp)
711{
712	if (entering(tcp)) {
713		tprintf("%#lx, ", tcp->u_arg[0]);
714		printflags(clockflags, tcp->u_arg[1], "TIMER_???");
715		tprints(", ");
716		printitv(tcp, tcp->u_arg[2]);
717		tprints(", ");
718	} else {
719		if (syserror(tcp))
720			tprintf("%#lx", tcp->u_arg[3]);
721		else
722			printitv(tcp, tcp->u_arg[3]);
723	}
724	return 0;
725}
726
727int
728sys_timer_gettime(struct tcb *tcp)
729{
730	if (entering(tcp)) {
731		tprintf("%#lx, ", tcp->u_arg[0]);
732	} else {
733		if (syserror(tcp))
734			tprintf("%#lx", tcp->u_arg[1]);
735		else
736			printitv(tcp, tcp->u_arg[1]);
737	}
738	return 0;
739}
740
741static void
742print_rtc(struct tcb *tcp, const struct rtc_time *rt)
743{
744	tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
745		"tm_mday=%d, tm_mon=%d, tm_year=%d, ",
746		rt->tm_sec, rt->tm_min, rt->tm_hour,
747		rt->tm_mday, rt->tm_mon, rt->tm_year);
748	if (!abbrev(tcp))
749		tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
750			rt->tm_wday, rt->tm_yday, rt->tm_isdst);
751	else
752		tprints("...}");
753}
754
755int
756rtc_ioctl(struct tcb *tcp, long code, long arg)
757{
758	switch (code) {
759	case RTC_ALM_SET:
760	case RTC_SET_TIME:
761		if (entering(tcp)) {
762			struct rtc_time rt;
763			if (umove(tcp, arg, &rt) < 0)
764				tprintf(", %#lx", arg);
765			else {
766				tprints(", ");
767				print_rtc(tcp, &rt);
768			}
769		}
770		break;
771	case RTC_ALM_READ:
772	case RTC_RD_TIME:
773		if (exiting(tcp)) {
774			struct rtc_time rt;
775			if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
776				tprintf(", %#lx", arg);
777			else {
778				tprints(", ");
779				print_rtc(tcp, &rt);
780			}
781		}
782		break;
783	case RTC_IRQP_SET:
784	case RTC_EPOCH_SET:
785		if (entering(tcp))
786			tprintf(", %lu", arg);
787		break;
788	case RTC_IRQP_READ:
789	case RTC_EPOCH_READ:
790		if (exiting(tcp))
791			tprintf(", %lu", arg);
792		break;
793	case RTC_WKALM_SET:
794		if (entering(tcp)) {
795			struct rtc_wkalrm wk;
796			if (umove(tcp, arg, &wk) < 0)
797				tprintf(", %#lx", arg);
798			else {
799				tprintf(", {enabled=%d, pending=%d, ",
800					wk.enabled, wk.pending);
801				print_rtc(tcp, &wk.time);
802				tprints("}");
803			}
804		}
805		break;
806	case RTC_WKALM_RD:
807		if (exiting(tcp)) {
808			struct rtc_wkalrm wk;
809			if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
810				tprintf(", %#lx", arg);
811			else {
812				tprintf(", {enabled=%d, pending=%d, ",
813					wk.enabled, wk.pending);
814				print_rtc(tcp, &wk.time);
815				tprints("}");
816			}
817		}
818		break;
819	default:
820		if (entering(tcp))
821			tprintf(", %#lx", arg);
822		break;
823	}
824	return 1;
825}
826
827#ifndef TFD_TIMER_ABSTIME
828#define TFD_TIMER_ABSTIME (1 << 0)
829#endif
830
831#include "xlat/timerfdflags.h"
832
833int
834sys_timerfd(struct tcb *tcp)
835{
836	if (entering(tcp)) {
837		/* It does not matter that the kernel uses itimerspec.  */
838		tprintf("%ld, ", tcp->u_arg[0]);
839		printclockname(tcp->u_arg[0]);
840		tprints(", ");
841		printflags(timerfdflags, tcp->u_arg[2], "TFD_???");
842		tprints(", ");
843		printitv(tcp, tcp->u_arg[3]);
844	}
845	return 0;
846}
847
848int
849sys_timerfd_create(struct tcb *tcp)
850{
851	if (entering(tcp)) {
852		printclockname(tcp->u_arg[0]);
853		tprints(", ");
854		printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
855	}
856	return 0;
857}
858
859int
860sys_timerfd_settime(struct tcb *tcp)
861{
862	if (entering(tcp)) {
863		printfd(tcp, tcp->u_arg[0]);
864		tprints(", ");
865		printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
866		tprints(", ");
867		printitv(tcp, tcp->u_arg[2]);
868		tprints(", ");
869		printitv(tcp, tcp->u_arg[3]);
870	}
871	return 0;
872}
873
874int
875sys_timerfd_gettime(struct tcb *tcp)
876{
877	if (entering(tcp)) {
878		printfd(tcp, tcp->u_arg[0]);
879		tprints(", ");
880		printitv(tcp, tcp->u_arg[1]);
881	}
882	return 0;
883}
884