]> granicus.if.org Git - strace/blob - time.c
Generate xlat/*.in files
[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 <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
43 struct timeval32
44 {
45         u_int32_t tv_sec, tv_usec;
46 };
47
48 static void
49 tprint_timeval32(struct tcb *tcp, const struct timeval32 *tv)
50 {
51         tprintf("{%u, %u}", tv->tv_sec, tv->tv_usec);
52 }
53
54 static void
55 tprint_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
61 void
62 printtv_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
69 char *
70 sprinttv(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
119 void
120 print_timespec(struct tcb *tcp, long addr)
121 {
122         char buf[TIMESPEC_TEXT_BUFSIZE];
123         sprint_timespec(buf, tcp, addr);
124         tprints(buf);
125 }
126
127 void
128 sprint_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
161 int
162 sys_time(struct tcb *tcp)
163 {
164         if (exiting(tcp)) {
165                 printnum(tcp, tcp->u_arg[0], "%ld");
166         }
167         return 0;
168 }
169
170 int
171 sys_stime(struct tcb *tcp)
172 {
173         if (exiting(tcp)) {
174                 printnum(tcp, tcp->u_arg[0], "%ld");
175         }
176         return 0;
177 }
178
179 int
180 sys_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
196 int
197 sys_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
212 int
213 sys_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
224 int
225 sys_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
236 int
237 sys_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
251 int
252 sys_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
284 static void
285 printitv_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
332 int
333 sys_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
348 int
349 sys_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
364 int
365 sys_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
382 int
383 sys_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
402 #include "xlat/adjtimex_status.h"
403
404 #include "xlat/adjtimex_state.h"
405
406 #if SUPPORTED_PERSONALITIES > 1
407 static int
408 tprint_timex32(struct tcb *tcp, long addr)
409 {
410         struct {
411                 unsigned int modes;
412                 int     offset;
413                 int     freq;
414                 int     maxerror;
415                 int     esterror;
416                 int     status;
417                 int     constant;
418                 int     precision;
419                 int     tolerance;
420                 struct timeval32 time;
421                 int     tick;
422                 int     ppsfreq;
423                 int     jitter;
424                 int     shift;
425                 int     stabil;
426                 int     jitcnt;
427                 int     calcnt;
428                 int     errcnt;
429                 int     stbcnt;
430         } tx;
431
432         if (umove(tcp, addr, &tx) < 0)
433                 return -1;
434
435         tprints("{modes=");
436         printflags(adjtimex_modes, tx.modes, "ADJ_???");
437         tprintf(", offset=%d, freq=%d, maxerror=%d, ",
438                 tx.offset, tx.freq, tx.maxerror);
439         tprintf("esterror=%u, status=", tx.esterror);
440         printflags(adjtimex_status, tx.status, "STA_???");
441         tprintf(", constant=%d, precision=%u, ",
442                 tx.constant, tx.precision);
443         tprintf("tolerance=%d, time=", tx.tolerance);
444         tprint_timeval32(tcp, &tx.time);
445         tprintf(", tick=%d, ppsfreq=%d, jitter=%d",
446                 tx.tick, tx.ppsfreq, tx.jitter);
447         tprintf(", shift=%d, stabil=%d, jitcnt=%d",
448                 tx.shift, tx.stabil, tx.jitcnt);
449         tprintf(", calcnt=%d, errcnt=%d, stbcnt=%d",
450                 tx.calcnt, tx.errcnt, tx.stbcnt);
451         tprints("}");
452         return 0;
453 }
454 #endif /* SUPPORTED_PERSONALITIES > 1 */
455
456 static int
457 tprint_timex(struct tcb *tcp, long addr)
458 {
459         struct timex tx;
460
461 #if SUPPORTED_PERSONALITIES > 1
462         if (current_wordsize == 4)
463                 return tprint_timex32(tcp, addr);
464 #endif
465         if (umove(tcp, addr, &tx) < 0)
466                 return -1;
467
468 #if LINUX_VERSION_CODE < 66332
469         tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
470                 tx.mode, tx.offset, tx.frequency);
471         tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
472                 tx.maxerror, tx.esterror, tx.status);
473         tprintf("time_constant=%ld, precision=%lu, ",
474                 tx.time_constant, tx.precision);
475         tprintf("tolerance=%ld, time=", tx.tolerance);
476         tprint_timeval(tcp, &tx.time);
477 #else
478         tprints("{modes=");
479         printflags(adjtimex_modes, tx.modes, "ADJ_???");
480         tprintf(", offset=%ld, freq=%ld, maxerror=%ld, ",
481                 (long) tx.offset, (long) tx.freq, (long) tx.maxerror);
482         tprintf("esterror=%lu, status=", (long) tx.esterror);
483         printflags(adjtimex_status, tx.status, "STA_???");
484         tprintf(", constant=%ld, precision=%lu, ",
485                 (long) tx.constant, (long) tx.precision);
486         tprintf("tolerance=%ld, time=", (long) tx.tolerance);
487         tprint_timeval(tcp, &tx.time);
488         tprintf(", tick=%ld, ppsfreq=%ld, jitter=%ld",
489                 (long) tx.tick, (long) tx.ppsfreq, (long) tx.jitter);
490         tprintf(", shift=%d, stabil=%ld, jitcnt=%ld",
491                 tx.shift, (long) tx.stabil, (long) tx.jitcnt);
492         tprintf(", calcnt=%ld, errcnt=%ld, stbcnt=%ld",
493                 (long) tx.calcnt, (long) tx.errcnt, (long) tx.stbcnt);
494 #endif
495         tprints("}");
496         return 0;
497 }
498
499 static int
500 do_adjtimex(struct tcb *tcp, long addr)
501 {
502         if (addr == 0)
503                 tprints("NULL");
504         else if (syserror(tcp) || !verbose(tcp))
505                 tprintf("%#lx", addr);
506         else if (tprint_timex(tcp, addr) < 0)
507                 tprints("{...}");
508         if (syserror(tcp))
509                 return 0;
510         tcp->auxstr = xlookup(adjtimex_state, tcp->u_rval);
511         if (tcp->auxstr)
512                 return RVAL_STR;
513         return 0;
514 }
515
516 int
517 sys_adjtimex(struct tcb *tcp)
518 {
519         if (exiting(tcp))
520                 return do_adjtimex(tcp, tcp->u_arg[0]);
521         return 0;
522 }
523
524 #include "xlat/clockflags.h"
525
526 #include "xlat/clocknames.h"
527
528 #ifdef CLOCKID_TO_FD
529 #include "xlat/cpuclocknames.h"
530 #endif
531
532 static void
533 printclockname(int clockid)
534 {
535 #ifdef CLOCKID_TO_FD
536         if (clockid < 0) {
537                 if ((clockid & CLOCKFD_MASK) == CLOCKFD)
538                         tprintf("FD_TO_CLOCKID(%d)", CLOCKID_TO_FD(clockid));
539                 else {
540                         if(CPUCLOCK_PERTHREAD(clockid))
541                                 tprintf("MAKE_THREAD_CPUCLOCK(%d,", CPUCLOCK_PID(clockid));
542                         else
543                                 tprintf("MAKE_PROCESS_CPUCLOCK(%d,", CPUCLOCK_PID(clockid));
544                         printxval(cpuclocknames, clockid & CLOCKFD_MASK, "CPUCLOCK_???");
545                         tprints(")");
546                 }
547         }
548         else
549 #endif
550                 printxval(clocknames, clockid, "CLOCK_???");
551 }
552
553 int
554 sys_clock_settime(struct tcb *tcp)
555 {
556         if (entering(tcp)) {
557                 printclockname(tcp->u_arg[0]);
558                 tprints(", ");
559                 printtv(tcp, tcp->u_arg[1]);
560         }
561         return 0;
562 }
563
564 int
565 sys_clock_gettime(struct tcb *tcp)
566 {
567         if (entering(tcp)) {
568                 printclockname(tcp->u_arg[0]);
569                 tprints(", ");
570         } else {
571                 if (syserror(tcp))
572                         tprintf("%#lx", tcp->u_arg[1]);
573                 else
574                         printtv(tcp, tcp->u_arg[1]);
575         }
576         return 0;
577 }
578
579 int
580 sys_clock_nanosleep(struct tcb *tcp)
581 {
582         if (entering(tcp)) {
583                 printclockname(tcp->u_arg[0]);
584                 tprints(", ");
585                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
586                 tprints(", ");
587                 printtv(tcp, tcp->u_arg[2]);
588                 tprints(", ");
589         } else {
590                 if (syserror(tcp))
591                         tprintf("%#lx", tcp->u_arg[3]);
592                 else
593                         printtv(tcp, tcp->u_arg[3]);
594         }
595         return 0;
596 }
597
598 int
599 sys_clock_adjtime(struct tcb *tcp)
600 {
601         if (exiting(tcp))
602                 return do_adjtimex(tcp, tcp->u_arg[1]);
603         printclockname(tcp->u_arg[0]);
604         tprints(", ");
605         return 0;
606 }
607
608 #ifndef SIGEV_THREAD_ID
609 # define SIGEV_THREAD_ID 4
610 #endif
611 #include "xlat/sigev_value.h"
612
613 #if SUPPORTED_PERSONALITIES > 1
614 static void
615 printsigevent32(struct tcb *tcp, long arg)
616 {
617         struct {
618                 int     sigev_value;
619                 int     sigev_signo;
620                 int     sigev_notify;
621
622                 union {
623                         int     tid;
624                         struct {
625                                 int     function, attribute;
626                         } thread;
627                 } un;
628         } sev;
629
630         if (umove(tcp, arg, &sev) < 0)
631                 tprints("{...}");
632         else {
633                 tprintf("{%#x, ", sev.sigev_value);
634                 if (sev.sigev_notify == SIGEV_SIGNAL)
635                         tprintf("%s, ", signame(sev.sigev_signo));
636                 else
637                         tprintf("%u, ", sev.sigev_signo);
638                 printxval(sigev_value, sev.sigev_notify, "SIGEV_???");
639                 tprints(", ");
640                 if (sev.sigev_notify == SIGEV_THREAD_ID)
641                         tprintf("{%d}", sev.un.tid);
642                 else if (sev.sigev_notify == SIGEV_THREAD)
643                         tprintf("{%#x, %#x}",
644                                 sev.un.thread.function,
645                                 sev.un.thread.attribute);
646                 else
647                         tprints("{...}");
648                 tprints("}");
649         }
650 }
651 #endif
652
653 void
654 printsigevent(struct tcb *tcp, long arg)
655 {
656         struct sigevent sev;
657
658 #if SUPPORTED_PERSONALITIES > 1
659         if (current_wordsize == 4) {
660                 printsigevent32(tcp, arg);
661                 return;
662         }
663 #endif
664         if (umove(tcp, arg, &sev) < 0)
665                 tprints("{...}");
666         else {
667                 tprintf("{%p, ", sev.sigev_value.sival_ptr);
668                 if (sev.sigev_notify == SIGEV_SIGNAL)
669                         tprintf("%s, ", signame(sev.sigev_signo));
670                 else
671                         tprintf("%u, ", sev.sigev_signo);
672                 printxval(sigev_value, sev.sigev_notify, "SIGEV_???");
673                 tprints(", ");
674                 if (sev.sigev_notify == SIGEV_THREAD_ID)
675 #if defined(HAVE_STRUCT_SIGEVENT__SIGEV_UN__PAD)
676                         /* _pad[0] is the _tid field which might not be
677                            present in the userlevel definition of the
678                            struct.  */
679                         tprintf("{%d}", sev._sigev_un._pad[0]);
680 #elif defined(HAVE_STRUCT_SIGEVENT___PAD)
681                         tprintf("{%d}", sev.__pad[0]);
682 #else
683 # warning unfamiliar struct sigevent => incomplete SIGEV_THREAD_ID decoding
684                         tprints("{...}");
685 #endif
686                 else if (sev.sigev_notify == SIGEV_THREAD)
687                         tprintf("{%p, %p}", sev.sigev_notify_function,
688                                 sev.sigev_notify_attributes);
689                 else
690                         tprints("{...}");
691                 tprints("}");
692         }
693 }
694
695 int
696 sys_timer_create(struct tcb *tcp)
697 {
698         if (entering(tcp)) {
699                 printclockname(tcp->u_arg[0]);
700                 tprints(", ");
701                 printsigevent(tcp, tcp->u_arg[1]);
702                 tprints(", ");
703         } else {
704                 int timer_id;
705
706                 if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &timer_id) < 0)
707                         tprintf("%#lx", tcp->u_arg[2]);
708                 else
709                         tprintf("{%d}", timer_id);
710         }
711         return 0;
712 }
713
714 int
715 sys_timer_settime(struct tcb *tcp)
716 {
717         if (entering(tcp)) {
718                 tprintf("%#lx, ", tcp->u_arg[0]);
719                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
720                 tprints(", ");
721                 printitv(tcp, tcp->u_arg[2]);
722                 tprints(", ");
723         } else {
724                 if (syserror(tcp))
725                         tprintf("%#lx", tcp->u_arg[3]);
726                 else
727                         printitv(tcp, tcp->u_arg[3]);
728         }
729         return 0;
730 }
731
732 int
733 sys_timer_gettime(struct tcb *tcp)
734 {
735         if (entering(tcp)) {
736                 tprintf("%#lx, ", tcp->u_arg[0]);
737         } else {
738                 if (syserror(tcp))
739                         tprintf("%#lx", tcp->u_arg[1]);
740                 else
741                         printitv(tcp, tcp->u_arg[1]);
742         }
743         return 0;
744 }
745
746 static void
747 print_rtc(struct tcb *tcp, const struct rtc_time *rt)
748 {
749         tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
750                 "tm_mday=%d, tm_mon=%d, tm_year=%d, ",
751                 rt->tm_sec, rt->tm_min, rt->tm_hour,
752                 rt->tm_mday, rt->tm_mon, rt->tm_year);
753         if (!abbrev(tcp))
754                 tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
755                         rt->tm_wday, rt->tm_yday, rt->tm_isdst);
756         else
757                 tprints("...}");
758 }
759
760 int
761 rtc_ioctl(struct tcb *tcp, long code, long arg)
762 {
763         switch (code) {
764         case RTC_ALM_SET:
765         case RTC_SET_TIME:
766                 if (entering(tcp)) {
767                         struct rtc_time rt;
768                         if (umove(tcp, arg, &rt) < 0)
769                                 tprintf(", %#lx", arg);
770                         else {
771                                 tprints(", ");
772                                 print_rtc(tcp, &rt);
773                         }
774                 }
775                 break;
776         case RTC_ALM_READ:
777         case RTC_RD_TIME:
778                 if (exiting(tcp)) {
779                         struct rtc_time rt;
780                         if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
781                                 tprintf(", %#lx", arg);
782                         else {
783                                 tprints(", ");
784                                 print_rtc(tcp, &rt);
785                         }
786                 }
787                 break;
788         case RTC_IRQP_SET:
789         case RTC_EPOCH_SET:
790                 if (entering(tcp))
791                         tprintf(", %lu", arg);
792                 break;
793         case RTC_IRQP_READ:
794         case RTC_EPOCH_READ:
795                 if (exiting(tcp))
796                         tprintf(", %lu", arg);
797                 break;
798         case RTC_WKALM_SET:
799                 if (entering(tcp)) {
800                         struct rtc_wkalrm wk;
801                         if (umove(tcp, arg, &wk) < 0)
802                                 tprintf(", %#lx", arg);
803                         else {
804                                 tprintf(", {enabled=%d, pending=%d, ",
805                                         wk.enabled, wk.pending);
806                                 print_rtc(tcp, &wk.time);
807                                 tprints("}");
808                         }
809                 }
810                 break;
811         case RTC_WKALM_RD:
812                 if (exiting(tcp)) {
813                         struct rtc_wkalrm wk;
814                         if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
815                                 tprintf(", %#lx", arg);
816                         else {
817                                 tprintf(", {enabled=%d, pending=%d, ",
818                                         wk.enabled, wk.pending);
819                                 print_rtc(tcp, &wk.time);
820                                 tprints("}");
821                         }
822                 }
823                 break;
824         default:
825                 if (entering(tcp))
826                         tprintf(", %#lx", arg);
827                 break;
828         }
829         return 1;
830 }
831
832 #ifndef TFD_TIMER_ABSTIME
833 #define TFD_TIMER_ABSTIME (1 << 0)
834 #endif
835
836 #include "xlat/timerfdflags.h"
837
838 int
839 sys_timerfd(struct tcb *tcp)
840 {
841         if (entering(tcp)) {
842                 /* It does not matter that the kernel uses itimerspec.  */
843                 tprintf("%ld, ", tcp->u_arg[0]);
844                 printclockname(tcp->u_arg[0]);
845                 tprints(", ");
846                 printflags(timerfdflags, tcp->u_arg[2], "TFD_???");
847                 tprints(", ");
848                 printitv(tcp, tcp->u_arg[3]);
849         }
850         return 0;
851 }
852
853 int
854 sys_timerfd_create(struct tcb *tcp)
855 {
856         if (entering(tcp)) {
857                 printclockname(tcp->u_arg[0]);
858                 tprints(", ");
859                 printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
860         }
861         return 0;
862 }
863
864 int
865 sys_timerfd_settime(struct tcb *tcp)
866 {
867         if (entering(tcp)) {
868                 printfd(tcp, tcp->u_arg[0]);
869                 tprints(", ");
870                 printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
871                 tprints(", ");
872                 printitv(tcp, tcp->u_arg[2]);
873                 tprints(", ");
874                 printitv(tcp, tcp->u_arg[3]);
875         }
876         return 0;
877 }
878
879 int
880 sys_timerfd_gettime(struct tcb *tcp)
881 {
882         if (entering(tcp)) {
883                 printfd(tcp, tcp->u_arg[0]);
884                 tprints(", ");
885                 printitv(tcp, tcp->u_arg[1]);
886         }
887         return 0;
888 }