import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / aparser / parser.c
1 #include "parser.h"
2
3 /*******************************************************************
4  Attempt, if needed, to grow a data buffer.
5  Also depends on the data stream mode (io).
6  ********************************************************************/
7
8 BOOL io_grow(io_struct *ps, uint32 extra_space)
9 {
10         uint32 new_size;
11         char *new_data;
12
13         ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space);
14
15         if(ps->data_offset + extra_space <= ps->buffer_size)
16                 return True;
17
18         /*
19          * We cannot grow the buffer if we're not reading
20          * into the io_struct, or if we don't own the memory.
21          */
22
23         if(UNMARSHALLING(ps) || !ps->is_dynamic) {
24                 DEBUG(0,("io_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
25                                 (unsigned int)extra_space));
26                 return False;
27         }
28         
29         /*
30          * Decide how much extra space we really need.
31          */
32
33         extra_space -= (ps->buffer_size - ps->data_offset);
34         if(ps->buffer_size == 0) {
35                 new_size = extra_space;
36
37                 if((new_data = malloc(new_size)) == NULL) {
38                         DEBUG(0,("io_grow: Malloc failure for size %u.\n", (unsigned int)new_size));
39                         return False;
40                 }
41                 memset(new_data, '\0', new_size );
42         } else {
43                 /*
44                  * If the current buffer size is bigger than the space needed, just 
45                  * double it, else add extra_space.
46                  */
47                 new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space);               
48
49                 if ((new_data = Realloc(ps->data_p, new_size)) == NULL) {
50                         DEBUG(0,("io_grow: Realloc failure for size %u.\n",
51                                 (unsigned int)new_size));
52                         return False;
53                 }
54         }
55         ps->buffer_size = new_size;
56         ps->data_p = new_data;
57
58         return True;
59 }
60
61
62 /*******************************************************************
63  Ensure we can read/write to a given offset.
64  ********************************************************************/
65
66 char *io_mem_get(io_struct *ps, uint32 extra_size)
67 {
68         if(UNMARSHALLING(ps)) {
69                 /*
70                  * If reading, ensure that we can read the requested size item.
71                  */
72                 if (ps->data_offset + extra_size > ps->buffer_size) {
73                         DEBUG(0,("io_mem_get: reading data of size %u would overrun buffer.\n",
74                                         (unsigned int)extra_size ));
75                         return NULL;
76                 }
77         } else {
78                 /*
79                  * Writing - grow the buffer if needed.
80                  */
81                 if(!io_grow(ps, extra_size))
82                         return False;
83         }
84         return &ps->data_p[ps->data_offset];
85 }
86
87 /*******************************************************************
88  Initialise a parse structure - malloc the data if requested.
89  ********************************************************************/
90
91 BOOL io_init(io_struct *ps, uint32 size, BOOL io)
92 {
93         ZERO_STRUCTP(ps);
94         ps->io = io;
95         ps->bigendian_data = False;
96         ps->is_dynamic = False;
97         ps->data_offset = 0;
98         ps->buffer_size = 0;
99         ps->data_p = NULL;
100
101         if (size != 0) {
102                 ps->buffer_size = size;
103                 if((ps->data_p = (char *)malloc((size_t)size)) == NULL) {
104                         DEBUG(0,("io_init: malloc fail for %u bytes.\n", (unsigned int)size));
105                         return False;
106                 }
107                 ps->is_dynamic = True; /* We own this memory. */
108         }
109
110         return True;
111 }
112
113 /*******************************************************************
114  debug output for parsing info.
115
116  XXXX side-effect of this function is to increase the debug depth XXXX
117
118  ********************************************************************/
119 void io_debug(io_struct *ps, int depth, char *desc, char *fn_name)
120 {
121         DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc));
122 }
123
124 /*******************************************************************
125  Align a the data_len to a multiple of align bytes - filling with
126  zeros.
127  ********************************************************************/
128
129 BOOL io_align2(io_struct *ps, int offset)
130 {
131         uint32 mod = (ps->data_offset + offset) & (2-1);
132
133         if (mod != 0) {
134                 uint32 extra_space = (2 - mod);
135                 if(!io_grow(ps, extra_space))
136                         return False;
137                 memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
138                 ps->data_offset += extra_space;
139         }
140
141         return True;
142 }
143
144 BOOL io_align4(io_struct *ps, int offset)
145 {
146         uint32 mod = (ps->data_offset + offset) & (4-1);
147
148         if (mod != 0) {
149                 uint32 extra_space = (4 - mod);
150                 if(!io_grow(ps, extra_space))
151                         return False;
152                 memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
153                 ps->data_offset += extra_space;
154         }
155
156         return True;
157 }
158
159 /*******************************************************************
160  Align a the data_len to a multiple of align bytes - filling with
161  zeros.
162  ********************************************************************/
163
164 BOOL io_align(io_struct *ps, int align)
165 {
166         uint32 mod;
167
168         if (!ps->autoalign) return True;
169
170         mod = ps->data_offset & (align-1);
171
172         if (align != 0 && mod != 0) {
173                 uint32 extra_space = (align - mod);
174                 if(!io_grow(ps, extra_space))
175                         return False;
176                 memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
177                 ps->data_offset += extra_space;
178         }
179
180         return True;
181 }
182
183
184 /*******************************************************************
185  read from a socket into memory.
186  ********************************************************************/
187 BOOL io_read(io_struct *ps, int fd, size_t len, int timeout)
188 {
189         BOOL ok;
190         size_t prev_size = ps->buffer_size;
191         if (!io_grow(ps, len))
192         {
193                 return False;
194         }
195
196         if (timeout > 0)
197         {
198                 ok = (read(fd, &ps->data_p[prev_size], len) == len);
199         }
200         else 
201         {
202                 ok = (read(fd, &ps->data_p[prev_size], len) == len);
203         }
204         return ok;
205 }
206
207
208 /*******************************************************************
209  do IO on a uint32.
210  ********************************************************************/
211 BOOL io_uint32(char *name, io_struct *ps, int depth, uint32 *data32, unsigned flags)
212 {
213         char *q;
214
215         if (!(flags & PARSE_SCALARS)) return True;
216
217         if (!io_align(ps, 4)) return False;
218
219         q = io_mem_get(ps, sizeof(uint32));
220         if (q == NULL) return False;
221
222         DBG_RW_IVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data32)
223         ps->data_offset += sizeof(uint32);
224
225         return True;
226 }
227
228 /*******************************************************************
229  do IO on a uint16.
230  ********************************************************************/
231 BOOL io_uint16(char *name, io_struct *ps, int depth, uint16 *data16, unsigned flags)
232 {
233         char *q;
234
235         if (!(flags & PARSE_SCALARS)) return True;
236
237         if (!io_align(ps, 2)) return False;
238
239         q = io_mem_get(ps, sizeof(uint16));
240         if (q == NULL) return False;
241
242         DBG_RW_SVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data16)
243         ps->data_offset += sizeof(uint16);
244
245         return True;
246 }
247
248 /*******************************************************************
249  do IO on a uint8.
250  ********************************************************************/
251 BOOL io_uint8(char *name, io_struct *ps, int depth, uint8 *data8, unsigned flags)
252 {
253         char *q;
254
255         if (!(flags & PARSE_SCALARS)) return True;
256
257         q = io_mem_get(ps, sizeof(uint8));
258         if (q == NULL) return False;
259
260         DBG_RW_IVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data8)
261         ps->data_offset += sizeof(uint8);
262
263         return True;
264 }
265
266 /*******************************************************************
267  do IO on a pointer
268  ********************************************************************/
269 BOOL io_pointer(char *desc, io_struct *ps, int depth, void **p, unsigned flags)
270 {
271         uint32 v;
272
273         if (!(flags & PARSE_SCALARS)) return True;
274
275         v = (*p) ? 0xdeadbeef : 0;
276         if (!io_uint32(desc, ps, depth, &v, flags)) return False;
277         *p = (void *) (v ? 0xdeadbeef : 0);
278         return True;
279 }
280
281 /*******************************************************************
282  Stream a null-terminated string.  
283  ********************************************************************/
284 BOOL io_SMBSTR(char *name, io_struct *ps, int depth, char **str, unsigned flags)
285 {
286         char *q;
287         uint8 *start;
288         int i;
289         size_t len;
290         int start_offset = ps->data_offset;
291
292         if (!(flags & PARSE_SCALARS)) return True;
293         
294         if (UNMARSHALLING(ps)) {
295                 *str = io_mem_get(ps, 0);
296                 if (*str == NULL)
297                         return False;
298                 len = strlen(*str);
299                 ps->data_offset += len + 1;
300         }
301         else
302         {
303                 len = strlen(*str)+1;
304                 start = (uint8*)q;
305
306                 for(i = 0; i < len; i++) {
307                         q = io_mem_get(ps, 1);
308                         if (q == NULL)
309                                 return False;
310
311                         RW_CVAL(ps->io, q, (*str)[i],0);
312                         ps->data_offset++;
313                 }
314         }
315
316         DEBUG(5,("%s%04x %s: %s\n", tab_depth(depth),
317                                 start_offset, name, *str));
318         return True;
319 }
320
321 /******************************************************************
322  do IO on a byte array
323  ********************************************************************/
324 BOOL io_uint8s(char *name, io_struct *ps, int depth, uint8 **data8s, int len, unsigned flags)
325 {
326         char *q;
327         size_t num_bytes = len * sizeof(uint8);
328
329         if (!(flags & PARSE_SCALARS)) return True;
330
331         q = io_mem_get(ps, num_bytes);
332         if (q == NULL) return False;
333
334         if (MARSHALLING(ps))
335         {
336                 DBG_RW_PCVAL(True, name, depth, ps->data_offset, ps->io, q, *data8s, len)
337         }
338         else
339         {
340                 *data8s = q;
341                 dump_data(depth+5, *data8s, num_bytes);
342         }
343         ps->data_offset += num_bytes;
344
345         return True;
346 }
347 /******************************************************************
348  do IO on a fixed-size byte array
349  ********************************************************************/
350 BOOL io_uint8s_fixed(char *name, io_struct *ps, int depth, uint8 *data8s, int len, unsigned flags)
351 {
352         char *q;
353         size_t num_bytes = len * sizeof(uint8);
354
355         if (!(flags & PARSE_SCALARS)) return True;
356
357         q = io_mem_get(ps, num_bytes);
358         if (q == NULL) return False;
359
360         DBG_RW_PCVAL(True, name, depth, ps->data_offset, ps->io, q, data8s, len)
361         ps->data_offset += num_bytes;
362
363         return True;
364 }
365
366
367 /******************************************************************
368  do IO on an io (eh?? :)
369  ********************************************************************/
370 BOOL io_io_struct(char *name, io_struct *ps, int depth, io_struct *io, unsigned flags)
371 {
372         char *q;
373         uint16 len;
374
375         if (!(flags & PARSE_SCALARS)) return True;
376
377         q = io_mem_get(ps, sizeof(uint16));
378         if (q == NULL) return False;
379
380         /* length first */
381         if (MARSHALLING(ps))
382         {
383                 len = io->data_offset;
384         }
385         if (!io_uint16("len", ps, depth+1, &len, flags))
386         {
387                 return False;
388         }
389         if (UNMARSHALLING(ps))
390         {
391                 if (!io_init(io, len, UNMARSHALL))
392                 {
393                         return False;
394                 }
395         }
396
397         /* now data */
398         q = io_mem_get(ps, len * sizeof(uint8));
399         if (q == NULL) return False;
400
401         if (MARSHALLING(ps))
402         {
403                 DBG_RW_PCVAL(False, name, depth+1, ps->data_offset, ps->io, q, io->data_p, len)
404         }
405         else
406         {
407                 io->data_p = q;
408                 dump_data(depth+5, q, len);
409         }
410         ps->data_offset += len;
411
412         return True;
413 }
414
415 /******************************************************************
416  do IO on a unicode array
417  ********************************************************************/
418 BOOL io_wstring(char *name, io_struct *ps, int depth, uint16 *data16s, int len, unsigned flags)
419 {
420         char *q;
421
422         if (!(flags & PARSE_SCALARS)) return True;
423
424         if (!io_align(ps, 2)) return False;
425
426         q = io_mem_get(ps, len * sizeof(uint16));
427         if (q == NULL) return False;
428
429         DBG_RW_PSVAL(True, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, data16s, len)
430         ps->data_offset += (len * sizeof(uint16));
431
432         return True;
433 }
434
435
436 /******************************************************************
437 allocate some memory for a parse structure
438  ********************************************************************/
439 void io_free(io_struct *ps)
440 {
441         if (ps->is_dynamic && ps->data_p)
442         {
443                 free(ps->data_p);
444                 ps->data_p = NULL;
445         }
446 }
447
448 /******************************************************************
449 allocate some memory for a parse structure
450  ********************************************************************/
451 BOOL io_alloc(char *name, io_struct *ps, void **ptr, unsigned size)
452 {
453         (*ptr) = (void *)malloc(size);
454         if (*ptr) return True;
455         return False;
456 }
457
458 /******************************************************************
459 realloc some memory for a parse structure
460  ********************************************************************/
461 BOOL io_realloc(char *name, io_struct *ps, void **ptr, unsigned size)
462 {
463         BOOL ret = True;
464         void *tp;
465
466         tp = (void *)Realloc(*ptr, size);
467         if (tp) *ptr = tp;
468         else ret = False;
469         return ret;
470 }
471