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