]> granicus.if.org Git - strace/blob - util.c
tests: check decoding of netlink smc_diag_msg attributes
[strace] / util.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  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7  *                     Linux for s390 port by D.J. Barrow
8  *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
9  * Copyright (c) 1999-2017 The strace developers.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include "defs.h"
36 #include <sys/param.h>
37 #include <fcntl.h>
38 #include <stdarg.h>
39 #ifdef HAVE_SYS_XATTR_H
40 # include <sys/xattr.h>
41 #endif
42 #include <sys/uio.h>
43 #include <asm/unistd.h>
44
45 #include "scno.h"
46 #include "regs.h"
47 #include "ptrace.h"
48
49 int
50 string_to_uint_ex(const char *const str, char **const endptr,
51                   const unsigned int max_val, const char *const accepted_ending)
52 {
53         char *end;
54         long val;
55
56         if (!*str)
57                 return -1;
58
59         errno = 0;
60         val = strtol(str, &end, 10);
61
62         if (str == end || val < 0 || (unsigned long) val > max_val
63             || (val == LONG_MAX && errno == ERANGE))
64                 return -1;
65
66         if (*end && (!accepted_ending || !strchr(accepted_ending, *end)))
67                 return -1;
68
69         if (endptr)
70                 *endptr = end;
71
72         return (int) val;
73 }
74
75 int
76 string_to_uint(const char *const str)
77 {
78         return string_to_uint_upto(str, INT_MAX);
79 }
80
81 int
82 tv_nz(const struct timeval *a)
83 {
84         return a->tv_sec || a->tv_usec;
85 }
86
87 int
88 tv_cmp(const struct timeval *a, const struct timeval *b)
89 {
90         if (a->tv_sec < b->tv_sec
91             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
92                 return -1;
93         if (a->tv_sec > b->tv_sec
94             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
95                 return 1;
96         return 0;
97 }
98
99 double
100 tv_float(const struct timeval *tv)
101 {
102         return tv->tv_sec + tv->tv_usec/1000000.0;
103 }
104
105 void
106 tv_add(struct timeval *tv, const struct timeval *a, const struct timeval *b)
107 {
108         tv->tv_sec = a->tv_sec + b->tv_sec;
109         tv->tv_usec = a->tv_usec + b->tv_usec;
110         if (tv->tv_usec >= 1000000) {
111                 tv->tv_sec++;
112                 tv->tv_usec -= 1000000;
113         }
114 }
115
116 void
117 tv_sub(struct timeval *tv, const struct timeval *a, const struct timeval *b)
118 {
119         tv->tv_sec = a->tv_sec - b->tv_sec;
120         tv->tv_usec = a->tv_usec - b->tv_usec;
121         if (((long) tv->tv_usec) < 0) {
122                 tv->tv_sec--;
123                 tv->tv_usec += 1000000;
124         }
125 }
126
127 void
128 tv_div(struct timeval *tv, const struct timeval *a, int n)
129 {
130         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
131         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
132         tv->tv_usec %= 1000000;
133 }
134
135 void
136 tv_mul(struct timeval *tv, const struct timeval *a, int n)
137 {
138         tv->tv_usec = a->tv_usec * n;
139         tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
140         tv->tv_usec %= 1000000;
141 }
142
143 #if !defined HAVE_STPCPY
144 char *
145 stpcpy(char *dst, const char *src)
146 {
147         while ((*dst = *src++) != '\0')
148                 dst++;
149         return dst;
150 }
151 #endif
152
153 /* Find a next bit which is set.
154  * Starts testing at cur_bit.
155  * Returns -1 if no more bits are set.
156  *
157  * We never touch bytes we don't need to.
158  * On big-endian, array is assumed to consist of
159  * current_wordsize wide words: for example, is current_wordsize is 4,
160  * the bytes are walked in 3,2,1,0, 7,6,5,4, 11,10,9,8 ... sequence.
161  * On little-endian machines, word size is immaterial.
162  */
163 int
164 next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
165 {
166         const unsigned endian = 1;
167         int little_endian = *(char *) (void *) &endian;
168
169         const uint8_t *array = bit_array;
170         unsigned pos = cur_bit / 8;
171         unsigned pos_xor_mask = little_endian ? 0 : current_wordsize-1;
172
173         for (;;) {
174                 uint8_t bitmask;
175                 uint8_t cur_byte;
176
177                 if (cur_bit >= size_bits)
178                         return -1;
179                 cur_byte = array[pos ^ pos_xor_mask];
180                 if (cur_byte == 0) {
181                         cur_bit = (cur_bit + 8) & (-8);
182                         pos++;
183                         continue;
184                 }
185                 bitmask = 1 << (cur_bit & 7);
186                 for (;;) {
187                         if (cur_byte & bitmask)
188                                 return cur_bit;
189                         cur_bit++;
190                         if (cur_bit >= size_bits)
191                                 return -1;
192                         bitmask <<= 1;
193                         /* This check *can't be* optimized out: */
194                         if (bitmask == 0)
195                                 break;
196                 }
197                 pos++;
198         }
199 }
200
201 /*
202  * Fetch 64bit argument at position arg_no and
203  * return the index of the next argument.
204  */
205 int
206 getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
207 {
208 #if SIZEOF_KERNEL_LONG_T > 4
209 # ifndef current_klongsize
210         if (current_klongsize < SIZEOF_KERNEL_LONG_T) {
211 #  if defined(AARCH64) || defined(POWERPC64)
212                 /* Align arg_no to the next even number. */
213                 arg_no = (arg_no + 1) & 0xe;
214 #  endif /* AARCH64 || POWERPC64 */
215                 *val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
216                 arg_no += 2;
217         } else
218 # endif /* !current_klongsize */
219         {
220                 *val = tcp->u_arg[arg_no];
221                 arg_no++;
222         }
223 #else /* SIZEOF_KERNEL_LONG_T == 4 */
224 # if defined __ARM_EABI__       \
225   || defined LINUX_MIPSO32      \
226   || defined POWERPC            \
227   || defined XTENSA
228         /* Align arg_no to the next even number. */
229         arg_no = (arg_no + 1) & 0xe;
230 # elif defined SH
231         /*
232          * The SH4 ABI does allow long longs in odd-numbered registers, but
233          * does not allow them to be split between registers and memory - and
234          * there are only four argument registers for normal functions.  As a
235          * result, pread, for example, takes an extra padding argument before
236          * the offset.  This was changed late in the 2.4 series (around 2.4.20).
237          */
238         if (arg_no == 3)
239                 arg_no++;
240 # endif /* __ARM_EABI__ || LINUX_MIPSO32 || POWERPC || XTENSA || SH */
241         *val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
242         arg_no += 2;
243 #endif
244
245         return arg_no;
246 }
247
248 /*
249  * Print 64bit argument at position arg_no and
250  * return the index of the next argument.
251  */
252 int
253 printllval(struct tcb *tcp, const char *format, int arg_no)
254 {
255         unsigned long long val = 0;
256
257         arg_no = getllval(tcp, &val, arg_no);
258         tprintf(format, val);
259         return arg_no;
260 }
261
262 void
263 printaddr(const kernel_ulong_t addr)
264 {
265         if (!addr)
266                 tprints("NULL");
267         else
268                 tprintf("%#" PRI_klx, addr);
269 }
270
271 #define DEF_PRINTNUM(name, type) \
272 bool                                                                    \
273 printnum_ ## name(struct tcb *const tcp, const kernel_ulong_t addr,     \
274                   const char *const fmt)                                \
275 {                                                                       \
276         type num;                                                       \
277         if (umove_or_printaddr(tcp, addr, &num))                        \
278                 return false;                                           \
279         tprints("[");                                                   \
280         tprintf(fmt, num);                                              \
281         tprints("]");                                                   \
282         return true;                                                    \
283 }
284
285 #define DEF_PRINTNUM_ADDR(name, type) \
286 bool                                                                    \
287 printnum_addr_ ## name(struct tcb *tcp, const kernel_ulong_t addr)      \
288 {                                                                       \
289         type num;                                                       \
290         if (umove_or_printaddr(tcp, addr, &num))                        \
291                 return false;                                           \
292         tprints("[");                                                   \
293         printaddr(num);                                                 \
294         tprints("]");                                                   \
295         return true;                                                    \
296 }
297
298 #define DEF_PRINTPAIR(name, type) \
299 bool                                                                    \
300 printpair_ ## name(struct tcb *const tcp, const kernel_ulong_t addr,    \
301                    const char *const fmt)                               \
302 {                                                                       \
303         type pair[2];                                                   \
304         if (umove_or_printaddr(tcp, addr, &pair))                       \
305                 return false;                                           \
306         tprints("[");                                                   \
307         tprintf(fmt, pair[0]);                                          \
308         tprints(", ");                                                  \
309         tprintf(fmt, pair[1]);                                          \
310         tprints("]");                                                   \
311         return true;                                                    \
312 }
313
314 DEF_PRINTNUM(int, int)
315 DEF_PRINTNUM_ADDR(int, unsigned int)
316 DEF_PRINTPAIR(int, int)
317 DEF_PRINTNUM(short, short)
318 DEF_PRINTNUM(int64, uint64_t)
319 DEF_PRINTNUM_ADDR(int64, uint64_t)
320 DEF_PRINTPAIR(int64, uint64_t)
321
322 #ifndef current_wordsize
323 bool
324 printnum_long_int(struct tcb *const tcp, const kernel_ulong_t addr,
325                   const char *const fmt_long, const char *const fmt_int)
326 {
327         if (current_wordsize > sizeof(int)) {
328                 return printnum_int64(tcp, addr, fmt_long);
329         } else {
330                 return printnum_int(tcp, addr, fmt_int);
331         }
332 }
333
334 bool
335 printnum_addr_long_int(struct tcb *tcp, const kernel_ulong_t addr)
336 {
337         if (current_wordsize > sizeof(int)) {
338                 return printnum_addr_int64(tcp, addr);
339         } else {
340                 return printnum_addr_int(tcp, addr);
341         }
342 }
343 #endif /* !current_wordsize */
344
345 #ifndef current_klongsize
346 bool
347 printnum_addr_klong_int(struct tcb *tcp, const kernel_ulong_t addr)
348 {
349         if (current_klongsize > sizeof(int)) {
350                 return printnum_addr_int64(tcp, addr);
351         } else {
352                 return printnum_addr_int(tcp, addr);
353         }
354 }
355 #endif /* !current_klongsize */
356
357 /**
358  * Prints time to a (static internal) buffer and returns pointer to it.
359  *
360  * @param sec           Seconds since epoch.
361  * @param part_sec      Amount of second parts since the start of a second.
362  * @param max_part_sec  Maximum value of a valid part_sec.
363  * @param width         1 + floor(log10(max_part_sec)).
364  */
365 static const char *
366 sprinttime_ex(const long long sec, const unsigned long long part_sec,
367               const unsigned int max_part_sec, const int width)
368 {
369         static char buf[sizeof(int) * 3 * 6 + sizeof(part_sec) * 3
370                         + sizeof("+0000")];
371
372         if ((sec == 0 && part_sec == 0) || part_sec > max_part_sec)
373                 return NULL;
374
375         time_t t = (time_t) sec;
376         struct tm *tmp = (sec == t) ? localtime(&t) : NULL;
377         if (!tmp)
378                 return NULL;
379
380         size_t pos = strftime(buf, sizeof(buf), "%FT%T", tmp);
381         if (!pos)
382                 return NULL;
383
384         if (part_sec > 0) {
385                 int ret = snprintf(buf + pos, sizeof(buf) - pos, ".%0*llu",
386                                    width, part_sec);
387
388                 if (ret < 0 || (size_t) ret >= sizeof(buf) - pos)
389                         return NULL;
390
391                 pos += ret;
392         }
393
394         return strftime(buf + pos, sizeof(buf) - pos, "%z", tmp) ? buf : NULL;
395 }
396
397 const char *
398 sprinttime(long long sec)
399 {
400         return sprinttime_ex(sec, 0, 0, 0);
401 }
402
403 const char *
404 sprinttime_usec(long long sec, unsigned long long usec)
405 {
406         return sprinttime_ex(sec, usec, 999999, 6);
407 }
408
409 const char *
410 sprinttime_nsec(long long sec, unsigned long long nsec)
411 {
412         return sprinttime_ex(sec, nsec, 999999999, 9);
413 }
414
415 enum sock_proto
416 getfdproto(struct tcb *tcp, int fd)
417 {
418 #ifdef HAVE_SYS_XATTR_H
419         size_t bufsize = 256;
420         char buf[bufsize];
421         ssize_t r;
422         char path[sizeof("/proc/%u/fd/%u") + 2 * sizeof(int)*3];
423
424         if (fd < 0)
425                 return SOCK_PROTO_UNKNOWN;
426
427         sprintf(path, "/proc/%u/fd/%u", tcp->pid, fd);
428         r = getxattr(path, "system.sockprotoname", buf, bufsize - 1);
429         if (r <= 0)
430                 return SOCK_PROTO_UNKNOWN;
431         else {
432                 /*
433                  * This is a protection for the case when the kernel
434                  * side does not append a null byte to the buffer.
435                  */
436                 buf[r] = '\0';
437
438                 return get_proto_by_name(buf);
439         }
440 #else
441         return SOCK_PROTO_UNKNOWN;
442 #endif
443 }
444
445 unsigned long
446 getfdinode(struct tcb *tcp, int fd)
447 {
448         char path[PATH_MAX + 1];
449
450         if (getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
451                 const char *str = STR_STRIP_PREFIX(path, "socket:[");
452
453                 if (str != path) {
454                         const size_t str_len = strlen(str);
455                         if (str_len && str[str_len - 1] == ']')
456                                 return strtoul(str, NULL, 10);
457                 }
458         }
459
460         return 0;
461 }
462
463 void
464 printfd(struct tcb *tcp, int fd)
465 {
466         char path[PATH_MAX + 1];
467         if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
468                 const char *str;
469                 size_t len;
470                 unsigned long inode;
471
472                 tprintf("%d<", fd);
473                 if (show_fd_path <= 1
474                     || (str = STR_STRIP_PREFIX(path, "socket:[")) == path
475                     || !(len = strlen(str))
476                     || str[len - 1] != ']'
477                     || !(inode = strtoul(str, NULL, 10))
478                     || !print_sockaddr_by_inode(tcp, fd, inode)) {
479                         print_quoted_string(path, strlen(path),
480                                             QUOTE_OMIT_LEADING_TRAILING_QUOTES);
481                 }
482                 tprints(">");
483         } else
484                 tprintf("%d", fd);
485 }
486
487 /*
488  * Quote string `instr' of length `size'
489  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
490  *
491  * If QUOTE_0_TERMINATED `style' flag is set,
492  * treat `instr' as a NUL-terminated string,
493  * checking up to (`size' + 1) bytes of `instr'.
494  *
495  * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
496  * do not add leading and trailing quoting symbols.
497  *
498  * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
499  * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
500  */
501 int
502 string_quote(const char *instr, char *outstr, const unsigned int size,
503              const unsigned int style)
504 {
505         const unsigned char *ustr = (const unsigned char *) instr;
506         char *s = outstr;
507         unsigned int i;
508         int usehex, c, eol;
509
510         if (style & QUOTE_0_TERMINATED)
511                 eol = '\0';
512         else
513                 eol = 0x100; /* this can never match a char */
514
515         usehex = 0;
516         if ((xflag > 1) || (style & QUOTE_FORCE_HEX)) {
517                 usehex = 1;
518         } else if (xflag) {
519                 /* Check for presence of symbol which require
520                    to hex-quote the whole string. */
521                 for (i = 0; i < size; ++i) {
522                         c = ustr[i];
523                         /* Check for NUL-terminated string. */
524                         if (c == eol)
525                                 break;
526
527                         /* Force hex unless c is printable or whitespace */
528                         if (c > 0x7e) {
529                                 usehex = 1;
530                                 break;
531                         }
532                         /* In ASCII isspace is only these chars: "\t\n\v\f\r".
533                          * They happen to have ASCII codes 9,10,11,12,13.
534                          */
535                         if (c < ' ' && (unsigned)(c - 9) >= 5) {
536                                 usehex = 1;
537                                 break;
538                         }
539                 }
540         }
541
542         if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
543                 *s++ = '\"';
544
545         if (usehex) {
546                 /* Hex-quote the whole string. */
547                 for (i = 0; i < size; ++i) {
548                         c = ustr[i];
549                         /* Check for NUL-terminated string. */
550                         if (c == eol)
551                                 goto asciz_ended;
552                         *s++ = '\\';
553                         *s++ = 'x';
554                         *s++ = "0123456789abcdef"[c >> 4];
555                         *s++ = "0123456789abcdef"[c & 0xf];
556                 }
557         } else {
558                 for (i = 0; i < size; ++i) {
559                         c = ustr[i];
560                         /* Check for NUL-terminated string. */
561                         if (c == eol)
562                                 goto asciz_ended;
563                         if ((i == (size - 1)) &&
564                             (style & QUOTE_OMIT_TRAILING_0) && (c == '\0'))
565                                 goto asciz_ended;
566                         switch (c) {
567                                 case '\"': case '\\':
568                                         *s++ = '\\';
569                                         *s++ = c;
570                                         break;
571                                 case '\f':
572                                         *s++ = '\\';
573                                         *s++ = 'f';
574                                         break;
575                                 case '\n':
576                                         *s++ = '\\';
577                                         *s++ = 'n';
578                                         break;
579                                 case '\r':
580                                         *s++ = '\\';
581                                         *s++ = 'r';
582                                         break;
583                                 case '\t':
584                                         *s++ = '\\';
585                                         *s++ = 't';
586                                         break;
587                                 case '\v':
588                                         *s++ = '\\';
589                                         *s++ = 'v';
590                                         break;
591                                 default:
592                                         if (c >= ' ' && c <= 0x7e)
593                                                 *s++ = c;
594                                         else {
595                                                 /* Print \octal */
596                                                 *s++ = '\\';
597                                                 if (i + 1 < size
598                                                     && ustr[i + 1] >= '0'
599                                                     && ustr[i + 1] <= '9'
600                                                 ) {
601                                                         /* Print \ooo */
602                                                         *s++ = '0' + (c >> 6);
603                                                         *s++ = '0' + ((c >> 3) & 0x7);
604                                                 } else {
605                                                         /* Print \[[o]o]o */
606                                                         if ((c >> 3) != 0) {
607                                                                 if ((c >> 6) != 0)
608                                                                         *s++ = '0' + (c >> 6);
609                                                                 *s++ = '0' + ((c >> 3) & 0x7);
610                                                         }
611                                                 }
612                                                 *s++ = '0' + (c & 0x7);
613                                         }
614                                         break;
615                         }
616                 }
617         }
618
619         if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
620                 *s++ = '\"';
621         *s = '\0';
622
623         /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
624         if (style & QUOTE_0_TERMINATED && ustr[i] == '\0') {
625                 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
626                  * but next char is NUL.
627                  */
628                 return 0;
629         }
630
631         return 1;
632
633  asciz_ended:
634         if (!(style & QUOTE_OMIT_LEADING_TRAILING_QUOTES))
635                 *s++ = '\"';
636         *s = '\0';
637         /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
638         return 0;
639 }
640
641 #ifndef ALLOCA_CUTOFF
642 # define ALLOCA_CUTOFF  4032
643 #endif
644 #define use_alloca(n) ((n) <= ALLOCA_CUTOFF)
645
646 /*
647  * Quote string `str' of length `size' and print the result.
648  *
649  * If QUOTE_0_TERMINATED `style' flag is set,
650  * treat `str' as a NUL-terminated string and
651  * quote at most (`size' - 1) bytes.
652  *
653  * If QUOTE_OMIT_LEADING_TRAILING_QUOTES `style' flag is set,
654  * do not add leading and trailing quoting symbols.
655  *
656  * Returns 0 if QUOTE_0_TERMINATED is set and NUL was seen, 1 otherwise.
657  * Note that if QUOTE_0_TERMINATED is not set, always returns 1.
658  */
659 int
660 print_quoted_string(const char *str, unsigned int size,
661                     const unsigned int style)
662 {
663         char *buf;
664         char *outstr;
665         unsigned int alloc_size;
666         int rc;
667
668         if (size && style & QUOTE_0_TERMINATED)
669                 --size;
670
671         alloc_size = 4 * size;
672         if (alloc_size / 4 != size) {
673                 error_msg("Out of memory");
674                 tprints("???");
675                 return -1;
676         }
677         alloc_size += 1 + (style & QUOTE_OMIT_LEADING_TRAILING_QUOTES ? 0 : 2);
678
679         if (use_alloca(alloc_size)) {
680                 outstr = alloca(alloc_size);
681                 buf = NULL;
682         } else {
683                 outstr = buf = malloc(alloc_size);
684                 if (!buf) {
685                         error_msg("Out of memory");
686                         tprints("???");
687                         return -1;
688                 }
689         }
690
691         rc = string_quote(str, outstr, size, style);
692         tprints(outstr);
693
694         free(buf);
695         return rc;
696 }
697
698 /*
699  * Print path string specified by address `addr' and length `n'.
700  * If path length exceeds `n', append `...' to the output.
701  */
702 void
703 printpathn(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int n)
704 {
705         char path[PATH_MAX + 1];
706         int nul_seen;
707
708         if (!addr) {
709                 tprints("NULL");
710                 return;
711         }
712
713         /* Cap path length to the path buffer size */
714         if (n > sizeof(path) - 1)
715                 n = sizeof(path) - 1;
716
717         /* Fetch one byte more to find out whether path length > n. */
718         nul_seen = umovestr(tcp, addr, n + 1, path);
719         if (nul_seen < 0)
720                 printaddr(addr);
721         else {
722                 path[n++] = '\0';
723                 print_quoted_string(path, n, QUOTE_0_TERMINATED);
724                 if (!nul_seen)
725                         tprints("...");
726         }
727 }
728
729 void
730 printpath(struct tcb *const tcp, const kernel_ulong_t addr)
731 {
732         /* Size must correspond to char path[] size in printpathn */
733         printpathn(tcp, addr, PATH_MAX);
734 }
735
736 /*
737  * Print string specified by address `addr' and length `len'.
738  * If `user_style' has QUOTE_0_TERMINATED bit set, treat the string
739  * as a NUL-terminated string.
740  * Pass `user_style' on to `string_quote'.
741  * Append `...' to the output if either the string length exceeds `max_strlen',
742  * or QUOTE_0_TERMINATED bit is set and the string length exceeds `len'.
743  */
744 void
745 printstr_ex(struct tcb *const tcp, const kernel_ulong_t addr,
746             const kernel_ulong_t len, const unsigned int user_style)
747 {
748         static char *str;
749         static char *outstr;
750
751         unsigned int size;
752         unsigned int style = user_style;
753         int rc;
754         int ellipsis;
755
756         if (!addr) {
757                 tprints("NULL");
758                 return;
759         }
760         /* Allocate static buffers if they are not allocated yet. */
761         if (!str) {
762                 const unsigned int outstr_size =
763                         4 * max_strlen + /* for quotes and NUL */ 3;
764                 /*
765                  * We can assume that outstr_size / 4 == max_strlen
766                  * since we have a guarantee that max_strlen <= -1U / 4.
767                  */
768
769                 str = xmalloc(max_strlen + 1);
770                 outstr = xmalloc(outstr_size);
771         }
772
773         /* Fetch one byte more because string_quote may look one byte ahead. */
774         size = max_strlen + 1;
775
776         if (size > len)
777                 size = len;
778         if (style & QUOTE_0_TERMINATED)
779                 rc = umovestr(tcp, addr, size, str);
780         else
781                 rc = umoven(tcp, addr, size, str);
782
783         if (rc < 0) {
784                 printaddr(addr);
785                 return;
786         }
787
788         if (size > max_strlen)
789                 size = max_strlen;
790         else
791                 str[size] = '\xff';
792
793         /* If string_quote didn't see NUL and (it was supposed to be ASCIZ str
794          * or we were requested to print more than -s NUM chars)...
795          */
796         ellipsis = string_quote(str, outstr, size, style)
797                    && len
798                    && ((style & QUOTE_0_TERMINATED)
799                        || len > max_strlen);
800
801         tprints(outstr);
802         if (ellipsis)
803                 tprints("...");
804 }
805
806 void
807 dumpiov_upto(struct tcb *const tcp, const int len, const kernel_ulong_t addr,
808              kernel_ulong_t data_size)
809 {
810 #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
811         union {
812                 struct { uint32_t base; uint32_t len; } *iov32;
813                 struct { uint64_t base; uint64_t len; } *iov64;
814         } iovu;
815 #define iov iovu.iov64
816 #define sizeof_iov \
817         (current_wordsize == 4 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
818 #define iov_iov_base(i) \
819         (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].base : iovu.iov64[i].base)
820 #define iov_iov_len(i) \
821         (current_wordsize == 4 ? (uint64_t) iovu.iov32[i].len : iovu.iov64[i].len)
822 #else
823         struct iovec *iov;
824 #define sizeof_iov sizeof(*iov)
825 #define iov_iov_base(i) ptr_to_kulong(iov[i].iov_base)
826 #define iov_iov_len(i) iov[i].iov_len
827 #endif
828         int i;
829         unsigned size;
830
831         size = sizeof_iov * len;
832         /* Assuming no sane program has millions of iovs */
833         if ((unsigned)len > 1024*1024 /* insane or negative size? */
834             || (iov = malloc(size)) == NULL) {
835                 error_msg("Out of memory");
836                 return;
837         }
838         if (umoven(tcp, addr, size, iov) >= 0) {
839                 for (i = 0; i < len; i++) {
840                         kernel_ulong_t iov_len = iov_iov_len(i);
841                         if (iov_len > data_size)
842                                 iov_len = data_size;
843                         if (!iov_len)
844                                 break;
845                         data_size -= iov_len;
846                         /* include the buffer number to make it easy to
847                          * match up the trace with the source */
848                         tprintf(" * %" PRI_klu " bytes in buffer %d\n", iov_len, i);
849                         dumpstr(tcp, iov_iov_base(i), iov_len);
850                 }
851         }
852         free(iov);
853 #undef sizeof_iov
854 #undef iov_iov_base
855 #undef iov_iov_len
856 #undef iov
857 }
858
859 void
860 dumpstr(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
861 {
862         static int strsize = -1;
863         static unsigned char *str;
864
865         char outbuf[
866                 (
867                         (sizeof(
868                         "xx xx xx xx xx xx xx xx  xx xx xx xx xx xx xx xx  "
869                         "1234567890123456") + /*in case I'm off by few:*/ 4)
870                 /*align to 8 to make memset easier:*/ + 7) & -8
871         ];
872         const unsigned char *src;
873         int i;
874
875         memset(outbuf, ' ', sizeof(outbuf));
876
877         if (strsize < len + 16) {
878                 free(str);
879                 str = malloc(len + 16);
880                 if (!str) {
881                         strsize = -1;
882                         error_msg("Out of memory");
883                         return;
884                 }
885                 strsize = len + 16;
886         }
887
888         if (umoven(tcp, addr, len, str) < 0)
889                 return;
890
891         /* Space-pad to 16 bytes */
892         i = len;
893         while (i & 0xf)
894                 str[i++] = ' ';
895
896         i = 0;
897         src = str;
898         while (i < len) {
899                 char *dst = outbuf;
900                 /* Hex dump */
901                 do {
902                         if (i < len) {
903                                 *dst++ = "0123456789abcdef"[*src >> 4];
904                                 *dst++ = "0123456789abcdef"[*src & 0xf];
905                         } else {
906                                 *dst++ = ' ';
907                                 *dst++ = ' ';
908                         }
909                         dst++; /* space is there by memset */
910                         i++;
911                         if ((i & 7) == 0)
912                                 dst++; /* space is there by memset */
913                         src++;
914                 } while (i & 0xf);
915                 /* ASCII dump */
916                 i -= 16;
917                 src -= 16;
918                 do {
919                         if (*src >= ' ' && *src < 0x7f)
920                                 *dst++ = *src;
921                         else
922                                 *dst++ = '.';
923                         src++;
924                 } while (++i & 0xf);
925                 *dst = '\0';
926                 tprintf(" | %05x  %s |\n", i - 16, outbuf);
927         }
928 }
929
930 static bool process_vm_readv_not_supported;
931
932 #ifndef HAVE_PROCESS_VM_READV
933 /*
934  * Need to do this since process_vm_readv() is not yet available in libc.
935  * When libc is be updated, only "static bool process_vm_readv_not_supported"
936  * line should remain.
937  */
938 /* Have to avoid duplicating with the C library headers. */
939 static ssize_t strace_process_vm_readv(pid_t pid,
940                  const struct iovec *lvec,
941                  unsigned long liovcnt,
942                  const struct iovec *rvec,
943                  unsigned long riovcnt,
944                  unsigned long flags)
945 {
946         return syscall(__NR_process_vm_readv, (long)pid, lvec, liovcnt, rvec, riovcnt, flags);
947 }
948 # define process_vm_readv strace_process_vm_readv
949 #endif /* !HAVE_PROCESS_VM_READV */
950
951 static ssize_t
952 vm_read_mem(const pid_t pid, void *const laddr,
953             const kernel_ulong_t raddr, const size_t len)
954 {
955         const unsigned long truncated_raddr = raddr;
956
957         if (raddr != (kernel_ulong_t) truncated_raddr) {
958                 errno = EIO;
959                 return -1;
960         }
961
962         const struct iovec local = {
963                 .iov_base = laddr,
964                 .iov_len = len
965         };
966         const struct iovec remote = {
967                 .iov_base = (void *) truncated_raddr,
968                 .iov_len = len
969         };
970
971         return process_vm_readv(pid, &local, 1, &remote, 1, 0);
972 }
973
974 /*
975  * move `len' bytes of data from process `pid'
976  * at address `addr' to our space at `our_addr'
977  */
978 int
979 umoven(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len,
980        void *const our_addr)
981 {
982         char *laddr = our_addr;
983         int pid = tcp->pid;
984         unsigned int n, m, nread;
985         union {
986                 long val;
987                 char x[sizeof(long)];
988         } u;
989
990 #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
991         if (current_wordsize < sizeof(addr)
992             && (addr & (~(kernel_ulong_t) -1U))) {
993                 return -1;
994         }
995 #endif
996
997         if (!process_vm_readv_not_supported) {
998                 int r = vm_read_mem(pid, laddr, addr, len);
999                 if ((unsigned int) r == len)
1000                         return 0;
1001                 if (r >= 0) {
1002                         error_msg("umoven: short read (%u < %u) @0x%" PRI_klx,
1003                                   (unsigned int) r, len, addr);
1004                         return -1;
1005                 }
1006                 switch (errno) {
1007                         case ENOSYS:
1008                                 process_vm_readv_not_supported = 1;
1009                                 break;
1010                         case EPERM:
1011                                 /* operation not permitted, try PTRACE_PEEKDATA */
1012                                 break;
1013                         case ESRCH:
1014                                 /* the process is gone */
1015                                 return -1;
1016                         case EFAULT: case EIO:
1017                                 /* address space is inaccessible */
1018                                 return -1;
1019                         default:
1020                                 /* all the rest is strange and should be reported */
1021                                 perror_msg("process_vm_readv");
1022                                 return -1;
1023                 }
1024         }
1025
1026         nread = 0;
1027         if (addr & (sizeof(long) - 1)) {
1028                 /* addr not a multiple of sizeof(long) */
1029                 n = addr & (sizeof(long) - 1);  /* residue */
1030                 addr &= -sizeof(long);          /* aligned address */
1031                 errno = 0;
1032                 u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
1033                 switch (errno) {
1034                         case 0:
1035                                 break;
1036                         case ESRCH: case EINVAL:
1037                                 /* these could be seen if the process is gone */
1038                                 return -1;
1039                         case EFAULT: case EIO: case EPERM:
1040                                 /* address space is inaccessible */
1041                                 return -1;
1042                         default:
1043                                 /* all the rest is strange and should be reported */
1044                                 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
1045                                             pid, addr);
1046                                 return -1;
1047                 }
1048                 m = MIN(sizeof(long) - n, len);
1049                 memcpy(laddr, &u.x[n], m);
1050                 addr += sizeof(long);
1051                 laddr += m;
1052                 nread += m;
1053                 len -= m;
1054         }
1055         while (len) {
1056                 errno = 0;
1057                 u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
1058                 switch (errno) {
1059                         case 0:
1060                                 break;
1061                         case ESRCH: case EINVAL:
1062                                 /* these could be seen if the process is gone */
1063                                 return -1;
1064                         case EFAULT: case EIO: case EPERM:
1065                                 /* address space is inaccessible */
1066                                 if (nread) {
1067                                         perror_msg("umoven: short read (%u < %u) @0x%" PRI_klx,
1068                                                    nread, nread + len, addr - nread);
1069                                 }
1070                                 return -1;
1071                         default:
1072                                 /* all the rest is strange and should be reported */
1073                                 perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
1074                                             pid, addr);
1075                                 return -1;
1076                 }
1077                 m = MIN(sizeof(long), len);
1078                 memcpy(laddr, u.x, m);
1079                 addr += sizeof(long);
1080                 laddr += m;
1081                 nread += m;
1082                 len -= m;
1083         }
1084
1085         return 0;
1086 }
1087
1088 int
1089 umoven_or_printaddr(struct tcb *const tcp, const kernel_ulong_t addr,
1090                     const unsigned int len, void *const our_addr)
1091 {
1092         if (!addr || !verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
1093             umoven(tcp, addr, len, our_addr) < 0) {
1094                 printaddr(addr);
1095                 return -1;
1096         }
1097         return 0;
1098 }
1099
1100 int
1101 umoven_or_printaddr_ignore_syserror(struct tcb *const tcp,
1102                                     const kernel_ulong_t addr,
1103                                     const unsigned int len,
1104                                     void *const our_addr)
1105 {
1106         if (!addr || !verbose(tcp) || umoven(tcp, addr, len, our_addr) < 0) {
1107                 printaddr(addr);
1108                 return -1;
1109         }
1110         return 0;
1111 }
1112
1113 /*
1114  * Like `umove' but make the additional effort of looking
1115  * for a terminating zero byte.
1116  *
1117  * Returns < 0 on error, > 0 if NUL was seen,
1118  * (TODO if useful: return count of bytes including NUL),
1119  * else 0 if len bytes were read but no NUL byte seen.
1120  *
1121  * Note: there is no guarantee we won't overwrite some bytes
1122  * in laddr[] _after_ terminating NUL (but, of course,
1123  * we never write past laddr[len-1]).
1124  */
1125 int
1126 umovestr(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, char *laddr)
1127 {
1128         const unsigned long x01010101 = (unsigned long) 0x0101010101010101ULL;
1129         const unsigned long x80808080 = (unsigned long) 0x8080808080808080ULL;
1130
1131         int pid = tcp->pid;
1132         unsigned int n, m, nread;
1133         union {
1134                 unsigned long val;
1135                 char x[sizeof(long)];
1136         } u;
1137
1138 #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
1139         if (current_wordsize < sizeof(addr)
1140             && (addr & (~(kernel_ulong_t) -1U))) {
1141                 return -1;
1142         }
1143 #endif
1144
1145         nread = 0;
1146         if (!process_vm_readv_not_supported) {
1147                 const size_t page_size = get_pagesize();
1148                 const size_t page_mask = page_size - 1;
1149
1150                 while (len > 0) {
1151                         unsigned int chunk_len;
1152                         unsigned int end_in_page;
1153
1154                         /*
1155                          * Don't cross pages, otherwise we can get EFAULT
1156                          * and fail to notice that terminating NUL lies
1157                          * in the existing (first) page.
1158                          */
1159                         chunk_len = len > page_size ? page_size : len;
1160                         end_in_page = (addr + chunk_len) & page_mask;
1161                         if (chunk_len > end_in_page) /* crosses to the next page */
1162                                 chunk_len -= end_in_page;
1163
1164                         int r = vm_read_mem(pid, laddr, addr, chunk_len);
1165                         if (r > 0) {
1166                                 if (memchr(laddr, '\0', r))
1167                                         return 1;
1168                                 addr += r;
1169                                 laddr += r;
1170                                 nread += r;
1171                                 len -= r;
1172                                 continue;
1173                         }
1174                         switch (errno) {
1175                                 case ENOSYS:
1176                                         process_vm_readv_not_supported = 1;
1177                                         goto vm_readv_didnt_work;
1178                                 case ESRCH:
1179                                         /* the process is gone */
1180                                         return -1;
1181                                 case EPERM:
1182                                         /* operation not permitted, try PTRACE_PEEKDATA */
1183                                         if (!nread)
1184                                                 goto vm_readv_didnt_work;
1185                                         /* fall through */
1186                                 case EFAULT: case EIO:
1187                                         /* address space is inaccessible */
1188                                         if (nread) {
1189                                                 perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx,
1190                                                            nread, nread + len, addr - nread);
1191                                         }
1192                                         return -1;
1193                                 default:
1194                                         /* all the rest is strange and should be reported */
1195                                         perror_msg("process_vm_readv");
1196                                         return -1;
1197                         }
1198                 }
1199                 return 0;
1200         }
1201  vm_readv_didnt_work:
1202
1203         if (addr & (sizeof(long) - 1)) {
1204                 /* addr not a multiple of sizeof(long) */
1205                 n = addr & (sizeof(long) - 1);  /* residue */
1206                 addr &= -sizeof(long);          /* aligned address */
1207                 errno = 0;
1208                 u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
1209                 switch (errno) {
1210                         case 0:
1211                                 break;
1212                         case ESRCH: case EINVAL:
1213                                 /* these could be seen if the process is gone */
1214                                 return -1;
1215                         case EFAULT: case EIO: case EPERM:
1216                                 /* address space is inaccessible */
1217                                 return -1;
1218                         default:
1219                                 /* all the rest is strange and should be reported */
1220                                 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
1221                                             pid, addr);
1222                                 return -1;
1223                 }
1224                 m = MIN(sizeof(long) - n, len);
1225                 memcpy(laddr, &u.x[n], m);
1226                 while (n & (sizeof(long) - 1))
1227                         if (u.x[n++] == '\0')
1228                                 return 1;
1229                 addr += sizeof(long);
1230                 laddr += m;
1231                 nread += m;
1232                 len -= m;
1233         }
1234
1235         while (len) {
1236                 errno = 0;
1237                 u.val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
1238                 switch (errno) {
1239                         case 0:
1240                                 break;
1241                         case ESRCH: case EINVAL:
1242                                 /* these could be seen if the process is gone */
1243                                 return -1;
1244                         case EFAULT: case EIO: case EPERM:
1245                                 /* address space is inaccessible */
1246                                 if (nread) {
1247                                         perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx,
1248                                                    nread, nread + len, addr - nread);
1249                                 }
1250                                 return -1;
1251                         default:
1252                                 /* all the rest is strange and should be reported */
1253                                 perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
1254                                            pid, addr);
1255                                 return -1;
1256                 }
1257                 m = MIN(sizeof(long), len);
1258                 memcpy(laddr, u.x, m);
1259                 /* "If a NUL char exists in this word" */
1260                 if ((u.val - x01010101) & ~u.val & x80808080)
1261                         return 1;
1262                 addr += sizeof(long);
1263                 laddr += m;
1264                 nread += m;
1265                 len -= m;
1266         }
1267         return 0;
1268 }
1269
1270 /*
1271  * Iteratively fetch and print up to nmemb elements of elem_size size
1272  * from the array that starts at tracee's address start_addr.
1273  *
1274  * Array elements are being fetched to the address specified by elem_buf.
1275  *
1276  * The fetcher callback function specified by umoven_func should follow
1277  * the same semantics as umoven_or_printaddr function.
1278  *
1279  * The printer callback function specified by print_func is expected
1280  * to print something; if it returns false, no more iterations will be made.
1281  *
1282  * The pointer specified by opaque_data is passed to each invocation
1283  * of print_func callback function.
1284  *
1285  * This function prints:
1286  * - "NULL", if start_addr is NULL;
1287  * - "[]", if nmemb is 0;
1288  * - start_addr, if nmemb * elem_size overflows or wraps around;
1289  * - nothing, if the first element cannot be fetched
1290  *   (if umoven_func returns non-zero), but it is assumed that
1291  *   umoven_func has printed the address it failed to fetch data from;
1292  * - elements of the array, delimited by ", ", with the array itself
1293  *   enclosed with [] brackets.
1294  *
1295  * If abbrev(tcp) is true, then
1296  * - the maximum number of elements printed equals to max_strlen;
1297  * - "..." is printed instead of max_strlen+1 element
1298  *   and no more iterations will be made.
1299  *
1300  * This function returns true only if
1301  * - umoven_func has been called at least once AND
1302  * - umoven_func has not returned false.
1303  */
1304 bool
1305 print_array(struct tcb *const tcp,
1306             const kernel_ulong_t start_addr,
1307             const size_t nmemb,
1308             void *const elem_buf,
1309             const size_t elem_size,
1310             int (*const umoven_func)(struct tcb *,
1311                                      kernel_ulong_t,
1312                                      unsigned int,
1313                                      void *),
1314             bool (*const print_func)(struct tcb *,
1315                                      void *elem_buf,
1316                                      size_t elem_size,
1317                                      void *opaque_data),
1318             void *const opaque_data)
1319 {
1320         if (!start_addr) {
1321                 tprints("NULL");
1322                 return false;
1323         }
1324
1325         if (!nmemb) {
1326                 tprints("[]");
1327                 return false;
1328         }
1329
1330         const size_t size = nmemb * elem_size;
1331         const kernel_ulong_t end_addr = start_addr + size;
1332
1333         if (end_addr <= start_addr || size / elem_size != nmemb) {
1334                 printaddr(start_addr);
1335                 return false;
1336         }
1337
1338         const kernel_ulong_t abbrev_end =
1339                 (abbrev(tcp) && max_strlen < nmemb) ?
1340                         start_addr + elem_size * max_strlen : end_addr;
1341         kernel_ulong_t cur;
1342
1343         for (cur = start_addr; cur < end_addr; cur += elem_size) {
1344                 if (cur != start_addr)
1345                         tprints(", ");
1346
1347                 if (umoven_func(tcp, cur, elem_size, elem_buf))
1348                         break;
1349
1350                 if (cur == start_addr)
1351                         tprints("[");
1352
1353                 if (cur >= abbrev_end) {
1354                         tprints("...");
1355                         cur = end_addr;
1356                         break;
1357                 }
1358
1359                 if (!print_func(tcp, elem_buf, elem_size, opaque_data)) {
1360                         cur = end_addr;
1361                         break;
1362                 }
1363         }
1364         if (cur != start_addr)
1365                 tprints("]");
1366
1367         return cur >= end_addr;
1368 }
1369
1370 int
1371 printargs(struct tcb *tcp)
1372 {
1373         const int n = tcp->s_ent->nargs;
1374         int i;
1375         for (i = 0; i < n; ++i)
1376                 tprintf("%s%#" PRI_klx, i ? ", " : "", tcp->u_arg[i]);
1377         return RVAL_DECODED;
1378 }
1379
1380 int
1381 printargs_u(struct tcb *tcp)
1382 {
1383         const int n = tcp->s_ent->nargs;
1384         int i;
1385         for (i = 0; i < n; ++i)
1386                 tprintf("%s%u", i ? ", " : "",
1387                         (unsigned int) tcp->u_arg[i]);
1388         return RVAL_DECODED;
1389 }
1390
1391 int
1392 printargs_d(struct tcb *tcp)
1393 {
1394         const int n = tcp->s_ent->nargs;
1395         int i;
1396         for (i = 0; i < n; ++i)
1397                 tprintf("%s%d", i ? ", " : "",
1398                         (int) tcp->u_arg[i]);
1399         return RVAL_DECODED;
1400 }
1401
1402 /* Print abnormal high bits of a kernel_ulong_t value. */
1403 void
1404 print_abnormal_hi(const kernel_ulong_t val)
1405 {
1406         if (current_klongsize > 4) {
1407                 const unsigned int hi = (unsigned int) ((uint64_t) val >> 32);
1408                 if (hi)
1409                         tprintf("%#x<<32|", hi);
1410         }
1411 }
1412
1413 #if defined _LARGEFILE64_SOURCE && defined HAVE_OPEN64
1414 # define open_file open64
1415 #else
1416 # define open_file open
1417 #endif
1418
1419 int
1420 read_int_from_file(const char *const fname, int *const pvalue)
1421 {
1422         const int fd = open_file(fname, O_RDONLY);
1423         if (fd < 0)
1424                 return -1;
1425
1426         long lval;
1427         char buf[sizeof(lval) * 3];
1428         int n = read(fd, buf, sizeof(buf) - 1);
1429         int saved_errno = errno;
1430         close(fd);
1431
1432         if (n < 0) {
1433                 errno = saved_errno;
1434                 return -1;
1435         }
1436
1437         buf[n] = '\0';
1438         char *endptr = 0;
1439         errno = 0;
1440         lval = strtol(buf, &endptr, 10);
1441         if (!endptr || (*endptr && '\n' != *endptr)
1442 #if INT_MAX < LONG_MAX
1443             || lval > INT_MAX || lval < INT_MIN
1444 #endif
1445             || ERANGE == errno) {
1446                 if (!errno)
1447                         errno = EINVAL;
1448                 return -1;
1449         }
1450
1451         *pvalue = (int) lval;
1452         return 0;
1453 }