xref: /openbmc/linux/include/linux/seq_buf.h (revision 96928d90)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
23a161d99SSteven Rostedt (Red Hat) #ifndef _LINUX_SEQ_BUF_H
33a161d99SSteven Rostedt (Red Hat) #define _LINUX_SEQ_BUF_H
43a161d99SSteven Rostedt (Red Hat) 
53a161d99SSteven Rostedt (Red Hat) #include <linux/fs.h>
63a161d99SSteven Rostedt (Red Hat) 
73a161d99SSteven Rostedt (Red Hat) /*
83a161d99SSteven Rostedt (Red Hat)  * Trace sequences are used to allow a function to call several other functions
93a161d99SSteven Rostedt (Red Hat)  * to create a string of data to use.
103a161d99SSteven Rostedt (Red Hat)  */
113a161d99SSteven Rostedt (Red Hat) 
123a161d99SSteven Rostedt (Red Hat) /**
133a161d99SSteven Rostedt (Red Hat)  * seq_buf - seq buffer structure
143a161d99SSteven Rostedt (Red Hat)  * @buffer:	pointer to the buffer
153a161d99SSteven Rostedt (Red Hat)  * @size:	size of the buffer
163a161d99SSteven Rostedt (Red Hat)  * @len:	the amount of data inside the buffer
173a161d99SSteven Rostedt (Red Hat)  * @readpos:	The next position to read in the buffer.
183a161d99SSteven Rostedt (Red Hat)  */
193a161d99SSteven Rostedt (Red Hat) struct seq_buf {
209a777793SSteven Rostedt (Red Hat) 	char			*buffer;
219a777793SSteven Rostedt (Red Hat) 	size_t			size;
229a777793SSteven Rostedt (Red Hat) 	size_t			len;
239a777793SSteven Rostedt (Red Hat) 	loff_t			readpos;
243a161d99SSteven Rostedt (Red Hat) };
253a161d99SSteven Rostedt (Red Hat) 
seq_buf_clear(struct seq_buf * s)260736c033SSteven Rostedt (Red Hat) static inline void seq_buf_clear(struct seq_buf *s)
270736c033SSteven Rostedt (Red Hat) {
280736c033SSteven Rostedt (Red Hat) 	s->len = 0;
290736c033SSteven Rostedt (Red Hat) 	s->readpos = 0;
300736c033SSteven Rostedt (Red Hat) }
310736c033SSteven Rostedt (Red Hat) 
323a161d99SSteven Rostedt (Red Hat) static inline void
seq_buf_init(struct seq_buf * s,char * buf,unsigned int size)33d9a9280aSArnd Bergmann seq_buf_init(struct seq_buf *s, char *buf, unsigned int size)
343a161d99SSteven Rostedt (Red Hat) {
353a161d99SSteven Rostedt (Red Hat) 	s->buffer = buf;
363a161d99SSteven Rostedt (Red Hat) 	s->size = size;
370736c033SSteven Rostedt (Red Hat) 	seq_buf_clear(s);
383a161d99SSteven Rostedt (Red Hat) }
393a161d99SSteven Rostedt (Red Hat) 
403a161d99SSteven Rostedt (Red Hat) /*
413a161d99SSteven Rostedt (Red Hat)  * seq_buf have a buffer that might overflow. When this happens
423a161d99SSteven Rostedt (Red Hat)  * the len and size are set to be equal.
433a161d99SSteven Rostedt (Red Hat)  */
443a161d99SSteven Rostedt (Red Hat) static inline bool
seq_buf_has_overflowed(struct seq_buf * s)453a161d99SSteven Rostedt (Red Hat) seq_buf_has_overflowed(struct seq_buf *s)
463a161d99SSteven Rostedt (Red Hat) {
478cd709aeSSteven Rostedt (Red Hat) 	return s->len > s->size;
483a161d99SSteven Rostedt (Red Hat) }
493a161d99SSteven Rostedt (Red Hat) 
503a161d99SSteven Rostedt (Red Hat) static inline void
seq_buf_set_overflow(struct seq_buf * s)513a161d99SSteven Rostedt (Red Hat) seq_buf_set_overflow(struct seq_buf *s)
523a161d99SSteven Rostedt (Red Hat) {
538cd709aeSSteven Rostedt (Red Hat) 	s->len = s->size + 1;
543a161d99SSteven Rostedt (Red Hat) }
553a161d99SSteven Rostedt (Red Hat) 
563a161d99SSteven Rostedt (Red Hat) /*
573a161d99SSteven Rostedt (Red Hat)  * How much buffer is left on the seq_buf?
583a161d99SSteven Rostedt (Red Hat)  */
593a161d99SSteven Rostedt (Red Hat) static inline unsigned int
seq_buf_buffer_left(struct seq_buf * s)603a161d99SSteven Rostedt (Red Hat) seq_buf_buffer_left(struct seq_buf *s)
613a161d99SSteven Rostedt (Red Hat) {
623a161d99SSteven Rostedt (Red Hat) 	if (seq_buf_has_overflowed(s))
633a161d99SSteven Rostedt (Red Hat) 		return 0;
643a161d99SSteven Rostedt (Red Hat) 
658cd709aeSSteven Rostedt (Red Hat) 	return s->size - s->len;
663a161d99SSteven Rostedt (Red Hat) }
673a161d99SSteven Rostedt (Red Hat) 
68eeab9815SSteven Rostedt (Red Hat) /* How much buffer was written? */
seq_buf_used(struct seq_buf * s)69eeab9815SSteven Rostedt (Red Hat) static inline unsigned int seq_buf_used(struct seq_buf *s)
70eeab9815SSteven Rostedt (Red Hat) {
71eeab9815SSteven Rostedt (Red Hat) 	return min(s->len, s->size);
72eeab9815SSteven Rostedt (Red Hat) }
73eeab9815SSteven Rostedt (Red Hat) 
7401cb06a4SSteven Rostedt (Red Hat) /**
75f2616c77SSteven Rostedt (VMware)  * seq_buf_terminate - Make sure buffer is nul terminated
76f2616c77SSteven Rostedt (VMware)  * @s: the seq_buf descriptor to terminate.
77f2616c77SSteven Rostedt (VMware)  *
78f2616c77SSteven Rostedt (VMware)  * This makes sure that the buffer in @s is nul terminated and
79f2616c77SSteven Rostedt (VMware)  * safe to read as a string.
80f2616c77SSteven Rostedt (VMware)  *
81f2616c77SSteven Rostedt (VMware)  * Note, if this is called when the buffer has overflowed, then
82f2616c77SSteven Rostedt (VMware)  * the last byte of the buffer is zeroed, and the len will still
83f2616c77SSteven Rostedt (VMware)  * point passed it.
84f2616c77SSteven Rostedt (VMware)  *
85f2616c77SSteven Rostedt (VMware)  * After this function is called, s->buffer is safe to use
86f2616c77SSteven Rostedt (VMware)  * in string operations.
87f2616c77SSteven Rostedt (VMware)  */
seq_buf_terminate(struct seq_buf * s)88f2616c77SSteven Rostedt (VMware) static inline void seq_buf_terminate(struct seq_buf *s)
89f2616c77SSteven Rostedt (VMware) {
90f2616c77SSteven Rostedt (VMware) 	if (WARN_ON(s->size == 0))
91f2616c77SSteven Rostedt (VMware) 		return;
92f2616c77SSteven Rostedt (VMware) 
93f2616c77SSteven Rostedt (VMware) 	if (seq_buf_buffer_left(s))
94f2616c77SSteven Rostedt (VMware) 		s->buffer[s->len] = 0;
95f2616c77SSteven Rostedt (VMware) 	else
96f2616c77SSteven Rostedt (VMware) 		s->buffer[s->size - 1] = 0;
97f2616c77SSteven Rostedt (VMware) }
98f2616c77SSteven Rostedt (VMware) 
99f2616c77SSteven Rostedt (VMware) /**
10001cb06a4SSteven Rostedt (Red Hat)  * seq_buf_get_buf - get buffer to write arbitrary data to
10101cb06a4SSteven Rostedt (Red Hat)  * @s: the seq_buf handle
10201cb06a4SSteven Rostedt (Red Hat)  * @bufp: the beginning of the buffer is stored here
10301cb06a4SSteven Rostedt (Red Hat)  *
10401cb06a4SSteven Rostedt (Red Hat)  * Return the number of bytes available in the buffer, or zero if
10501cb06a4SSteven Rostedt (Red Hat)  * there's no space.
10601cb06a4SSteven Rostedt (Red Hat)  */
seq_buf_get_buf(struct seq_buf * s,char ** bufp)10701cb06a4SSteven Rostedt (Red Hat) static inline size_t seq_buf_get_buf(struct seq_buf *s, char **bufp)
10801cb06a4SSteven Rostedt (Red Hat) {
10901cb06a4SSteven Rostedt (Red Hat) 	WARN_ON(s->len > s->size + 1);
11001cb06a4SSteven Rostedt (Red Hat) 
11101cb06a4SSteven Rostedt (Red Hat) 	if (s->len < s->size) {
11201cb06a4SSteven Rostedt (Red Hat) 		*bufp = s->buffer + s->len;
11301cb06a4SSteven Rostedt (Red Hat) 		return s->size - s->len;
11401cb06a4SSteven Rostedt (Red Hat) 	}
11501cb06a4SSteven Rostedt (Red Hat) 
11601cb06a4SSteven Rostedt (Red Hat) 	*bufp = NULL;
11701cb06a4SSteven Rostedt (Red Hat) 	return 0;
11801cb06a4SSteven Rostedt (Red Hat) }
11901cb06a4SSteven Rostedt (Red Hat) 
12001cb06a4SSteven Rostedt (Red Hat) /**
12101cb06a4SSteven Rostedt (Red Hat)  * seq_buf_commit - commit data to the buffer
12201cb06a4SSteven Rostedt (Red Hat)  * @s: the seq_buf handle
12301cb06a4SSteven Rostedt (Red Hat)  * @num: the number of bytes to commit
12401cb06a4SSteven Rostedt (Red Hat)  *
12501cb06a4SSteven Rostedt (Red Hat)  * Commit @num bytes of data written to a buffer previously acquired
12601cb06a4SSteven Rostedt (Red Hat)  * by seq_buf_get.  To signal an error condition, or that the data
12701cb06a4SSteven Rostedt (Red Hat)  * didn't fit in the available space, pass a negative @num value.
12801cb06a4SSteven Rostedt (Red Hat)  */
seq_buf_commit(struct seq_buf * s,int num)12901cb06a4SSteven Rostedt (Red Hat) static inline void seq_buf_commit(struct seq_buf *s, int num)
13001cb06a4SSteven Rostedt (Red Hat) {
13101cb06a4SSteven Rostedt (Red Hat) 	if (num < 0) {
13201cb06a4SSteven Rostedt (Red Hat) 		seq_buf_set_overflow(s);
13301cb06a4SSteven Rostedt (Red Hat) 	} else {
13401cb06a4SSteven Rostedt (Red Hat) 		/* num must be negative on overflow */
13501cb06a4SSteven Rostedt (Red Hat) 		BUG_ON(s->len + num > s->size);
13601cb06a4SSteven Rostedt (Red Hat) 		s->len += num;
13701cb06a4SSteven Rostedt (Red Hat) 	}
13801cb06a4SSteven Rostedt (Red Hat) }
13901cb06a4SSteven Rostedt (Red Hat) 
1403a161d99SSteven Rostedt (Red Hat) extern __printf(2, 3)
1413a161d99SSteven Rostedt (Red Hat) int seq_buf_printf(struct seq_buf *s, const char *fmt, ...);
1423a161d99SSteven Rostedt (Red Hat) extern __printf(2, 0)
1433a161d99SSteven Rostedt (Red Hat) int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args);
1443a161d99SSteven Rostedt (Red Hat) extern int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s);
1453a161d99SSteven Rostedt (Red Hat) extern int seq_buf_to_user(struct seq_buf *s, char __user *ubuf,
1463a161d99SSteven Rostedt (Red Hat) 			   int cnt);
1473a161d99SSteven Rostedt (Red Hat) extern int seq_buf_puts(struct seq_buf *s, const char *str);
1483a161d99SSteven Rostedt (Red Hat) extern int seq_buf_putc(struct seq_buf *s, unsigned char c);
1493a161d99SSteven Rostedt (Red Hat) extern int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len);
1503a161d99SSteven Rostedt (Red Hat) extern int seq_buf_putmem_hex(struct seq_buf *s, const void *mem,
1513a161d99SSteven Rostedt (Red Hat) 			      unsigned int len);
152dd23180aSSteven Rostedt (Red Hat) extern int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc);
153353cade3SPiotr Maziarz extern int seq_buf_hex_dump(struct seq_buf *s, const char *prefix_str,
154353cade3SPiotr Maziarz 			    int prefix_type, int rowsize, int groupsize,
155353cade3SPiotr Maziarz 			    const void *buf, size_t len, bool ascii);
1563a161d99SSteven Rostedt (Red Hat) 
1572448913eSSteven Rostedt (Red Hat) #ifdef CONFIG_BINARY_PRINTF
1582448913eSSteven Rostedt (Red Hat) extern int
1592448913eSSteven Rostedt (Red Hat) seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary);
1602448913eSSteven Rostedt (Red Hat) #endif
1612448913eSSteven Rostedt (Red Hat) 
162*96928d90SSergey Senozhatsky void seq_buf_do_printk(struct seq_buf *s, const char *lvl);
163*96928d90SSergey Senozhatsky 
1643a161d99SSteven Rostedt (Red Hat) #endif /* _LINUX_SEQ_BUF_H */
165