1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 
21                    Serialisation Support Functions
22                           John Walker
23 */
24 
25 
26 #include "bacula.h"
27 #include "serial.h"
28 
29 /*
30 
31         NOTE:  The following functions should work on any
32                vaguely contemporary platform.  Production
33                builds should use optimised macros (void
34                on platforms with network byte order and IEEE
35                floating point format as native.
36 
37 */
38 
39 /*  serial_int16  --  Serialise a signed 16 bit integer.  */
40 
serial_int16(uint8_t ** const ptr,const int16_t v)41 void serial_int16(uint8_t * * const ptr, const int16_t v)
42 {
43     int16_t vo = htons(v);
44 
45     memcpy(*ptr, &vo, sizeof vo);
46     *ptr += sizeof vo;
47 }
48 
49 /*  serial_uint16  --  Serialise an unsigned 16 bit integer.  */
50 
serial_uint16(uint8_t ** const ptr,const uint16_t v)51 void serial_uint16(uint8_t * * const ptr, const uint16_t v)
52 {
53     uint16_t vo = htons(v);
54 
55     memcpy(*ptr, &vo, sizeof vo);
56     *ptr += sizeof vo;
57 }
58 
59 /*  serial_int32  --  Serialise a signed 32 bit integer.  */
60 
serial_int32(uint8_t ** const ptr,const int32_t v)61 void serial_int32(uint8_t * * const ptr, const int32_t v)
62 {
63     int32_t vo = htonl(v);
64 
65     memcpy(*ptr, &vo, sizeof vo);
66     *ptr += sizeof vo;
67 }
68 
69 /*  serial_uint32  --  Serialise an unsigned 32 bit integer.  */
70 
serial_uint32(uint8_t ** const ptr,const uint32_t v)71 void serial_uint32(uint8_t * * const ptr, const uint32_t v)
72 {
73     uint32_t vo = htonl(v);
74 
75     memcpy(*ptr, &vo, sizeof vo);
76     *ptr += sizeof vo;
77 }
78 
79 /*  serial_int64  --  Serialise a signed 64 bit integer.  */
80 
serial_int64(uint8_t ** const ptr,const int64_t v)81 void serial_int64(uint8_t * * const ptr, const int64_t v)
82 {
83     if (bigendian()) {
84         memcpy(*ptr, &v, sizeof(int64_t));
85     } else {
86         int i;
87         uint8_t rv[sizeof(int64_t)];
88         uint8_t *pv = (uint8_t *) &v;
89 
90         for (i = 0; i < 8; i++) {
91             rv[i] = pv[7 - i];
92         }
93         memcpy(*ptr, &rv, sizeof(int64_t));
94     }
95     *ptr += sizeof(int64_t);
96 }
97 
98 
99 /*  serial_uint64  --  Serialise an unsigned 64 bit integer.  */
100 
serial_uint64(uint8_t ** const ptr,const uint64_t v)101 void serial_uint64(uint8_t * * const ptr, const uint64_t v)
102 {
103     if (bigendian()) {
104         memcpy(*ptr, &v, sizeof(uint64_t));
105     } else {
106         int i;
107         uint8_t rv[sizeof(uint64_t)];
108         uint8_t *pv = (uint8_t *) &v;
109 
110         for (i = 0; i < 8; i++) {
111             rv[i] = pv[7 - i];
112         }
113         memcpy(*ptr, &rv, sizeof(uint64_t));
114     }
115     *ptr += sizeof(uint64_t);
116 }
117 
118 
119 /*  serial_btime  --  Serialise an btime_t 64 bit integer.  */
120 
serial_btime(uint8_t ** const ptr,const btime_t v)121 void serial_btime(uint8_t * * const ptr, const btime_t v)
122 {
123     if (bigendian()) {
124         memcpy(*ptr, &v, sizeof(btime_t));
125     } else {
126         int i;
127         uint8_t rv[sizeof(btime_t)];
128         uint8_t *pv = (uint8_t *) &v;
129 
130         for (i = 0; i < 8; i++) {
131             rv[i] = pv[7 - i];
132         }
133         memcpy(*ptr, &rv, sizeof(btime_t));
134     }
135     *ptr += sizeof(btime_t);
136 }
137 
138 
139 
140 /*  serial_float64  --  Serialise a 64 bit IEEE floating point number.
141                         This code assumes that the host floating point
142                         format is IEEE and that floating point quantities
143                         are stored in IEEE format either LSB first or MSB
144                         first.  More creative host formats will require
145                         additional transformations here.  */
146 
serial_float64(uint8_t ** const ptr,const float64_t v)147 void serial_float64(uint8_t * * const ptr, const float64_t v)
148 {
149     if (bigendian()) {
150         memcpy(*ptr, &v, sizeof(float64_t));
151     } else {
152         int i;
153         uint8_t rv[sizeof(float64_t)];
154         uint8_t *pv = (uint8_t *) &v;
155 
156         for (i = 0; i < 8; i++) {
157             rv[i] = pv[7 - i];
158         }
159         memcpy(*ptr, &rv, sizeof(float64_t));
160     }
161     *ptr += sizeof(float64_t);
162 }
163 
serial_string(uint8_t ** const ptr,const char * const str)164 void serial_string(uint8_t * * const ptr, const char * const str)
165 {
166    int i;
167    char *dest = (char *)*ptr;
168    char *src = (char *)str;
169    for (i=0; src[i] != 0;  i++) {
170       dest[i] = src[i];
171    }
172    dest[i++] = 0;                  /* terminate output string */
173    *ptr += i;                      /* update pointer */
174 // Dmsg2(000, "ser src=%s dest=%s\n", src, dest);
175 }
176 
177 
178 /*  unserial_int16  --  Unserialise a signed 16 bit integer.  */
179 
unserial_int16(uint8_t ** const ptr)180 int16_t unserial_int16(uint8_t * * const ptr)
181 {
182     int16_t vo;
183 
184     memcpy(&vo, *ptr, sizeof vo);
185     *ptr += sizeof vo;
186     return ntohs(vo);
187 }
188 
189 /*  unserial_uint16  --  Unserialise an unsigned 16 bit integer.  */
190 
unserial_uint16(uint8_t ** const ptr)191 uint16_t unserial_uint16(uint8_t * * const ptr)
192 {
193     uint16_t vo;
194 
195     memcpy(&vo, *ptr, sizeof vo);
196     *ptr += sizeof vo;
197     return ntohs(vo);
198 }
199 
200 /*  unserial_int32  --  Unserialise a signed 32 bit integer.  */
201 
unserial_int32(uint8_t ** const ptr)202 int32_t unserial_int32(uint8_t * * const ptr)
203 {
204     int32_t vo;
205 
206     memcpy(&vo, *ptr, sizeof vo);
207     *ptr += sizeof vo;
208     return ntohl(vo);
209 }
210 
211 /*  unserial_uint32  --  Unserialise an unsigned 32 bit integer.  */
212 
unserial_uint32(uint8_t ** const ptr)213 uint32_t unserial_uint32(uint8_t * * const ptr)
214 {
215     uint32_t vo;
216 
217     memcpy(&vo, *ptr, sizeof vo);
218     *ptr += sizeof vo;
219     return ntohl(vo);
220 }
221 
222 /*  unserial_int64  --  Unserialise a 64 bit integer.  */
223 
unserial_int64(uint8_t ** const ptr)224 int64_t unserial_int64(uint8_t * * const ptr)
225 {
226     int64_t v;
227 
228     if (bigendian()) {
229         memcpy(&v, *ptr, sizeof(int64_t));
230     } else {
231         int i;
232         uint8_t rv[sizeof(int64_t)];
233         uint8_t *pv = (uint8_t *) &v;
234 
235         memcpy(&v, *ptr, sizeof(uint64_t));
236         for (i = 0; i < 8; i++) {
237             rv[i] = pv[7 - i];
238         }
239         memcpy(&v, &rv, sizeof(uint64_t));
240     }
241     *ptr += sizeof(uint64_t);
242     return v;
243 }
244 
245 /*  unserial_uint64  --  Unserialise an unsigned 64 bit integer.  */
246 
unserial_uint64(uint8_t ** const ptr)247 uint64_t unserial_uint64(uint8_t * * const ptr)
248 {
249     uint64_t v;
250 
251     if (bigendian()) {
252         memcpy(&v, *ptr, sizeof(uint64_t));
253     } else {
254         int i;
255         uint8_t rv[sizeof(uint64_t)];
256         uint8_t *pv = (uint8_t *) &v;
257 
258         memcpy(&v, *ptr, sizeof(uint64_t));
259         for (i = 0; i < 8; i++) {
260             rv[i] = pv[7 - i];
261         }
262         memcpy(&v, &rv, sizeof(uint64_t));
263     }
264     *ptr += sizeof(uint64_t);
265     return v;
266 }
267 
268 /*  unserial_btime  --  Unserialise a btime_t 64 bit integer.  */
269 
unserial_btime(uint8_t ** const ptr)270 btime_t unserial_btime(uint8_t * * const ptr)
271 {
272     btime_t v;
273 
274     if (bigendian()) {
275         memcpy(&v, *ptr, sizeof(btime_t));
276     } else {
277         int i;
278         uint8_t rv[sizeof(btime_t)];
279         uint8_t *pv = (uint8_t *) &v;
280 
281         memcpy(&v, *ptr, sizeof(btime_t));
282         for (i = 0; i < 8; i++) {
283             rv[i] = pv[7 - i];
284         }
285         memcpy(&v, &rv, sizeof(btime_t));
286     }
287     *ptr += sizeof(btime_t);
288     return v;
289 }
290 
291 
292 
293 /*  unserial_float64  --  Unserialise a 64 bit IEEE floating point number.
294                          This code assumes that the host floating point
295                          format is IEEE and that floating point quantities
296                          are stored in IEEE format either LSB first or MSB
297                          first.  More creative host formats will require
298                          additional transformations here.  */
299 
unserial_float64(uint8_t ** const ptr)300 float64_t unserial_float64(uint8_t * * const ptr)
301 {
302     float64_t v;
303 
304     if (bigendian()) {
305         memcpy(&v, *ptr, sizeof(float64_t));
306     } else {
307         int i;
308         uint8_t rv[sizeof(float64_t)];
309         uint8_t *pv = (uint8_t *) &v;
310 
311         memcpy(&v, *ptr, sizeof(float64_t));
312         for (i = 0; i < 8; i++) {
313             rv[i] = pv[7 - i];
314         }
315         memcpy(&v, &rv, sizeof(float64_t));
316     }
317     *ptr += sizeof(float64_t);
318     return v;
319 }
320 
unserial_string(uint8_t ** const ptr,char * const str,int max)321 void unserial_string(uint8_t * * const ptr, char * const str, int max)
322 {
323    int i;
324    char *src = (char*)(*ptr);
325    char *dest = str;
326    for (i=0; i<max && src[i] != 0;  i++) {
327       dest[i] = src[i];
328    }
329    dest[i++] = 0;            /* terminate output string */
330    *ptr += i;                /* update pointer */
331 // Dmsg2(000, "unser src=%s dest=%s\n", src, dest);
332 }
333