xref: /linux-6.15/include/linux/seq_buf.h (revision d0ed46b6)
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