fix broken time64 clock_adjtime
[oweals/musl.git] / src / linux / clock_adjtime.c
1 #include <sys/timex.h>
2 #include <time.h>
3 #include <errno.h>
4 #include "syscall.h"
5
6 #define IS32BIT(x) !((x)+0x80000000ULL>>32)
7
8 struct ktimex64 {
9         unsigned modes;
10         int :32;
11         long long offset, freq, maxerror, esterror;
12         int status;
13         int :32;
14         long long constant, precision, tolerance;
15         long long time_sec, time_usec;
16         long long tick, ppsfreq, jitter;
17         int shift;
18         int :32;
19         long long stabil, jitcnt, calcnt, errcnt, stbcnt;
20         int tai;
21         int __padding[11];
22 };
23
24 struct ktimex {
25         unsigned modes;
26         long offset, freq, maxerror, esterror;
27         int status;
28         long constant, precision, tolerance;
29         long time_sec, time_usec;
30         long tick, ppsfreq, jitter;
31         int shift;
32         long stabil, jitcnt, calcnt, errcnt, stbcnt;
33         int tai;
34         int __padding[11];
35 };
36
37 int clock_adjtime (clockid_t clock_id, struct timex *utx)
38 {
39         int r = -ENOSYS;
40 #ifdef SYS_clock_adjtime64
41         if (SYS_clock_adjtime == SYS_clock_adjtime64 ||
42             (utx->modes & ADJ_SETOFFSET) && !IS32BIT(utx->time.tv_sec)) {
43                 struct ktimex64 ktx = {
44                         .modes = utx->modes,
45                         .offset = utx->offset,
46                         .freq = utx->freq,
47                         .maxerror = utx->maxerror,
48                         .esterror = utx->esterror,
49                         .status = utx->status,
50                         .constant = utx->constant,
51                         .precision = utx->precision,
52                         .tolerance = utx->tolerance,
53                         .time_sec = utx->time.tv_sec,
54                         .time_usec = utx->time.tv_usec,
55                         .tick = utx->tick,
56                         .ppsfreq = utx->ppsfreq,
57                         .jitter = utx->jitter,
58                         .shift = utx->shift,
59                         .stabil = utx->stabil,
60                         .jitcnt = utx->jitcnt,
61                         .calcnt = utx->calcnt,
62                         .errcnt = utx->errcnt,
63                         .stbcnt = utx->stbcnt,
64                         .tai = utx->tai,
65                 };
66                 r = __syscall(SYS_clock_adjtime64, clock_id, &ktx);
67                 if (r>=0) {
68                         utx->modes = ktx.modes;
69                         utx->offset = ktx.offset;
70                         utx->freq = ktx.freq;
71                         utx->maxerror = ktx.maxerror;
72                         utx->esterror = ktx.esterror;
73                         utx->status = ktx.status;
74                         utx->constant = ktx.constant;
75                         utx->precision = ktx.precision;
76                         utx->tolerance = ktx.tolerance;
77                         utx->time.tv_sec = ktx.time_sec;
78                         utx->time.tv_usec = ktx.time_usec;
79                         utx->tick = ktx.tick;
80                         utx->ppsfreq = ktx.ppsfreq;
81                         utx->jitter = ktx.jitter;
82                         utx->shift = ktx.shift;
83                         utx->stabil = ktx.stabil;
84                         utx->jitcnt = ktx.jitcnt;
85                         utx->calcnt = ktx.calcnt;
86                         utx->errcnt = ktx.errcnt;
87                         utx->stbcnt = ktx.stbcnt;
88                         utx->tai = ktx.tai;
89                 }
90         }
91         if (SYS_clock_adjtime == SYS_clock_adjtime64 || r!=-ENOSYS)
92                 return __syscall_ret(r);
93         if ((utx->modes & ADJ_SETOFFSET) && !IS32BIT(utx->time.tv_sec))
94                 return __syscall_ret(-ENOTSUP);
95 #endif
96         if (sizeof(time_t) > sizeof(long)) {
97                 struct ktimex ktx = {
98                         .modes = utx->modes,
99                         .offset = utx->offset,
100                         .freq = utx->freq,
101                         .maxerror = utx->maxerror,
102                         .esterror = utx->esterror,
103                         .status = utx->status,
104                         .constant = utx->constant,
105                         .precision = utx->precision,
106                         .tolerance = utx->tolerance,
107                         .time_sec = utx->time.tv_sec,
108                         .time_usec = utx->time.tv_usec,
109                         .tick = utx->tick,
110                         .ppsfreq = utx->ppsfreq,
111                         .jitter = utx->jitter,
112                         .shift = utx->shift,
113                         .stabil = utx->stabil,
114                         .jitcnt = utx->jitcnt,
115                         .calcnt = utx->calcnt,
116                         .errcnt = utx->errcnt,
117                         .stbcnt = utx->stbcnt,
118                         .tai = utx->tai,
119                 };
120 #ifdef SYS_adjtimex
121                 if (clock_id==CLOCK_REALTIME) r = __syscall(SYS_adjtimex, &ktx);
122                 else
123 #endif
124                 r = __syscall(SYS_clock_adjtime, clock_id, &ktx);
125                 if (r>=0) {
126                         utx->modes = ktx.modes;
127                         utx->offset = ktx.offset;
128                         utx->freq = ktx.freq;
129                         utx->maxerror = ktx.maxerror;
130                         utx->esterror = ktx.esterror;
131                         utx->status = ktx.status;
132                         utx->constant = ktx.constant;
133                         utx->precision = ktx.precision;
134                         utx->tolerance = ktx.tolerance;
135                         utx->time.tv_sec = ktx.time_sec;
136                         utx->time.tv_usec = ktx.time_usec;
137                         utx->tick = ktx.tick;
138                         utx->ppsfreq = ktx.ppsfreq;
139                         utx->jitter = ktx.jitter;
140                         utx->shift = ktx.shift;
141                         utx->stabil = ktx.stabil;
142                         utx->jitcnt = ktx.jitcnt;
143                         utx->calcnt = ktx.calcnt;
144                         utx->errcnt = ktx.errcnt;
145                         utx->stbcnt = ktx.stbcnt;
146                         utx->tai = ktx.tai;
147                 }
148                 return __syscall_ret(r);
149         }
150 #ifdef SYS_adjtimex
151         if (clock_id==CLOCK_REALTIME) return syscall(SYS_adjtimex, utx);
152 #endif
153         return syscall(SYS_clock_adjtime, clock_id, utx);
154 }