1 /*
2                                   NETWIB
3                              Network library
4                 Copyright(c) 1999-2010 Laurent Constantin
5                                   -----
6 
7   Main server   : http://www.laurentconstantin.com/
8   Backup server : http://laurentconstantin.free.fr/
9   [my current email address is on the web servers]
10 
11                                   -----
12   This file is part of Netwib.
13 
14   Netwib is free software: you can redistribute it and/or modify
15   it under the terms of the GNU General Public License version 3
16   as published by the Free Software Foundation.
17 
18   Netwib is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details (http://www.gnu.org/).
22 
23 ------------------------------------------------------------------------
24 */
25 
26 #include <netwib/inc/maininc.h>
27 
28 /*-------------------------------------------------------------*/
29 #define NETWIB_PRIV_BUF_DEFAULT_APPEND1  1024
30 #define NETWIB_PRIV_BUF_DEFAULT_APPEND2 16384
31 
32 /*-------------------------------------------------------------*/
33 #define NETWIB_PRIV_BUF_PTR_CLOSED ((netwib_data)1)
34 
35 /*-------------------------------------------------------------*/
36 #if NETWIB_DEBUG_LEAK==1
37  /* MSBs bitfield stores leakid */
38  #define netwib__priv_buf_get_leakid(pbuf) (pbuf->flags>>NETWIB_BUF_FLAGS_USEDBITS)
39  #define netwib__priv_buf_set_leakid(pbuf,leakid) { pbuf->flags = (leakid<<NETWIB_BUF_FLAGS_USEDBITS) | (pbuf->flags&((1<<NETWIB_BUF_FLAGS_USEDBITS)-1)); }
40 #else
41  /* field inittype stores only inittype */
42  #define netwib__priv_buf_get_leakid(pbuf)
43  #define netwib__priv_buf_set_leakid(pbuf,leakid)
44 #endif
45 
46 /*-------------------------------------------------------------*/
47 #define netwib__priv_buf_cangrow(pb) ((pb)->flags&(NETWIB_BUF_FLAGS_ALLOC|NETWIB_BUF_FLAGS_CANALLOC))
48 
49 /*-------------------------------------------------------------*/
50 #define netwib__priv_buf_canslide(pb) (((pb)->flags&NETWIB_BUF_FLAGS_CANSLIDE) && (pb)->beginoffset!=0 && (!netwib__priv_buf_cangrow(pb) || ((pb)->beginoffset> (pb)->totalsize/2)))
51 #define netwib__priv_buf_slide(pb) {netwib_c_memcpy((pb)->totalptr, netwib__buf_ref_data_ptr(pb), netwib__buf_ref_data_size(pb)); (pb)->endoffset -= (pb)->beginoffset; (pb)->beginoffset = 0;}
52 
53 /*-------------------------------------------------------------*/
netwib_priv_buf_realloc(netwib_uint32 neededspace,netwib_buf * pbuf)54 static netwib_err netwib_priv_buf_realloc(netwib_uint32 neededspace,
55                                           netwib_buf *pbuf)
56 {
57   netwib_data data;
58   netwib_uint32 reallocsize;
59   netwib_uint32 allocstep;
60 
61   if (neededspace == 0) {
62     return(NETWIB_ERR_OK);
63   }
64 
65   allocstep = NETWIB_PRIV_BUF_DEFAULT_APPEND1;
66   if (pbuf->totalsize > NETWIB_PRIV_BUF_DEFAULT_APPEND2) {
67     allocstep = NETWIB_PRIV_BUF_DEFAULT_APPEND2;
68   }
69   reallocsize = pbuf->totalsize;
70   reallocsize += ((neededspace-1)/allocstep + 1) * allocstep;
71 
72   if (pbuf->flags & NETWIB_BUF_FLAGS_ALLOC) {
73     /* realloc */
74 #if NETWIB_DEBUG_LEAK==1
75     netwib_er(netwib_debug_leak_del_buf(pbuf->totalptr,
76                                         netwib__priv_buf_get_leakid(pbuf)));
77 #endif
78     if (pbuf->flags & NETWIB_BUF_FLAGS_SENSITIVE) {
79       /* slow but safe */
80       netwib_er(netwib_ptr_malloc(reallocsize, (netwib_ptr*)&data));
81       netwib_c_memcpy(data, pbuf->totalptr, pbuf->totalsize);
82       netwib_c_memset(pbuf->totalptr, 0, pbuf->totalsize);
83       netwib_er(netwib_ptr_free((netwib_ptr*)&pbuf->totalptr));
84       pbuf->totalptr = data;
85     } else {
86       netwib_er(netwib_ptr_realloc(reallocsize, (netwib_ptr*)&pbuf->totalptr));
87     }
88 #if NETWIB_DEBUG_LEAK==1
89     netwib_er(netwib_debug_leak_add_buf(pbuf->totalptr,
90                                         netwib__priv_buf_get_leakid(pbuf)));
91 #endif
92   } else {
93     /* allocate buffer */
94     netwib_er(netwib_ptr_malloc(reallocsize, (netwib_ptr*)&data));
95     if (pbuf->flags & NETWIB_BUF_FLAGS_CANALLOC) {
96       /* convert an array to an allocated memory */
97       netwib_c_memcpy(data, pbuf->totalptr, pbuf->totalsize);
98       if ( (pbuf->flags & NETWIB_BUF_FLAGS_SENSITIVE) &&
99            !(pbuf->flags & NETWIB_BUF_FLAGS_SENSITIVE_READONLY)) {
100         netwib_c_memset(pbuf->totalptr, 0, pbuf->totalsize);
101       }
102       pbuf->totalptr = data;
103       /* we do not need to change beginoffset and endoffset */
104       pbuf->flags &= ~NETWIB_BUF_FLAGS_CANALLOC;
105       pbuf->flags |= NETWIB_BUF_FLAGS_ALLOC;
106     } else {
107       return(NETWIB_ERR_LOINTERNALERROR);
108     }
109 #if NETWIB_DEBUG_LEAK==1
110     {
111       netwib_uint32 leakid;
112       netwib_er(netwib_debug_leak_id_buf(&leakid));
113       netwib__priv_buf_set_leakid(pbuf, leakid);
114       netwib_er(netwib_debug_leak_add_buf(pbuf->totalptr, leakid));
115     }
116 #endif
117   }
118 
119   pbuf->totalsize = reallocsize;
120 
121   return(NETWIB_ERR_OK);
122 }
123 
124 /*-------------------------------------------------------------*/
netwib_buf_init_malloc(netwib_uint32 allocsize,netwib_buf * pbuf)125 netwib_err netwib_buf_init_malloc(netwib_uint32 allocsize,
126                                   netwib_buf *pbuf)
127 {
128   netwib_data data;
129   netwib_uint32 totalsize;
130 
131   /* parameter verification */
132   if (pbuf == NULL) {
133     /* nothing to alloc */
134     return(NETWIB_ERR_OK);
135   }
136 
137   /* better to warn user */
138   if (allocsize == 0) {
139     return(NETWIB_ERR_PATOOLOW);
140   }
141 
142   /* compute totalsize */
143   totalsize = allocsize;
144 
145   /* allocate memory */
146   netwib_er(netwib_ptr_malloc(totalsize, (netwib_ptr*)&data));
147 
148   /* set values */
149   pbuf->flags = NETWIB_BUF_FLAGS_ALLOC;
150   pbuf->totalptr = data;
151   pbuf->totalsize = totalsize;
152   pbuf->beginoffset = 0;
153   pbuf->endoffset = 0;
154 
155 #if NETWIB_DEBUG_LEAK==1
156   {
157     netwib_uint32 leakid;
158     netwib_er(netwib_debug_leak_id_buf(&leakid));
159     netwib__priv_buf_set_leakid(pbuf, leakid);
160     netwib_er(netwib_debug_leak_add_buf(pbuf->totalptr, leakid));
161   }
162 #endif
163 
164   return(NETWIB_ERR_OK);
165 }
166 
167 /*-------------------------------------------------------------*/
netwib_buf_init_ext_array(netwib_constptr array,netwib_uint32 arraysize,netwib_uint32 beginoffset,netwib_uint32 endoffset,netwib_bufext * pbuf)168 netwib_err netwib_buf_init_ext_array(netwib_constptr array,
169                                      netwib_uint32 arraysize,
170                                      netwib_uint32 beginoffset,
171                                      netwib_uint32 endoffset,
172                                      netwib_bufext *pbuf)
173 {
174   /* parameters verification */
175   if (array == NULL && arraysize)
176     return(NETWIB_ERR_PANULLPTRSIZE);
177   if (beginoffset > arraysize)
178     return(NETWIB_ERR_PATOOHIGH);
179   if (endoffset > arraysize)
180     return(NETWIB_ERR_PATOOHIGH);
181   if (pbuf == NULL) {
182     /* nothing to do */
183     return(NETWIB_ERR_OK);
184   }
185 
186   /* set values */
187   pbuf->flags = 0;
188   netwib__priv_buf_set_leakid(pbuf, NETWIB_DEBUG_LEAK_ID_BUF_IGNORE);
189   pbuf->totalptr = netwib_priv_castdata(array);
190   pbuf->totalsize = arraysize;
191   pbuf->beginoffset = beginoffset;
192   pbuf->endoffset = endoffset;
193 
194   return(NETWIB_ERR_OK);
195 }
196 
197 /*-------------------------------------------------------------*/
netwib_buf_init_ext_storagearray(netwib_constptr array,netwib_uint32 arraysize,netwib_bufext * pbuf)198 netwib_err netwib_buf_init_ext_storagearray(netwib_constptr array,
199                                             netwib_uint32 arraysize,
200                                             netwib_bufext *pbuf)
201 {
202   /* parameters verification */
203   if (array == NULL && arraysize)
204     return(NETWIB_ERR_PANULLPTRSIZE);
205   if (pbuf == NULL) {
206     /* nothing to do */
207     return(NETWIB_ERR_OK);
208   }
209 
210   /* set values */
211   pbuf->flags = NETWIB_BUF_FLAGS_CANALLOC;
212   netwib__priv_buf_set_leakid(pbuf, NETWIB_DEBUG_LEAK_ID_BUF_IGNORE);
213   pbuf->totalptr = netwib_priv_castdata(array);
214   pbuf->totalsize = arraysize;
215   pbuf->beginoffset = 0;
216   pbuf->endoffset = 0;
217 
218   return(NETWIB_ERR_OK);
219 }
220 
221 /*-------------------------------------------------------------*/
netwib_buf_init_ext_buf(netwib_constbuf * pbufin,netwib_bufext * pbuf)222 netwib_err netwib_buf_init_ext_buf(netwib_constbuf *pbufin,
223                                    netwib_bufext *pbuf)
224 {
225   if (pbuf == NULL) {
226     /* nothing to do */
227     return(NETWIB_ERR_OK);
228   }
229 
230   /* set values */
231   pbuf->flags = 0;
232   netwib__priv_buf_set_leakid(pbuf, NETWIB_DEBUG_LEAK_ID_BUF_IGNORE);
233   pbuf->totalptr = netwib__buf_ref_data_ptr(pbufin);
234   pbuf->totalsize = netwib__buf_ref_data_size(pbufin);
235   pbuf->beginoffset = 0;
236   pbuf->endoffset = netwib__buf_ref_data_size(pbufin);
237   netwib__buf_transfersensitive(pbufin, pbuf);
238 
239   return(NETWIB_ERR_OK);
240 }
241 
242 /*-------------------------------------------------------------*/
netwib_buf_init_ext_string(netwib_conststring str,netwib_bufext * pbuf)243 netwib_err netwib_buf_init_ext_string(netwib_conststring str,
244                                       netwib_bufext *pbuf)
245 {
246   /* parameter verification */
247   if (pbuf == NULL) {
248     /* nothing to do */
249     return(NETWIB_ERR_OK);
250   }
251 
252   /* set values */
253   pbuf->flags = 0;
254   netwib__priv_buf_set_leakid(pbuf, NETWIB_DEBUG_LEAK_ID_BUF_IGNORE);
255   pbuf->beginoffset = 0;
256   if (str) {
257     pbuf->endoffset = netwib_c_strlen(str);
258     pbuf->totalptr = netwib_priv_castdata(str);
259     pbuf->totalsize = pbuf->endoffset + 1;
260   } else {
261     pbuf->endoffset = 0;
262     pbuf->totalptr = NULL;
263     pbuf->totalsize = 0;
264   }
265 
266   return(NETWIB_ERR_OK);
267 }
268 
269 /*-------------------------------------------------------------*/
netwib_buf_shift(netwib_buf * pbuf,netwib_int32 offset,netwib_bool truncbegend)270 netwib_err netwib_buf_shift(netwib_buf *pbuf,
271                             netwib_int32 offset,
272                             netwib_bool truncbegend)
273 {
274   netwib_uint32 offsetpos, datasize;
275 
276   /* simple cases */
277   if (pbuf == NULL) {
278     /* shifting an empty buffer does not change it */
279     return(NETWIB_ERR_OK);
280   }
281   if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
282     return(NETWIB_ERR_LOOBJUSECLOSED);
283 
284 #if NETWIB_DEBUG_LEAK==1
285   netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
286                                         netwib__priv_buf_get_leakid(pbuf)));
287 #endif
288 
289   /* simple case */
290   if (offset == 0) {
291     return(NETWIB_ERR_OK);
292   }
293 
294   /* if truncate */
295   if (truncbegend) {
296     datasize = pbuf->endoffset - pbuf->beginoffset;
297     if (offset < 0) {
298       offsetpos = (netwib_uint32)-offset;
299       if (offsetpos >= datasize) {
300         pbuf->endoffset = pbuf->beginoffset;
301         return(NETWIB_ERR_OK);
302       }
303       netwib_c_memcpy(pbuf->totalptr + pbuf->beginoffset,
304                       pbuf->totalptr + pbuf->beginoffset + offsetpos,
305                       datasize - offsetpos);
306       pbuf->endoffset += offset;
307       return(NETWIB_ERR_OK);
308     }
309     offsetpos = (netwib_uint32)offset;
310     if (offsetpos >= datasize) {
311       pbuf->beginoffset = pbuf->endoffset;
312       return(NETWIB_ERR_OK);
313     }
314     netwib_c_memmove(pbuf->totalptr + pbuf->beginoffset + offset,
315                      pbuf->totalptr + pbuf->beginoffset,
316                      datasize - offsetpos);
317     pbuf->beginoffset += offset;
318     return(NETWIB_ERR_OK);
319   }
320 
321   /* now, do not truncate */
322   if (offset < 0) {
323     offsetpos = (netwib_uint32)-offset;
324 
325     /* simple left shift */
326     if (offsetpos <= pbuf->beginoffset) {
327       netwib_c_memcpy(pbuf->totalptr + pbuf->beginoffset + offset,
328                       pbuf->totalptr + pbuf->beginoffset,
329                       pbuf->endoffset - pbuf->beginoffset);
330       pbuf->beginoffset += offset;
331       pbuf->endoffset += offset;
332       return(NETWIB_ERR_OK);
333     }
334 
335     /* full overwrite left shift */
336     if (offsetpos >= pbuf->endoffset) {
337       pbuf->beginoffset = 0;
338       pbuf->endoffset = 0;
339       return(NETWIB_ERR_OK);
340     }
341 
342     /* half overwrite left shift */
343     netwib_c_memcpy(pbuf->totalptr,
344                     pbuf->totalptr - offset,
345                     pbuf->endoffset + offset);
346     pbuf->beginoffset = 0;
347     pbuf->endoffset += offset;
348     return(NETWIB_ERR_OK);
349   }
350 
351   offsetpos = (netwib_uint32)offset;
352 
353   /* simple right shift */
354   if (offsetpos <= pbuf->totalsize - pbuf->endoffset) {
355     netwib_c_memmove(pbuf->totalptr + pbuf->beginoffset + offset,
356                      pbuf->totalptr + pbuf->beginoffset,
357                      pbuf->endoffset - pbuf->beginoffset);
358     pbuf->beginoffset += offset;
359     pbuf->endoffset += offset;
360     return(NETWIB_ERR_OK);
361   }
362 
363   if (!netwib__priv_buf_cangrow(pbuf)) {
364     /* will truncate */
365     if (offsetpos > pbuf->totalsize - pbuf->beginoffset) {
366       pbuf->beginoffset = pbuf->totalsize;
367     } else {
368       netwib_c_memmove(pbuf->totalptr + pbuf->beginoffset + offset,
369                        pbuf->totalptr + pbuf->beginoffset,
370                        pbuf->totalsize - pbuf->beginoffset - offset);
371       pbuf->beginoffset += offset;
372     }
373     pbuf->endoffset = pbuf->totalsize;
374     return(NETWIB_ERR_OK);
375   }
376 
377   /* right shift with realloc */
378   netwib_er(netwib_priv_buf_realloc(offset - pbuf->totalsize+pbuf->endoffset,
379                                     pbuf));
380   netwib_c_memmove(pbuf->totalptr + pbuf->beginoffset + offset,
381                    pbuf->totalptr + pbuf->beginoffset,
382                    pbuf->endoffset - pbuf->beginoffset);
383   pbuf->beginoffset += offset;
384   pbuf->endoffset += offset;
385 
386   return(NETWIB_ERR_OK);
387 }
388 
389 /*-------------------------------------------------------------*/
netwib_buf_append_data(netwib_constdata data,netwib_uint32 datasize,netwib_buf * pbuf)390 netwib_err netwib_buf_append_data(netwib_constdata data,
391                                   netwib_uint32 datasize,
392                                   netwib_buf *pbuf)
393 {
394   netwib_uint32 leftsize;
395 
396   /* parameters verification */
397   if (data == NULL && datasize) {
398     return(NETWIB_ERR_PANULLPTRSIZE);
399   }
400 
401   /* simple case */
402   if (pbuf == NULL) {
403     /* nothing to append to nothing */
404     return(NETWIB_ERR_OK);
405   }
406   if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
407     return(NETWIB_ERR_LOOBJUSECLOSED);
408 #if NETWIB_DEBUG_LEAK==1
409   netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
410                                         netwib__priv_buf_get_leakid(pbuf)));
411 #endif
412   if (datasize == 0) {
413     return(NETWIB_ERR_OK);
414   }
415 
416   /* append */
417   leftsize = pbuf->totalsize - pbuf->endoffset;
418   if (datasize <= leftsize) {
419     /* if sufficient, only append data */
420     netwib_c_memcpy(pbuf->totalptr+pbuf->endoffset, data, datasize);
421     pbuf->endoffset += datasize;
422     return(NETWIB_ERR_OK);
423   }
424 
425   /* no space for data : check if we can slide */
426   if (netwib__priv_buf_canslide(pbuf)) {
427     leftsize += pbuf->beginoffset;
428     if (datasize <= leftsize) {
429       netwib__priv_buf_slide(pbuf);
430       netwib_c_memcpy(pbuf->totalptr+pbuf->endoffset, data, datasize);
431       pbuf->endoffset += datasize;
432       return(NETWIB_ERR_OK);
433     }
434   }
435 
436   /* no space for data */
437   if (!netwib__priv_buf_cangrow(pbuf)) {
438     return(NETWIB_ERR_DATANOSPACE);
439   }
440 
441   /* we need to realloc */
442   if (netwib__priv_buf_canslide(pbuf)) {
443     /* decide to slide even if it is not sufficient : on next call,
444        we will no more slide (it's better to slide when there is a small
445        amount of memory to copy) */
446     netwib__priv_buf_slide(pbuf);
447   }
448   netwib_er(netwib_priv_buf_realloc(datasize - leftsize, pbuf));
449   /* now, copy data */
450   netwib_c_memcpy(pbuf->totalptr+pbuf->endoffset, data, datasize);
451   pbuf->endoffset += datasize;
452   return(NETWIB_ERR_OK);
453 }
454 
455 /*-------------------------------------------------------------*/
netwib_buf_append_string(netwib_conststring str,netwib_buf * pbuf)456 netwib_err netwib_buf_append_string(netwib_conststring str,
457                                     netwib_buf *pbuf)
458 {
459   if (str != NULL && pbuf != NULL) {
460     netwib_er(netwib_buf_append_data((netwib_constdata)str,
461                                      netwib_c_strlen(str),
462                                      pbuf));
463   }
464 
465   return(NETWIB_ERR_OK);
466 }
467 
468 /*-------------------------------------------------------------*/
netwib_buf_append_buf(netwib_constbuf * pbuftoappend,netwib_buf * pbuf)469 netwib_err netwib_buf_append_buf(netwib_constbuf *pbuftoappend,
470                                  netwib_buf *pbuf)
471 {
472 
473   if (pbuftoappend == NULL || pbuf == NULL) {
474     /* nothing to append */
475     return(NETWIB_ERR_OK);
476   }
477 
478   if (pbuftoappend->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
479     return(NETWIB_ERR_LOOBJUSECLOSED);
480   }
481 #if NETWIB_DEBUG_LEAK==1
482   netwib_er(netwib_debug_leak_valid_buf(pbuftoappend->totalptr,
483                                         netwib__priv_buf_get_leakid(pbuftoappend)));
484 #endif
485   netwib__buf_transfersensitive(pbuftoappend, pbuf);
486 
487   if (pbuftoappend->beginoffset < pbuftoappend->endoffset) {
488     netwib_er(netwib_buf_append_data(pbuftoappend->totalptr +
489                                      pbuftoappend->beginoffset,
490                                      pbuftoappend->endoffset -
491                                      pbuftoappend->beginoffset,
492                                      pbuf));
493   }
494 
495   return(NETWIB_ERR_OK);
496 }
497 
498 /*-------------------------------------------------------------*/
netwib_buf_append_byte(netwib_byte b,netwib_buf * pbuf)499 netwib_err netwib_buf_append_byte(netwib_byte b,
500                                   netwib_buf *pbuf)
501 {
502   netwib_uint32 leftsize;
503 
504   /* simple case */
505   if (pbuf == NULL) {
506     /* nothing to append */
507     return(NETWIB_ERR_OK);
508   }
509   if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
510     return(NETWIB_ERR_LOOBJUSECLOSED);
511 #if NETWIB_DEBUG_LEAK==1
512   netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
513                                         netwib__priv_buf_get_leakid(pbuf)));
514 #endif
515 
516   /* append */
517   leftsize = pbuf->totalsize - pbuf->endoffset;
518   if (leftsize > 0) {
519     /* if sufficient, only append data */
520     pbuf->totalptr[pbuf->endoffset] = b;
521     pbuf->endoffset++;
522     return(NETWIB_ERR_OK);
523   }
524 
525   /* no space for data : check if we can slide */
526   if (netwib__priv_buf_canslide(pbuf)) {
527     if (pbuf->beginoffset) {
528       netwib__priv_buf_slide(pbuf);
529       pbuf->totalptr[pbuf->endoffset] = b;
530       pbuf->endoffset++;
531       return(NETWIB_ERR_OK);
532     }
533   }
534 
535   if (!netwib__priv_buf_cangrow(pbuf)) {
536     /* there is no space */
537     return(NETWIB_ERR_DATANOSPACE);
538   }
539 
540   /* we need to realloc */
541   if (netwib__priv_buf_canslide(pbuf)) {
542     netwib__priv_buf_slide(pbuf);
543   }
544   netwib_er(netwib_priv_buf_realloc(1, pbuf));
545 
546   /* now, copy data */
547   pbuf->totalptr[pbuf->endoffset] = b;
548   pbuf->endoffset++;
549   return(NETWIB_ERR_OK);
550 }
551 
552 /*-------------------------------------------------------------*/
netwib_buf_prepend_buf(netwib_constbuf * pbuftoprepend,netwib_buf * pbuf)553 netwib_err netwib_buf_prepend_buf(netwib_constbuf *pbuftoprepend,
554                                   netwib_buf *pbuf)
555 {
556   netwib_uint32 buftoprependsize;
557 
558   /* simple case */
559   if (pbuftoprepend == NULL || pbuf == NULL) {
560     /* nothing to prepend */
561     return(NETWIB_ERR_OK);
562   }
563 
564   if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
565     return(NETWIB_ERR_LOOBJUSECLOSED);
566   if (pbuftoprepend->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
567     return(NETWIB_ERR_LOOBJUSECLOSED);
568 #if NETWIB_DEBUG_LEAK==1
569   netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
570                                         netwib__priv_buf_get_leakid(pbuf)));
571   netwib_er(netwib_debug_leak_valid_buf(pbuftoprepend->totalptr,
572                                         netwib__priv_buf_get_leakid(pbuftoprepend)));
573 #endif
574   netwib__buf_transfersensitive(pbuftoprepend, pbuf);
575 
576   buftoprependsize = netwib__buf_ref_data_size(pbuftoprepend);
577   if (buftoprependsize > pbuf->beginoffset) {
578     /* need some shift */
579     netwib_er(netwib_buf_shift(pbuf, buftoprependsize - pbuf->beginoffset,
580                                NETWIB_FALSE));
581   }
582   pbuf->beginoffset -= buftoprependsize;
583   netwib_c_memcpy(netwib__buf_ref_data_ptr(pbuf),
584                  netwib__buf_ref_data_ptr(pbuftoprepend),
585                  buftoprependsize);
586 
587   return(NETWIB_ERR_OK);
588 }
589 
590 /*-------------------------------------------------------------*/
netwib_buf_ref_string(netwib_buf * pbuf,netwib_string * pstr)591 netwib_err netwib_buf_ref_string(netwib_buf *pbuf,
592                                  netwib_string *pstr)
593 {
594   netwib_char *pc, *pfirst;
595 
596   /* simple case */
597   if (pbuf == NULL) {
598     /* it's not possible to obtain info if this pointer is NULL */
599     return(NETWIB_ERR_DATANOSPACE);
600   }
601   if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
602     return(NETWIB_ERR_LOOBJUSECLOSED);
603   }
604 #if NETWIB_DEBUG_LEAK==1
605   netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
606                                         netwib__priv_buf_get_leakid(pbuf)));
607 #endif
608 
609   /* eventually add a '\0' */
610   if (pbuf->endoffset < pbuf->totalsize) {
611     /* there is room to add a '\0' */
612     if (pbuf->totalptr[pbuf->endoffset] != '\0') {
613       /* we do this check because external array might be constant string
614          (so it cannot be set) */
615       pbuf->totalptr[pbuf->endoffset] = '\0';
616     }
617   } else if (netwib__priv_buf_canslide(pbuf)) {
618     /* buffer can be slided, slide it to add a '\0' */
619     netwib__priv_buf_slide(pbuf);
620     pbuf->totalptr[pbuf->endoffset] = '\0';
621   } else if (netwib__priv_buf_cangrow(pbuf)) {
622     /* buffer can be reallocated */
623     netwib_er(netwib_priv_buf_realloc(1, pbuf));
624     /* now, set zero */
625     pbuf->totalptr[pbuf->endoffset] = '\0';
626   } else if (netwib__buf_ref_data_size(pbuf)) {
627     /* our last chance is to find a zero in the middle of the buffer */
628     pfirst = (netwib_string)pbuf->totalptr + pbuf->beginoffset;
629     pc = (netwib_string)pbuf->totalptr + pbuf->endoffset - 1;
630     while (NETWIB_TRUE) {
631       if (*pc == '\0') {
632         /* we are lucky, there is one */
633         break;
634       }
635       if (pc == pfirst) {
636         break;
637       }
638       pc--;
639     }
640     if (*pc != '\0') {
641       return(NETWIB_ERR_DATANOSPACE);
642     }
643   } else {
644     /* we didn't found a zero, and there is no room to put it */
645     return(NETWIB_ERR_DATANOSPACE);
646   }
647 
648   if (pstr != NULL) {
649     /* set output */
650     *pstr = (netwib_string)netwib__buf_ref_data_ptr(pbuf);
651   }
652 
653   return(NETWIB_ERR_OK);
654 }
655 
656 /*-------------------------------------------------------------*/
netwib_constbuf_ref_string(netwib_constbuf * pbuf,netwib_string * pstr)657 netwib_err netwib_constbuf_ref_string(netwib_constbuf *pbuf,
658                                       netwib_string *pstr)
659 {
660   netwib_char *pc, *pfirst;
661 
662   /* simple case */
663   if (pbuf == NULL) {
664     /* it's not possible to obtain info if this pointer is NULL */
665     return(NETWIB_ERR_DATANOSPACE);
666   }
667   if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
668     return(NETWIB_ERR_LOOBJUSECLOSED);
669   }
670 #if NETWIB_DEBUG_LEAK==1
671   netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
672                                         netwib__priv_buf_get_leakid(pbuf)));
673 #endif
674 
675   /* check if there is already a '\0' */
676   if (pbuf->endoffset < pbuf->totalsize &&
677       pbuf->totalptr[pbuf->endoffset] == '\0') {
678     /* ok */
679   } else if (netwib__buf_ref_data_size(pbuf)) {
680     /* our last chance is to find a zero in the middle of the buffer */
681     pfirst = (netwib_string)pbuf->totalptr + pbuf->beginoffset;
682     pc = (netwib_string)pbuf->totalptr + pbuf->endoffset - 1;
683     while (NETWIB_TRUE) {
684       if (*pc == '\0') {
685         /* we are lucky, there is one */
686         break;
687       }
688       if (pc == pfirst) {
689         break;
690       }
691       pc--;
692     }
693     if (*pc != '\0') {
694       return(NETWIB_ERR_DATANOSPACE);
695     }
696   } else {
697     /* we didn't found a zero, and there is no room to put it */
698     return(NETWIB_ERR_DATANOSPACE);
699   }
700 
701   if (pstr != NULL) {
702     /* set output */
703     *pstr = (netwib_string)netwib__buf_ref_data_ptr(pbuf);
704   }
705 
706   return(NETWIB_ERR_OK);
707 }
708 
709 /*-------------------------------------------------------------*/
netwib_buf_wantspace(netwib_buf * pbuf,netwib_uint32 wantedspace,netwib_data * pdata)710 netwib_err netwib_buf_wantspace(netwib_buf *pbuf,
711                                 netwib_uint32 wantedspace,
712                                 netwib_data *pdata)
713 {
714   netwib_uint32 leftsize;
715 
716   /* simple case */
717   if (pbuf == NULL) {
718     /* it's not possible to obtain info if this pointer is NULL */
719     return(NETWIB_ERR_PANULLPTR);
720   }
721   if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
722     return(NETWIB_ERR_LOOBJUSECLOSED);
723   }
724 #if NETWIB_DEBUG_LEAK==1
725   netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
726                                         netwib__priv_buf_get_leakid(pbuf)));
727 #endif
728 
729   leftsize = pbuf->totalsize - pbuf->endoffset;
730   if (wantedspace <= leftsize) {
731     /* sufficient space */
732     if (pdata != NULL) {
733       *pdata = pbuf->totalptr + pbuf->endoffset;
734     }
735     return(NETWIB_ERR_OK);
736   }
737 
738   /* no space for data : check if we can slide */
739   if (netwib__priv_buf_canslide(pbuf)) {
740     leftsize += pbuf->beginoffset;
741     if (wantedspace <= leftsize) {
742       netwib__priv_buf_slide(pbuf);
743       if (pdata != NULL) {
744         *pdata = pbuf->totalptr + pbuf->endoffset;
745       }
746       return(NETWIB_ERR_OK);
747     }
748   }
749 
750   if (!netwib__priv_buf_cangrow(pbuf)) {
751     /* cannot realloc */
752     return(NETWIB_ERR_DATANOSPACE);
753   }
754 
755   /* realloc */
756   if (netwib__priv_buf_canslide(pbuf)) {
757     netwib__priv_buf_slide(pbuf);
758   }
759   netwib_er(netwib_priv_buf_realloc(wantedspace - leftsize, pbuf));
760 
761   if (pdata != NULL) {
762     *pdata = pbuf->totalptr + pbuf->endoffset;
763   }
764 
765   return(NETWIB_ERR_OK);
766 }
767 
768 /*-------------------------------------------------------------*/
netwib_buf_wishspace(netwib_buf * pbuf,netwib_uint32 wantedspace,netwib_data * pdata,netwib_uint32 * pobtainedspace)769 netwib_err netwib_buf_wishspace(netwib_buf *pbuf,
770                                 netwib_uint32 wantedspace,
771                                 netwib_data *pdata,
772                                 netwib_uint32 *pobtainedspace)
773 {
774   netwib_uint32 leftsize;
775 
776   /* simple case */
777   if (pbuf == NULL) {
778     /* it's not possible to obtain info if this pointer is NULL */
779     return(NETWIB_ERR_PANULLPTR);
780   }
781   if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
782     return(NETWIB_ERR_LOOBJUSECLOSED);
783   }
784 #if NETWIB_DEBUG_LEAK==1
785   netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
786                                       netwib__priv_buf_get_leakid(pbuf)));
787 #endif
788 
789   leftsize = pbuf->totalsize - pbuf->endoffset;
790   if (wantedspace <= leftsize) {
791     /* sufficient space */
792     if (pdata != NULL) {
793       *pdata = pbuf->totalptr + pbuf->endoffset;
794     }
795     if (pobtainedspace != NULL) *pobtainedspace = leftsize;
796     return(NETWIB_ERR_OK);
797   }
798 
799   /* slide if possible */
800   if (netwib__priv_buf_canslide(pbuf)) {
801     netwib__priv_buf_slide(pbuf);
802   }
803 
804   if (!netwib__priv_buf_cangrow(pbuf)) {
805     /* cannot realloc, so return current size */
806     if (pdata != NULL) {
807       *pdata = pbuf->totalptr + pbuf->endoffset;
808     }
809     if (pobtainedspace != NULL) *pobtainedspace = leftsize;
810     return(NETWIB_ERR_OK);
811   }
812 
813   /* realloc */
814   netwib_er(netwib_priv_buf_realloc(wantedspace - leftsize, pbuf));
815 
816   if (pdata != NULL) {
817     *pdata = pbuf->totalptr + pbuf->endoffset;
818   }
819   if (pobtainedspace != NULL) {
820     *pobtainedspace = pbuf->totalsize - pbuf->endoffset;
821   }
822 
823   return(NETWIB_ERR_OK);
824 }
825 
826 /*-------------------------------------------------------------*/
netwib_buf_cmp(netwib_constbuf * pbuf1,netwib_constbuf * pbuf2,netwib_cmp * pcmp)827 netwib_err netwib_buf_cmp(netwib_constbuf *pbuf1,
828                           netwib_constbuf *pbuf2,
829                           netwib_cmp *pcmp)
830 {
831   netwib_uint32 data1size, data2size, commonsize;
832   netwib_cmp cmp=NETWIB_CMP_LT;
833   int reti;
834 
835   /* parameter verification */
836   if (pbuf1 != NULL) {
837     if (pbuf1->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
838       return(NETWIB_ERR_LOOBJUSECLOSED);
839     }
840 #if NETWIB_DEBUG_LEAK==1
841     netwib_er(netwib_debug_leak_valid_buf(pbuf1->totalptr,
842                                           netwib__priv_buf_get_leakid(pbuf1)));
843 #endif
844   }
845   if (pbuf2 != NULL) {
846     if (pbuf2->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
847       return(NETWIB_ERR_LOOBJUSECLOSED);
848     }
849 #if NETWIB_DEBUG_LEAK==1
850     netwib_er(netwib_debug_leak_valid_buf(pbuf2->totalptr,
851                                           netwib__priv_buf_get_leakid(pbuf2)));
852 #endif
853   }
854 
855   data1size = netwib__buf_ref_data_sizenull(pbuf1);
856   data2size = netwib__buf_ref_data_sizenull(pbuf2);
857   if (data1size == 0 && data2size == 0) {
858     cmp = NETWIB_CMP_EQ;
859   } else if (data1size == 0) {
860     cmp = NETWIB_CMP_LT;
861   } else if (data2size == 0) {
862     cmp = NETWIB_CMP_GT;
863   } else {
864     commonsize = (data1size<data2size)?data1size:data2size;
865     reti = netwib_c_memcmp(pbuf1->totalptr+pbuf1->beginoffset,
866                            pbuf2->totalptr+pbuf2->beginoffset, commonsize);
867     if (reti == 0) {
868       if (data1size == data2size) {
869         cmp = NETWIB_CMP_EQ;
870       } else {
871         cmp = (data1size<data2size)?NETWIB_CMP_LT:NETWIB_CMP_GT;
872       }
873     } else if (reti < 0) {
874       cmp = NETWIB_CMP_LT;
875     } else {
876       cmp = NETWIB_CMP_GT;
877     }
878   }
879 
880   if (pcmp != NULL) *pcmp = cmp;
881   return(NETWIB_ERR_OK);
882 }
883 
884 /*-------------------------------------------------------------*/
netwib_buf_casecmp(netwib_constbuf * pbuf1,netwib_constbuf * pbuf2,netwib_cmp * pcmp)885 netwib_err netwib_buf_casecmp(netwib_constbuf *pbuf1,
886                               netwib_constbuf *pbuf2,
887                               netwib_cmp *pcmp)
888 {
889   netwib_uint32 data1size, data2size, commonsize;
890   netwib_cmp cmp=NETWIB_CMP_LT;
891   int reti;
892 
893   /* parameter verification */
894   if (pbuf1 != NULL) {
895     if (pbuf1->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
896       return(NETWIB_ERR_LOOBJUSECLOSED);
897     }
898 #if NETWIB_DEBUG_LEAK==1
899     netwib_er(netwib_debug_leak_valid_buf(pbuf1->totalptr,
900                                           netwib__priv_buf_get_leakid(pbuf1)));
901 #endif
902   }
903   if (pbuf2 != NULL) {
904     if (pbuf2->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
905       return(NETWIB_ERR_LOOBJUSECLOSED);
906     }
907 #if NETWIB_DEBUG_LEAK==1
908     netwib_er(netwib_debug_leak_valid_buf(pbuf2->totalptr,
909                                           netwib__priv_buf_get_leakid(pbuf2)));
910 #endif
911   }
912 
913   data1size = netwib__buf_ref_data_sizenull(pbuf1);
914   data2size = netwib__buf_ref_data_sizenull(pbuf2);
915   if (data1size == 0 && data2size == 0) {
916     cmp = NETWIB_CMP_EQ;
917   } else if (data1size == 0) {
918     cmp = NETWIB_CMP_LT;
919   } else if (data2size == 0) {
920     cmp = NETWIB_CMP_GT;
921   } else {
922     commonsize = (data1size<data2size)?data1size:data2size;
923     reti = netwib_c_memcasecmp(pbuf1->totalptr+pbuf1->beginoffset,
924                                pbuf2->totalptr+pbuf2->beginoffset, commonsize);
925     if (reti == 0) {
926       if (data1size == data2size) {
927         cmp = NETWIB_CMP_EQ;
928       } else {
929         cmp = (data1size<data2size)?NETWIB_CMP_LT:NETWIB_CMP_GT;
930       }
931     } else if (reti < 0) {
932       cmp = NETWIB_CMP_LT;
933     } else {
934       cmp = NETWIB_CMP_GT;
935     }
936   }
937 
938   if (pcmp != NULL) *pcmp = cmp;
939   return(NETWIB_ERR_OK);
940 }
941 
942 /*-------------------------------------------------------------*/
netwib_buf_cmp_string(netwib_constbuf * pbuf1,netwib_conststring string2,netwib_cmp * pcmp)943 netwib_err netwib_buf_cmp_string(netwib_constbuf *pbuf1,
944                                  netwib_conststring string2,
945                                  netwib_cmp *pcmp)
946 {
947   netwib_conststring ps;
948   netwib_data data;
949   netwib_uint32 datasize;
950   netwib_char c1, c2=0;
951   netwib_cmp cmp=NETWIB_CMP_LT;
952 
953   /* parameter verification */
954   if (pbuf1 != NULL) {
955     if (pbuf1->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
956       return(NETWIB_ERR_LOOBJUSECLOSED);
957     }
958 #if NETWIB_DEBUG_LEAK==1
959     netwib_er(netwib_debug_leak_valid_buf(pbuf1->totalptr,
960                                           netwib__priv_buf_get_leakid(pbuf1)));
961 #endif
962   }
963 
964   datasize = netwib__buf_ref_data_sizenull(pbuf1);
965   data = datasize?netwib__buf_ref_data_ptr(pbuf1):NULL;
966   ps = string2;
967 
968   while (NETWIB_TRUE) {
969     if (string2 == NULL) {
970       c2 = '\0';
971     } else {
972       c2 = *ps++;
973     }
974     if (c2 == '\0') {
975       if (datasize == 0) {
976         cmp = NETWIB_CMP_EQ;
977       } else {
978         cmp = NETWIB_CMP_GT;
979       }
980       break;
981     }
982     if (datasize == 0) {
983       cmp = NETWIB_CMP_LT;
984       break;
985     }
986     c1 = *data++;
987     datasize--;
988     if (c1 > c2) {
989       cmp = NETWIB_CMP_GT;
990       break;
991     } else if (c1 < c2) {
992       cmp = NETWIB_CMP_LT;
993       break;
994     }
995   }
996 
997   if (pcmp != NULL) *pcmp = cmp;
998   return(NETWIB_ERR_OK);
999 }
1000 
1001 /*-------------------------------------------------------------*/
netwib_buf_casecmp_string(netwib_constbuf * pbuf1,netwib_conststring string2,netwib_cmp * pcmp)1002 netwib_err netwib_buf_casecmp_string(netwib_constbuf *pbuf1,
1003                                      netwib_conststring string2,
1004                                      netwib_cmp *pcmp)
1005 {
1006   netwib_conststring ps;
1007   netwib_data data;
1008   netwib_uint32 datasize;
1009   netwib_char c1, c2=0;
1010   netwib_cmp cmp=NETWIB_CMP_LT;
1011 
1012   /* parameter verification */
1013   if (pbuf1 != NULL) {
1014     if (pbuf1->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
1015       return(NETWIB_ERR_LOOBJUSECLOSED);
1016     }
1017 #if NETWIB_DEBUG_LEAK==1
1018     netwib_er(netwib_debug_leak_valid_buf(pbuf1->totalptr,
1019                                           netwib__priv_buf_get_leakid(pbuf1)));
1020 #endif
1021   }
1022 
1023   datasize = netwib__buf_ref_data_sizenull(pbuf1);
1024   data = datasize?netwib__buf_ref_data_ptr(pbuf1):NULL;
1025   ps = string2;
1026 
1027   while (NETWIB_TRUE) {
1028     if (string2 == NULL) {
1029       c2 = '\0';
1030     } else {
1031       c2 = *ps++;
1032     }
1033     if (c2 == '\0') {
1034       if (datasize == 0) {
1035         cmp = NETWIB_CMP_EQ;
1036       } else {
1037         cmp = NETWIB_CMP_GT;
1038       }
1039       break;
1040     }
1041     if (datasize == 0) {
1042       cmp = NETWIB_CMP_LT;
1043       break;
1044     }
1045     c1 = *data++;
1046     datasize--;
1047     netwib_c2_lower(c2);
1048     netwib_c2_lower(c1);
1049     if (c1 > c2) {
1050       cmp = NETWIB_CMP_GT;
1051       break;
1052     } else if (c1 < c2) {
1053       cmp = NETWIB_CMP_LT;
1054       break;
1055     }
1056   }
1057 
1058   if (pcmp != NULL) *pcmp = cmp;
1059   return(NETWIB_ERR_OK);
1060 }
1061 
1062 /*-------------------------------------------------------------*/
netwib_buf_close(netwib_buf * pbuf)1063 netwib_err netwib_buf_close(netwib_buf *pbuf)
1064 {
1065   /* simple case */
1066   if (pbuf == NULL) {
1067     /* nothing to close */
1068     return(NETWIB_ERR_OK);
1069   }
1070 
1071   if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
1072     return(NETWIB_ERR_LOOBJCLOSEALREADYCLOSED);
1073   }
1074 
1075   netwib_er(netwib_priv_buf_wipe(pbuf));
1076 
1077   if (pbuf->flags&NETWIB_BUF_FLAGS_ALLOC) {
1078 #if NETWIB_DEBUG_LEAK==1
1079     netwib_er(netwib_debug_leak_del_buf(pbuf->totalptr,
1080                                         netwib__priv_buf_get_leakid(pbuf)));
1081 #endif
1082     netwib_er(netwib_ptr_free((netwib_ptr*)&pbuf->totalptr));
1083   }
1084 
1085   pbuf->totalptr = NETWIB_PRIV_BUF_PTR_CLOSED;
1086 
1087   return(NETWIB_ERR_OK);
1088 }
1089 
1090