Home | History | Annotate | Download | only in strace
      1 #ifndef STRACE_XSTRING_H
      2 #define STRACE_XSTRING_H
      3 
      4 #include <stdarg.h>
      5 #include <stdio.h>
      6 
      7 #include "error_prints.h"
      8 #include "gcc_compat.h"
      9 
     10 /**
     11  * Print to static buffer and die on (really unexpected) errors and overflows.
     12  * Shouldn't be used directly; please refer to helper macros xsnprintf and
     13  * xsprint instead.
     14  *
     15  * @param str    String buffer to print into.
     16  * @param size   Size of the string buffer in bytes.
     17  * @param func   Function name from which this function is called.
     18  * @param argstr Stringified arguments (including format argument).
     19  * @param format Format string.
     20  * @param ...    Format arguments.
     21  * @return       Number of characters printed, excluding terminating null byte
     22  *               (the same as s(n)printf).
     23  */
     24 static inline int ATTRIBUTE_FORMAT((printf, 5, 6))
     25 xsnprintf_(char *str, size_t size, const char *func, const char *argstr,
     26 	   const char *format, ...)
     27 {
     28 	int ret;
     29 	va_list ap;
     30 
     31 	va_start(ap, format);
     32 	ret = vsnprintf(str, size, format, ap);
     33 	va_end(ap);
     34 
     35 	if (ret < 0 || (unsigned int) ret >= size)
     36 		error_msg_and_die("%s: got unexpected return value %d for "
     37 				  "snprintf(buf, %zu, %s)",
     38 				  func, ret, size, argstr);
     39 
     40 	return ret;
     41 }
     42 
     43 /**
     44  * snprintf that dies on (really unexpected) errors and overflows.
     45  *
     46  * @param str_  String buffer to print into.
     47  * @param size_ Size of the string buffer in bytes.
     48  * @param fmt_  Format string.
     49  * @param ...   Format arguments.
     50  */
     51 #define xsnprintf(str_, size_, fmt_, ...) \
     52 	xsnprintf_((str_), (size_), __func__, #fmt_ ", " #__VA_ARGS__, \
     53 		   (fmt_), __VA_ARGS__)
     54 
     55 /**
     56  * Print to a character array buffer and die on (really unexpected) errors and
     57  * overflows.  Buffer size is obtained with sizeof().
     58  *
     59  * @param str_  Character array buffer to print into.
     60  * @param fmt_  Format string.
     61  * @param ...   Format arguments.
     62  */
     63 #define xsprintf(str_, fmt_, ...) \
     64 	xsnprintf((str_), sizeof(str_) + MUST_BE_ARRAY(str_), (fmt_), \
     65 		  __VA_ARGS__)
     66 
     67 static inline size_t
     68 get_pos_diff_(char *str, size_t size, char *pos, const char *func,
     69 	   const char *call)
     70 {
     71 	if ((str + size) < str)
     72 		error_msg_and_die("%s: string size overflow (%p+%zu) in %s",
     73 				  func, str, size, call);
     74 
     75 	if (pos > (str + size))
     76 		error_msg_and_die("%s: got position (%p) beyond string "
     77 				  "(%p+%zu) in %s",
     78 				  func, pos, str, size, call);
     79 
     80 	if (pos < str)
     81 		error_msg_and_die("%s: got position %p before string %p in %s",
     82 				  func, pos, str, call);
     83 
     84 	return pos - str;
     85 }
     86 
     87 /**
     88  * Helper function for constructing string in a character array by appending
     89  * new formatted parts.  Returns new position.  Fails on error or buffer
     90  * overflow, in line with the rest of x* functions.  Obtains buffer size via
     91  * sizeof(str_).
     92  *
     93  * @param str_  Character array buffer to print into.
     94  * @param pos_  Current position.
     95  * @param fmt_  Format string.
     96  * @param ...   Format arguments.
     97  * @return      New position.
     98  */
     99 #define xappendstr(str_, pos_, fmt_, ...) \
    100 	(xsnprintf((pos_), sizeof(str_) + MUST_BE_ARRAY(str_) - \
    101 		   get_pos_diff_((str_), sizeof(str_), (pos_), __func__, \
    102 				 "xappendstr(" #str_ ", " #pos_ ", " #fmt_ ", " \
    103 				 #__VA_ARGS__ ")"), \
    104 		   (fmt_), ##__VA_ARGS__) + (pos_))
    105 
    106 #endif /* !STRACE_XSTRING_H */
    107