diff options
author | Alex Elder <elder@inktank.com> | 2012-07-11 09:24:45 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2012-07-30 12:29:57 -0400 |
commit | f8c36c58accd5c53a472b5c289910565b3df9f9d (patch) | |
tree | 905ff1a9df30c0200732af71b806c39145dcd641 /include/linux/ceph | |
parent | ad4f232f28e8059fa1de51f3127d8a6a2759ef16 (diff) |
libceph: define ceph_extract_encoded_string()
This adds a new utility routine which will return a dynamically-
allocated buffer containing a string that has been decoded from ceph
over-the-wire format. It also returns the length of the string
if the address of a size variable is supplied to receive it.
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'include/linux/ceph')
-rw-r--r-- | include/linux/ceph/decode.h | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h index bcbd66c84890..4bbf2db45f46 100644 --- a/include/linux/ceph/decode.h +++ b/include/linux/ceph/decode.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef __CEPH_DECODE_H | 1 | #ifndef __CEPH_DECODE_H |
2 | #define __CEPH_DECODE_H | 2 | #define __CEPH_DECODE_H |
3 | 3 | ||
4 | #include <linux/err.h> | ||
4 | #include <linux/bug.h> | 5 | #include <linux/bug.h> |
5 | #include <linux/time.h> | 6 | #include <linux/time.h> |
6 | #include <asm/unaligned.h> | 7 | #include <asm/unaligned.h> |
@@ -85,6 +86,52 @@ static inline int ceph_has_room(void **p, void *end, size_t n) | |||
85 | } while (0) | 86 | } while (0) |
86 | 87 | ||
87 | /* | 88 | /* |
89 | * Allocate a buffer big enough to hold the wire-encoded string, and | ||
90 | * decode the string into it. The resulting string will always be | ||
91 | * terminated with '\0'. If successful, *p will be advanced | ||
92 | * past the decoded data. Also, if lenp is not a null pointer, the | ||
93 | * length (not including the terminating '\0') will be recorded in | ||
94 | * *lenp. Note that a zero-length string is a valid return value. | ||
95 | * | ||
96 | * Returns a pointer to the newly-allocated string buffer, or a | ||
97 | * pointer-coded errno if an error occurs. Neither *p nor *lenp | ||
98 | * will have been updated if an error is returned. | ||
99 | * | ||
100 | * There are two possible failures: | ||
101 | * - converting the string would require accessing memory at or | ||
102 | * beyond the "end" pointer provided (-E | ||
103 | * - memory could not be allocated for the result | ||
104 | */ | ||
105 | static inline char *ceph_extract_encoded_string(void **p, void *end, | ||
106 | size_t *lenp, gfp_t gfp) | ||
107 | { | ||
108 | u32 len; | ||
109 | void *sp = *p; | ||
110 | char *buf; | ||
111 | |||
112 | ceph_decode_32_safe(&sp, end, len, bad); | ||
113 | if (!ceph_has_room(&sp, end, len)) | ||
114 | goto bad; | ||
115 | |||
116 | buf = kmalloc(len + 1, gfp); | ||
117 | if (!buf) | ||
118 | return ERR_PTR(-ENOMEM); | ||
119 | |||
120 | if (len) | ||
121 | memcpy(buf, sp, len); | ||
122 | buf[len] = '\0'; | ||
123 | |||
124 | *p = (char *) *p + sizeof (u32) + len; | ||
125 | if (lenp) | ||
126 | *lenp = (size_t) len; | ||
127 | |||
128 | return buf; | ||
129 | |||
130 | bad: | ||
131 | return ERR_PTR(-ERANGE); | ||
132 | } | ||
133 | |||
134 | /* | ||
88 | * struct ceph_timespec <-> struct timespec | 135 | * struct ceph_timespec <-> struct timespec |
89 | */ | 136 | */ |
90 | static inline void ceph_decode_timespec(struct timespec *ts, | 137 | static inline void ceph_decode_timespec(struct timespec *ts, |