1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_SEQ_BUF_H 3 #define _LINUX_SEQ_BUF_H 4 5 #include <linux/fs.h> 6 7 /* 8 * Trace sequences are used to allow a function to call several other functions 9 * to create a string of data to use. 10 */ 11 12 /** 13 * seq_buf - seq buffer structure 14 * @buffer: pointer to the buffer 15 * @size: size of the buffer 16 * @len: the amount of data inside the buffer 17 */ 18 struct seq_buf { 19 char *buffer; 20 size_t size; 21 size_t len; 22 }; 23 24 static inline void seq_buf_clear(struct seq_buf *s) 25 { 26 s->len = 0; 27 } 28 29 static inline void 30 seq_buf_init(struct seq_buf *s, char *buf, unsigned int size) 31 { 32 s->buffer = buf; 33 s->size = size; 34 seq_buf_clear(s); 35 } 36 37 /* 38 * seq_buf have a buffer that might overflow. When this happens 39 * the len and size are set to be equal. 40 */ 41 static inline bool 42 seq_buf_has_overflowed(struct seq_buf *s) 43 { 44 return s->len > s->size; 45 } 46 47 static inline void 48 seq_buf_set_overflow(struct seq_buf *s) 49 { 50 s->len = s->size + 1; 51 } 52 53 /* 54 * How much buffer is left on the seq_buf? 55 */ 56 static inline unsigned int 57 seq_buf_buffer_left(struct seq_buf *s) 58 { 59 if (seq_buf_has_overflowed(s)) 60 return 0; 61 62 return s->size - s->len; 63 } 64 65 /* How much buffer was written? */ 66 static inline unsigned int seq_buf_used(struct seq_buf *s) 67 { 68 return min(s->len, s->size); 69 } 70 71 /** 72 * seq_buf_terminate - Make sure buffer is nul terminated 73 * @s: the seq_buf descriptor to terminate. 74 * 75 * This makes sure that the buffer in @s is nul terminated and 76 * safe to read as a string. 77 * 78 * Note, if this is called when the buffer has overflowed, then 79 * the last byte of the buffer is zeroed, and the len will still 80 * point passed it. 81 * 82 * After this function is called, s->buffer is safe to use 83 * in string operations. 84 */ 85 static inline void seq_buf_terminate(struct seq_buf *s) 86 { 87 if (WARN_ON(s->size == 0)) 88 return; 89 90 if (seq_buf_buffer_left(s)) 91 s->buffer[s->len] = 0; 92 else 93 s->buffer[s->size - 1] = 0; 94 } 95 96 /** 97 * seq_buf_get_buf - get buffer to write arbitrary data to 98 * @s: the seq_buf handle 99 * @bufp: the beginning of the buffer is stored here 100 * 101 * Return the number of bytes available in the buffer, or zero if 102 * there's no space. 103 */ 104 static inline size_t seq_buf_get_buf(struct seq_buf *s, char **bufp) 105 { 106 WARN_ON(s->len > s->size + 1); 107 108 if (s->len < s->size) { 109 *bufp = s->buffer + s->len; 110 return s->size - s->len; 111 } 112 113 *bufp = NULL; 114 return 0; 115 } 116 117 /** 118 * seq_buf_commit - commit data to the buffer 119 * @s: the seq_buf handle 120 * @num: the number of bytes to commit 121 * 122 * Commit @num bytes of data written to a buffer previously acquired 123 * by seq_buf_get. To signal an error condition, or that the data 124 * didn't fit in the available space, pass a negative @num value. 125 */ 126 static inline void seq_buf_commit(struct seq_buf *s, int num) 127 { 128 if (num < 0) { 129 seq_buf_set_overflow(s); 130 } else { 131 /* num must be negative on overflow */ 132 BUG_ON(s->len + num > s->size); 133 s->len += num; 134 } 135 } 136 137 extern __printf(2, 3) 138 int seq_buf_printf(struct seq_buf *s, const char *fmt, ...); 139 extern __printf(2, 0) 140 int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args); 141 extern int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s); 142 extern int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, 143 size_t start, int cnt); 144 extern int seq_buf_puts(struct seq_buf *s, const char *str); 145 extern int seq_buf_putc(struct seq_buf *s, unsigned char c); 146 extern int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len); 147 extern int seq_buf_putmem_hex(struct seq_buf *s, const void *mem, 148 unsigned int len); 149 extern int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc); 150 extern int seq_buf_hex_dump(struct seq_buf *s, const char *prefix_str, 151 int prefix_type, int rowsize, int groupsize, 152 const void *buf, size_t len, bool ascii); 153 154 #ifdef CONFIG_BINARY_PRINTF 155 extern int 156 seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary); 157 #endif 158 159 void seq_buf_do_printk(struct seq_buf *s, const char *lvl); 160 161 #endif /* _LINUX_SEQ_BUF_H */ 162