seq_buf.c (10217B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * seq_buf.c 4 * 5 * Copyright (C) 2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 6 * 7 * The seq_buf is a handy tool that allows you to pass a descriptor around 8 * to a buffer that other functions can write to. It is similar to the 9 * seq_file functionality but has some differences. 10 * 11 * To use it, the seq_buf must be initialized with seq_buf_init(). 12 * This will set up the counters within the descriptor. You can call 13 * seq_buf_init() more than once to reset the seq_buf to start 14 * from scratch. 15 */ 16#include <linux/uaccess.h> 17#include <linux/seq_file.h> 18#include <linux/seq_buf.h> 19 20/** 21 * seq_buf_can_fit - can the new data fit in the current buffer? 22 * @s: the seq_buf descriptor 23 * @len: The length to see if it can fit in the current buffer 24 * 25 * Returns true if there's enough unused space in the seq_buf buffer 26 * to fit the amount of new data according to @len. 27 */ 28static bool seq_buf_can_fit(struct seq_buf *s, size_t len) 29{ 30 return s->len + len <= s->size; 31} 32 33/** 34 * seq_buf_print_seq - move the contents of seq_buf into a seq_file 35 * @m: the seq_file descriptor that is the destination 36 * @s: the seq_buf descriptor that is the source. 37 * 38 * Returns zero on success, non zero otherwise 39 */ 40int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s) 41{ 42 unsigned int len = seq_buf_used(s); 43 44 return seq_write(m, s->buffer, len); 45} 46 47/** 48 * seq_buf_vprintf - sequence printing of information. 49 * @s: seq_buf descriptor 50 * @fmt: printf format string 51 * @args: va_list of arguments from a printf() type function 52 * 53 * Writes a vnprintf() format into the sequencce buffer. 54 * 55 * Returns zero on success, -1 on overflow. 56 */ 57int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args) 58{ 59 int len; 60 61 WARN_ON(s->size == 0); 62 63 if (s->len < s->size) { 64 len = vsnprintf(s->buffer + s->len, s->size - s->len, fmt, args); 65 if (s->len + len < s->size) { 66 s->len += len; 67 return 0; 68 } 69 } 70 seq_buf_set_overflow(s); 71 return -1; 72} 73 74/** 75 * seq_buf_printf - sequence printing of information 76 * @s: seq_buf descriptor 77 * @fmt: printf format string 78 * 79 * Writes a printf() format into the sequence buffer. 80 * 81 * Returns zero on success, -1 on overflow. 82 */ 83int seq_buf_printf(struct seq_buf *s, const char *fmt, ...) 84{ 85 va_list ap; 86 int ret; 87 88 va_start(ap, fmt); 89 ret = seq_buf_vprintf(s, fmt, ap); 90 va_end(ap); 91 92 return ret; 93} 94EXPORT_SYMBOL_GPL(seq_buf_printf); 95 96#ifdef CONFIG_BINARY_PRINTF 97/** 98 * seq_buf_bprintf - Write the printf string from binary arguments 99 * @s: seq_buf descriptor 100 * @fmt: The format string for the @binary arguments 101 * @binary: The binary arguments for @fmt. 102 * 103 * When recording in a fast path, a printf may be recorded with just 104 * saving the format and the arguments as they were passed to the 105 * function, instead of wasting cycles converting the arguments into 106 * ASCII characters. Instead, the arguments are saved in a 32 bit 107 * word array that is defined by the format string constraints. 108 * 109 * This function will take the format and the binary array and finish 110 * the conversion into the ASCII string within the buffer. 111 * 112 * Returns zero on success, -1 on overflow. 113 */ 114int seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary) 115{ 116 unsigned int len = seq_buf_buffer_left(s); 117 int ret; 118 119 WARN_ON(s->size == 0); 120 121 if (s->len < s->size) { 122 ret = bstr_printf(s->buffer + s->len, len, fmt, binary); 123 if (s->len + ret < s->size) { 124 s->len += ret; 125 return 0; 126 } 127 } 128 seq_buf_set_overflow(s); 129 return -1; 130} 131#endif /* CONFIG_BINARY_PRINTF */ 132 133/** 134 * seq_buf_puts - sequence printing of simple string 135 * @s: seq_buf descriptor 136 * @str: simple string to record 137 * 138 * Copy a simple string into the sequence buffer. 139 * 140 * Returns zero on success, -1 on overflow 141 */ 142int seq_buf_puts(struct seq_buf *s, const char *str) 143{ 144 size_t len = strlen(str); 145 146 WARN_ON(s->size == 0); 147 148 /* Add 1 to len for the trailing null byte which must be there */ 149 len += 1; 150 151 if (seq_buf_can_fit(s, len)) { 152 memcpy(s->buffer + s->len, str, len); 153 /* Don't count the trailing null byte against the capacity */ 154 s->len += len - 1; 155 return 0; 156 } 157 seq_buf_set_overflow(s); 158 return -1; 159} 160 161/** 162 * seq_buf_putc - sequence printing of simple character 163 * @s: seq_buf descriptor 164 * @c: simple character to record 165 * 166 * Copy a single character into the sequence buffer. 167 * 168 * Returns zero on success, -1 on overflow 169 */ 170int seq_buf_putc(struct seq_buf *s, unsigned char c) 171{ 172 WARN_ON(s->size == 0); 173 174 if (seq_buf_can_fit(s, 1)) { 175 s->buffer[s->len++] = c; 176 return 0; 177 } 178 seq_buf_set_overflow(s); 179 return -1; 180} 181 182/** 183 * seq_buf_putmem - write raw data into the sequenc buffer 184 * @s: seq_buf descriptor 185 * @mem: The raw memory to copy into the buffer 186 * @len: The length of the raw memory to copy (in bytes) 187 * 188 * There may be cases where raw memory needs to be written into the 189 * buffer and a strcpy() would not work. Using this function allows 190 * for such cases. 191 * 192 * Returns zero on success, -1 on overflow 193 */ 194int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len) 195{ 196 WARN_ON(s->size == 0); 197 198 if (seq_buf_can_fit(s, len)) { 199 memcpy(s->buffer + s->len, mem, len); 200 s->len += len; 201 return 0; 202 } 203 seq_buf_set_overflow(s); 204 return -1; 205} 206 207#define MAX_MEMHEX_BYTES 8U 208#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1) 209 210/** 211 * seq_buf_putmem_hex - write raw memory into the buffer in ASCII hex 212 * @s: seq_buf descriptor 213 * @mem: The raw memory to write its hex ASCII representation of 214 * @len: The length of the raw memory to copy (in bytes) 215 * 216 * This is similar to seq_buf_putmem() except instead of just copying the 217 * raw memory into the buffer it writes its ASCII representation of it 218 * in hex characters. 219 * 220 * Returns zero on success, -1 on overflow 221 */ 222int seq_buf_putmem_hex(struct seq_buf *s, const void *mem, 223 unsigned int len) 224{ 225 unsigned char hex[HEX_CHARS]; 226 const unsigned char *data = mem; 227 unsigned int start_len; 228 int i, j; 229 230 WARN_ON(s->size == 0); 231 232 BUILD_BUG_ON(MAX_MEMHEX_BYTES * 2 >= HEX_CHARS); 233 234 while (len) { 235 start_len = min(len, MAX_MEMHEX_BYTES); 236#ifdef __BIG_ENDIAN 237 for (i = 0, j = 0; i < start_len; i++) { 238#else 239 for (i = start_len-1, j = 0; i >= 0; i--) { 240#endif 241 hex[j++] = hex_asc_hi(data[i]); 242 hex[j++] = hex_asc_lo(data[i]); 243 } 244 if (WARN_ON_ONCE(j == 0 || j/2 > len)) 245 break; 246 247 /* j increments twice per loop */ 248 hex[j++] = ' '; 249 250 seq_buf_putmem(s, hex, j); 251 if (seq_buf_has_overflowed(s)) 252 return -1; 253 254 len -= start_len; 255 data += start_len; 256 } 257 return 0; 258} 259 260/** 261 * seq_buf_path - copy a path into the sequence buffer 262 * @s: seq_buf descriptor 263 * @path: path to write into the sequence buffer. 264 * @esc: set of characters to escape in the output 265 * 266 * Write a path name into the sequence buffer. 267 * 268 * Returns the number of written bytes on success, -1 on overflow 269 */ 270int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc) 271{ 272 char *buf; 273 size_t size = seq_buf_get_buf(s, &buf); 274 int res = -1; 275 276 WARN_ON(s->size == 0); 277 278 if (size) { 279 char *p = d_path(path, buf, size); 280 if (!IS_ERR(p)) { 281 char *end = mangle_path(buf, p, esc); 282 if (end) 283 res = end - buf; 284 } 285 } 286 seq_buf_commit(s, res); 287 288 return res; 289} 290 291/** 292 * seq_buf_to_user - copy the sequence buffer to user space 293 * @s: seq_buf descriptor 294 * @ubuf: The userspace memory location to copy to 295 * @cnt: The amount to copy 296 * 297 * Copies the sequence buffer into the userspace memory pointed to 298 * by @ubuf. It starts from the last read position (@s->readpos) 299 * and writes up to @cnt characters or till it reaches the end of 300 * the content in the buffer (@s->len), which ever comes first. 301 * 302 * On success, it returns a positive number of the number of bytes 303 * it copied. 304 * 305 * On failure it returns -EBUSY if all of the content in the 306 * sequence has been already read, which includes nothing in the 307 * sequence (@s->len == @s->readpos). 308 * 309 * Returns -EFAULT if the copy to userspace fails. 310 */ 311int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt) 312{ 313 int len; 314 int ret; 315 316 if (!cnt) 317 return 0; 318 319 len = seq_buf_used(s); 320 321 if (len <= s->readpos) 322 return -EBUSY; 323 324 len -= s->readpos; 325 if (cnt > len) 326 cnt = len; 327 ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt); 328 if (ret == cnt) 329 return -EFAULT; 330 331 cnt -= ret; 332 333 s->readpos += cnt; 334 return cnt; 335} 336 337/** 338 * seq_buf_hex_dump - print formatted hex dump into the sequence buffer 339 * @s: seq_buf descriptor 340 * @prefix_str: string to prefix each line with; 341 * caller supplies trailing spaces for alignment if desired 342 * @prefix_type: controls whether prefix of an offset, address, or none 343 * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE) 344 * @rowsize: number of bytes to print per line; must be 16 or 32 345 * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1) 346 * @buf: data blob to dump 347 * @len: number of bytes in the @buf 348 * @ascii: include ASCII after the hex output 349 * 350 * Function is an analogue of print_hex_dump() and thus has similar interface. 351 * 352 * linebuf size is maximal length for one line. 353 * 32 * 3 - maximum bytes per line, each printed into 2 chars + 1 for 354 * separating space 355 * 2 - spaces separating hex dump and ascii representation 356 * 32 - ascii representation 357 * 1 - terminating '\0' 358 * 359 * Returns zero on success, -1 on overflow 360 */ 361int seq_buf_hex_dump(struct seq_buf *s, const char *prefix_str, int prefix_type, 362 int rowsize, int groupsize, 363 const void *buf, size_t len, bool ascii) 364{ 365 const u8 *ptr = buf; 366 int i, linelen, remaining = len; 367 unsigned char linebuf[32 * 3 + 2 + 32 + 1]; 368 int ret; 369 370 if (rowsize != 16 && rowsize != 32) 371 rowsize = 16; 372 373 for (i = 0; i < len; i += rowsize) { 374 linelen = min(remaining, rowsize); 375 remaining -= rowsize; 376 377 hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize, 378 linebuf, sizeof(linebuf), ascii); 379 380 switch (prefix_type) { 381 case DUMP_PREFIX_ADDRESS: 382 ret = seq_buf_printf(s, "%s%p: %s\n", 383 prefix_str, ptr + i, linebuf); 384 break; 385 case DUMP_PREFIX_OFFSET: 386 ret = seq_buf_printf(s, "%s%.8x: %s\n", 387 prefix_str, i, linebuf); 388 break; 389 default: 390 ret = seq_buf_printf(s, "%s%s\n", prefix_str, linebuf); 391 break; 392 } 393 if (ret) 394 return ret; 395 } 396 return 0; 397}