0001
0002
0003
0004
0005
0006 #include "trace-seq.h"
0007
0008 #include <stdio.h>
0009 #include <stdlib.h>
0010 #include <string.h>
0011 #include <stdarg.h>
0012
0013 #include <asm/bug.h>
0014 #include "event-parse.h"
0015 #include "event-utils.h"
0016
0017
0018
0019
0020
0021 #define TRACE_SEQ_POISON ((void *)0xdeadbeef)
0022 #define TRACE_SEQ_CHECK(s) \
0023 do { \
0024 if (WARN_ONCE((s)->buffer == TRACE_SEQ_POISON, \
0025 "Usage of trace_seq after it was destroyed")) \
0026 (s)->state = TRACE_SEQ__BUFFER_POISONED; \
0027 } while (0)
0028
0029 #define TRACE_SEQ_CHECK_RET_N(s, n) \
0030 do { \
0031 TRACE_SEQ_CHECK(s); \
0032 if ((s)->state != TRACE_SEQ__GOOD) \
0033 return n; \
0034 } while (0)
0035
0036 #define TRACE_SEQ_CHECK_RET(s) TRACE_SEQ_CHECK_RET_N(s, )
0037 #define TRACE_SEQ_CHECK_RET0(s) TRACE_SEQ_CHECK_RET_N(s, 0)
0038
0039
0040
0041
0042
0043 void trace_seq_init(struct trace_seq *s)
0044 {
0045 s->len = 0;
0046 s->readpos = 0;
0047 s->buffer_size = TRACE_SEQ_BUF_SIZE;
0048 s->buffer = malloc(s->buffer_size);
0049 if (s->buffer != NULL)
0050 s->state = TRACE_SEQ__GOOD;
0051 else
0052 s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
0053 }
0054
0055
0056
0057
0058
0059 void trace_seq_reset(struct trace_seq *s)
0060 {
0061 if (!s)
0062 return;
0063 TRACE_SEQ_CHECK(s);
0064 s->len = 0;
0065 s->readpos = 0;
0066 }
0067
0068
0069
0070
0071
0072
0073
0074 void trace_seq_destroy(struct trace_seq *s)
0075 {
0076 if (!s)
0077 return;
0078 TRACE_SEQ_CHECK_RET(s);
0079 free(s->buffer);
0080 s->buffer = TRACE_SEQ_POISON;
0081 }
0082
0083 static void expand_buffer(struct trace_seq *s)
0084 {
0085 char *buf;
0086
0087 buf = realloc(s->buffer, s->buffer_size + TRACE_SEQ_BUF_SIZE);
0088 if (WARN_ONCE(!buf, "Can't allocate trace_seq buffer memory")) {
0089 s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
0090 return;
0091 }
0092
0093 s->buffer = buf;
0094 s->buffer_size += TRACE_SEQ_BUF_SIZE;
0095 }
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 int
0113 trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
0114 {
0115 va_list ap;
0116 int len;
0117 int ret;
0118
0119 try_again:
0120 TRACE_SEQ_CHECK_RET0(s);
0121
0122 len = (s->buffer_size - 1) - s->len;
0123
0124 va_start(ap, fmt);
0125 ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
0126 va_end(ap);
0127
0128 if (ret >= len) {
0129 expand_buffer(s);
0130 goto try_again;
0131 }
0132
0133 if (ret > 0)
0134 s->len += ret;
0135
0136 return ret;
0137 }
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 int
0155 trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
0156 {
0157 int len;
0158 int ret;
0159
0160 try_again:
0161 TRACE_SEQ_CHECK_RET0(s);
0162
0163 len = (s->buffer_size - 1) - s->len;
0164
0165 ret = vsnprintf(s->buffer + s->len, len, fmt, args);
0166
0167 if (ret >= len) {
0168 expand_buffer(s);
0169 goto try_again;
0170 }
0171
0172 if (ret > 0)
0173 s->len += ret;
0174
0175 return ret;
0176 }
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 int trace_seq_puts(struct trace_seq *s, const char *str)
0189 {
0190 int len;
0191
0192 TRACE_SEQ_CHECK_RET0(s);
0193
0194 len = strlen(str);
0195
0196 while (len > ((s->buffer_size - 1) - s->len))
0197 expand_buffer(s);
0198
0199 TRACE_SEQ_CHECK_RET0(s);
0200
0201 memcpy(s->buffer + s->len, str, len);
0202 s->len += len;
0203
0204 return len;
0205 }
0206
0207 int trace_seq_putc(struct trace_seq *s, unsigned char c)
0208 {
0209 TRACE_SEQ_CHECK_RET0(s);
0210
0211 while (s->len >= (s->buffer_size - 1))
0212 expand_buffer(s);
0213
0214 TRACE_SEQ_CHECK_RET0(s);
0215
0216 s->buffer[s->len++] = c;
0217
0218 return 1;
0219 }
0220
0221 void trace_seq_terminate(struct trace_seq *s)
0222 {
0223 TRACE_SEQ_CHECK_RET(s);
0224
0225
0226 s->buffer[s->len] = 0;
0227 }
0228
0229 int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp)
0230 {
0231 TRACE_SEQ_CHECK(s);
0232
0233 switch (s->state) {
0234 case TRACE_SEQ__GOOD:
0235 return fprintf(fp, "%.*s", s->len, s->buffer);
0236 case TRACE_SEQ__BUFFER_POISONED:
0237 fprintf(fp, "%s\n", "Usage of trace_seq after it was destroyed");
0238 break;
0239 case TRACE_SEQ__MEM_ALLOC_FAILED:
0240 fprintf(fp, "%s\n", "Can't allocate trace_seq buffer memory");
0241 break;
0242 }
0243 return -1;
0244 }
0245
0246 int trace_seq_do_printf(struct trace_seq *s)
0247 {
0248 return trace_seq_do_fprintf(s, stdout);
0249 }