at v3.7-rc3 200 lines 4.8 kB view raw
1/* 2 * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 3 * 4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; 8 * version 2.1 of the License (not later!) 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20 */ 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <stdarg.h> 25 26#include "event-parse.h" 27#include "event-utils.h" 28 29/* 30 * The TRACE_SEQ_POISON is to catch the use of using 31 * a trace_seq structure after it was destroyed. 32 */ 33#define TRACE_SEQ_POISON ((void *)0xdeadbeef) 34#define TRACE_SEQ_CHECK(s) \ 35do { \ 36 if ((s)->buffer == TRACE_SEQ_POISON) \ 37 die("Usage of trace_seq after it was destroyed"); \ 38} while (0) 39 40/** 41 * trace_seq_init - initialize the trace_seq structure 42 * @s: a pointer to the trace_seq structure to initialize 43 */ 44void trace_seq_init(struct trace_seq *s) 45{ 46 s->len = 0; 47 s->readpos = 0; 48 s->buffer_size = TRACE_SEQ_BUF_SIZE; 49 s->buffer = malloc_or_die(s->buffer_size); 50} 51 52/** 53 * trace_seq_destroy - free up memory of a trace_seq 54 * @s: a pointer to the trace_seq to free the buffer 55 * 56 * Only frees the buffer, not the trace_seq struct itself. 57 */ 58void trace_seq_destroy(struct trace_seq *s) 59{ 60 if (!s) 61 return; 62 TRACE_SEQ_CHECK(s); 63 free(s->buffer); 64 s->buffer = TRACE_SEQ_POISON; 65} 66 67static void expand_buffer(struct trace_seq *s) 68{ 69 s->buffer_size += TRACE_SEQ_BUF_SIZE; 70 s->buffer = realloc(s->buffer, s->buffer_size); 71 if (!s->buffer) 72 die("Can't allocate trace_seq buffer memory"); 73} 74 75/** 76 * trace_seq_printf - sequence printing of trace information 77 * @s: trace sequence descriptor 78 * @fmt: printf format string 79 * 80 * It returns 0 if the trace oversizes the buffer's free 81 * space, 1 otherwise. 82 * 83 * The tracer may use either sequence operations or its own 84 * copy to user routines. To simplify formating of a trace 85 * trace_seq_printf is used to store strings into a special 86 * buffer (@s). Then the output may be either used by 87 * the sequencer or pulled into another buffer. 88 */ 89int 90trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 91{ 92 va_list ap; 93 int len; 94 int ret; 95 96 TRACE_SEQ_CHECK(s); 97 98 try_again: 99 len = (s->buffer_size - 1) - s->len; 100 101 va_start(ap, fmt); 102 ret = vsnprintf(s->buffer + s->len, len, fmt, ap); 103 va_end(ap); 104 105 if (ret >= len) { 106 expand_buffer(s); 107 goto try_again; 108 } 109 110 s->len += ret; 111 112 return 1; 113} 114 115/** 116 * trace_seq_vprintf - sequence printing of trace information 117 * @s: trace sequence descriptor 118 * @fmt: printf format string 119 * 120 * The tracer may use either sequence operations or its own 121 * copy to user routines. To simplify formating of a trace 122 * trace_seq_printf is used to store strings into a special 123 * buffer (@s). Then the output may be either used by 124 * the sequencer or pulled into another buffer. 125 */ 126int 127trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) 128{ 129 int len; 130 int ret; 131 132 TRACE_SEQ_CHECK(s); 133 134 try_again: 135 len = (s->buffer_size - 1) - s->len; 136 137 ret = vsnprintf(s->buffer + s->len, len, fmt, args); 138 139 if (ret >= len) { 140 expand_buffer(s); 141 goto try_again; 142 } 143 144 s->len += ret; 145 146 return len; 147} 148 149/** 150 * trace_seq_puts - trace sequence printing of simple string 151 * @s: trace sequence descriptor 152 * @str: simple string to record 153 * 154 * The tracer may use either the sequence operations or its own 155 * copy to user routines. This function records a simple string 156 * into a special buffer (@s) for later retrieval by a sequencer 157 * or other mechanism. 158 */ 159int trace_seq_puts(struct trace_seq *s, const char *str) 160{ 161 int len; 162 163 TRACE_SEQ_CHECK(s); 164 165 len = strlen(str); 166 167 while (len > ((s->buffer_size - 1) - s->len)) 168 expand_buffer(s); 169 170 memcpy(s->buffer + s->len, str, len); 171 s->len += len; 172 173 return len; 174} 175 176int trace_seq_putc(struct trace_seq *s, unsigned char c) 177{ 178 TRACE_SEQ_CHECK(s); 179 180 while (s->len >= (s->buffer_size - 1)) 181 expand_buffer(s); 182 183 s->buffer[s->len++] = c; 184 185 return 1; 186} 187 188void trace_seq_terminate(struct trace_seq *s) 189{ 190 TRACE_SEQ_CHECK(s); 191 192 /* There's always one character left on the buffer */ 193 s->buffer[s->len] = 0; 194} 195 196int trace_seq_do_printf(struct trace_seq *s) 197{ 198 TRACE_SEQ_CHECK(s); 199 return printf("%.*s", s->len, s->buffer); 200}