blob: 910aa07769f2d5f09a5637cca57b1494e276979f [file] [log] [blame]
Carl van Schaik6d7b2ff2018-07-06 22:00:55 +10001/*
2 * include/vservices/buffer.h
3 *
4 * Copyright (c) 2012-2018 General Dynamics
5 * Copyright (c) 2014 Open Kernel Labs, Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This file defines simple wrapper types for strings and variable-size buffers
12 * that are stored inside Virtual Services message buffers.
13 */
14
15#ifndef _VSERVICES_BUFFER_H_
16#define _VSERVICES_BUFFER_H_
17
18#include <linux/types.h>
19#include <linux/string.h>
20#include <linux/slab.h>
21
22struct vs_mbuf;
23
24/**
25 * struct vs_string - Virtual Services fixed sized string type
26 * @ptr: String pointer
27 * @max_size: Maximum length of the string in bytes
28 *
29 * A handle to a possibly NUL-terminated string stored in a message buffer. If
30 * the size of the string equals to max_size, the string is not NUL-terminated.
31 * If the protocol does not specify an encoding, the encoding is assumed to be
32 * UTF-8. Wide character encodings are not supported by this type; use struct
33 * vs_pbuf for wide character strings.
34 */
35struct vs_string {
36 char *ptr;
37 size_t max_size;
38};
39
40/**
41 * vs_string_copyout - Copy a Virtual Services string to a C string buffer.
42 * @dest: C string to copy to
43 * @src: Virtual Services string to copy from
44 * @max_size: Size of the destination buffer, including the NUL terminator.
45 *
46 * The behaviour is similar to strlcpy(): that is, the copied string
47 * is guaranteed not to exceed the specified size (including the NUL
48 * terminator byte), and is guaranteed to be NUL-terminated as long as
49 * the size is nonzero (unlike strncpy()).
50 *
51 * The return value is the size of the input string (even if the output was
52 * truncated); this is to make truncation easy to detect.
53 */
54static inline size_t
55vs_string_copyout(char *dest, const struct vs_string *src, size_t max_size)
56{
57 size_t src_len = strnlen(src->ptr, src->max_size);
58
59 if (max_size) {
60 size_t dest_len = min(src_len, max_size - 1);
61
62 memcpy(dest, src->ptr, dest_len);
63 dest[dest_len] = '\0';
64 }
65 return src_len;
66}
67
68/**
69 * vs_string_copyin_len - Copy a C string, up to a given length, into a Virtual
70 * Services string.
71 * @dest: Virtual Services string to copy to
72 * @src: C string to copy from
73 * @max_size: Maximum number of bytes to copy
74 *
75 * Returns the number of bytes copied, which may be less than the input
76 * string's length.
77 */
78static inline size_t
79vs_string_copyin_len(struct vs_string *dest, const char *src, size_t max_size)
80{
81 strncpy(dest->ptr, src, min(max_size, dest->max_size));
82
83 return strnlen(dest->ptr, dest->max_size);
84}
85
86/**
87 * vs_string_copyin - Copy a C string into a Virtual Services string.
88 * @dest: Virtual Services string to copy to
89 * @src: C string to copy from
90 *
91 * Returns the number of bytes copied, which may be less than the input
92 * string's length.
93 */
94static inline size_t
95vs_string_copyin(struct vs_string *dest, const char *src)
96{
97 return vs_string_copyin_len(dest, src, dest->max_size);
98}
99
100/**
101 * vs_string_length - Return the size of the string stored in a Virtual Services
102 * string.
103 * @str: Virtual Service string to get the length of
104 */
105static inline size_t
106vs_string_length(struct vs_string *str)
107{
108 return strnlen(str->ptr, str->max_size);
109}
110
111/**
112 * vs_string_dup - Allocate a C string buffer and copy a Virtual Services string
113 * into it.
114 * @str: Virtual Services string to duplicate
115 */
116static inline char *
117vs_string_dup(struct vs_string *str, gfp_t gfp)
118{
119 size_t len;
120 char *ret;
121
122 len = strnlen(str->ptr, str->max_size) + 1;
123 ret = kmalloc(len, gfp);
124 if (ret)
125 vs_string_copyout(ret, str, len);
126 return ret;
127}
128
129/**
130 * vs_string_max_size - Return the maximum size of a Virtual Services string,
131 * not including the NUL terminator if the lenght of the
132 * string is equal to max_size.
133 *
134 * @str Virtual Services string to return the maximum size of.
135 *
136 * @return The maximum size of the string.
137 */
138static inline size_t
139vs_string_max_size(struct vs_string *str)
140{
141 return str->max_size;
142}
143
144/**
145 * struct vs_pbuf - Handle to a variable-size buffered payload.
146 * @data: Data buffer
147 * @size: Current size of the buffer
148 * @max_size: Maximum size of the buffer
149 *
150 * This is similar to struct vs_string, except that has an explicitly
151 * stored size rather than being null-terminated. The functions that
152 * return ssize_t all return the new size of the modified buffer, and
153 * will return a negative size if the buffer overflows.
154 */
155struct vs_pbuf {
156 void *data;
157 size_t size, max_size;
158};
159
160/**
161 * vs_pbuf_size - Get the size of a pbuf
162 * @pbuf: pbuf to get the size of
163 */
164static inline size_t vs_pbuf_size(const struct vs_pbuf *pbuf)
165{
166 return pbuf->size;
167}
168
169/**
170 * vs_pbuf_data - Get the data pointer for a a pbuf
171 * @pbuf: pbuf to get the data pointer for
172 */
173static inline const void *vs_pbuf_data(const struct vs_pbuf *pbuf)
174{
175 return pbuf->data;
176}
177
178/**
179 * vs_pbuf_resize - Resize a pbuf
180 * @pbuf: pbuf to resize
181 * @size: New size
182 */
183static inline ssize_t vs_pbuf_resize(struct vs_pbuf *pbuf, size_t size)
184{
185 if (size > pbuf->max_size)
186 return -EOVERFLOW;
187
188 pbuf->size = size;
189 return size;
190}
191
192/**
193 * vs_pbuf_copyin - Copy data into a pbuf
194 * @pbuf: pbuf to copy data into
195 * @offset: Offset to copy data to
196 * @data: Pointer to data to copy into the pbuf
197 * @nbytes: Number of bytes to copy into the pbuf
198 */
199static inline ssize_t vs_pbuf_copyin(struct vs_pbuf *pbuf, off_t offset,
200 const void *data, size_t nbytes)
201{
202 if (offset + nbytes > pbuf->size)
203 return -EOVERFLOW;
204
205 memcpy(pbuf->data + offset, data, nbytes);
206
207 return nbytes;
208}
209
210/**
211 * vs_pbuf_append - Append data to a pbuf
212 * @pbuf: pbuf to append to
213 * @data: Pointer to data to append to the pbuf
214 * @nbytes: Number of bytes to append
215 */
216static inline ssize_t vs_pbuf_append(struct vs_pbuf *pbuf,
217 const void *data, size_t nbytes)
218{
219 if (pbuf->size + nbytes > pbuf->max_size)
220 return -EOVERFLOW;
221
222 memcpy(pbuf->data + pbuf->size, data, nbytes);
223 pbuf->size += nbytes;
224
225 return pbuf->size;
226}
227
228/**
229 * vs_pbuf_dup_string - Duplicate the contents of a pbuf as a C string. The
230 * string is allocated and must be freed using kfree.
231 * @pbuf: pbuf to convert
232 * @gfp_flags: GFP flags for the string allocation
233 */
234static inline char *vs_pbuf_dup_string(struct vs_pbuf *pbuf, gfp_t gfp_flags)
235{
236 return kstrndup(pbuf->data, pbuf->size, gfp_flags);
237}
238
239#endif /* _VSERVICES_BUFFER_H_ */