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