Back to home page

LXR

 
 

    


0001 /*
0002  * seq_buf.c
0003  *
0004  * Copyright (C) 2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
0005  *
0006  * The seq_buf is a handy tool that allows you to pass a descriptor around
0007  * to a buffer that other functions can write to. It is similar to the
0008  * seq_file functionality but has some differences.
0009  *
0010  * To use it, the seq_buf must be initialized with seq_buf_init().
0011  * This will set up the counters within the descriptor. You can call
0012  * seq_buf_init() more than once to reset the seq_buf to start
0013  * from scratch.
0014  */
0015 #include <linux/uaccess.h>
0016 #include <linux/seq_file.h>
0017 #include <linux/seq_buf.h>
0018 
0019 /**
0020  * seq_buf_can_fit - can the new data fit in the current buffer?
0021  * @s: the seq_buf descriptor
0022  * @len: The length to see if it can fit in the current buffer
0023  *
0024  * Returns true if there's enough unused space in the seq_buf buffer
0025  * to fit the amount of new data according to @len.
0026  */
0027 static bool seq_buf_can_fit(struct seq_buf *s, size_t len)
0028 {
0029     return s->len + len <= s->size;
0030 }
0031 
0032 /**
0033  * seq_buf_print_seq - move the contents of seq_buf into a seq_file
0034  * @m: the seq_file descriptor that is the destination
0035  * @s: the seq_buf descriptor that is the source.
0036  *
0037  * Returns zero on success, non zero otherwise
0038  */
0039 int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s)
0040 {
0041     unsigned int len = seq_buf_used(s);
0042 
0043     return seq_write(m, s->buffer, len);
0044 }
0045 
0046 /**
0047  * seq_buf_vprintf - sequence printing of information.
0048  * @s: seq_buf descriptor
0049  * @fmt: printf format string
0050  * @args: va_list of arguments from a printf() type function
0051  *
0052  * Writes a vnprintf() format into the sequencce buffer.
0053  *
0054  * Returns zero on success, -1 on overflow.
0055  */
0056 int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args)
0057 {
0058     int len;
0059 
0060     WARN_ON(s->size == 0);
0061 
0062     if (s->len < s->size) {
0063         len = vsnprintf(s->buffer + s->len, s->size - s->len, fmt, args);
0064         if (s->len + len < s->size) {
0065             s->len += len;
0066             return 0;
0067         }
0068     }
0069     seq_buf_set_overflow(s);
0070     return -1;
0071 }
0072 
0073 /**
0074  * seq_buf_printf - sequence printing of information
0075  * @s: seq_buf descriptor
0076  * @fmt: printf format string
0077  *
0078  * Writes a printf() format into the sequence buffer.
0079  *
0080  * Returns zero on success, -1 on overflow.
0081  */
0082 int seq_buf_printf(struct seq_buf *s, const char *fmt, ...)
0083 {
0084     va_list ap;
0085     int ret;
0086 
0087     va_start(ap, fmt);
0088     ret = seq_buf_vprintf(s, fmt, ap);
0089     va_end(ap);
0090 
0091     return ret;
0092 }
0093 
0094 #ifdef CONFIG_BINARY_PRINTF
0095 /**
0096  * seq_buf_bprintf - Write the printf string from binary arguments
0097  * @s: seq_buf descriptor
0098  * @fmt: The format string for the @binary arguments
0099  * @binary: The binary arguments for @fmt.
0100  *
0101  * When recording in a fast path, a printf may be recorded with just
0102  * saving the format and the arguments as they were passed to the
0103  * function, instead of wasting cycles converting the arguments into
0104  * ASCII characters. Instead, the arguments are saved in a 32 bit
0105  * word array that is defined by the format string constraints.
0106  *
0107  * This function will take the format and the binary array and finish
0108  * the conversion into the ASCII string within the buffer.
0109  *
0110  * Returns zero on success, -1 on overflow.
0111  */
0112 int seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary)
0113 {
0114     unsigned int len = seq_buf_buffer_left(s);
0115     int ret;
0116 
0117     WARN_ON(s->size == 0);
0118 
0119     if (s->len < s->size) {
0120         ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
0121         if (s->len + ret < s->size) {
0122             s->len += ret;
0123             return 0;
0124         }
0125     }
0126     seq_buf_set_overflow(s);
0127     return -1;
0128 }
0129 #endif /* CONFIG_BINARY_PRINTF */
0130 
0131 /**
0132  * seq_buf_puts - sequence printing of simple string
0133  * @s: seq_buf descriptor
0134  * @str: simple string to record
0135  *
0136  * Copy a simple string into the sequence buffer.
0137  *
0138  * Returns zero on success, -1 on overflow
0139  */
0140 int seq_buf_puts(struct seq_buf *s, const char *str)
0141 {
0142     unsigned int len = strlen(str);
0143 
0144     WARN_ON(s->size == 0);
0145 
0146     if (seq_buf_can_fit(s, len)) {
0147         memcpy(s->buffer + s->len, str, len);
0148         s->len += len;
0149         return 0;
0150     }
0151     seq_buf_set_overflow(s);
0152     return -1;
0153 }
0154 
0155 /**
0156  * seq_buf_putc - sequence printing of simple character
0157  * @s: seq_buf descriptor
0158  * @c: simple character to record
0159  *
0160  * Copy a single character into the sequence buffer.
0161  *
0162  * Returns zero on success, -1 on overflow
0163  */
0164 int seq_buf_putc(struct seq_buf *s, unsigned char c)
0165 {
0166     WARN_ON(s->size == 0);
0167 
0168     if (seq_buf_can_fit(s, 1)) {
0169         s->buffer[s->len++] = c;
0170         return 0;
0171     }
0172     seq_buf_set_overflow(s);
0173     return -1;
0174 }
0175 
0176 /**
0177  * seq_buf_putmem - write raw data into the sequenc buffer
0178  * @s: seq_buf descriptor
0179  * @mem: The raw memory to copy into the buffer
0180  * @len: The length of the raw memory to copy (in bytes)
0181  *
0182  * There may be cases where raw memory needs to be written into the
0183  * buffer and a strcpy() would not work. Using this function allows
0184  * for such cases.
0185  *
0186  * Returns zero on success, -1 on overflow
0187  */
0188 int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len)
0189 {
0190     WARN_ON(s->size == 0);
0191 
0192     if (seq_buf_can_fit(s, len)) {
0193         memcpy(s->buffer + s->len, mem, len);
0194         s->len += len;
0195         return 0;
0196     }
0197     seq_buf_set_overflow(s);
0198     return -1;
0199 }
0200 
0201 #define MAX_MEMHEX_BYTES    8U
0202 #define HEX_CHARS       (MAX_MEMHEX_BYTES*2 + 1)
0203 
0204 /**
0205  * seq_buf_putmem_hex - write raw memory into the buffer in ASCII hex
0206  * @s: seq_buf descriptor
0207  * @mem: The raw memory to write its hex ASCII representation of
0208  * @len: The length of the raw memory to copy (in bytes)
0209  *
0210  * This is similar to seq_buf_putmem() except instead of just copying the
0211  * raw memory into the buffer it writes its ASCII representation of it
0212  * in hex characters.
0213  *
0214  * Returns zero on success, -1 on overflow
0215  */
0216 int seq_buf_putmem_hex(struct seq_buf *s, const void *mem,
0217                unsigned int len)
0218 {
0219     unsigned char hex[HEX_CHARS];
0220     const unsigned char *data = mem;
0221     unsigned int start_len;
0222     int i, j;
0223 
0224     WARN_ON(s->size == 0);
0225 
0226     while (len) {
0227         start_len = min(len, HEX_CHARS - 1);
0228 #ifdef __BIG_ENDIAN
0229         for (i = 0, j = 0; i < start_len; i++) {
0230 #else
0231         for (i = start_len-1, j = 0; i >= 0; i--) {
0232 #endif
0233             hex[j++] = hex_asc_hi(data[i]);
0234             hex[j++] = hex_asc_lo(data[i]);
0235         }
0236         if (WARN_ON_ONCE(j == 0 || j/2 > len))
0237             break;
0238 
0239         /* j increments twice per loop */
0240         len -= j / 2;
0241         hex[j++] = ' ';
0242 
0243         seq_buf_putmem(s, hex, j);
0244         if (seq_buf_has_overflowed(s))
0245             return -1;
0246     }
0247     return 0;
0248 }
0249 
0250 /**
0251  * seq_buf_path - copy a path into the sequence buffer
0252  * @s: seq_buf descriptor
0253  * @path: path to write into the sequence buffer.
0254  * @esc: set of characters to escape in the output
0255  *
0256  * Write a path name into the sequence buffer.
0257  *
0258  * Returns the number of written bytes on success, -1 on overflow
0259  */
0260 int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc)
0261 {
0262     char *buf;
0263     size_t size = seq_buf_get_buf(s, &buf);
0264     int res = -1;
0265 
0266     WARN_ON(s->size == 0);
0267 
0268     if (size) {
0269         char *p = d_path(path, buf, size);
0270         if (!IS_ERR(p)) {
0271             char *end = mangle_path(buf, p, esc);
0272             if (end)
0273                 res = end - buf;
0274         }
0275     }
0276     seq_buf_commit(s, res);
0277 
0278     return res;
0279 }
0280 
0281 /**
0282  * seq_buf_to_user - copy the squence buffer to user space
0283  * @s: seq_buf descriptor
0284  * @ubuf: The userspace memory location to copy to
0285  * @cnt: The amount to copy
0286  *
0287  * Copies the sequence buffer into the userspace memory pointed to
0288  * by @ubuf. It starts from the last read position (@s->readpos)
0289  * and writes up to @cnt characters or till it reaches the end of
0290  * the content in the buffer (@s->len), which ever comes first.
0291  *
0292  * On success, it returns a positive number of the number of bytes
0293  * it copied.
0294  *
0295  * On failure it returns -EBUSY if all of the content in the
0296  * sequence has been already read, which includes nothing in the
0297  * sequence (@s->len == @s->readpos).
0298  *
0299  * Returns -EFAULT if the copy to userspace fails.
0300  */
0301 int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt)
0302 {
0303     int len;
0304     int ret;
0305 
0306     if (!cnt)
0307         return 0;
0308 
0309     len = seq_buf_used(s);
0310 
0311     if (len <= s->readpos)
0312         return -EBUSY;
0313 
0314     len -= s->readpos;
0315     if (cnt > len)
0316         cnt = len;
0317     ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
0318     if (ret == cnt)
0319         return -EFAULT;
0320 
0321     cnt -= ret;
0322 
0323     s->readpos += cnt;
0324     return cnt;
0325 }