1 /*
2  * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "defs.h"
29 
30 #include DEF_MPERS_TYPE(time_t)
31 #include DEF_MPERS_TYPE(timespec_t)
32 #include DEF_MPERS_TYPE(timeval_t)
33 
34 typedef struct timespec timespec_t;
35 typedef struct timeval timeval_t;
36 
37 #include MPERS_DEFS
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 static const char time_fmt[] = "{%jd, %jd}";
47 
48 static void
print_timespec_t(const timespec_t * t)49 print_timespec_t(const timespec_t *t)
50 {
51 	tprintf(time_fmt, (intmax_t) t->tv_sec, (intmax_t) t->tv_nsec);
52 }
53 
54 static void
print_timespec_t_utime(const timespec_t * t)55 print_timespec_t_utime(const timespec_t *t)
56 {
57 	switch (t->tv_nsec) {
58 	case UTIME_NOW:
59 		tprints("UTIME_NOW");
60 		break;
61 	case UTIME_OMIT:
62 		tprints("UTIME_OMIT");
63 		break;
64 	default:
65 		print_timespec_t(t);
66 		break;
67 	}
68 }
69 
70 static void
print_timeval_t(const timeval_t * t)71 print_timeval_t(const timeval_t *t)
72 {
73 	tprintf(time_fmt, (intmax_t) t->tv_sec, (intmax_t) t->tv_usec);
74 }
75 
MPERS_PRINTER_DECL(void,print_timespec)76 MPERS_PRINTER_DECL(void, print_timespec)(struct tcb *tcp, const long addr)
77 {
78 	timespec_t t;
79 
80 	if (umove_or_printaddr(tcp, addr, &t))
81 		return;
82 
83 	print_timespec_t(&t);
84 }
85 
MPERS_PRINTER_DECL(const char *,sprint_timespec)86 MPERS_PRINTER_DECL(const char *, sprint_timespec)(struct tcb *tcp, const long addr)
87 {
88 	timespec_t t;
89 	static char buf[sizeof(time_fmt) + 3 * sizeof(t)];
90 
91 	if (!addr) {
92 		strcpy(buf, "NULL");
93 	} else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
94 		   umove(tcp, addr, &t)) {
95 		snprintf(buf, sizeof(buf), "%#lx", addr);
96 	} else {
97 		snprintf(buf, sizeof(buf), time_fmt,
98 			 (intmax_t) t.tv_sec, (intmax_t) t.tv_nsec);
99 	}
100 
101 	return buf;
102 }
103 
MPERS_PRINTER_DECL(void,print_timespec_utime_pair)104 MPERS_PRINTER_DECL(void, print_timespec_utime_pair)(struct tcb *tcp, const long addr)
105 {
106 	timespec_t t[2];
107 
108 	if (umove_or_printaddr(tcp, addr, &t))
109 		return;
110 
111 	tprints("[");
112 	print_timespec_t_utime(&t[0]);
113 	tprints(", ");
114 	print_timespec_t_utime(&t[1]);
115 	tprints("]");
116 }
117 
MPERS_PRINTER_DECL(void,print_itimerspec)118 MPERS_PRINTER_DECL(void, print_itimerspec)(struct tcb *tcp, const long addr)
119 {
120 	timespec_t t[2];
121 
122 	if (umove_or_printaddr(tcp, addr, &t))
123 		return;
124 
125 	tprints("{it_interval=");
126 	print_timespec_t(&t[0]);
127 	tprints(", it_value=");
128 	print_timespec_t(&t[1]);
129 	tprints("}");
130 }
131 
MPERS_PRINTER_DECL(void,print_timeval)132 MPERS_PRINTER_DECL(void, print_timeval)(struct tcb *tcp, const long addr)
133 {
134 	timeval_t t;
135 
136 	if (umove_or_printaddr(tcp, addr, &t))
137 		return;
138 
139 	print_timeval_t(&t);
140 }
141 
MPERS_PRINTER_DECL(void,print_timeval_pair)142 MPERS_PRINTER_DECL(void, print_timeval_pair)(struct tcb *tcp, const long addr)
143 {
144 	timeval_t t[2];
145 
146 	if (umove_or_printaddr(tcp, addr, &t))
147 		return;
148 
149 	tprints("[");
150 	print_timeval_t(&t[0]);
151 	tprints(", ");
152 	print_timeval_t(&t[1]);
153 	tprints("]");
154 }
155 
MPERS_PRINTER_DECL(const char *,sprint_timeval)156 MPERS_PRINTER_DECL(const char *, sprint_timeval)(struct tcb *tcp, const long addr)
157 {
158 	timeval_t t;
159 	static char buf[sizeof(time_fmt) + 3 * sizeof(t)];
160 
161 	if (!addr) {
162 		strcpy(buf, "NULL");
163 	} else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
164 		   umove(tcp, addr, &t)) {
165 		snprintf(buf, sizeof(buf), "%#lx", addr);
166 	} else {
167 		snprintf(buf, sizeof(buf), time_fmt,
168 			 (intmax_t) t.tv_sec, (intmax_t) t.tv_usec);
169 	}
170 
171 	return buf;
172 }
173 
MPERS_PRINTER_DECL(void,print_itimerval)174 MPERS_PRINTER_DECL(void, print_itimerval)(struct tcb *tcp, const long addr)
175 {
176 	timeval_t t[2];
177 
178 	if (umove_or_printaddr(tcp, addr, &t))
179 		return;
180 
181 	tprints("{it_interval=");
182 	print_timeval_t(&t[0]);
183 	tprints(", it_value=");
184 	print_timeval_t(&t[1]);
185 	tprints("}");
186 }
187 
SYS_FUNC(time)188 SYS_FUNC(time)
189 {
190 	if (exiting(tcp)) {
191 		time_t t;
192 
193 		if (!umove_or_printaddr(tcp, tcp->u_arg[0], &t))
194 			tprintf("[%jd]", (intmax_t) t);
195 	}
196 
197 	return 0;
198 }
199 
200 #ifdef ALPHA
201 
202 typedef struct {
203 	int tv_sec, tv_usec;
204 } timeval32_t;
205 
206 static void
print_timeval32_t(const timeval32_t * t)207 print_timeval32_t(const timeval32_t *t)
208 {
209 	tprintf(time_fmt, (intmax_t) t->tv_sec, (intmax_t) t->tv_usec);
210 }
211 
212 void
print_timeval32(struct tcb * tcp,const long addr)213 print_timeval32(struct tcb *tcp, const long addr)
214 {
215 	timeval32_t t;
216 
217 	if (umove_or_printaddr(tcp, addr, &t))
218 		return;
219 
220 	print_timeval32_t(&t);
221 }
222 
223 void
print_timeval32_pair(struct tcb * tcp,const long addr)224 print_timeval32_pair(struct tcb *tcp, const long addr)
225 {
226 	timeval32_t t[2];
227 
228 	if (umove_or_printaddr(tcp, addr, &t))
229 		return;
230 
231 	tprints("[");
232 	print_timeval32_t(&t[0]);
233 	tprints(", ");
234 	print_timeval32_t(&t[1]);
235 	tprints("]");
236 }
237 
238 void
print_itimerval32(struct tcb * tcp,const long addr)239 print_itimerval32(struct tcb *tcp, const long addr)
240 {
241 	timeval32_t t[2];
242 
243 	if (umove_or_printaddr(tcp, addr, &t))
244 		return;
245 
246 	tprints("{it_interval=");
247 	print_timeval32_t(&t[0]);
248 	tprints(", it_value=");
249 	print_timeval32_t(&t[1]);
250 	tprints("}");
251 }
252 
253 const char *
sprint_timeval32(struct tcb * tcp,const long addr)254 sprint_timeval32(struct tcb *tcp, const long addr)
255 {
256 	timeval32_t t;
257 	static char buf[sizeof(time_fmt) + 3 * sizeof(t)];
258 
259 	if (!addr) {
260 		strcpy(buf, "NULL");
261 	} else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
262 		   umove(tcp, addr, &t)) {
263 		snprintf(buf, sizeof(buf), "%#lx", addr);
264 	} else {
265 		snprintf(buf, sizeof(buf), time_fmt,
266 			 (intmax_t) t.tv_sec, (intmax_t) t.tv_usec);
267 	}
268 
269 	return buf;
270 }
271 
272 #endif /* ALPHA */
273