fixing smbpasswd to link to smbd to obtain domain sid
[samba.git] / source3 / lib / membuffer.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba memory buffer functions
5    Copyright (C) Andrew Tridgell              1992-1997
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1997
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 /*******************************************************************
24  *
25  * Description: memory buffer / stream management.
26  * Author     : Luke K C Leighton
27  * Created    : Dec 1997
28  *
29
30  * this module is intended for use in streaming data in and out of
31  * buffers.  it is intended that a single data stream be subdivided
32  * into manageable sections.
33
34  * for example, an rpc header contains a length field, but until the
35  * data has been created, the length is unknown.  using this module,
36  * the header section can be tacked onto the front of the data memory
37  * list once the size of the data section preceding it is known.
38  
39  * the "margin" can be used to over-run and retrospectively lengthen
40  * the buffer.  this is to save time in some of the loops, where it is
41  * not particularly desirable to realloc data by 1, 2 or 4 bytes
42  * repetitively...
43
44  * each memory buffer contains a start and end offset.  the end of
45  * one buffer should equal to the start of the next in the chain.
46  * (end - start = len, instead of end - start + 1 = len)
47
48  * the debug log levels are very high in some of the routines: you
49  * have no idea how boring it gets staring at debug output from these
50
51  ********************************************************************/
52
53
54 #include "includes.h"
55
56 extern int DEBUGLEVEL;
57
58 /*******************************************************************
59  initialise a memory buffer.
60  ********************************************************************/
61 void mem_init(struct mem_buf *buf, int margin)
62 {
63         buf->dynamic   = True;
64         buf->data      = NULL;
65         buf->data_size = 0;
66         buf->data_used = 0;
67
68         buf->margin    = margin;
69
70         buf->next      = NULL;
71
72         buf->offset.start = 0;
73         buf->offset.end   = 0;
74 }
75
76 /*******************************************************************
77  initialise a memory buffer.
78
79  dynamic indicates memory has been dynamically allocated.
80  if mem_free is called, the memory will be freed.
81  ********************************************************************/
82 void mem_create(struct mem_buf *buf, char *data, int offset, int size, int margin, BOOL dynamic)
83 {
84         buf->dynamic   = dynamic;
85         buf->data      = data;
86         buf->data_size = size;
87         buf->data_used = size;
88
89         buf->margin    = margin;
90
91         buf->next      = NULL;
92
93         buf->offset.start = offset;
94         buf->offset.end   = offset + size;
95 }
96
97 /*******************************************************************
98  allocate a memory buffer.  assume it's empty
99  ********************************************************************/
100 BOOL mem_alloc_data(struct mem_buf *buf, int size)
101 {
102         if (!buf->dynamic)
103         {
104                 DEBUG(3,("mem_alloc_data: warning - memory buffer type is set to static\n"));
105         }
106
107         buf->data_size = size + buf->margin;
108         buf->data_used = size;
109
110         buf->data = malloc(buf->data_size);
111
112         if (buf->data == NULL && size != 0)
113         {
114                 DEBUG(3,("mem_alloc: could not malloc size %d\n",
115                                           buf->data_size));
116                 mem_init(buf, buf->margin);
117
118                 return False;
119         }
120
121         bzero(buf->data, buf->data_size);
122
123         return True;
124 }
125
126 /*******************************************************************
127  allocates a memory buffer structure
128  ********************************************************************/
129 BOOL mem_buf_copy(char *copy_into, struct mem_buf *buf,
130                                 uint32 offset, uint32 len)
131 {
132         uint32 end = offset + len;
133         char *q = NULL;
134         uint32 data_len = mem_buf_len(buf);
135         uint32 start_offset = offset;
136         struct mem_buf **bcp = &buf;
137         
138         if (buf == NULL || copy_into == NULL) return False;
139
140         DEBUG(200,("mem_buf_copy: data[%d..%d] offset %d len %d\n",
141                     buf->offset.start, data_len, offset, len));
142
143         /* there's probably an off-by-one bug, here, and i haven't even tested the code :-) */
144         while (offset < end && ((q = mem_data(bcp, offset)) != NULL))
145         {
146                 uint32 copy_len = (*bcp)->offset.end - offset;
147
148                 DEBUG(200,("\tdata[%d..%d] - offset %d len %d\n",
149                         (*bcp)->offset.start, (*bcp)->offset.end,
150                         offset, copy_len));
151
152                 memcpy(copy_into, q, copy_len);
153         
154                 offset    += copy_len;
155                 copy_into += copy_len;
156         }
157
158         if ((*bcp) != NULL)
159         {
160                 DEBUG(200,("mem_buf_copy: copied %d bytes\n", offset - start_offset));
161         }
162         else
163         {
164                 DEBUG(200,("mem_buf_copy: failed\n"));
165         }
166
167         return buf != NULL;
168 }
169
170 /*******************************************************************
171  allocates a memory buffer structure
172  ********************************************************************/
173 BOOL mem_buf_init(struct mem_buf **buf, uint32 margin)
174 {
175         if (buf == NULL) return False;
176
177         if ((*buf) == NULL)
178         {
179                 (*buf) = malloc(sizeof(**buf));
180                 if ((*buf) != NULL) 
181                 {
182                         mem_init((*buf), margin);
183                         return True;
184                 }
185         }
186         else
187         {
188                 (*buf)->margin = margin;
189                 return True;
190         }
191         return False;
192 }
193
194 /*******************************************************************
195  frees up a memory buffer.
196  ********************************************************************/
197 void mem_buf_free(struct mem_buf **buf)
198 {
199         if (buf == NULL) return;
200         if ((*buf) == NULL) return;
201
202         mem_free_data(*buf);            /* delete memory data */
203         free(*buf);                     /* delete item */
204         (*buf) = NULL;
205 }
206
207 /*******************************************************************
208  frees a memory buffer chain.  assumes that all items are malloced.
209  ********************************************************************/
210 static void mem_free_chain(struct mem_buf **buf)
211 {
212         if (buf == NULL) return;
213         if ((*buf) == NULL) return;
214
215         if ((*buf)->next != NULL)
216         {
217                 mem_free_chain(&((*buf)->next)); /* delete all other items in chain */
218         }
219         mem_buf_free(buf);
220 }
221
222 /*******************************************************************
223  frees a memory buffer.
224  ********************************************************************/
225 void mem_free_data(struct mem_buf *buf)
226 {
227         if (buf == NULL) return;
228
229         if (buf->data != NULL && buf->dynamic)
230         {
231                 free(buf->data);     /* delete data in this structure */
232         }
233         mem_init(buf, buf->margin);
234 }
235
236 /*******************************************************************
237  reallocate a memory buffer, including a safety margin
238  ********************************************************************/
239 BOOL mem_realloc_data(struct mem_buf *buf, int new_size)
240 {
241         char *new_data;
242
243         if (!buf->dynamic)
244         {
245                 DEBUG(3,("mem_realloc_data: memory buffer has not been dynamically allocated!\n"));
246                 return False;
247         }
248
249         if (new_size == 0)
250         {
251                 mem_free_data(buf);
252                 return True;
253         }
254
255         new_data = Realloc(buf->data, new_size + buf->margin);
256
257         if (new_data != NULL)
258         {
259                 buf->data = new_data;
260                 buf->data_size = new_size + buf->margin;
261                 buf->data_used = new_size;
262         }
263         else if (buf->data_size <= new_size)
264         {
265                 DEBUG(3,("mem_realloc: warning - could not realloc to %d(+%d)\n",
266                                   new_size, buf->margin));
267
268                 buf->data_used = new_size;
269         }
270         else 
271         {
272                 DEBUG(3,("mem_realloc: error - could not realloc to %d\n",
273                                   new_size));
274
275                 mem_free_data(buf);
276                 return False;
277         }
278
279         return True;
280 }
281
282 /*******************************************************************
283  reallocate a memory buffer, retrospectively :-)
284  ********************************************************************/
285 BOOL mem_grow_data(struct mem_buf **buf, BOOL io, int new_size, BOOL force_grow)
286 {
287         if (new_size + (*buf)->margin >= (*buf)->data_size)
288         {
289                 if (io && !force_grow)
290                 {
291                         DEBUG(3,("mem_grow_data: cannot resize when reading from a data stream\n"));
292                 }
293                 else
294                 {
295                         return mem_realloc_data((*buf), new_size);
296                 }
297         }
298         return True;
299 }
300
301 /*******************************************************************
302  search for a memory buffer that falls within the specified offset
303  ********************************************************************/
304 static BOOL mem_find(struct mem_buf **buf, uint32 offset)
305 {
306         struct mem_buf *f;
307         if (buf == NULL) return False;
308
309         f = *buf;
310
311         DEBUG(200,("mem_find: data[%d..%d] offset: %d\n",
312               f->offset.start, f->offset.end, offset));
313
314         while (f != NULL && offset >= f->offset.end)
315         {
316                 DEBUG(200,("mem_find: next[%d..%d]\n",
317                         f->offset.start, f->offset.end));
318
319                 f = f->next;
320         }
321
322         (*buf) = f;
323
324         if (f != NULL)
325         {
326                 DEBUG(200,("mem_find: found data[%d..%d]\n",
327                       (*buf)->offset.start,(*buf)->offset.end));
328         }
329
330         return f != NULL;
331 }
332
333
334 /*******************************************************************
335  add up the lengths of all sections.
336  ********************************************************************/
337 uint32 mem_buf_len(struct mem_buf *buf)
338 {
339         int len = 0;
340         while (buf != NULL)
341         {
342                 len += buf->offset.end - buf->offset.start;
343                 buf = buf->next;
344         }
345         return len;
346 }
347
348
349 /*******************************************************************
350  return the memory location specified by offset.  may return NULL.
351  ********************************************************************/
352 char *mem_data(struct mem_buf **buf, uint32 offset)
353 {
354         if (mem_find(buf, offset))
355         {
356                 return &((*buf)->data[offset - (*buf)->offset.start]);
357         }
358         return NULL;
359 }
360
361